-
-
+
+
{!_.isEmpty(mentions) && (
@@ -196,10 +210,8 @@ const RichTextEditor = ({
RichTextEditor.propTypes = {
className: PropTypes.string,
placeholder: PropTypes.string,
- /** Editor State */
- initialValue: PropTypes.instanceOf(EditorState),
- /** Editor State: Instance of
draft-js editor state */
- value: PropTypes.instanceOf(EditorState),
+ initialValue: PropTypes.string,
+ value: PropTypes.string,
onChange: PropTypes.func,
mentions: PropTypes.arrayOf(
PropTypes.shape({
@@ -220,9 +232,10 @@ RichTextEditor.defaultProps = {
RichTextEditor.createEmpty = EditorState.createEmpty;
RichTextEditor.createWithText = createEditorStateWithText;
-RichTextEditor.stateToHTML = (input) => stateToHTML(input.getCurrentContent());
-RichTextEditor.stateFromHTML = (input) => EditorState.createWithContent(stateFromHTML(input));
+RichTextEditor.stateToHTML = editorStateToHTML;
+RichTextEditor.stateFromHTML = editorStateFromHTML;
RichTextEditor.stateToPlainText = (input) => input.getCurrentContent().getPlainText();
RichTextEditor.stateToEntityList = (input) => convertToRaw(input.getCurrentContent()).entityMap;
+RichTextEditor.plainTextFromHTML = (input) => RichTextEditor.stateToPlainText(editorStateFromHTML(input));
export default RichTextEditor;
diff --git a/src/components/RichTextEditor/index.spec.jsx b/src/components/RichTextEditor/index.spec.jsx
index d99772e08..1904dd02d 100644
--- a/src/components/RichTextEditor/index.spec.jsx
+++ b/src/components/RichTextEditor/index.spec.jsx
@@ -53,14 +53,15 @@ describe('
', () => {
it('should warn when value is passed and onChange is not', () => {
console.warn = jest.fn();
- render(
);
+ const newState = '123';
+ render(
);
expect(console.warn).toHaveBeenCalledWith(
'Failed prop type: You have provided a `value` prop to RichTextEditor component without an `onChange` handler. This will render a read-only field.'
);
});
it('should set initial state correctly', () => {
- const { container } = render(
test')} />);
+ const { container } = render();
expect(getByClass(container, 'DraftEditor-root')).toHaveTextContent('test');
});
@@ -76,34 +77,35 @@ describe('', () => {
it('should pass state if onChange is supplied', () => {
const onChange = jest.fn();
- const { container } = render();
- expect(onChange).toHaveBeenCalledTimes(1);
+ const { container } = render();
+ expect(onChange).toHaveBeenCalledTimes(0);
const editorNode = container.querySelector('.public-DraftEditor-content');
const eventProperties = createPasteEvent('123');
const pasteEvent = createEvent.paste(editorNode, eventProperties);
fireEvent(editorNode, pasteEvent);
- expect(onChange).toHaveBeenCalledTimes(2);
- expect(RichTextEditor.stateToHTML(onChange.mock.calls[1][0])).toEqual('123
');
- expect(RichTextEditor.stateToPlainText(onChange.mock.calls[1][0])).toEqual('123');
- expect(RichTextEditor.stateToEntityList(onChange.mock.calls[1][0])).toEqual({});
+ expect(onChange).toHaveBeenCalledTimes(1);
+ expect(onChange.mock.calls[0][0]).toEqual('123
');
+ expect(RichTextEditor.stateToPlainText(RichTextEditor.stateFromHTML(onChange.mock.calls[0][0]))).toEqual('123');
+ expect(RichTextEditor.plainTextFromHTML(onChange.mock.calls[0][0])).toEqual('123');
+
+ expect(RichTextEditor.stateToEntityList(RichTextEditor.stateFromHTML(onChange.mock.calls[0][0]))).toEqual({});
});
it('should correctly handle key commands', () => {
jest.spyOn(RichUtils, 'handleKeyCommand');
const onChange = jest.fn();
- const newState = RichTextEditor.stateFromHTML('123');
+ const newState = '123';
const { container } = render();
- expect(onChange).toHaveBeenCalledTimes(1);
+ expect(onChange).toHaveBeenCalledTimes(0);
const editorNode = container.querySelector('.public-DraftEditor-content');
fireEvent.focus(editorNode);
- expect(onChange).toHaveBeenCalledTimes(2);
- expect(RichTextEditor.stateToHTML(onChange.mock.calls[1][0])).toEqual('123
');
+ expect(onChange).toHaveBeenCalledTimes(0);
fireEvent.keyDown(editorNode, { key: 'Backspace', keyCode: 8, which: 8 });
- expect(onChange).toHaveBeenCalledTimes(3);
- expect(RichTextEditor.stateToHTML(onChange.mock.calls[2][0])).toEqual('12
');
+ expect(onChange).toHaveBeenCalledTimes(1);
+ expect(onChange.mock.calls[0][0]).toEqual('12
');
expect(RichUtils.handleKeyCommand).toHaveBeenCalledTimes(1);
expect(RichUtils.handleKeyCommand.mock.calls[0][1]).toEqual('backspace');
});
@@ -111,35 +113,41 @@ describe('', () => {
it('should correctly handle the new state of key commands', () => {
jest.spyOn(RichUtils, 'handleKeyCommand');
const onChange = jest.fn();
- const newState = RichTextEditor.stateFromHTML('123');
+ const newState = '123';
const { container } = render();
const editorNode = container.querySelector('.public-DraftEditor-content');
fireEvent.focus(editorNode);
-
fireEvent.keyDown(editorNode, { key: 'b', keyCode: 66, which: 66, ctrlKey: true });
- expect(onChange).toHaveBeenCalledTimes(3);
+
+ expect(onChange).toHaveBeenCalledTimes(0);
expect(RichUtils.handleKeyCommand).toHaveBeenCalledTimes(1);
expect(RichUtils.handleKeyCommand.mock.calls[0][1]).toEqual('bold');
});
- it('should toggle italics', () => {
+ it('should toggle italics', async () => {
const onChange = jest.fn();
- const newState = RichTextEditor.stateFromHTML('123');
- const { queryAllByTestId, getByTestId } = render();
+ const newState = '123';
+ const { queryAllByTestId, getByTestId, container } = render(
+
+ );
expect(queryAllByTestId('button-wrapper')).toHaveLength(5);
expect(queryAllByTestId('button-wrapper')[1]).toContainElement(getByTestId('italics'));
+ const editorNode = container.querySelector('.public-DraftEditor-content');
+ fireEvent.focus(editorNode);
fireEvent.mouseDown(queryAllByTestId('button-wrapper')[1]);
- expect(onChange).toHaveBeenCalledTimes(2);
- expect(RichTextEditor.stateToHTML(onChange.mock.calls[1][0])).toEqual('123
');
+ expect(onChange).toHaveBeenCalledTimes(0);
+ fireEvent.keyDown(editorNode, { key: 'i', keyCode: 73, which: 73, ctrlKey: true });
+ expect(RichUtils.handleKeyCommand).toHaveBeenCalledTimes(1);
+ expect(RichUtils.handleKeyCommand.mock.calls[0][1]).toEqual('italic');
});
it('should correctly generate unordered list', () => {
const onChange = jest.fn();
- const newState = RichTextEditor.stateFromHTML('123');
+ const newState = '123';
const { queryAllByTestId, getByTestId } = render();
expect(queryAllByTestId('button-wrapper')).toHaveLength(5);
@@ -147,7 +155,12 @@ describe('', () => {
fireEvent.mouseDown(queryAllByTestId('button-wrapper')[4]);
- expect(onChange).toHaveBeenCalledTimes(2);
+ expect(onChange).toHaveBeenCalledTimes(1);
+ expect(onChange.mock.calls[0][0]).toEqual(
+ `
+ - 123
+
`
+ );
});
describe('mention feature', () => {
@@ -187,7 +200,7 @@ describe('', () => {
},
];
const onChange = jest.fn();
- const newState = RichTextEditor.stateFromHTML('@');
+ const newState = '@';
const { queryByTestId, queryAllByTestId, container } = render(
);
diff --git a/www/examples/RichTextEditor.mdx b/www/examples/RichTextEditor.mdx
index 65d92c280..0a563bd05 100644
--- a/www/examples/RichTextEditor.mdx
+++ b/www/examples/RichTextEditor.mdx
@@ -36,11 +36,15 @@ You have flexibility to create an controlled or uncontrolled editor based on you
```jsx live=true
const Example = () => {
const [state, setState] = React.useState(' ');
+ const [changeCount, setChangeCount] = React.useState(0);
return (
<>
setState(RichTextEditor.stateToHTML(output))}
+ onChange={(output) => {
+ setState(output);
+ setChangeCount(changeCount + 1);
+ }}
placeholder="Custom placeholder"
/>
@@ -49,6 +53,12 @@ const Example = () => {
HTML Output:
{state}
+
+
+
+ Change Time Count: {changeCount}
+
+
>
);
};
@@ -61,19 +71,31 @@ render(Example);
```jsx live=true
const Example = () => {
const [state, setState] = React.useState(
- RichTextEditor.stateFromHTML(
- `
test
asdasdasdasd
- test
- 123
`
- )
+ `
test
asdasdasdasd
- test
- 123
`
);
+ const [changeCount, setChangeCount] = React.useState(0);
+
return (
<>
-
+ {
+ setState(output);
+ setChangeCount(changeCount + 1);
+ }}
+ />
HTML Output:
-
{RichTextEditor.stateToHTML(state)}
+
{state}
+
+
+
+
+ Change Time Count: {changeCount}
+
>
);
@@ -107,35 +129,31 @@ const Example = () => {
},
];
- const [state, setState] = React.useState(RichTextEditor.stateFromHTML(' '));
+ const [state, setState] = React.useState('');
+ const [changeCount, setChangeCount] = React.useState(0);
return (
<>
-
+ {
+ setState(output);
+ setChangeCount(changeCount + 1);
+ }}
+ mentions={contacts}
+ />
Contacts List:
- <>
- {_(RichTextEditor.stateToEntityList(state))
- .filter({ type: 'mention' })
- .map(
- (
- {
- data: {
- mention: { name, title },
- },
- },
- index
- ) => (
-
- {index + 1}: {name} {title ? `, ${title}` : ''}
-
- )
- )
- .value()}
- >
+
{state}
+
+
+
+
+ Change Time Count: {changeCount}
+
>
);
@@ -148,7 +166,8 @@ render(Example);
```jsx live=true
const Example = () => {
- const [state, setState] = React.useState(RichTextEditor.stateFromHTML(' '));
+ const [state, setState] = React.useState('');
+ const [changeCount, setChangeCount] = React.useState(0);
const onFileSelect = () => '../assets/tile/adslot-logo-1.png';
@@ -157,12 +176,21 @@ const Example = () => {
return (
<>
-
+ {
+ setState(output);
+ setChangeCount(changeCount + 1);
+ }}
+ onFileSelect={onFileSelect}
+ onFileRemove={onFileRemove}
+ onHTMLChange={() => setChangeCount(changeCount + 1)}
+ />
PlainText Output:
-
{RichTextEditor.stateToPlainText(state)}
+
{state}
>
);