Skip to content

Commit

Permalink
Make all editor configuration optional. Fix #21
Browse files Browse the repository at this point in the history
  • Loading branch information
thibaudcolas committed Jan 15, 2017
1 parent d7e9262 commit d80c7b2
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 133 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
- `BLOCK_TYPES` property is now `blockTypes`.
- Inline styles and block types now use the `type` attribute instead of `style`.
- `imageFormats` are now assigned directly on the `IMAGE` entity type. #33
- All options are now direct props of `DraftailEditor` instead of attributes of the `options` prop. #21

### Fixed

Expand Down
31 changes: 13 additions & 18 deletions examples/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,6 @@ import DraftailEditor, { BLOCK_TYPE, INLINE_STYLE } from '../lib';

const mount = document.querySelector('[data-mount-basic]');

const options = {
enableHorizontalRule: true,
enableLineBreak: true,
entityTypes: [],
blockTypes: [
{ label: 'H2', type: BLOCK_TYPE.HEADER_TWO },
{ label: 'H3', type: BLOCK_TYPE.HEADER_THREE },
{ label: 'UL', type: BLOCK_TYPE.UNORDERED_LIST_ITEM, icon: 'icon-list-ul' },
{ label: 'OL', type: BLOCK_TYPE.ORDERED_LIST_ITEM, icon: 'icon-list-ol' },
],
inlineStyles: [
{ label: 'Bold', type: INLINE_STYLE.BOLD, icon: 'icon-bold' },
{ label: 'Italic', type: INLINE_STYLE.ITALIC, icon: 'icon-italic' },
{ label: 'Strikethrough', type: INLINE_STYLE.STRIKETHROUGH, icon: 'icon-pacman' },
],
};

const rawContentState = {
entityMap: {
0: {
Expand Down Expand Up @@ -137,8 +120,20 @@ const onSave = (contentState) => {
const editor = (
<DraftailEditor
rawContentState={rawContentState}
options={options}
onSave={onSave}
enableHorizontalRule={true}
enableLineBreak={true}
blockTypes={[
{ label: 'H2', type: BLOCK_TYPE.HEADER_TWO },
{ label: 'H3', type: BLOCK_TYPE.HEADER_THREE },
{ label: 'UL', type: BLOCK_TYPE.UNORDERED_LIST_ITEM, icon: 'icon-list-ul' },
{ label: 'OL', type: BLOCK_TYPE.ORDERED_LIST_ITEM, icon: 'icon-list-ol' },
]}
inlineStyles={[
{ label: 'Bold', type: INLINE_STYLE.BOLD, icon: 'icon-bold' },
{ label: 'Italic', type: INLINE_STYLE.ITALIC, icon: 'icon-italic' },
{ label: 'Strikethrough', type: INLINE_STYLE.STRIKETHROUGH, icon: 'icon-strikethrough' },
]}
/>
);

Expand Down
14 changes: 4 additions & 10 deletions examples/custom.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,6 @@ import DraftailEditor, { BLOCK_TYPE } from '../lib';

const mount = document.querySelector('[data-mount-custom]');

const options = {
entityTypes: [],
blockTypes: [
{ label: 'H2', type: BLOCK_TYPE.HEADER_TWO },
{ label: 'T&C', type: 'terms-and-conditions', element: 'div', className: 'u-smalltext' },
],
inlineStyles: [],
};

const rawContentState = {
entityMap: {},
blocks: [
Expand All @@ -35,8 +26,11 @@ const onSave = (contentState) => {
const editor = (
<DraftailEditor
rawContentState={rawContentState}
options={options}
onSave={onSave}
blockTypes={[
{ label: 'H2', type: BLOCK_TYPE.HEADER_TWO },
{ label: 'T&C', type: 'terms-and-conditions', element: 'div', className: 'u-smalltext' },
]}
/>
);

Expand Down
25 changes: 9 additions & 16 deletions examples/entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,6 @@ import Document, { findDocumentEntities } from './entities/Document';

const mount = document.querySelector('[data-mount-entities]');

const options = {
enableHorizontalRule: true,
enableLineBreak: true,
entityTypes: [
{ label: 'Link', type: ENTITY_TYPE.LINK, icon: 'icon-link', control: BasicLinkSource, strategy: findLinkEntities, component: Link },
{ label: 'Document', type: ENTITY_TYPE.DOCUMENT, icon: 'icon-doc-full', control: BasicDocumentSource, strategy: findDocumentEntities, component: Document },
],
blockTypes: [
{ label: 'H2', type: BLOCK_TYPE.HEADER_TWO },
{ label: 'H3', type: BLOCK_TYPE.HEADER_THREE },
{ label: 'Blockquote', type: BLOCK_TYPE.BLOCKQUOTE, icon: 'icon-openquote' },
],
inlineStyles: [],
};

const saveField = document.createElement('input');
saveField.type = 'hidden';
mount.parentNode.appendChild(saveField);
Expand Down Expand Up @@ -95,8 +80,16 @@ const rawContentState = {
const editor = (
<DraftailEditor
rawContentState={rawContentState}
options={options}
onSave={onSave}
entityTypes={[
{ label: 'Link', type: ENTITY_TYPE.LINK, icon: 'icon-link', control: BasicLinkSource, strategy: findLinkEntities, component: Link },
{ label: 'Document', type: ENTITY_TYPE.DOCUMENT, icon: 'icon-doc-full', control: BasicDocumentSource, strategy: findDocumentEntities, component: Document },
]}
blockTypes={[
{ label: 'H2', type: BLOCK_TYPE.HEADER_TWO },
{ label: 'H3', type: BLOCK_TYPE.HEADER_THREE },
{ label: 'Blockquote', type: BLOCK_TYPE.BLOCKQUOTE, icon: 'icon-openquote' },
]}
/>
);

Expand Down
56 changes: 26 additions & 30 deletions examples/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,6 @@ import Document, { findDocumentEntities } from './entities/Document';

const mount = document.querySelector('[data-mount-test]');

const options = {
enableHorizontalRule: true,
enableLineBreak: true,
entityTypes: [
{ label: 'Image', type: ENTITY_TYPE.IMAGE, icon: 'icon-image', control: BasicImageSource },
{ label: 'Embed', type: ENTITY_TYPE.EMBED, icon: 'icon-media', control: BasicEmbedSource },
{ label: 'Link', type: ENTITY_TYPE.LINK, icon: 'icon-link', control: BasicLinkSource, strategy: findLinkEntities, component: Link },
{ label: 'Document', type: ENTITY_TYPE.DOCUMENT, icon: 'icon-doc-full', control: BasicDocumentSource, strategy: findDocumentEntities, component: Document },
// { label: 'Model', type: ENTITY_TYPE.MODEL, icon: 'icon-cog', control: GenericModelSource, strategy: findModelEntities, component: Model },
],
blockTypes: [
{ label: 'H2', type: BLOCK_TYPE.HEADER_TWO },
{ label: 'H3', type: BLOCK_TYPE.HEADER_THREE },
{ label: 'H4', type: BLOCK_TYPE.HEADER_FOUR },
{ label: 'H5', type: BLOCK_TYPE.HEADER_FIVE },
{ label: 'Blockquote', type: BLOCK_TYPE.BLOCKQUOTE, icon: 'icon-openquote' },
{ label: 'UL', type: BLOCK_TYPE.UNORDERED_LIST_ITEM, icon: 'icon-list-ul' },
{ label: 'OL', type: BLOCK_TYPE.ORDERED_LIST_ITEM, icon: 'icon-list-ol' },
{ label: 'T&C', type: 'terms-and-conditions', element: 'div', className: 'u-smalltext' },
],
inlineStyles: [
{ label: 'Bold', type: INLINE_STYLE.BOLD, icon: 'icon-bold' },
{ label: 'Italic', type: INLINE_STYLE.ITALIC, icon: 'icon-italic' },
{ label: 'Underline', type: INLINE_STYLE.UNDERLINE, icon: 'icon-underline' },
{ label: 'Monospace', type: INLINE_STYLE.CODE, icon: 'icon-pacman' },
{ label: 'Strikethrough', type: INLINE_STYLE.STRIKETHROUGH, icon: 'icon-strikethrough' },
],
};

const onSave = (rawContentState) => {
const serialised = JSON.stringify(rawContentState);
sessionStorage.setItem('entities:rawContentState', serialised);
Expand All @@ -51,8 +22,33 @@ const onSave = (rawContentState) => {
const editor = (
<DraftailEditor
rawContentState={JSON.parse(sessionStorage.getItem('entities:rawContentState')) || {}}
options={options}
onSave={onSave}
enableHorizontalRule={true}
enableLineBreak={true}
entityTypes={[
{ label: 'Image', type: ENTITY_TYPE.IMAGE, icon: 'icon-image', control: BasicImageSource, imageFormats: [] },
{ label: 'Embed', type: ENTITY_TYPE.EMBED, icon: 'icon-media', control: BasicEmbedSource },
{ label: 'Link', type: ENTITY_TYPE.LINK, icon: 'icon-link', control: BasicLinkSource, strategy: findLinkEntities, component: Link },
{ label: 'Document', type: ENTITY_TYPE.DOCUMENT, icon: 'icon-doc-full', control: BasicDocumentSource, strategy: findDocumentEntities, component: Document },
// { label: 'Model', type: ENTITY_TYPE.MODEL, icon: 'icon-cog', control: GenericModelSource, strategy: findModelEntities, component: Model },
]}
blockTypes={[
{ label: 'H2', type: BLOCK_TYPE.HEADER_TWO },
{ label: 'H3', type: BLOCK_TYPE.HEADER_THREE },
{ label: 'H4', type: BLOCK_TYPE.HEADER_FOUR },
{ label: 'H5', type: BLOCK_TYPE.HEADER_FIVE },
{ label: 'Blockquote', type: BLOCK_TYPE.BLOCKQUOTE, icon: 'icon-openquote' },
{ label: 'UL', type: BLOCK_TYPE.UNORDERED_LIST_ITEM, icon: 'icon-list-ul' },
{ label: 'OL', type: BLOCK_TYPE.ORDERED_LIST_ITEM, icon: 'icon-list-ol' },
{ label: 'T&C', type: 'terms-and-conditions', element: 'div', className: 'u-smalltext' },
]}
inlineStyles={[
{ label: 'Bold', type: INLINE_STYLE.BOLD, icon: 'icon-bold' },
{ label: 'Italic', type: INLINE_STYLE.ITALIC, icon: 'icon-italic' },
{ label: 'Underline', type: INLINE_STYLE.UNDERLINE, icon: 'icon-underline' },
{ label: 'Monospace', type: INLINE_STYLE.CODE, icon: 'icon-pacman' },
{ label: 'Strikethrough', type: INLINE_STYLE.STRIKETHROUGH, icon: 'icon-strikethrough' },
]}
/>
);

Expand Down
3 changes: 2 additions & 1 deletion lib/blocks/ImageBlock.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class ImageBlock extends Component {
renderMediaOptions() {
const { entityConfig, onCancel } = this.props;
const { alignment, altText } = this.state;
const imageFormats = entityConfig.imageFormats || [];

// TODO Add <label> elt for Alt text field.
return (
Expand All @@ -78,7 +79,7 @@ class ImageBlock extends Component {
<div className="RichEditor-col">
<h4>Image alignment</h4>
<p>
{entityConfig.imageFormats.map((format) => {
{imageFormats.map((format) => {
return (
<label key={format.value}>
<input
Expand Down
99 changes: 48 additions & 51 deletions lib/components/DraftailEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,14 @@ import Tooltip from '../components/Tooltip';
import DividerBlock from '../blocks/DividerBlock';
import MediaBlock from '../blocks/MediaBlock';

const defaultOptions = {
enableHorizontalRule: false,
enableLineBreak: false,
imageFormats: [],
entityTypes: [],
blockTypes: [],
inlineStyles: [],
};

/**
* The top-level component for the Draftail Draft.js editor.
*/
class DraftailEditor extends Component {
constructor(props) {
super(props);
const { rawContentState, options } = props;
const decorators = options.entityTypes.filter(type => !!type.strategy);
const { rawContentState, entityTypes } = props;
const decorators = entityTypes.filter(type => !!type.strategy);

this.state = {
editorState: conversion.createEditorState(rawContentState, decorators),
Expand Down Expand Up @@ -104,8 +95,8 @@ class DraftailEditor extends Component {
}

toggleDialog(entityType, entity = null) {
const { options } = this.props;
const dialogOptions = options.entityTypes.find(item => item.type === entityType);
const { entityTypes } = this.props;
const dialogOptions = entityTypes.find(item => item.type === entityType);

this.setState({
readOnly: true,
Expand All @@ -115,7 +106,7 @@ class DraftailEditor extends Component {
}

handleReturn(e) {
const { options } = this.props;
const { enableLineBreak } = this.props;
const { editorState } = this.state;
let ret = false;

Expand All @@ -135,7 +126,7 @@ class DraftailEditor extends Component {
}
}
} else {
if (!options.enableLineBreak) {
if (!enableLineBreak) {
// Quick hack to disable soft line breaks.
// eslint-disable-next-line no-param-reassign
e.which = 0;
Expand Down Expand Up @@ -241,7 +232,7 @@ class DraftailEditor extends Component {
}

blockRenderer(block) {
const { options } = this.props;
const { entityTypes } = this.props;
const { editorState } = this.state;
let entity;
let isHorizontalRule;
Expand All @@ -264,7 +255,7 @@ class DraftailEditor extends Component {
editable: false,
props: {
entity: entity,
entityConfig: options.entityTypes.find(item => item.type === entity.type),
entityConfig: entityTypes.find(item => item.type === entity.type),
lockEditor: this.lockEditor,
unlockEditor: this.unlockEditor,
editorState: editorState,
Expand Down Expand Up @@ -357,7 +348,7 @@ class DraftailEditor extends Component {
}

render() {
const { options } = this.props;
const { enableHorizontalRule, enableLineBreak, blockTypes, inlineStyles, entityTypes } = this.props;
const { editorState, readOnly } = this.state;

/* eslint-disable jsx-a11y/no-static-element-interactions */
Expand All @@ -370,7 +361,11 @@ class DraftailEditor extends Component {
>
<Toolbar
editorState={editorState}
options={options}
enableHorizontalRule={enableHorizontalRule}
enableLineBreak={enableLineBreak}
blockTypes={blockTypes}
inlineStyles={inlineStyles}
entityTypes={entityTypes}
readOnly={readOnly}
toggleBlockType={this.toggleBlockType}
toggleInlineStyle={this.toggleInlineStyle}
Expand All @@ -385,12 +380,12 @@ class DraftailEditor extends Component {
onChange={this.onChange}
readOnly={readOnly}
handleReturn={this.handleReturn}
keyBindingFn={config.getKeyBindingFn(options.blockTypes, options.inlineStyles, options.entityTypes)}
keyBindingFn={config.getKeyBindingFn(blockTypes, inlineStyles, entityTypes)}
handleKeyCommand={this.handleKeyCommand}
onTab={this.onTab}
blockRendererFn={this.blockRenderer}
blockRenderMap={config.getBlockRenderMap(options.blockTypes)}
blockStyleFn={config.getBlockStyleFn(options.blockTypes)}
blockRenderMap={config.getBlockRenderMap(blockTypes)}
blockStyleFn={config.getBlockStyleFn(blockTypes)}
/>

{this.renderTooltip()}
Expand All @@ -404,41 +399,43 @@ class DraftailEditor extends Component {
DraftailEditor.propTypes = {
rawContentState: React.PropTypes.object,
onSave: React.PropTypes.func,
options: React.PropTypes.shape({
enableHorizontalRule: React.PropTypes.boolean,
enableLineBreak: React.PropTypes.boolean,
entityTypes: React.PropTypes.arrayOf(React.PropTypes.shape({
enableHorizontalRule: React.PropTypes.bool,
enableLineBreak: React.PropTypes.bool,
entityTypes: React.PropTypes.arrayOf(React.PropTypes.shape({
label: React.PropTypes.string.isRequired,
type: React.PropTypes.string.isRequired,
icon: React.PropTypes.string,
control: React.PropTypes.func.isRequired,
strategy: React.PropTypes.func,
component: React.PropTypes.func,
// A bit dodgy. Specific to the IMAGE type or whatever uses the ImageBlock.
imageFormats: React.PropTypes.arrayOf(React.PropTypes.shape({
label: React.PropTypes.string.isRequired,
type: React.PropTypes.string.isRequired,
icon: React.PropTypes.string,
control: React.PropTypes.func.isRequired,
strategy: React.PropTypes.func,
component: React.PropTypes.func,
// A bit dodgy. Specific to the IMAGE type or whatever uses the ImageBlock.
imageFormats: React.PropTypes.arrayOf(React.PropTypes.shape({
label: React.PropTypes.string.isRequired,
value: React.PropTypes.string.isRequired,
})),
})).isRequired,
blockTypes: React.PropTypes.arrayOf(React.PropTypes.shape({
label: React.PropTypes.string.isRequired,
type: React.PropTypes.string.isRequired,
icon: React.PropTypes.string,
element: React.PropTypes.string,
className: React.PropTypes.string,
})).isRequired,
inlineStyles: React.PropTypes.arrayOf(React.PropTypes.shape({
label: React.PropTypes.string.isRequired,
type: React.PropTypes.string.isRequired,
icon: React.PropTypes.string,
})).isRequired,
}),
value: React.PropTypes.string.isRequired,
})),
})),
blockTypes: React.PropTypes.arrayOf(React.PropTypes.shape({
label: React.PropTypes.string.isRequired,
type: React.PropTypes.string.isRequired,
icon: React.PropTypes.string,
element: React.PropTypes.string,
className: React.PropTypes.string,
})),
inlineStyles: React.PropTypes.arrayOf(React.PropTypes.shape({
label: React.PropTypes.string.isRequired,
type: React.PropTypes.string.isRequired,
icon: React.PropTypes.string,
})),
};

DraftailEditor.defaultProps = {
rawContentState: {},
onSave: () => {},
options: defaultOptions,
enableHorizontalRule: false,
enableLineBreak: false,
entityTypes: [],
blockTypes: [],
inlineStyles: [],
};

export default DraftailEditor;
Loading

0 comments on commit d80c7b2

Please sign in to comment.