diff --git a/.babelrc b/.babelrc index 6b35d80..d785532 100644 --- a/.babelrc +++ b/.babelrc @@ -1,9 +1,10 @@ { - presets: [ - 'env', - 'react' + "presets": [ + "env", + "react", + "stage-2", ], - plugins: [ - 'transform-object-rest-spread' + "plugins": [ + "transform-object-rest-spread" ] } diff --git a/README.md b/README.md index f373440..c24cb9c 100644 --- a/README.md +++ b/README.md @@ -36,18 +36,16 @@ const EditorWithPlugins = plugins(Editor); // Rich text editor component with pl const toHTML = plugins(convertFromHTML); // function to convert from HTML including plugin functionality const fromHTML = plugins(convertToHTML); // function to convert to HTML including plugin functionality -const MyEditor = React.createClass({ - getInitialState() { - return { - editorState: EditorState.createWithContent(fromHTML('
')) - }; - }, - - onChange(editorState) { +class MyEditor extends React.Comonent { + state = { + editorState: EditorState.createWithContent(fromHTML('
')) + } + + onChange = (editorState) => { const html = toHTML(editorState.getCurrentContent()); console.log(html); // don't actually convert to HTML on every change! this.setState({editorState}); - }, + } render() { return ( diff --git a/example/ToolbarButton.js b/example/ToolbarButton.js index 7388406..7b3c823 100644 --- a/example/ToolbarButton.js +++ b/example/ToolbarButton.js @@ -1,13 +1,5 @@ -window.ToolbarButton = createReactClass({ - getDefaultProps: function() { - return { - active: false, - label: '', - onClick: function() {} - }; - }, - - render: function() { +class ToolbarButton extends React.Component { + render () { var toolbarButtonStyle = { display: 'inline-block', minWidth: '24px', @@ -29,4 +21,12 @@ window.ToolbarButton = createReactClass({ }, this.props.label) ); } -}); +}; + +ToolbarButton.defaultProps = { + active: false, + label: '', + onClick: function() {} +}; + +window.ToolbarButton = ToolbarButton; \ No newline at end of file diff --git a/example/blockStyles.html b/example/blockStyles.html index eb52965..9e79096 100644 --- a/example/blockStyles.html +++ b/example/blockStyles.html @@ -16,7 +16,6 @@
- @@ -95,19 +94,17 @@ const toHTML = BlockPlugin(convertToHTML); const fromHTML = BlockPlugin(convertFromHTML); - const BlockStylesExample = createReactClass({ - getInitialState() { - return { - editorState: EditorState.createWithContent( - fromHTML('

Block style plugin

') - ) - }; - }, + class BlockStylesExample extends React.Component { + state = { + editorState: EditorState.createWithContent( + fromHTML('

Block style plugin

') + ) + } - onChange(editorState) { + onChange = (editorState) => { console.log(toHTML(editorState.getCurrentContent())); this.setState({editorState}); - }, + } render() { return ( @@ -125,7 +122,7 @@ ); } - }); + }; const WrappedComponent = KeyCommandController(BlockStylesExample); @@ -135,6 +132,6 @@ ); diff --git a/example/inlineStyles.html b/example/inlineStyles.html index 1a7323f..66ca917 100644 --- a/example/inlineStyles.html +++ b/example/inlineStyles.html @@ -16,7 +16,6 @@
- @@ -93,19 +92,17 @@ const toHTML = InlinePlugin(convertToHTML); const fromHTML = InlinePlugin(convertFromHTML); - const InlineStylesExample = createReactClass({ - getInitialState() { - return { - editorState: EditorState.createWithContent( - fromHTML('
Inline styles example
') - ) - }; - }, + class InlineStylesExample extends React.Component { + state = { + editorState: EditorState.createWithContent( + fromHTML('
Inline styles example
') + ) + } - onChange(editorState) { + onChange = (editorState) => { console.log(toHTML(editorState.getCurrentContent())); this.setState({editorState}); - }, + } render() { return ( @@ -116,7 +113,7 @@ /> ); } - }); + }; ReactDOM.render( , @@ -124,6 +121,6 @@ ); diff --git a/example/link.html b/example/link.html index 053a97f..ced37da 100644 --- a/example/link.html +++ b/example/link.html @@ -16,7 +16,6 @@
- @@ -122,19 +121,17 @@ const toHTML = LinkPlugin(convertToHTML); const fromHTML = LinkPlugin(convertFromHTML); - const LinkExample = createReactClass({ - getInitialState() { - return { - editorState: EditorState.createWithContent( - fromHTML('
Link example Draft
') - ) - }; - }, + class LinkExample extends React.Component { + state = { + editorState: EditorState.createWithContent( + fromHTML('
Link example Draft
') + ) + } - onChange(editorState) { + onChange = (editorState) => { console.log(toHTML(editorState.getCurrentContent())); this.setState({editorState}); - }, + } render() { return ( @@ -144,7 +141,7 @@ /> ); } - }); + }; ReactDOM.render( , @@ -152,6 +149,6 @@ ); diff --git a/example/mention.html b/example/mention.html index d1f2f34..4573d22 100644 --- a/example/mention.html +++ b/example/mention.html @@ -16,7 +16,6 @@
- @@ -104,32 +103,20 @@ return results; }; - const MentionResults = createReactClass({ - propTypes: { - search: PropTypes.string.isRequired, - offset: PropTypes.number.isRequired, - length: PropTypes.number.isRequired, - results: PropTypes.array.isRequired, - onSelect: PropTypes.func.isRequired, - addKeyCommandListener: PropTypes.func.isRequired, - removeKeyCommandListener: PropTypes.func.isRequired - }, - - getInitialState() { - return { - selection: 0 - }; - }, + class MentionResults extends React.Component { + state = { + selection: 0 + } componentDidMount() { this.props.addKeyCommandListener(this.handleKeyCommand); - }, + } componentWillUnmount() { this.props.removeKeyCommandListener(this.handleKeyCommand); - }, + } - handleKeyCommand(editorState, command, keyboardEvent) { + handleKeyCommand = (editorState, command, keyboardEvent) => { const { search, offset, @@ -163,9 +150,9 @@ default: return null; } - }, + } - arrowUp() { + arrowUp = () => { const {selection} = this.state; if (selection > 0) { @@ -173,9 +160,9 @@ selection: selection - 1 }); } - }, + } - arrowDown() { + arrowDown = () => { const {results} = this.props; const {selection} = this.state; @@ -184,9 +171,9 @@ selection: selection + 1 }); } - }, + } - selectItem({value, text}) { + selectItem = ({value, text}) => { const { search, offset, @@ -195,9 +182,9 @@ } = this.props; onSelect({value, text}, {search, offset, length}); - }, + } - renderResults() { + renderResults = () => { const { results, } = this.props; @@ -254,7 +241,7 @@ ); }); - }, + } render() { return ( @@ -269,19 +256,22 @@ ); } - }); + }; - const TYPING_TRIGGER_REGEX = new RegExp('(\\B@[\\w\\s]{1,10})$'); + MentionResults.propTypes = { + search: PropTypes.string.isRequired, + offset: PropTypes.number.isRequired, + length: PropTypes.number.isRequired, + results: PropTypes.array.isRequired, + onSelect: PropTypes.func.isRequired, + addKeyCommandListener: PropTypes.func.isRequired, + removeKeyCommandListener: PropTypes.func.isRequired + }; - const MentionOverlay = createReactClass({ - propTypes: { - editorState: PropTypes.object.isRequired, - onChange: PropTypes.func.isRequired, - addKeyCommandListener: PropTypes.func.isRequired, - removeKeyCommandListener: PropTypes.func.isRequired - }, + const TYPING_TRIGGER_REGEX = new RegExp('(\\B@[\\w\\s]{1,10})$'); - getCurrentSearch() { + class MentionOverlay extends React.Component { + getCurrentSearch = () => { const selection = this.props.editorState.getSelection(); const contentState = this.props.editorState.getCurrentContent(); const blockText = contentState.getBlockForKey(selection.getStartKey()).getText(); @@ -305,9 +295,9 @@ offset: offset - beforeCursorText.length - 1, length: 1 + beforeCursorText.length + pastCursorText.length }; - }, + } - selectOption(option, {offset, length}) { + selectOption = (option, {offset, length}) => { const { editorState, onChange @@ -337,14 +327,14 @@ 'insert-characters' ) ); - }, + } - getResults(search) { + getResults = (search) => { const regex = new RegExp(search.trim(), 'i'); return this.props.users.filter(({value, text}) => { return (text.match(regex) !== null || value.toString().match(regex) !== null); }); - }, + } render() { const { @@ -360,7 +350,7 @@ top, left, height - } = getVisibleSelectionRect(window); + } = getVisibleSelectionRect(window) || {}; const results = this.getResults(currentSearch.search); @@ -390,7 +380,14 @@ return null; } - }); + }; + + MentionOverlay.propTypes = { + editorState: PropTypes.object.isRequired, + onChange: PropTypes.func.isRequired, + addKeyCommandListener: PropTypes.func.isRequired, + removeKeyCommandListener: PropTypes.func.isRequired + }; const MentionPlugin = createPlugin({ decorators: MentionDecorator, @@ -403,19 +400,17 @@ const toHTML = MentionPlugin(convertToHTML); const fromHTML = MentionPlugin(convertFromHTML); - const MentionExample = createReactClass({ - getInitialState() { - return { - editorState: EditorState.createWithContent( - fromHTML('
Mention example @user1. Type @ to add a new mention for User 1 or User 2
') - ) - }; - }, + class MentionExample extends React.Component { + state = { + editorState: EditorState.createWithContent( + fromHTML('
Mention example @user1. Type @ to add a new mention for User 1 or User 2
') + ) + } - onChange(editorState) { + onChange = (editorState) => { console.log(toHTML(editorState.getCurrentContent())); this.setState({editorState}); - }, + } render() { return ( @@ -426,7 +421,7 @@ /> ); } - }); + }; ReactDOM.render( , @@ -434,6 +429,6 @@ ); diff --git a/example/token.html b/example/token.html index d12ae6a..ab673cb 100644 --- a/example/token.html +++ b/example/token.html @@ -16,7 +16,6 @@
- @@ -126,19 +125,17 @@ const toHTML = TokenPlugin(convertToHTML); const fromHTML = TokenPlugin(convertFromHTML); - const TokenExample = createReactClass({ - getInitialState() { - return { - editorState: EditorState.createWithContent( - fromHTML('
Token example {{ token }}
') - ) - }; - }, + class TokenExample extends React.Component { + state ={ + editorState: EditorState.createWithContent( + fromHTML('
Token example {{ token }}
') + ) + } - onChange(editorState) { + onChange = (editorState) => { console.log(toHTML(editorState.getCurrentContent())); this.setState({editorState}); - }, + } render() { return ( @@ -148,7 +145,7 @@ /> ); } - }); + }; ReactDOM.render( , @@ -156,6 +153,6 @@ ); diff --git a/package.json b/package.json index 6e4a904..f958db4 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ "react-dom": "^15.0.0 || ^16.0.0" }, "dependencies": { - "create-react-class": "^15.6.2", "immutable": "^3.8.1", "invariant": "^2.2.1", "prop-types": "^15.6.0" @@ -43,6 +42,7 @@ "babel-plugin-transform-object-rest-spread": "^6.6.5", "babel-preset-env": "^1.6.1", "babel-preset-react": "^6.5.0", + "babel-preset-stage-2": "^6.24.1", "babel-standalone": "^6.7.7", "draft-convert": "^1.3.1", "draft-js": "^0.8.1", diff --git a/src/components/Editor.js b/src/components/Editor.js index 4dc6d26..20f4223 100644 --- a/src/components/Editor.js +++ b/src/components/Editor.js @@ -1,6 +1,5 @@ import React from 'react'; import PropTypes from 'prop-types'; -import createReactClass from 'create-react-class'; import {List} from 'immutable'; import { Editor, @@ -11,68 +10,15 @@ import { import KeyCommandController from './KeyCommandController'; import OverlayWrapper from './OverlayWrapper'; -const propTypes = { - className: PropTypes.string, - editorState: PropTypes.object, - onChange: PropTypes.func, - decorators: PropTypes.array, - baseDecorator: PropTypes.func, - styleMap: PropTypes.object, - buttons: PropTypes.array, - overlays: PropTypes.array, - blockRendererFn: PropTypes.func, - blockStyleFn: PropTypes.func, - keyBindingFn: PropTypes.func, - addKeyCommandListener: PropTypes.func.isRequired, - removeKeyCommandListener: PropTypes.func.isRequired, - handleReturn: PropTypes.func, - onEscape: PropTypes.func, - onTab: PropTypes.func, - onUpArrow: PropTypes.func, - onDownArrow: PropTypes.func, - readOnly: PropTypes.bool, - showButtons: PropTypes.bool -}; - -const EditorWrapper = createReactClass({ - propTypes, - - childContextTypes: { - getEditorState: PropTypes.func, - getReadOnly: PropTypes.func, - setReadOnly: PropTypes.func, - onChange: PropTypes.func, - focus: PropTypes.func, - blur: PropTypes.func - }, - - getDefaultProps() { - return { - className: '', - editorState: EditorState.createEmpty(), - onChange: () => {}, - decorators: [], - baseDecorator: CompositeDecorator, - styleMap: {}, - buttons: [], - overlays: [], - blockRendererFn: () => {}, - blockStyleFn: () => {}, - keyBindingFn: () => {}, - readOnly: false, - showButtons: true - }; - }, - - getInitialState() { +class EditorWrapper extends React.Component { + constructor(props) { + super(props); const { baseDecorator } = this.props; - - const decorator = new baseDecorator(this.props.decorators); - return { - decorator, + this.state = { + decorator: new baseDecorator(this.props.decorators), readOnly: false }; - }, + } getChildContext() { return { @@ -83,7 +29,7 @@ const EditorWrapper = createReactClass({ focus: this.focus, blur: this.blur }; - }, + } componentWillReceiveProps(nextProps) { if (nextProps.decorators.length === this.state.decorator._decorators.length) { @@ -96,48 +42,48 @@ const EditorWrapper = createReactClass({ } this.setState({decorator: new nextProps.baseDecorator(nextProps.decorators)}); - }, + } - keyBindingFn(e) { + keyBindingFn = (e) => { const pluginsCommand = this.props.keyBindingFn(e); if (pluginsCommand) { return pluginsCommand; } return getDefaultKeyBinding(e); - }, + } - handleReturn(e) { + handleReturn = (e) => { return (this.props.handleReturn && this.props.handleReturn(e)) || this.props.handleKeyCommand('return', e); - }, + } - onEscape(e) { + onEscape = (e) => { return (this.props.onEscape && this.props.onEscape(e)) || this.props.handleKeyCommand('escape', e); - }, + } - onTab(e) { + onTab = (e) => { return (this.props.onTab && this.props.onTab(e)) || this.props.handleKeyCommand('tab', e); - }, + } - onUpArrow(e) { + onUpArrow = (e) => { return (this.props.onUpArrow && this.props.onUpArrow(e)) || this.props.handleKeyCommand('up-arrow', e); - }, + } - onDownArrow(e) { + onDownArrow = (e) => { return (this.props.onDownArrow && this.props.onDownArrow(e)) || this.props.handleKeyCommand('down-arrow', e); - }, + } - focus() { + focus = () => { this.refs.editor.focus(); - }, + } - blur() { + blur = () => { this.refs.editor.blur(); - }, + } - getOtherProps() { + getOtherProps = () => { const propKeys = Object.keys(this.props); - const propTypeKeys = Object.keys(propTypes); + const propTypeKeys = Object.keys(EditorWrapper.propTypes); const propsToPass = propKeys.filter((prop) => { return propTypeKeys.indexOf(prop) === -1; @@ -147,17 +93,17 @@ const EditorWrapper = createReactClass({ acc[prop] = this.props[prop]; return acc; }, {}); - }, + } - getReadOnly() { + getReadOnly = () => { return this.state.readOnly || this.props.readOnly; - }, + } - setReadOnly(readOnly) { + setReadOnly = (readOnly) => { this.setState({readOnly}); - }, + } - getDecoratedState() { + getDecoratedState = () => { const {editorState} = this.props; const {decorator} = this.state; @@ -168,9 +114,9 @@ const EditorWrapper = createReactClass({ } return EditorState.set(editorState, {decorator}); - }, + } - renderPluginButtons() { + renderPluginButtons = () => { const { onChange, addKeyCommandListener, @@ -197,9 +143,9 @@ const EditorWrapper = createReactClass({ /> ); }); - }, + } - renderOverlays() { + renderOverlays = () => { const { onChange, addKeyCommandListener, @@ -221,7 +167,7 @@ const EditorWrapper = createReactClass({ ); }); - }, + } render() { const { @@ -268,6 +214,54 @@ const EditorWrapper = createReactClass({ ); } -}); +}; + +EditorWrapper.childContextTypes = { + getEditorState: PropTypes.func, + getReadOnly: PropTypes.func, + setReadOnly: PropTypes.func, + onChange: PropTypes.func, + focus: PropTypes.func, + blur: PropTypes.func +}; + +EditorWrapper.defaultProps = { + className: '', + editorState: EditorState.createEmpty(), + onChange: () => {}, + decorators: [], + baseDecorator: CompositeDecorator, + styleMap: {}, + buttons: [], + overlays: [], + blockRendererFn: () => {}, + blockStyleFn: () => {}, + keyBindingFn: () => {}, + readOnly: false, + showButtons: true +}; + +EditorWrapper.propTypes = { + className: PropTypes.string, + editorState: PropTypes.object, + onChange: PropTypes.func, + decorators: PropTypes.array, + baseDecorator: PropTypes.func, + styleMap: PropTypes.object, + buttons: PropTypes.array, + overlays: PropTypes.array, + blockRendererFn: PropTypes.func, + blockStyleFn: PropTypes.func, + keyBindingFn: PropTypes.func, + addKeyCommandListener: PropTypes.func.isRequired, + removeKeyCommandListener: PropTypes.func.isRequired, + handleReturn: PropTypes.func, + onEscape: PropTypes.func, + onTab: PropTypes.func, + onUpArrow: PropTypes.func, + onDownArrow: PropTypes.func, + readOnly: PropTypes.bool, + showButtons: PropTypes.bool +}; export default KeyCommandController(EditorWrapper); diff --git a/src/components/KeyCommandController.js b/src/components/KeyCommandController.js index f5e378d..e5927b5 100644 --- a/src/components/KeyCommandController.js +++ b/src/components/KeyCommandController.js @@ -1,6 +1,5 @@ import React from 'react'; import PropTypes from 'prop-types'; -import createReactClass from 'create-react-class'; import invariant from 'invariant'; import {List} from 'immutable'; import {EditorState} from 'draft-js'; @@ -11,146 +10,148 @@ const providedProps = { handleKeyCommand: PropTypes.func }; -const KeyCommandController = (Component) => createReactClass({ - displayName: `KeyCommandController(${Component.displayName})`, - - propTypes: { - editorState: PropTypes.object, - onChange: PropTypes.func, - keyCommandListeners: PropTypes.arrayOf(PropTypes.func), - ...providedProps - }, - - getDefaultProps() { - return { - keyCommandListeners: [] - }; - }, - - componentWillMount() { - this.keyCommandOverrides = List(this.props.keyCommandListeners); - this.keyCommandListeners = List(); - }, - - componentDidMount() { - // ensure valid props for deferral - const propNames = Object.keys(providedProps); - const presentProps = propNames.filter((propName) => this.props[propName] !== undefined); - const nonePresent = presentProps.length === 0; - const allPresent = presentProps.length === propNames.length; - - invariant( - nonePresent || allPresent, - `KeyCommandController: A KeyCommandController is receiving only some props (${presentProps.join(', ')}) necessary to defer to a parent key command controller.` - ); - - if (allPresent) { - this.props.keyCommandListeners.forEach((listener) => { - this.props.addKeyCommandListener(listener); - }); +const KeyCommandController = (Component) => { + class KeyCommand extends React.Component { + componentWillMount() { + this.keyCommandOverrides = List(this.props.keyCommandListeners); + this.keyCommandListeners = List(); } - }, - componentWillUnmount() { - if (this.props.removeKeyCommandListener) { - this.props.keyCommandListeners.forEach((listener) => { - this.props.removeKeyCommandListener(listener); - }); + componentDidMount() { + // ensure valid props for deferral + const propNames = Object.keys(providedProps); + const presentProps = propNames.filter((propName) => this.props[propName] !== undefined); + const nonePresent = presentProps.length === 0; + const allPresent = presentProps.length === propNames.length; + + invariant( + nonePresent || allPresent, + `KeyCommandController: A KeyCommandController is receiving only some props (${presentProps.join(', ')}) necessary to defer to a parent key command controller.` + ); + + if (allPresent) { + this.props.keyCommandListeners.forEach((listener) => { + this.props.addKeyCommandListener(listener); + }); + } } - }, - - addKeyCommandListener(listener) { - const {addKeyCommandListener} = this.props; - if (addKeyCommandListener) { - addKeyCommandListener(listener); - return; + componentWillUnmount() { + if (this.props.removeKeyCommandListener) { + this.props.keyCommandListeners.forEach((listener) => { + this.props.removeKeyCommandListener(listener); + }); + } } - this.keyCommandListeners = this.keyCommandListeners.unshift(listener); - }, + addKeyCommandListener = (listener) => { + const {addKeyCommandListener} = this.props; - removeKeyCommandListener(listener) { - const {removeKeyCommandListener} = this.props; + if (addKeyCommandListener) { + addKeyCommandListener(listener); + return; + } - if (removeKeyCommandListener) { - removeKeyCommandListener(listener); - return; + this.keyCommandListeners = this.keyCommandListeners.unshift(listener); } - this.keyCommandListeners = this.keyCommandListeners.filterNot((l) => l === listener); - }, + removeKeyCommandListener = (listener) => { + const {removeKeyCommandListener} = this.props; - handleKeyCommand(command, keyboardEvent = null) { - const {editorState, onChange, handleKeyCommand} = this.props; + if (removeKeyCommandListener) { + removeKeyCommandListener(listener); + return; + } - if (handleKeyCommand) { - return handleKeyCommand(command, keyboardEvent); + this.keyCommandListeners = this.keyCommandListeners.filterNot((l) => l === listener); } - const result = this.keyCommandListeners.concat(this.keyCommandOverrides).reduce(({state, hasChanged}, listener) => { - if (hasChanged === true) { - return { - state, - hasChanged - }; + handleKeyCommand = (command, keyboardEvent = null) => { + const {editorState, onChange, handleKeyCommand} = this.props; + + if (handleKeyCommand) { + return handleKeyCommand(command, keyboardEvent); } - const listenerResult = listener(state, command, keyboardEvent); - const isEditorState = listenerResult instanceof EditorState; + const result = this.keyCommandListeners.concat(this.keyCommandOverrides).reduce(({state, hasChanged}, listener) => { + if (hasChanged === true) { + return { + state, + hasChanged + }; + } - if (listenerResult === true || (isEditorState && listenerResult !== state)) { - if (isEditorState) { - onChange(listenerResult); + const listenerResult = listener(state, command, keyboardEvent); + const isEditorState = listenerResult instanceof EditorState; + + if (listenerResult === true || (isEditorState && listenerResult !== state)) { + if (isEditorState) { + onChange(listenerResult); + return { + state: listenerResult, + hasChanged: true + }; + } return { - state: listenerResult, + state, hasChanged: true }; } + return { state, - hasChanged: true + hasChanged }; - } + }, {state: editorState, hasChanged: false}); - return { - state, - hasChanged - }; - }, {state: editorState, hasChanged: false}); - - return result.hasChanged; - }, - - focus() { - this.refs.editor.focus(); - }, - - blur() { - this.refs.editor.blur(); - }, - - render() { - const { - editorState, - onChange, - keyCommandListeners, // eslint-disable-line no-unused-vars - ...others - } = this.props; - - - return ( - - ); + return result.hasChanged; + } + + focus = () => { + this.refs.editor.focus(); + } + + blur = () => { + this.refs.editor.blur(); + } + + render() { + const { + editorState, + onChange, + keyCommandListeners, // eslint-disable-line no-unused-vars + ...others + } = this.props; + + + return ( + + ); + } } -}); + + KeyCommand.displayName = `KeyCommandController(${Component.displayName})`; + + KeyCommand.propTypes = { + editorState: PropTypes.object, + onChange: PropTypes.func, + keyCommandListeners: PropTypes.arrayOf(PropTypes.func), + ...providedProps + }; + + KeyCommand.defaultProps = { + keyCommandListeners: [] + }; + + return KeyCommand; +}; export default KeyCommandController; diff --git a/src/components/OverlayWrapper.js b/src/components/OverlayWrapper.js index 9f1274a..bffb717 100644 --- a/src/components/OverlayWrapper.js +++ b/src/components/OverlayWrapper.js @@ -1,33 +1,34 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import createReactClass from 'create-react-class'; -export default createReactClass({ - getInitialState() { +export default class OverlayWrapper extends React.Component { + constructor(props) { + super(props); const node = document.createElement('div'); document.body.appendChild(node); - - return {node}; - }, + this.state = { + node + }; + } componentDidMount() { this.renderOverlay(); - }, + } componentDidUpdate() { this.renderOverlay(); - }, + } componentWillUnmount() { ReactDOM.unmountComponentAtNode(this.state.node); - }, + } renderOverlay() { const child = React.Children.only(this.props.children); ReactDOM.render(child, this.state.node); - }, + } render() { return null; } -}); +}; diff --git a/src/components/Toolbar.js b/src/components/Toolbar.js index 9c8fc4d..9a42c69 100644 --- a/src/components/Toolbar.js +++ b/src/components/Toolbar.js @@ -1,32 +1,18 @@ import React from 'react'; import PropTypes from 'prop-types'; -import createReactClass from 'create-react-class'; import KeyCommandController from './KeyCommandController'; -const Toolbar = createReactClass({ - propTypes: { - editorState: PropTypes.object, - onChange: PropTypes.func, - buttons: PropTypes.array, - addKeyCommandListener: PropTypes.func.isRequired, - removeKeyCommandListener: PropTypes.func.isRequired - }, - - childContextTypes: { - getEditorState: PropTypes.func, - onChange: PropTypes.func - }, - +class Toolbar extends React.Component { getChildContext() { return { getEditorState: this.getEditorState, onChange: this.props.onChange }; - }, + } getEditorState() { return this.props.editorState; - }, + } renderButtons() { const { @@ -50,7 +36,7 @@ const Toolbar = createReactClass({ /> ); }); - }, + } render() { return ( @@ -59,6 +45,19 @@ const Toolbar = createReactClass({ ); } -}); +}; + +Toolbar.propTypes = { + editorState: PropTypes.object, + onChange: PropTypes.func, + buttons: PropTypes.array, + addKeyCommandListener: PropTypes.func.isRequired, + removeKeyCommandListener: PropTypes.func.isRequired +}; + +Toolbar.childContextTypes = { + getEditorState: PropTypes.func, + onChange: PropTypes.func +}; export default KeyCommandController(Toolbar); diff --git a/src/plugins/createPlugin.js b/src/plugins/createPlugin.js index c70e3ba..1a9c07a 100644 --- a/src/plugins/createPlugin.js +++ b/src/plugins/createPlugin.js @@ -1,6 +1,5 @@ import React from 'react'; import PropTypes from 'prop-types'; -import createReactClass from 'create-react-class'; import {OrderedSet} from 'immutable'; import memoize from '../util/memoize'; import compose from '../util/compose'; @@ -50,44 +49,18 @@ const createPlugin = ({ if (ToWrap.prototype && ToWrap.prototype.isReactComponent) { // wrapping an Editor component - return createReactClass({ - displayName, - - propTypes: { - styleMap: PropTypes.object, - decorators: PropTypes.array, - buttons: PropTypes.array, - overlays: PropTypes.array, - blockRendererFn: PropTypes.func, - blockStyleFn: PropTypes.func, - keyBindingFn: PropTypes.func, - keyCommandListeners: PropTypes.arrayOf(PropTypes.func) - }, - - getDefaultProps() { - return { - styleMap: emptyObject, - decorators: emptyArray, - buttons: emptyArray, - overlays: emptyArray, - blockRendererFn: emptyFunction, - blockStyleFn: emptyFunction, - keyBindingFn: emptyFunction, - keyCommandListeners: emptyArray - }; - }, - - focus() { + class Wrapper extends React.Component { + focus = () => { if (this.refs.child.focus) { this.refs.child.focus(); } - }, + } - blur() { + blur = () => { if (this.refs.child.blur) { this.refs.child.blur(); } - }, + } render() { const newStyleMap = memoizedAssign(this.props.styleMap, styleMap); @@ -114,7 +87,33 @@ const createPlugin = ({ /> ); } - }); + }; + + Wrapper.displayName = displayName; + + Wrapper.propTypes = { + styleMap: PropTypes.object, + decorators: PropTypes.array, + buttons: PropTypes.array, + overlays: PropTypes.array, + blockRendererFn: PropTypes.func, + blockStyleFn: PropTypes.func, + keyBindingFn: PropTypes.func, + keyCommandListeners: PropTypes.arrayOf(PropTypes.func) + }; + + Wrapper.defaultProps = { + styleMap: emptyObject, + decorators: emptyArray, + buttons: emptyArray, + overlays: emptyArray, + blockRendererFn: emptyFunction, + blockStyleFn: emptyFunction, + keyBindingFn: emptyFunction, + keyCommandListeners: emptyArray + }; + + return Wrapper; } else { // wrapping a converter function return (...args) => { diff --git a/yarn.lock b/yarn.lock index 48e6d5a..ffb3b7a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -185,6 +185,14 @@ babel-generator@^6.26.0: source-map "^0.5.6" trim-right "^1.0.1" +babel-helper-bindify-decorators@^6.24.1: + version "6.24.1" + resolved "https://widen.jfrog.io/widen/api/npm/npm-virtual/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz?dl=https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" @@ -227,6 +235,15 @@ babel-helper-explode-assignable-expression@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" +babel-helper-explode-class@^6.24.1: + version "6.24.1" + resolved "https://widen.jfrog.io/widen/api/npm/npm-virtual/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz?dl=https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" + dependencies: + babel-helper-bindify-decorators "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + babel-helper-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" @@ -319,6 +336,22 @@ babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" +babel-plugin-syntax-async-generators@^6.5.0: + version "6.13.0" + resolved "https://widen.jfrog.io/widen/api/npm/npm-virtual/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz?dl=https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" + +babel-plugin-syntax-class-properties@^6.8.0: + version "6.13.0" + resolved "https://widen.jfrog.io/widen/api/npm/npm-virtual/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz?dl=https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" + +babel-plugin-syntax-decorators@^6.13.0: + version "6.13.0" + resolved "https://widen.jfrog.io/widen/api/npm/npm-virtual/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz?dl=https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" + +babel-plugin-syntax-dynamic-import@^6.18.0: + version "6.18.0" + resolved "https://widen.jfrog.io/widen/api/npm/npm-virtual/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz?dl=https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" + babel-plugin-syntax-exponentiation-operator@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" @@ -339,7 +372,15 @@ babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" -babel-plugin-transform-async-to-generator@^6.22.0: +babel-plugin-transform-async-generator-functions@^6.24.1: + version "6.24.1" + resolved "https://widen.jfrog.io/widen/api/npm/npm-virtual/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz?dl=https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-generators "^6.5.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" dependencies: @@ -347,6 +388,25 @@ babel-plugin-transform-async-to-generator@^6.22.0: babel-plugin-syntax-async-functions "^6.8.0" babel-runtime "^6.22.0" +babel-plugin-transform-class-properties@^6.24.1: + version "6.24.1" + resolved "https://widen.jfrog.io/widen/api/npm/npm-virtual/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz?dl=https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" + dependencies: + babel-helper-function-name "^6.24.1" + babel-plugin-syntax-class-properties "^6.8.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-decorators@^6.24.1: + version "6.24.1" + resolved "https://widen.jfrog.io/widen/api/npm/npm-virtual/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz?dl=https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" + dependencies: + babel-helper-explode-class "^6.24.1" + babel-plugin-syntax-decorators "^6.13.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-types "^6.24.1" + babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" @@ -515,7 +575,7 @@ babel-plugin-transform-es2015-unicode-regex@^6.22.0: babel-runtime "^6.22.0" regexpu-core "^2.0.0" -babel-plugin-transform-exponentiation-operator@^6.22.0: +babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" dependencies: @@ -530,7 +590,7 @@ babel-plugin-transform-flow-strip-types@^6.22.0: babel-plugin-syntax-flow "^6.18.0" babel-runtime "^6.22.0" -babel-plugin-transform-object-rest-spread@^6.6.5: +babel-plugin-transform-object-rest-spread@^6.22.0, babel-plugin-transform-object-rest-spread@^6.6.5: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" dependencies: @@ -638,6 +698,25 @@ babel-preset-react@^6.5.0: babel-plugin-transform-react-jsx-source "^6.22.0" babel-preset-flow "^6.23.0" +babel-preset-stage-2@^6.24.1: + version "6.24.1" + resolved "https://widen.jfrog.io/widen/api/npm/npm-virtual/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz?dl=https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" + dependencies: + babel-plugin-syntax-dynamic-import "^6.18.0" + babel-plugin-transform-class-properties "^6.24.1" + babel-plugin-transform-decorators "^6.24.1" + babel-preset-stage-3 "^6.24.1" + +babel-preset-stage-3@^6.24.1: + version "6.24.1" + resolved "https://widen.jfrog.io/widen/api/npm/npm-virtual/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz?dl=https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" + dependencies: + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-generator-functions "^6.24.1" + babel-plugin-transform-async-to-generator "^6.24.1" + babel-plugin-transform-exponentiation-operator "^6.24.1" + babel-plugin-transform-object-rest-spread "^6.22.0" + babel-register@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" @@ -890,14 +969,6 @@ core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" -create-react-class@^15.6.2: - version "15.6.2" - resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.2.tgz#cf1ed15f12aad7f14ef5f2dfe05e6c42f91ef02a" - dependencies: - fbjs "^0.8.9" - loose-envify "^1.3.1" - object-assign "^4.1.1" - cryptiles@2.x.x: version "2.0.5" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" @@ -1050,7 +1121,7 @@ extsprintf@1.3.0, extsprintf@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" -fbjs@^0.8.16, fbjs@^0.8.3, fbjs@^0.8.9: +fbjs@^0.8.16, fbjs@^0.8.3: version "0.8.16" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" dependencies: