@portabletext/editor 1.6.0 → 1.6.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -69,6 +69,7 @@ import {usePortableTextEditor} from './hooks/usePortableTextEditor'
69
69
  import {usePortableTextEditorReadOnlyStatus} from './hooks/usePortableTextReadOnly'
70
70
  import {createWithHotkeys, createWithInsertData} from './plugins'
71
71
  import {PortableTextEditor} from './PortableTextEditor'
72
+ import {withSyncRangeDecorations} from './withSyncRangeDecorations'
72
73
 
73
74
  const debug = debugWithName('component:Editable')
74
75
 
@@ -163,27 +164,33 @@ export const PortableTextEditable = forwardRef<
163
164
 
164
165
  const blockTypeName = schemaTypes.block.name
165
166
 
166
- // React/UI-specific plugins
167
- const withInsertData = useMemo(
168
- () => createWithInsertData(editorActor, schemaTypes),
169
- [editorActor, schemaTypes],
170
- )
171
- const withHotKeys = useMemo(
172
- () => createWithHotkeys(editorActor, portableTextEditor, hotkeys),
173
- [editorActor, hotkeys, portableTextEditor],
174
- )
175
-
176
167
  // Output a minimal React editor inside Editable when in readOnly mode.
177
168
  // NOTE: make sure all the plugins used here can be safely run over again at any point.
178
169
  // There will be a problem if they redefine editor methods and then calling the original method within themselves.
179
170
  useMemo(() => {
171
+ // React/UI-specific plugins
172
+ const withInsertData = createWithInsertData(editorActor, schemaTypes)
173
+
180
174
  if (readOnly) {
181
175
  debug('Editable is in read only mode')
182
176
  return withInsertData(slateEditor)
183
177
  }
178
+ const withHotKeys = createWithHotkeys(
179
+ editorActor,
180
+ portableTextEditor,
181
+ hotkeys,
182
+ )
183
+
184
184
  debug('Editable is in edit mode')
185
185
  return withInsertData(withHotKeys(slateEditor))
186
- }, [readOnly, slateEditor, withHotKeys, withInsertData])
186
+ }, [
187
+ editorActor,
188
+ hotkeys,
189
+ portableTextEditor,
190
+ readOnly,
191
+ schemaTypes,
192
+ slateEditor,
193
+ ])
187
194
 
188
195
  const renderElement = useCallback(
189
196
  (eProps: RenderElementProps) => (
@@ -381,9 +388,6 @@ export const PortableTextEditable = forwardRef<
381
388
  }
382
389
  }, [hasInvalidValue, propsSelection, restoreSelectionFromProps])
383
390
 
384
- // Store reference to original apply function (see below for usage in useEffect)
385
- const originalApply = useMemo(() => slateEditor.apply, [slateEditor])
386
-
387
391
  const [syncedRangeDecorations, setSyncedRangeDecorations] = useState(false)
388
392
  useEffect(() => {
389
393
  if (!syncedRangeDecorations) {
@@ -402,16 +406,9 @@ export const PortableTextEditable = forwardRef<
402
406
 
403
407
  // Sync range decorations after an operation is applied
404
408
  useEffect(() => {
405
- slateEditor.apply = (op: Operation) => {
406
- originalApply(op)
407
- if (op.type !== 'set_selection') {
408
- syncRangeDecorations(op)
409
- }
410
- }
411
- return () => {
412
- slateEditor.apply = originalApply
413
- }
414
- }, [originalApply, slateEditor, syncRangeDecorations])
409
+ const teardown = withSyncRangeDecorations(slateEditor, syncRangeDecorations)
410
+ return () => teardown()
411
+ }, [slateEditor, syncRangeDecorations])
415
412
 
416
413
  // Handle from props onCopy function
417
414
  const handleCopy = useCallback(
@@ -0,0 +1,20 @@
1
+ import type {BaseEditor, Operation} from 'slate'
2
+ import type {ReactEditor} from 'slate-react'
3
+ import type {PortableTextSlateEditor} from '../types/editor'
4
+
5
+ // React Compiler considers `slateEditor` as immutable, and opts-out if we do this inline in a useEffect, doing it in a function moves it out of the scope, and opts-in again for the rest of the component.
6
+ export function withSyncRangeDecorations(
7
+ slateEditor: BaseEditor & ReactEditor & PortableTextSlateEditor,
8
+ syncRangeDecorations: (operation?: Operation) => void,
9
+ ) {
10
+ const originalApply = slateEditor.apply
11
+ slateEditor.apply = (op: Operation) => {
12
+ originalApply(op)
13
+ if (op.type !== 'set_selection') {
14
+ syncRangeDecorations(op)
15
+ }
16
+ }
17
+ return () => {
18
+ slateEditor.apply = originalApply
19
+ }
20
+ }