@plone/volto-slate 18.0.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/.eslintrc.js +6 -0
  2. package/.release-it.json +25 -0
  3. package/CHANGELOG.md +19 -0
  4. package/LICENSE.md +21 -0
  5. package/README.md +10 -0
  6. package/build/messages/src/blocks/Table/TableBlockEdit.json +90 -0
  7. package/build/messages/src/blocks/Text/DefaultTextBlockEditor.json +6 -0
  8. package/build/messages/src/blocks/Text/DetachedTextBlockEditor.json +6 -0
  9. package/build/messages/src/blocks/Text/SlashMenu.json +6 -0
  10. package/build/messages/src/editor/plugins/AdvancedLink/index.json +10 -0
  11. package/build/messages/src/editor/plugins/Link/index.json +10 -0
  12. package/build/messages/src/editor/plugins/Table/index.json +30 -0
  13. package/build/messages/src/elementEditor/messages.json +10 -0
  14. package/build/messages/src/widgets/HtmlSlateWidget.json +6 -0
  15. package/build/messages/src/widgets/RichTextWidgetView.json +6 -0
  16. package/locales/de/LC_MESSAGES/volto.po +148 -0
  17. package/locales/en/LC_MESSAGES/volto.po +148 -0
  18. package/locales/volto.pot +182 -0
  19. package/package.json +42 -0
  20. package/src/actions/content.js +30 -0
  21. package/src/actions/index.js +3 -0
  22. package/src/actions/plugins.js +9 -0
  23. package/src/actions/selection.js +22 -0
  24. package/src/blocks/Table/Cell.jsx +87 -0
  25. package/src/blocks/Table/Cell.test.js +54 -0
  26. package/src/blocks/Table/TableBlockEdit.jsx +694 -0
  27. package/src/blocks/Table/TableBlockEdit.test.js +40 -0
  28. package/src/blocks/Table/TableBlockView.jsx +150 -0
  29. package/src/blocks/Table/TableBlockView.test.js +49 -0
  30. package/src/blocks/Table/__snapshots__/Cell.test.js.snap +3 -0
  31. package/src/blocks/Table/__snapshots__/TableBlockEdit.test.js.snap +22 -0
  32. package/src/blocks/Table/__snapshots__/TableBlockView.test.js.snap +27 -0
  33. package/src/blocks/Table/deconstruct.js +113 -0
  34. package/src/blocks/Table/extensions/normalizeTable.js +5 -0
  35. package/src/blocks/Table/index.js +60 -0
  36. package/src/blocks/Table/schema.js +122 -0
  37. package/src/blocks/Text/DefaultTextBlockEditor.jsx +304 -0
  38. package/src/blocks/Text/DetachedTextBlockEditor.jsx +77 -0
  39. package/src/blocks/Text/MarkdownIntroduction.jsx +59 -0
  40. package/src/blocks/Text/PluginSidebar.jsx +18 -0
  41. package/src/blocks/Text/ShortcutListing.jsx +28 -0
  42. package/src/blocks/Text/SlashMenu.jsx +203 -0
  43. package/src/blocks/Text/TextBlockEdit.jsx +38 -0
  44. package/src/blocks/Text/TextBlockEdit.test.js +107 -0
  45. package/src/blocks/Text/TextBlockSchema.js +54 -0
  46. package/src/blocks/Text/TextBlockView.jsx +31 -0
  47. package/src/blocks/Text/__snapshots__/TextBlockEdit.test.js.snap +62 -0
  48. package/src/blocks/Text/css/editor.css +18 -0
  49. package/src/blocks/Text/extensions/Readme.md +49 -0
  50. package/src/blocks/Text/extensions/breakList.js +100 -0
  51. package/src/blocks/Text/extensions/index.js +6 -0
  52. package/src/blocks/Text/extensions/insertBreak.js +57 -0
  53. package/src/blocks/Text/extensions/isSelected.js +7 -0
  54. package/src/blocks/Text/extensions/normalizeExternalData.js +7 -0
  55. package/src/blocks/Text/extensions/withDeserializers.js +87 -0
  56. package/src/blocks/Text/extensions/withLists.js +5 -0
  57. package/src/blocks/Text/index.js +171 -0
  58. package/src/blocks/Text/keyboard/backspaceInList.js +58 -0
  59. package/src/blocks/Text/keyboard/breakBlocks.js +3 -0
  60. package/src/blocks/Text/keyboard/cancelEsc.js +7 -0
  61. package/src/blocks/Text/keyboard/indentListItems.js +240 -0
  62. package/src/blocks/Text/keyboard/index.js +52 -0
  63. package/src/blocks/Text/keyboard/joinBlocks.js +180 -0
  64. package/src/blocks/Text/keyboard/moveListItems.js +124 -0
  65. package/src/blocks/Text/keyboard/slashMenu.js +19 -0
  66. package/src/blocks/Text/keyboard/softBreak.js +7 -0
  67. package/src/blocks/Text/keyboard/traverseBlocks.js +81 -0
  68. package/src/blocks/Text/keyboard/unwrapEmptyString.js +26 -0
  69. package/src/blocks/Text/schema.js +39 -0
  70. package/src/constants.js +123 -0
  71. package/src/editor/EditorContext.jsx +5 -0
  72. package/src/editor/EditorReference.jsx +22 -0
  73. package/src/editor/SlateEditor.jsx +375 -0
  74. package/src/editor/config.jsx +344 -0
  75. package/src/editor/decorate.js +68 -0
  76. package/src/editor/deserialize.js +185 -0
  77. package/src/editor/extensions/index.js +6 -0
  78. package/src/editor/extensions/insertBreak.js +15 -0
  79. package/src/editor/extensions/insertData.js +161 -0
  80. package/src/editor/extensions/isInline.js +14 -0
  81. package/src/editor/extensions/normalizeExternalData.js +8 -0
  82. package/src/editor/extensions/normalizeNode.js +48 -0
  83. package/src/editor/extensions/withDeserializers.js +15 -0
  84. package/src/editor/extensions/withTestingFeatures.jsx +84 -0
  85. package/src/editor/index.js +14 -0
  86. package/src/editor/less/editor.less +173 -0
  87. package/src/editor/less/globals.less +18 -0
  88. package/src/editor/less/slate.less +28 -0
  89. package/src/editor/plugins/AdvancedLink/deserialize.js +90 -0
  90. package/src/editor/plugins/AdvancedLink/extensions.js +32 -0
  91. package/src/editor/plugins/AdvancedLink/index.js +50 -0
  92. package/src/editor/plugins/AdvancedLink/render.jsx +37 -0
  93. package/src/editor/plugins/AdvancedLink/schema.js +114 -0
  94. package/src/editor/plugins/AdvancedLink/styles.less +8 -0
  95. package/src/editor/plugins/Blockquote/index.js +30 -0
  96. package/src/editor/plugins/Callout/index.js +34 -0
  97. package/src/editor/plugins/Image/deconstruct.js +30 -0
  98. package/src/editor/plugins/Image/extensions.js +51 -0
  99. package/src/editor/plugins/Image/index.js +11 -0
  100. package/src/editor/plugins/Image/render.jsx +22 -0
  101. package/src/editor/plugins/Link/extensions.js +58 -0
  102. package/src/editor/plugins/Link/index.js +159 -0
  103. package/src/editor/plugins/Link/render.jsx +54 -0
  104. package/src/editor/plugins/Markdown/constants.js +81 -0
  105. package/src/editor/plugins/Markdown/extensions.js +336 -0
  106. package/src/editor/plugins/Markdown/index.js +28 -0
  107. package/src/editor/plugins/Markdown/utils.js +198 -0
  108. package/src/editor/plugins/StyleMenu/StyleMenu.jsx +153 -0
  109. package/src/editor/plugins/StyleMenu/index.js +19 -0
  110. package/src/editor/plugins/StyleMenu/style.less +29 -0
  111. package/src/editor/plugins/StyleMenu/utils.js +168 -0
  112. package/src/editor/plugins/Table/TableButton.jsx +142 -0
  113. package/src/editor/plugins/Table/TableCell.jsx +44 -0
  114. package/src/editor/plugins/Table/TableContainer.jsx +37 -0
  115. package/src/editor/plugins/Table/TableSizePicker.jsx +83 -0
  116. package/src/editor/plugins/Table/extensions.js +87 -0
  117. package/src/editor/plugins/Table/index.js +390 -0
  118. package/src/editor/plugins/Table/less/public.less +29 -0
  119. package/src/editor/plugins/Table/less/table.less +28 -0
  120. package/src/editor/plugins/Table/render.jsx +30 -0
  121. package/src/editor/plugins/index.js +19 -0
  122. package/src/editor/render.jsx +224 -0
  123. package/src/editor/ui/BasicToolbar.jsx +11 -0
  124. package/src/editor/ui/BlockButton.jsx +31 -0
  125. package/src/editor/ui/ClearFormattingButton.jsx +21 -0
  126. package/src/editor/ui/ExpandedToolbar.jsx +18 -0
  127. package/src/editor/ui/Expando.jsx +5 -0
  128. package/src/editor/ui/InlineToolbar.jsx +69 -0
  129. package/src/editor/ui/MarkButton.jsx +23 -0
  130. package/src/editor/ui/MarkElementButton.jsx +30 -0
  131. package/src/editor/ui/Menu.jsx +13 -0
  132. package/src/editor/ui/PositionedToolbar.jsx +32 -0
  133. package/src/editor/ui/Separator.jsx +7 -0
  134. package/src/editor/ui/SlateContextToolbar.jsx +13 -0
  135. package/src/editor/ui/SlateToolbar.jsx +96 -0
  136. package/src/editor/ui/Toolbar.jsx +103 -0
  137. package/src/editor/ui/ToolbarButton.jsx +33 -0
  138. package/src/editor/ui/ToolbarButton.test.js +25 -0
  139. package/src/editor/ui/__snapshots__/ToolbarButton.test.js.snap +16 -0
  140. package/src/editor/ui/index.js +15 -0
  141. package/src/editor/utils.js +248 -0
  142. package/src/elementEditor/ContextButtons.jsx +57 -0
  143. package/src/elementEditor/PluginEditor.jsx +124 -0
  144. package/src/elementEditor/Readme.md +6 -0
  145. package/src/elementEditor/SchemaProvider.jsx +4 -0
  146. package/src/elementEditor/SidebarEditor.jsx +46 -0
  147. package/src/elementEditor/ToolbarButton.jsx +44 -0
  148. package/src/elementEditor/index.js +5 -0
  149. package/src/elementEditor/makeInlineElementPlugin.js +100 -0
  150. package/src/elementEditor/messages.js +14 -0
  151. package/src/elementEditor/utils.js +227 -0
  152. package/src/hooks/index.js +3 -0
  153. package/src/hooks/useEditorContext.js +6 -0
  154. package/src/hooks/useIsomorphicLayoutEffect.js +7 -0
  155. package/src/hooks/useSelectionPosition.js +25 -0
  156. package/src/i18n.js +180 -0
  157. package/src/icons/hashlink.svg +57 -0
  158. package/src/index.js +61 -0
  159. package/src/reducers/content.js +74 -0
  160. package/src/reducers/index.js +3 -0
  161. package/src/reducers/plugins.js +17 -0
  162. package/src/reducers/selection.js +16 -0
  163. package/src/utils/blocks.js +379 -0
  164. package/src/utils/blocks.test.js +138 -0
  165. package/src/utils/editor.js +31 -0
  166. package/src/utils/image.js +25 -0
  167. package/src/utils/index.js +11 -0
  168. package/src/utils/internals.js +46 -0
  169. package/src/utils/lists.js +92 -0
  170. package/src/utils/marks.js +104 -0
  171. package/src/utils/mime-types.js +24 -0
  172. package/src/utils/nodes.js +4 -0
  173. package/src/utils/ops.js +20 -0
  174. package/src/utils/random.js +17 -0
  175. package/src/utils/selection.js +236 -0
  176. package/src/utils/slate-string-utils.js +409 -0
  177. package/src/utils/volto-blocks.js +314 -0
  178. package/src/widgets/ErrorBoundary.jsx +27 -0
  179. package/src/widgets/HtmlSlateWidget.jsx +138 -0
  180. package/src/widgets/ObjectByTypeWidget.jsx +49 -0
  181. package/src/widgets/RichTextWidget.jsx +72 -0
  182. package/src/widgets/RichTextWidgetView.jsx +36 -0
  183. package/src/widgets/style.css +21 -0
@@ -0,0 +1,375 @@
1
+ import ReactDOM from 'react-dom';
2
+ import cx from 'classnames';
3
+ import { isEqual } from 'lodash';
4
+ import { Transforms, Editor } from 'slate'; // , Transforms
5
+ import { Slate, Editable, ReactEditor } from 'slate-react';
6
+ import React, { Component } from 'react'; // , useState
7
+ import { v4 as uuid } from 'uuid';
8
+
9
+ import config from '@plone/volto/registry';
10
+
11
+ import { Element, Leaf } from './render';
12
+
13
+ import withTestingFeatures from './extensions/withTestingFeatures';
14
+ import {
15
+ makeEditor,
16
+ toggleInlineFormat,
17
+ toggleMark,
18
+ parseDefaultSelection,
19
+ } from '@plone/volto-slate/utils';
20
+ import { InlineToolbar } from './ui';
21
+ import EditorContext from './EditorContext';
22
+
23
+ import isHotkey from 'is-hotkey';
24
+
25
+ import './less/editor.less';
26
+
27
+ import Toolbar from './ui/Toolbar';
28
+
29
+ const handleHotKeys = (editor, event, config) => {
30
+ let wasHotkey = false;
31
+
32
+ for (const hk of Object.entries(config.hotkeys)) {
33
+ const [shortcut, { format, type }] = hk;
34
+ if (isHotkey(shortcut, event)) {
35
+ event.preventDefault();
36
+
37
+ if (type === 'inline') {
38
+ toggleInlineFormat(editor, format);
39
+ } else {
40
+ // type === 'mark'
41
+ toggleMark(editor, format);
42
+ }
43
+
44
+ wasHotkey = true;
45
+ }
46
+ }
47
+
48
+ return wasHotkey;
49
+ };
50
+
51
+ // TODO: implement onFocus
52
+ class SlateEditor extends Component {
53
+ constructor(props) {
54
+ super(props);
55
+
56
+ this.createEditor = this.createEditor.bind(this);
57
+ this.multiDecorator = this.multiDecorator.bind(this);
58
+ this.handleChange = this.handleChange.bind(this);
59
+ this.getSavedSelection = this.getSavedSelection.bind(this);
60
+ this.setSavedSelection = this.setSavedSelection.bind(this);
61
+
62
+ this.savedSelection = null;
63
+
64
+ const uid = uuid(); // used to namespace the editor's plugins
65
+
66
+ this.slateSettings = props.slateSettings || config.settings.slate;
67
+
68
+ this.state = {
69
+ editor: this.createEditor(uid),
70
+ showExpandedToolbar: config.settings.slate.showExpandedToolbar,
71
+ internalValue: this.props.value || this.slateSettings.defaultValue(),
72
+ uid,
73
+ };
74
+
75
+ this.editor = null;
76
+ this.selectionTimeout = null;
77
+ }
78
+
79
+ getSavedSelection() {
80
+ return this.savedSelection;
81
+ }
82
+ setSavedSelection(selection) {
83
+ this.savedSelection = selection;
84
+ }
85
+
86
+ createEditor(uid) {
87
+ // extensions are "editor plugins" or "editor wrappers". It's a similar
88
+ // similar to OOP inheritance, where a callable creates a new copy of the
89
+ // editor, while replacing or adding new capabilities to that editor.
90
+ // Extensions are purely JS, no React components.
91
+ const editor = makeEditor({ extensions: this.props.extensions });
92
+
93
+ // When the editor loses focus it no longer has a valid selections. This
94
+ // makes it impossible to have complex types of interactions (like filling
95
+ // in another text box, operating a select menu, etc). For this reason we
96
+ // save the active selection
97
+
98
+ editor.getSavedSelection = this.getSavedSelection;
99
+ editor.setSavedSelection = this.setSavedSelection;
100
+ editor.uid = uid || this.state.uid;
101
+
102
+ return editor;
103
+ }
104
+
105
+ handleChange(value) {
106
+ ReactDOM.unstable_batchedUpdates(() => {
107
+ this.setState({ internalValue: value });
108
+ if (this.props.onChange && !isEqual(value, this.props.value)) {
109
+ this.props.onChange(value, this.editor);
110
+ }
111
+ });
112
+ }
113
+
114
+ multiDecorator([node, path]) {
115
+ // Decorations (such as higlighting node types, selection, etc).
116
+ const { runtimeDecorators = [] } = this.slateSettings;
117
+ return runtimeDecorators.reduce(
118
+ (acc, deco) => deco(this.state.editor, [node, path], acc),
119
+ [],
120
+ );
121
+ }
122
+
123
+ componentDidMount() {
124
+ // watch the dom change
125
+
126
+ if (this.props.selected) {
127
+ let focused = true;
128
+ try {
129
+ focused = ReactEditor.isFocused(this.state.editor);
130
+ } catch {}
131
+ if (!focused) {
132
+ setTimeout(() => {
133
+ try {
134
+ ReactEditor.focus(this.state.editor);
135
+ } catch {}
136
+ }, 100); // flush
137
+ }
138
+
139
+ this.state.editor.normalize({ force: true });
140
+ }
141
+ }
142
+
143
+ componentWillUnmount() {
144
+ this.isUnmounted = true;
145
+ }
146
+
147
+ componentDidUpdate(prevProps) {
148
+ if (!isEqual(prevProps.extensions, this.props.extensions)) {
149
+ this.setState({ editor: this.createEditor() });
150
+ return;
151
+ }
152
+
153
+ if (
154
+ this.props.value &&
155
+ !isEqual(this.props.value, this.state.internalValue)
156
+ ) {
157
+ const { editor } = this.state;
158
+ editor.children = this.props.value;
159
+
160
+ if (this.props.defaultSelection) {
161
+ const selection = parseDefaultSelection(
162
+ editor,
163
+ this.props.defaultSelection,
164
+ );
165
+
166
+ ReactEditor.focus(editor);
167
+ Transforms.select(editor, selection);
168
+ } else {
169
+ Transforms.select(editor, Editor.end(editor, []));
170
+ }
171
+
172
+ this.setState({
173
+ internalValue: this.props.value,
174
+ });
175
+ return;
176
+ }
177
+
178
+ const { editor } = this.state;
179
+
180
+ if (!prevProps.selected && this.props.selected) {
181
+ // if the SlateEditor becomes selected from unselected
182
+
183
+ if (window.getSelection().type === 'None') {
184
+ // TODO: why is this condition checked?
185
+ Transforms.select(
186
+ this.state.editor,
187
+ Editor.range(this.state.editor, Editor.start(this.state.editor, [])),
188
+ );
189
+ }
190
+
191
+ ReactEditor.focus(this.state.editor);
192
+ }
193
+
194
+ if (this.props.selected && this.props.onUpdate) {
195
+ this.props.onUpdate(editor);
196
+ }
197
+ }
198
+
199
+ shouldComponentUpdate(nextProps, nextState) {
200
+ const { selected = true, value, readOnly } = nextProps;
201
+ const res =
202
+ selected ||
203
+ this.props.selected !== selected ||
204
+ this.props.readOnly !== readOnly ||
205
+ !isEqual(value, this.props.value);
206
+ return res;
207
+ }
208
+
209
+ render() {
210
+ const {
211
+ selected,
212
+ placeholder,
213
+ onKeyDown,
214
+ testingEditorRef,
215
+ readOnly,
216
+ className,
217
+ renderExtensions = [],
218
+ editableProps = {},
219
+ } = this.props;
220
+ const slateSettings = this.slateSettings;
221
+
222
+ // renderExtensions is needed because the editor is memoized, so if these
223
+ // extensions need an updated state (for example to insert updated
224
+ // blockProps) then we need to always wrap the editor with them
225
+ const editor = renderExtensions.reduce(
226
+ (acc, apply) => apply(acc),
227
+ this.state.editor,
228
+ );
229
+
230
+ // Reset selection if field is reset
231
+ if (
232
+ editor.selection &&
233
+ this.props.value?.length === 1 &&
234
+ this.props.value[0].children.length === 1 &&
235
+ this.props.value[0].children[0].text === ''
236
+ ) {
237
+ Transforms.select(editor, {
238
+ anchor: { path: [0, 0], offset: 0 },
239
+ focus: { path: [0, 0], offset: 0 },
240
+ });
241
+ }
242
+ this.editor = editor;
243
+
244
+ if (testingEditorRef) {
245
+ testingEditorRef.current = editor;
246
+ }
247
+
248
+ // debug-values are `data-` HTML attributes in withTestingFeatures HOC
249
+
250
+ return (
251
+ <div
252
+ {...this.props['debug-values']}
253
+ className={cx('slate-editor', {
254
+ 'show-toolbar': this.state.showExpandedToolbar,
255
+ selected,
256
+ })}
257
+ tabIndex={-1}
258
+ >
259
+ <EditorContext.Provider value={editor}>
260
+ <Slate
261
+ editor={editor}
262
+ initialValue={this.props.value || slateSettings.defaultValue()}
263
+ onChange={this.handleChange}
264
+ >
265
+ {selected ? (
266
+ <>
267
+ <InlineToolbar
268
+ editor={editor}
269
+ className={className}
270
+ slateSettings={this.props.slateSettings}
271
+ />
272
+ {Object.keys(slateSettings.elementToolbarButtons).map(
273
+ (t, i) => {
274
+ return (
275
+ <Toolbar elementType={t} key={i}>
276
+ {slateSettings.elementToolbarButtons[t].map(
277
+ (Btn, b) => {
278
+ return <Btn editor={editor} key={b} />;
279
+ },
280
+ )}
281
+ </Toolbar>
282
+ );
283
+ },
284
+ )}
285
+ </>
286
+ ) : (
287
+ ''
288
+ )}
289
+ <Editable
290
+ tabIndex={this.props.tabIndex || 0}
291
+ readOnly={readOnly}
292
+ placeholder={placeholder}
293
+ renderElement={(props) => <Element {...props} />}
294
+ renderLeaf={(props) => <Leaf {...props} />}
295
+ decorate={this.multiDecorator}
296
+ spellCheck={false}
297
+ scrollSelectionIntoView={
298
+ slateSettings.scrollIntoView ? undefined : () => null
299
+ }
300
+ onBlur={() => {
301
+ this.props.onBlur && this.props.onBlur();
302
+ return null;
303
+ }}
304
+ onClick={this.props.onClick}
305
+ onSelect={(e) => {
306
+ if (!selected && this.props.onFocus) {
307
+ // we can't overwrite the onFocus of Editable, as the onFocus
308
+ // in Slate has too much builtin behaviour that's not
309
+ // accessible otherwise. Instead we try to detect such an
310
+ // event based on observing selected state
311
+ if (!editor.selection) {
312
+ setTimeout(() => {
313
+ this.props.onFocus();
314
+ }, 100); // TODO: why 100 is chosen here?
315
+ }
316
+ }
317
+
318
+ if (this.selectionTimeout) clearTimeout(this.selectionTimeout);
319
+ this.selectionTimeout = setTimeout(() => {
320
+ if (
321
+ editor.selection &&
322
+ !isEqual(editor.selection, this.savedSelection) &&
323
+ !this.isUnmounted
324
+ ) {
325
+ this.setState((state) => ({ update: !this.state.update }));
326
+ this.setSavedSelection(
327
+ JSON.parse(JSON.stringify(editor.selection)),
328
+ );
329
+ }
330
+ }, 200);
331
+ }}
332
+ onKeyDown={(event) => {
333
+ const handled = handleHotKeys(editor, event, slateSettings);
334
+ if (handled) return;
335
+ onKeyDown && onKeyDown({ editor, event });
336
+ }}
337
+ {...editableProps}
338
+ />
339
+ {selected &&
340
+ slateSettings.persistentHelpers.map((Helper, i) => {
341
+ return <Helper key={i} editor={editor} />;
342
+ })}
343
+ {this.props.debug ? (
344
+ <ul>
345
+ <li>{selected ? 'selected' : 'no-selected'}</li>
346
+ <li>
347
+ savedSelection: {JSON.stringify(editor.getSavedSelection())}
348
+ </li>
349
+ <li>live selection: {JSON.stringify(editor.selection)}</li>
350
+ <li>children: {JSON.stringify(editor.children)}</li>
351
+ <li> {selected ? 'selected' : 'notselected'}</li>
352
+ <li>
353
+ {ReactEditor.isFocused(editor) ? 'focused' : 'unfocused'}
354
+ </li>
355
+ </ul>
356
+ ) : (
357
+ ''
358
+ )}
359
+ {this.props.children}
360
+ </Slate>
361
+ </EditorContext.Provider>
362
+ </div>
363
+ );
364
+ }
365
+ }
366
+
367
+ SlateEditor.defaultProps = {
368
+ extensions: [],
369
+ className: '',
370
+ };
371
+
372
+ // May be needed to wrap in React.memo(), it used to be wrapped in connect()
373
+ export default __CLIENT__ && window?.Cypress
374
+ ? withTestingFeatures(SlateEditor)
375
+ : SlateEditor;