Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@

> Documentation: [draftail.org/docs/next/getting-started](https://www.draftail.org/docs/next/getting-started)

### Added

- Make it possible to hide buttons with default labels by setting their `label` to `null`. [#442](https://github.com/springload/draftail/pull/442)

### Changed

- Improve the editor props’ JSDoc annotations. [#441](https://github.com/springload/draftail/pull/441)

### Fixed

- Fix empty buttons appearing when providing custom formats without a defined label or icon. [#442](https://github.com/springload/draftail/pull/442)

## [[v1.3.0]](https://github.com/springload/draftail/releases/tag/v1.3.0)

> Documentation: [draftail.org/docs/getting-started](https://www.draftail.org/docs/getting-started)
Expand Down
44 changes: 44 additions & 0 deletions examples/components/BlockPicker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// @flow
import React from "react";
import { EditorState, RichUtils } from "draft-js";

import { BLOCK_TYPE } from "../../lib";

type Props = {|
getEditorState: () => EditorState,
onChange: (EditorState) => void,
|};

/**
* A traditional text style picker.
*/
const BlockPicker = ({ getEditorState, onChange }: Props) => {
const editorState = getEditorState();

return (
<select
onChange={(e) => {
const selection = editorState.getSelection();
let nextState = editorState;
nextState = RichUtils.toggleBlockType(nextState, e.target.value);
nextState = EditorState.forceSelection(nextState, selection);
onChange(nextState);
}}
style={{ maxWidth: "3rem" }}
>
{[
[BLOCK_TYPE.HEADER_TWO, "H2"],
[BLOCK_TYPE.HEADER_THREE, "H3"],
[BLOCK_TYPE.HEADER_FOUR, "H4"],
["tiny-text", "ₜᵢₙᵧ"],
[BLOCK_TYPE.UNSTYLED, "¶"],
].map(([type, label]) => (
<option key={type} value={type}>
{label}
</option>
))}
</select>
);
};

export default BlockPicker;
4 changes: 0 additions & 4 deletions examples/components/ColorPicker.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,3 @@
padding-block-start: 1rem;
padding-block-end: 1rem;
}

.Draftail-ToolbarButton[name^="COLOR_"] {
display: none;
}
13 changes: 12 additions & 1 deletion examples/docs.story.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
import EditorWrapper from "./components/EditorWrapper";
import PrismDecorator from "./components/PrismDecorator";
import ReadingTime from "./components/ReadingTime";
import BlockPicker from "./components/BlockPicker";

storiesOf("Docs", module)
// Add a decorator rendering story as a component for hooks support.
Expand Down Expand Up @@ -204,7 +205,17 @@ storiesOf("Docs", module)
entityMap: {},
}}
stripPastedStyles={false}
controls={[ReadingTime]}
blockTypes={[
{ type: BLOCK_TYPE.HEADER_TWO, label: null },
{ type: BLOCK_TYPE.HEADER_THREE, label: null },
{ type: BLOCK_TYPE.HEADER_FOUR, label: null },
BLOCK_CONTROL.CODE,
{
type: "tiny-text",
element: "blockquote",
},
]}
controls={[BlockPicker, ReadingTime]}
/>
))
.add("UI theming", () => (
Expand Down
4 changes: 0 additions & 4 deletions examples/plugins/sectionBreakPlugin.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
[name="section-break"] {
display: none;
}

.SectionBreak {
border-bottom: 1px solid #aaa;
text-align: center;
Expand Down
2 changes: 1 addition & 1 deletion lib/components/DraftailEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import DividerBlock from "../blocks/DividerBlock";

type ControlProp = {|
/** Describes the control in the editor UI, concisely. */
label?: string,
label?: ?string,
/** Describes the control in the editor UI. */
description?: string,
/** Represents the control in the editor UI. */
Expand Down
13 changes: 8 additions & 5 deletions lib/components/ToolbarDefaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type { IconProp } from "./Icon";

type ControlProp = {
// Describes the control in the editor UI, concisely.
label?: string,
label?: ?string,
// Describes the control in the editor UI.
description?: string,
// Represents the control in the editor UI.
Expand All @@ -27,7 +27,7 @@ type ControlProp = {
const getButtonLabel = (type: string, config: boolean | ControlProp) => {
const icon = typeof config === "boolean" ? undefined : config.icon;

if (typeof config.label === "string") {
if (typeof config.label === "string" || config.label === null) {
return config.label;
}

Expand All @@ -38,6 +38,9 @@ const getButtonLabel = (type: string, config: boolean | ControlProp) => {
return LABELS[type];
};

const showButton = (config: ControlProp & { type: string }) =>
Boolean(config.icon) || Boolean(getButtonLabel(config.type, config));

const getButtonTitle = (type: string, config: boolean | ControlProp) => {
const description =
typeof config === "boolean" || typeof config.description === "undefined"
Expand Down Expand Up @@ -104,7 +107,7 @@ class ToolbarDefaults extends PureComponent<ToolbarDefaultProps> {
} = this.props;
return [
<ToolbarGroup key="styles">
{inlineStyles.map((t) => (
{inlineStyles.filter(showButton).map((t) => (
<ToolbarButton
key={t.type}
name={t.type}
Expand All @@ -118,7 +121,7 @@ class ToolbarDefaults extends PureComponent<ToolbarDefaultProps> {
</ToolbarGroup>,

<ToolbarGroup key="blocks">
{blockTypes.map((t) => (
{blockTypes.filter(showButton).map((t) => (
<ToolbarButton
key={t.type}
name={t.type}
Expand Down Expand Up @@ -166,7 +169,7 @@ class ToolbarDefaults extends PureComponent<ToolbarDefaultProps> {
</ToolbarGroup>,

<ToolbarGroup key="entities">
{entityTypes.map((t) => (
{entityTypes.filter(showButton).map((t) => (
<ToolbarButton
key={t.type}
name={t.type}
Expand Down
81 changes: 81 additions & 0 deletions lib/components/ToolbarDefaults.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,87 @@ describe("ToolbarDefaults", () => {
expect(wrapper.find("ToolbarButton").prop("label")).toBe("Format as bold");
});

it("custom button without label nor icon", () => {
const wrapper = mount(
<ToolbarDefaults
{...mockProps}
blockTypes={[
{
type: "emphasize",
},
]}
inlineStyles={[
{
type: "EMPHASIZE",
},
]}
entityTypes={[
{
type: "CUSTOM_LINK",
source: () => {},
},
]}
/>,
);
expect(wrapper.find("ToolbarButton").exists()).toBe(false);
});

it("built-in button with empty label", () => {
const wrapper = mount(
<ToolbarDefaults
{...mockProps}
blockTypes={[
{
type: "blockquote",
label: "",
},
]}
inlineStyles={[
{
type: "BOLD",
label: "",
},
]}
entityTypes={[
{
type: "LINK",
label: "",
source: () => {},
},
]}
/>,
);
expect(wrapper.find("ToolbarButton").exists()).toBe(false);
});

it("built-in button with null label", () => {
const wrapper = mount(
<ToolbarDefaults
{...mockProps}
blockTypes={[
{
type: "blockquote",
label: null,
},
]}
inlineStyles={[
{
type: "BOLD",
label: null,
},
]}
entityTypes={[
{
type: "LINK",
label: null,
source: () => {},
},
]}
/>,
);
expect(wrapper.find("ToolbarButton").exists()).toBe(false);
});

it("button titles with shortcut", () => {
expect(
mount(
Expand Down