@portabletext/editor 1.52.3 → 1.52.5

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.52.3",
3
+ "version": "1.52.5",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -78,7 +78,7 @@
78
78
  "slate": "0.115.1",
79
79
  "slate-dom": "^0.114.0",
80
80
  "slate-react": "0.114.2",
81
- "use-effect-event": "^2.0.0",
81
+ "use-effect-event": "^1.0.2",
82
82
  "xstate": "^5.19.4",
83
83
  "@portabletext/block-tools": "1.1.30",
84
84
  "@portabletext/patches": "1.1.4"
@@ -534,24 +534,9 @@ export const PortableTextEditable = forwardRef<
534
534
 
535
535
  if (!event.isDefaultPrevented()) {
536
536
  relayActor.send({type: 'focused', event})
537
-
538
- const selection = slateEditor.selection
539
- ? slateRangeToSelection({
540
- schema: editorActor.getSnapshot().context.schema,
541
- editor: slateEditor,
542
- range: slateEditor.selection,
543
- })
544
- : null
545
-
546
- if (selection) {
547
- editorActor.send({
548
- type: 'update selection',
549
- selection,
550
- })
551
- }
552
537
  }
553
538
  },
554
- [editorActor, onFocus, slateEditor, relayActor],
539
+ [onFocus, relayActor],
555
540
  )
556
541
 
557
542
  const handleClick = useCallback(
@@ -0,0 +1,51 @@
1
+ import {slateRangeToSelection} from '../../internal-utils/slate-utils'
2
+ import {SLATE_TO_PORTABLE_TEXT_RANGE} from '../../internal-utils/weakMaps'
3
+ import type {PortableTextSlateEditor} from '../../types/editor'
4
+ import type {EditorActor} from '../editor-machine'
5
+
6
+ export function pluginUpdateSelection({
7
+ editor,
8
+ editorActor,
9
+ }: {
10
+ editor: PortableTextSlateEditor
11
+ editorActor: EditorActor
12
+ }) {
13
+ const updateSelection = () => {
14
+ if (editor.selection) {
15
+ const existingSelection = SLATE_TO_PORTABLE_TEXT_RANGE.get(
16
+ editor.selection,
17
+ )
18
+
19
+ if (existingSelection) {
20
+ editorActor.send({
21
+ type: 'update selection',
22
+ selection: existingSelection,
23
+ })
24
+ } else {
25
+ const selection = slateRangeToSelection({
26
+ schema: editorActor.getSnapshot().context.schema,
27
+ editor,
28
+ range: editor.selection,
29
+ })
30
+
31
+ SLATE_TO_PORTABLE_TEXT_RANGE.set(editor.selection, selection)
32
+
33
+ editorActor.send({type: 'update selection', selection})
34
+ }
35
+ } else {
36
+ editorActor.send({type: 'update selection', selection: null})
37
+ }
38
+ }
39
+
40
+ const {onChange} = editor
41
+
42
+ editor.onChange = () => {
43
+ onChange()
44
+
45
+ if (!editorActor.getSnapshot().matches({setup: 'setting up'})) {
46
+ updateSelection()
47
+ }
48
+ }
49
+
50
+ return editor
51
+ }
@@ -8,11 +8,11 @@ import {createWithObjectKeys} from './createWithObjectKeys'
8
8
  import {createWithPatches} from './createWithPatches'
9
9
  import {createWithPlaceholderBlock} from './createWithPlaceholderBlock'
10
10
  import {createWithPortableTextMarkModel} from './createWithPortableTextMarkModel'
11
- import {createWithPortableTextSelections} from './createWithPortableTextSelections'
12
11
  import {createWithSchemaTypes} from './createWithSchemaTypes'
13
12
  import {createWithUndoRedo} from './createWithUndoRedo'
14
13
  import {createWithUtils} from './createWithUtils'
15
14
  import {pluginUpdateMarkState} from './slate-plugin.update-mark-state'
15
+ import {pluginUpdateSelection} from './slate-plugin.update-selection'
16
16
  import {pluginUpdateValue} from './slate-plugin.update-value'
17
17
 
18
18
  export interface OriginalEditorFunctions {
@@ -54,8 +54,6 @@ export const withPlugins = <T extends Editor>(
54
54
  const withUtils = createWithUtils({
55
55
  editorActor,
56
56
  })
57
- const withPortableTextSelections =
58
- createWithPortableTextSelections(editorActor)
59
57
  const withEventListeners = createWithEventListeners(editorActor)
60
58
 
61
59
  // Ordering is important here, selection dealing last, data manipulation in the middle and core model stuff first.
@@ -68,15 +66,16 @@ export const withPlugins = <T extends Editor>(
68
66
  withMaxBlocks(
69
67
  withUndoRedo(
70
68
  withPatches(
71
- withPortableTextSelections(
72
- pluginUpdateValue(
69
+ pluginUpdateSelection({
70
+ editorActor,
71
+ editor: pluginUpdateValue(
73
72
  editorActor.getSnapshot().context,
74
73
  pluginUpdateMarkState(
75
74
  editorActor.getSnapshot().context,
76
75
  e,
77
76
  ),
78
77
  ),
79
- ),
78
+ }),
80
79
  ),
81
80
  ),
82
81
  ),
@@ -1,7 +1,7 @@
1
1
  import type {Patch} from '@portabletext/patches'
2
2
  import type {PortableTextBlock} from '@sanity/types'
3
3
  import type {FocusEvent} from 'react'
4
- import {emit, setup, type ActorRefFrom} from 'xstate'
4
+ import {assign, emit, setup, type ActorRefFrom} from 'xstate'
5
5
  import type {EditorSelection, InvalidValueResolution} from '../types/editor'
6
6
 
7
7
  /**
@@ -96,14 +96,61 @@ export type RelayActor = ActorRefFrom<typeof relayMachine>
96
96
 
97
97
  export const relayMachine = setup({
98
98
  types: {
99
+ context: {} as {
100
+ prevSelection: EditorSelection
101
+ lastEventWasFocused: boolean
102
+ },
99
103
  events: {} as InternalEditorEmittedEvent,
100
104
  emitted: {} as InternalEditorEmittedEvent,
101
105
  },
102
106
  }).createMachine({
103
107
  id: 'relay',
108
+ context: {
109
+ prevSelection: null,
110
+ lastEventWasFocused: false,
111
+ },
104
112
  on: {
113
+ 'focused': {
114
+ actions: [
115
+ assign({
116
+ lastEventWasFocused: true,
117
+ }),
118
+ emit(({event}) => event),
119
+ ],
120
+ },
121
+ 'selection': [
122
+ {
123
+ guard: ({context}) => context.lastEventWasFocused,
124
+ actions: [
125
+ assign({
126
+ prevSelection: ({event}) => event.selection,
127
+ }),
128
+ emit(({event}) => event),
129
+ assign({
130
+ lastEventWasFocused: false,
131
+ }),
132
+ ],
133
+ },
134
+ {
135
+ guard: ({context, event}) => context.prevSelection !== event.selection,
136
+ actions: [
137
+ assign({
138
+ prevSelection: ({event}) => event.selection,
139
+ }),
140
+ emit(({event}) => event),
141
+ assign({
142
+ lastEventWasFocused: false,
143
+ }),
144
+ ],
145
+ },
146
+ ],
105
147
  '*': {
106
- actions: emit(({event}) => event),
148
+ actions: [
149
+ emit(({event}) => event),
150
+ assign({
151
+ lastEventWasFocused: false,
152
+ }),
153
+ ],
107
154
  },
108
155
  },
109
156
  })
@@ -1,60 +0,0 @@
1
- import type {BaseRange} from 'slate'
2
- import {debugWithName} from '../../internal-utils/debug'
3
- import {slateRangeToSelection} from '../../internal-utils/slate-utils'
4
- import {SLATE_TO_PORTABLE_TEXT_RANGE} from '../../internal-utils/weakMaps'
5
- import type {EditorSelection, PortableTextSlateEditor} from '../../types/editor'
6
- import type {EditorActor} from '../editor-machine'
7
-
8
- const debug = debugWithName('plugin:withPortableTextSelections')
9
- const debugVerbose = debug.enabled && false
10
-
11
- // This plugin will make sure that we emit a PT selection whenever the editor has changed.
12
- export function createWithPortableTextSelections(
13
- editorActor: EditorActor,
14
- ): (editor: PortableTextSlateEditor) => PortableTextSlateEditor {
15
- let prevSelection: BaseRange | null = null
16
- return function withPortableTextSelections(
17
- editor: PortableTextSlateEditor,
18
- ): PortableTextSlateEditor {
19
- const emitPortableTextSelection = () => {
20
- if (prevSelection !== editor.selection) {
21
- let ptRange: EditorSelection | null = null
22
- if (editor.selection) {
23
- const existing = SLATE_TO_PORTABLE_TEXT_RANGE.get(editor.selection)
24
- if (existing) {
25
- ptRange = existing
26
- } else {
27
- ptRange = slateRangeToSelection({
28
- schema: editorActor.getSnapshot().context.schema,
29
- editor,
30
- range: editor.selection,
31
- })
32
- SLATE_TO_PORTABLE_TEXT_RANGE.set(editor.selection, ptRange)
33
- }
34
- }
35
- if (debugVerbose) {
36
- debug(
37
- `Emitting selection ${JSON.stringify(ptRange || null)} (${JSON.stringify(
38
- editor.selection,
39
- )})`,
40
- )
41
- }
42
- if (ptRange) {
43
- editorActor.send({type: 'update selection', selection: ptRange})
44
- } else {
45
- editorActor.send({type: 'update selection', selection: null})
46
- }
47
- }
48
- prevSelection = editor.selection
49
- }
50
-
51
- const {onChange} = editor
52
- editor.onChange = () => {
53
- onChange()
54
- if (!editorActor.getSnapshot().matches({setup: 'setting up'})) {
55
- emitPortableTextSelection()
56
- }
57
- }
58
- return editor
59
- }
60
- }