@portabletext/editor 1.49.8 → 1.49.9
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/lib/index.cjs +4190 -4086
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +4 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +4180 -4076
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/editor/Editable.tsx +1 -0
- package/src/editor/PortableTextEditor.tsx +68 -33
- package/src/editor/__tests__/PortableTextEditor.test.tsx +1 -0
- package/src/editor/create-editor.ts +104 -80
- package/src/editor/create-slate-editor.tsx +4 -21
- package/src/editor/editor-provider.tsx +43 -23
- package/src/editor/mutation-machine.ts +3 -0
- package/src/editor/sync-machine.ts +3 -0
- package/src/internal-utils/applyPatch.ts +21 -4
- package/src/internal-utils/stop-actor.ts +43 -0
- package/src/internal-utils/use-constant.ts +15 -0
package/package.json
CHANGED
package/src/editor/Editable.tsx
CHANGED
|
@@ -1169,6 +1169,7 @@ export const PortableTextEditable = forwardRef<
|
|
|
1169
1169
|
return hasInvalidValue ? null : (
|
|
1170
1170
|
<SlateEditable
|
|
1171
1171
|
{...restProps}
|
|
1172
|
+
data-read-only={readOnly}
|
|
1172
1173
|
autoFocus={false}
|
|
1173
1174
|
className={restProps.className || 'pt-editable'}
|
|
1174
1175
|
decorate={decorate}
|
|
@@ -14,10 +14,9 @@ import {
|
|
|
14
14
|
} from 'react'
|
|
15
15
|
import {Subject} from 'rxjs'
|
|
16
16
|
import {Slate} from 'slate-react'
|
|
17
|
-
import {createActor} from 'xstate'
|
|
18
|
-
import {createCoreConverters} from '../converters/converters.core'
|
|
19
17
|
import {debugWithName} from '../internal-utils/debug'
|
|
20
18
|
import {compileType} from '../internal-utils/schema'
|
|
19
|
+
import {stopActor} from '../internal-utils/stop-actor'
|
|
21
20
|
import type {AddedAnnotationPaths} from '../operations/behavior.operation.annotation.add'
|
|
22
21
|
import type {
|
|
23
22
|
EditableAPI,
|
|
@@ -30,13 +29,14 @@ import type {
|
|
|
30
29
|
} from '../types/editor'
|
|
31
30
|
import {createInternalEditor, type InternalEditor} from './create-editor'
|
|
32
31
|
import {EditorActorContext} from './editor-actor-context'
|
|
33
|
-
import
|
|
32
|
+
import type {EditorActor} from './editor-machine'
|
|
34
33
|
import {legacySchemaToEditorSchema} from './editor-schema'
|
|
35
34
|
import {PortableTextEditorContext} from './hooks/usePortableTextEditor'
|
|
36
35
|
import {PortableTextEditorSelectionProvider} from './hooks/usePortableTextEditorSelection'
|
|
37
|
-
import {defaultKeyGenerator} from './key-generator'
|
|
38
36
|
import {createLegacySchema} from './legacy-schema'
|
|
37
|
+
import type {MutationActor} from './mutation-machine'
|
|
39
38
|
import {eventToChange} from './route-events-to-changes'
|
|
39
|
+
import type {SyncActor} from './sync-machine'
|
|
40
40
|
|
|
41
41
|
const debug = debugWithName('component:PortableTextEditor')
|
|
42
42
|
|
|
@@ -132,6 +132,14 @@ export class PortableTextEditor extends Component<
|
|
|
132
132
|
*/
|
|
133
133
|
private editable: EditableAPI
|
|
134
134
|
|
|
135
|
+
private actors?: {
|
|
136
|
+
editorActor: EditorActor
|
|
137
|
+
mutationActor: MutationActor
|
|
138
|
+
syncActor: SyncActor
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private unsubscribers: Array<() => void> = []
|
|
142
|
+
|
|
135
143
|
constructor(props: PortableTextEditorProps) {
|
|
136
144
|
super(props)
|
|
137
145
|
|
|
@@ -141,45 +149,60 @@ export class PortableTextEditor extends Component<
|
|
|
141
149
|
.getSnapshot()
|
|
142
150
|
.context.getLegacySchema()
|
|
143
151
|
} else {
|
|
144
|
-
const
|
|
145
|
-
props.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
getLegacySchema: () => legacySchema,
|
|
154
|
-
initialValue: props.value,
|
|
155
|
-
keyGenerator: props.keyGenerator ?? defaultKeyGenerator,
|
|
156
|
-
maxBlocks:
|
|
157
|
-
props.maxBlocks === undefined
|
|
158
|
-
? undefined
|
|
159
|
-
: Number.parseInt(props.maxBlocks.toString(), 10),
|
|
160
|
-
readOnly: props.readOnly,
|
|
161
|
-
schema,
|
|
162
|
-
},
|
|
152
|
+
const {actors, editor, subscriptions} = createInternalEditor({
|
|
153
|
+
initialValue: props.value,
|
|
154
|
+
keyGenerator: props.keyGenerator,
|
|
155
|
+
maxBlocks:
|
|
156
|
+
props.maxBlocks === undefined
|
|
157
|
+
? undefined
|
|
158
|
+
: Number.parseInt(props.maxBlocks.toString(), 10),
|
|
159
|
+
readOnly: props.readOnly,
|
|
160
|
+
schema: props.schemaType,
|
|
163
161
|
})
|
|
164
|
-
editorActor.start()
|
|
165
162
|
|
|
166
|
-
|
|
167
|
-
|
|
163
|
+
this.unsubscribers.push(
|
|
164
|
+
(() => {
|
|
165
|
+
const subscription = actors.editorActor.on('*', (event) => {
|
|
166
|
+
const change = eventToChange(event)
|
|
168
167
|
|
|
169
|
-
|
|
170
|
-
|
|
168
|
+
if (change) {
|
|
169
|
+
props.onChange(change)
|
|
171
170
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
171
|
+
this.change$.next(change)
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
return () => {
|
|
176
|
+
subscription.unsubscribe()
|
|
177
|
+
}
|
|
178
|
+
})(),
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
for (const subscription of subscriptions) {
|
|
182
|
+
this.unsubscribers.push(subscription())
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
this.actors = actors
|
|
175
186
|
|
|
176
|
-
this.editor =
|
|
177
|
-
this.schemaTypes =
|
|
187
|
+
this.editor = editor
|
|
188
|
+
this.schemaTypes = actors.editorActor
|
|
189
|
+
.getSnapshot()
|
|
190
|
+
.context.getLegacySchema()
|
|
178
191
|
}
|
|
179
192
|
|
|
180
193
|
this.editable = this.editor._internal.editable
|
|
181
194
|
}
|
|
182
195
|
|
|
196
|
+
componentDidMount(): void {
|
|
197
|
+
if (!this.actors) {
|
|
198
|
+
return
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
this.actors.editorActor.start()
|
|
202
|
+
this.actors.mutationActor.start()
|
|
203
|
+
this.actors.syncActor.start()
|
|
204
|
+
}
|
|
205
|
+
|
|
183
206
|
componentDidUpdate(prevProps: PortableTextEditorProps) {
|
|
184
207
|
// Set up the schema type lookup table again if the source schema type changes
|
|
185
208
|
if (
|
|
@@ -233,6 +256,18 @@ export class PortableTextEditor extends Component<
|
|
|
233
256
|
}
|
|
234
257
|
}
|
|
235
258
|
|
|
259
|
+
componentWillUnmount(): void {
|
|
260
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
261
|
+
unsubscribe()
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (this.actors) {
|
|
265
|
+
stopActor(this.actors.editorActor)
|
|
266
|
+
stopActor(this.actors.mutationActor)
|
|
267
|
+
stopActor(this.actors.syncActor)
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
236
271
|
public setEditable = (editable: EditableAPI) => {
|
|
237
272
|
this.editor._internal.editable = {
|
|
238
273
|
...this.editor._internal.editable,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {createActor
|
|
1
|
+
import {createActor} from 'xstate'
|
|
2
2
|
import {createCoreConverters} from '../converters/converters.core'
|
|
3
3
|
import type {Editor, EditorConfig} from '../editor'
|
|
4
4
|
import {debugWithName} from '../internal-utils/debug'
|
|
@@ -10,6 +10,7 @@ import {createEditorPriority} from '../priority/priority.types'
|
|
|
10
10
|
import type {EditableAPI, PortableTextSlateEditor} from '../types/editor'
|
|
11
11
|
import {createSlateEditor, type SlateEditor} from './create-slate-editor'
|
|
12
12
|
import type {EditorActor} from './editor-machine'
|
|
13
|
+
import {editorMachine} from './editor-machine'
|
|
13
14
|
import {
|
|
14
15
|
compileSchemaDefinitionToLegacySchema,
|
|
15
16
|
legacySchemaToEditorSchema,
|
|
@@ -17,11 +18,11 @@ import {
|
|
|
17
18
|
import {getEditorSnapshot} from './editor-selector'
|
|
18
19
|
import {defaultKeyGenerator} from './key-generator'
|
|
19
20
|
import {createLegacySchema} from './legacy-schema'
|
|
20
|
-
import {mutationMachine} from './mutation-machine'
|
|
21
|
+
import {mutationMachine, type MutationActor} from './mutation-machine'
|
|
21
22
|
import {createEditableAPI} from './plugins/createWithEditableAPI'
|
|
22
|
-
import {syncMachine} from './sync-machine'
|
|
23
|
+
import {syncMachine, type SyncActor} from './sync-machine'
|
|
23
24
|
|
|
24
|
-
const debug = debugWithName('
|
|
25
|
+
const debug = debugWithName('setup')
|
|
25
26
|
|
|
26
27
|
export type InternalEditor = Editor & {
|
|
27
28
|
_internal: {
|
|
@@ -61,18 +62,30 @@ export function editorConfigToMachineInput(config: EditorConfig) {
|
|
|
61
62
|
} as const
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
export function createInternalEditor(
|
|
65
|
-
|
|
65
|
+
export function createInternalEditor(config: EditorConfig): {
|
|
66
|
+
actors: {
|
|
67
|
+
editorActor: EditorActor
|
|
68
|
+
mutationActor: MutationActor
|
|
69
|
+
syncActor: SyncActor
|
|
70
|
+
}
|
|
71
|
+
editor: InternalEditor
|
|
72
|
+
subscriptions: Array<() => () => void>
|
|
73
|
+
} {
|
|
74
|
+
debug('Creating new Editor instance')
|
|
75
|
+
|
|
76
|
+
const subscriptions: Array<() => () => void> = []
|
|
77
|
+
const editorActor = createActor(editorMachine, {
|
|
78
|
+
input: editorConfigToMachineInput(config),
|
|
79
|
+
})
|
|
80
|
+
const slateEditor = createSlateEditor({editorActor, subscriptions})
|
|
66
81
|
const editable = createEditableAPI(slateEditor.instance, editorActor)
|
|
67
82
|
const {mutationActor, syncActor} = createActors({
|
|
68
83
|
editorActor,
|
|
69
84
|
slateEditor: slateEditor.instance,
|
|
85
|
+
subscriptions,
|
|
70
86
|
})
|
|
71
87
|
|
|
72
|
-
|
|
73
|
-
syncActor.start()
|
|
74
|
-
|
|
75
|
-
return {
|
|
88
|
+
const editor = {
|
|
76
89
|
getSnapshot: () =>
|
|
77
90
|
getEditorSnapshot({
|
|
78
91
|
editorActorSnapshot: editorActor.getSnapshot(),
|
|
@@ -182,32 +195,28 @@ export function createInternalEditor(editorActor: EditorActor): InternalEditor {
|
|
|
182
195
|
editorActor,
|
|
183
196
|
slateEditor,
|
|
184
197
|
},
|
|
185
|
-
}
|
|
186
|
-
}
|
|
198
|
+
} satisfies InternalEditor
|
|
187
199
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
200
|
+
return {
|
|
201
|
+
actors: {
|
|
202
|
+
editorActor,
|
|
203
|
+
mutationActor,
|
|
204
|
+
syncActor,
|
|
205
|
+
},
|
|
206
|
+
editor,
|
|
207
|
+
subscriptions,
|
|
193
208
|
}
|
|
194
|
-
|
|
209
|
+
}
|
|
195
210
|
|
|
196
211
|
function createActors(config: {
|
|
197
212
|
editorActor: EditorActor
|
|
198
213
|
slateEditor: PortableTextSlateEditor
|
|
214
|
+
subscriptions: Array<() => () => void>
|
|
199
215
|
}): {
|
|
200
|
-
syncActor:
|
|
201
|
-
mutationActor:
|
|
216
|
+
syncActor: SyncActor
|
|
217
|
+
mutationActor: MutationActor
|
|
202
218
|
} {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
if (existingActor) {
|
|
206
|
-
debug('Reusing existing actors')
|
|
207
|
-
return existingActor
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
debug('Creating new actors')
|
|
219
|
+
debug('Creating new Actors')
|
|
211
220
|
|
|
212
221
|
const mutationActor = createActor(mutationMachine, {
|
|
213
222
|
input: {
|
|
@@ -228,67 +237,82 @@ function createActors(config: {
|
|
|
228
237
|
},
|
|
229
238
|
})
|
|
230
239
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
type: 'mutation',
|
|
239
|
-
patches: event.patches,
|
|
240
|
-
snapshot: event.snapshot,
|
|
241
|
-
value: event.snapshot,
|
|
242
|
-
})
|
|
243
|
-
}
|
|
244
|
-
})
|
|
245
|
-
|
|
246
|
-
syncActor.on('*', (event) => {
|
|
247
|
-
switch (event.type) {
|
|
248
|
-
case 'invalid value':
|
|
249
|
-
config.editorActor.send({
|
|
250
|
-
...event,
|
|
251
|
-
type: 'notify.invalid value',
|
|
252
|
-
})
|
|
253
|
-
break
|
|
254
|
-
case 'value changed':
|
|
255
|
-
config.editorActor.send({
|
|
256
|
-
...event,
|
|
257
|
-
type: 'notify.value changed',
|
|
258
|
-
})
|
|
259
|
-
break
|
|
260
|
-
case 'patch':
|
|
240
|
+
config.subscriptions.push(() => {
|
|
241
|
+
const subscription = mutationActor.on('*', (event) => {
|
|
242
|
+
if (event.type === 'has pending patches') {
|
|
243
|
+
syncActor.send({type: 'has pending patches'})
|
|
244
|
+
}
|
|
245
|
+
if (event.type === 'mutation') {
|
|
246
|
+
syncActor.send({type: 'mutation'})
|
|
261
247
|
config.editorActor.send({
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
config.editorActor.getSnapshot().context.schema.block.name,
|
|
267
|
-
KEY_TO_VALUE_ELEMENT.get(config.slateEditor),
|
|
268
|
-
),
|
|
248
|
+
type: 'mutation',
|
|
249
|
+
patches: event.patches,
|
|
250
|
+
snapshot: event.snapshot,
|
|
251
|
+
value: event.snapshot,
|
|
269
252
|
})
|
|
270
|
-
|
|
253
|
+
}
|
|
254
|
+
})
|
|
271
255
|
|
|
272
|
-
|
|
273
|
-
|
|
256
|
+
return () => {
|
|
257
|
+
subscription.unsubscribe()
|
|
274
258
|
}
|
|
275
259
|
})
|
|
276
260
|
|
|
277
|
-
config.
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
261
|
+
config.subscriptions.push(() => {
|
|
262
|
+
const subscription = syncActor.on('*', (event) => {
|
|
263
|
+
switch (event.type) {
|
|
264
|
+
case 'invalid value':
|
|
265
|
+
config.editorActor.send({
|
|
266
|
+
...event,
|
|
267
|
+
type: 'notify.invalid value',
|
|
268
|
+
})
|
|
269
|
+
break
|
|
270
|
+
case 'value changed':
|
|
271
|
+
config.editorActor.send({
|
|
272
|
+
...event,
|
|
273
|
+
type: 'notify.value changed',
|
|
274
|
+
})
|
|
275
|
+
break
|
|
276
|
+
case 'patch':
|
|
277
|
+
config.editorActor.send({
|
|
278
|
+
...event,
|
|
279
|
+
type: 'internal.patch',
|
|
280
|
+
value: fromSlateValue(
|
|
281
|
+
config.slateEditor.children,
|
|
282
|
+
config.editorActor.getSnapshot().context.schema.block.name,
|
|
283
|
+
KEY_TO_VALUE_ELEMENT.get(config.slateEditor),
|
|
284
|
+
),
|
|
285
|
+
})
|
|
286
|
+
break
|
|
287
|
+
|
|
288
|
+
default:
|
|
289
|
+
config.editorActor.send(event)
|
|
290
|
+
}
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
return () => {
|
|
294
|
+
subscription.unsubscribe()
|
|
286
295
|
}
|
|
287
296
|
})
|
|
288
297
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
298
|
+
config.subscriptions.push(() => {
|
|
299
|
+
const subscription = config.editorActor.on('*', (event) => {
|
|
300
|
+
if (
|
|
301
|
+
config.editorActor.getSnapshot().matches({'edit mode': 'read only'})
|
|
302
|
+
) {
|
|
303
|
+
syncActor.send({type: 'update readOnly', readOnly: true})
|
|
304
|
+
} else {
|
|
305
|
+
syncActor.send({type: 'update readOnly', readOnly: false})
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (event.type === 'internal.patch') {
|
|
309
|
+
mutationActor.send({...event, type: 'patch'})
|
|
310
|
+
}
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
return () => {
|
|
314
|
+
subscription.unsubscribe()
|
|
315
|
+
}
|
|
292
316
|
})
|
|
293
317
|
|
|
294
318
|
return {
|
|
@@ -9,10 +9,11 @@ import type {PortableTextSlateEditor} from '../types/editor'
|
|
|
9
9
|
import type {EditorActor} from './editor-machine'
|
|
10
10
|
import {withPlugins} from './plugins/with-plugins'
|
|
11
11
|
|
|
12
|
-
const debug = debugWithName('
|
|
12
|
+
const debug = debugWithName('setup')
|
|
13
13
|
|
|
14
14
|
type SlateEditorConfig = {
|
|
15
15
|
editorActor: EditorActor
|
|
16
|
+
subscriptions: Array<() => () => void>
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export type SlateEditor = {
|
|
@@ -20,33 +21,17 @@ export type SlateEditor = {
|
|
|
20
21
|
initialValue: Array<Descendant>
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
const slateEditors = new WeakMap<EditorActor, SlateEditor>()
|
|
24
|
-
|
|
25
24
|
export function createSlateEditor(config: SlateEditorConfig): SlateEditor {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (existingSlateEditor) {
|
|
29
|
-
debug('Reusing existing Slate editor instance', config.editorActor.id)
|
|
30
|
-
return existingSlateEditor
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
debug('Creating new Slate editor instance', config.editorActor.id)
|
|
34
|
-
|
|
35
|
-
const unsubscriptions: Array<() => void> = []
|
|
36
|
-
const subscriptions: Array<() => () => void> = []
|
|
25
|
+
debug('Creating new Slate editor instance')
|
|
37
26
|
|
|
38
27
|
const instance = withPlugins(withReact(createEditor()), {
|
|
39
28
|
editorActor: config.editorActor,
|
|
40
|
-
subscriptions,
|
|
29
|
+
subscriptions: config.subscriptions,
|
|
41
30
|
})
|
|
42
31
|
|
|
43
32
|
KEY_TO_VALUE_ELEMENT.set(instance, {})
|
|
44
33
|
KEY_TO_SLATE_ELEMENT.set(instance, {})
|
|
45
34
|
|
|
46
|
-
for (const subscription of subscriptions) {
|
|
47
|
-
unsubscriptions.push(subscription())
|
|
48
|
-
}
|
|
49
|
-
|
|
50
35
|
const initialValue = [instance.pteCreateTextBlock({decorators: []})]
|
|
51
36
|
|
|
52
37
|
const slateEditor: SlateEditor = {
|
|
@@ -54,7 +39,5 @@ export function createSlateEditor(config: SlateEditorConfig): SlateEditor {
|
|
|
54
39
|
initialValue,
|
|
55
40
|
}
|
|
56
41
|
|
|
57
|
-
slateEditors.set(config.editorActor, slateEditor)
|
|
58
|
-
|
|
59
42
|
return slateEditor
|
|
60
43
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {useActorRef} from '@xstate/react'
|
|
2
1
|
import type React from 'react'
|
|
3
|
-
import {
|
|
2
|
+
import {useEffect} from 'react'
|
|
4
3
|
import {Slate} from 'slate-react'
|
|
5
4
|
import type {EditorConfig} from '../editor'
|
|
6
|
-
import {
|
|
5
|
+
import {stopActor} from '../internal-utils/stop-actor'
|
|
6
|
+
import useConstant from '../internal-utils/use-constant'
|
|
7
|
+
import {createInternalEditor} from './create-editor'
|
|
7
8
|
import {EditorActorContext} from './editor-actor-context'
|
|
8
9
|
import {EditorContext} from './editor-context'
|
|
9
|
-
import {editorMachine} from './editor-machine'
|
|
10
10
|
import {PortableTextEditorContext} from './hooks/usePortableTextEditor'
|
|
11
11
|
import {PortableTextEditorSelectionProvider} from './hooks/usePortableTextEditorSelection'
|
|
12
12
|
import {
|
|
@@ -42,36 +42,56 @@ export type EditorProviderProps = {
|
|
|
42
42
|
* @group Components
|
|
43
43
|
*/
|
|
44
44
|
export function EditorProvider(props: EditorProviderProps) {
|
|
45
|
-
const
|
|
46
|
-
|
|
45
|
+
const {internalEditor, portableTextEditor} = useConstant(() => {
|
|
46
|
+
const internalEditor = createInternalEditor(props.initialConfig)
|
|
47
|
+
const portableTextEditor = new PortableTextEditor({
|
|
48
|
+
editor: internalEditor.editor,
|
|
49
|
+
} as unknown as PortableTextEditorProps)
|
|
50
|
+
|
|
51
|
+
return {internalEditor, portableTextEditor}
|
|
47
52
|
})
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
[
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const unsubscribers: Array<() => void> = []
|
|
56
|
+
|
|
57
|
+
for (const subscription of internalEditor.subscriptions) {
|
|
58
|
+
unsubscribers.push(subscription())
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
internalEditor.actors.editorActor.start()
|
|
62
|
+
internalEditor.actors.mutationActor.start()
|
|
63
|
+
internalEditor.actors.syncActor.start()
|
|
64
|
+
|
|
65
|
+
return () => {
|
|
66
|
+
for (const unsubscribe of unsubscribers) {
|
|
67
|
+
unsubscribe()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
stopActor(internalEditor.actors.editorActor)
|
|
71
|
+
stopActor(internalEditor.actors.mutationActor)
|
|
72
|
+
stopActor(internalEditor.actors.syncActor)
|
|
73
|
+
}
|
|
74
|
+
}, [internalEditor])
|
|
59
75
|
|
|
60
76
|
return (
|
|
61
|
-
<EditorContext.Provider value={internalEditor}>
|
|
77
|
+
<EditorContext.Provider value={internalEditor.editor}>
|
|
62
78
|
<RouteEventsToChanges
|
|
63
|
-
editorActor={editorActor}
|
|
79
|
+
editorActor={internalEditor.actors.editorActor}
|
|
64
80
|
onChange={(change) => {
|
|
65
81
|
portableTextEditor.change$.next(change)
|
|
66
82
|
}}
|
|
67
83
|
/>
|
|
68
|
-
<EditorActorContext.Provider value={editorActor}>
|
|
84
|
+
<EditorActorContext.Provider value={internalEditor.actors.editorActor}>
|
|
69
85
|
<Slate
|
|
70
|
-
editor={internalEditor._internal.slateEditor.instance}
|
|
71
|
-
initialValue={
|
|
86
|
+
editor={internalEditor.editor._internal.slateEditor.instance}
|
|
87
|
+
initialValue={
|
|
88
|
+
internalEditor.editor._internal.slateEditor.initialValue
|
|
89
|
+
}
|
|
72
90
|
>
|
|
73
91
|
<PortableTextEditorContext.Provider value={portableTextEditor}>
|
|
74
|
-
<PortableTextEditorSelectionProvider
|
|
92
|
+
<PortableTextEditorSelectionProvider
|
|
93
|
+
editorActor={internalEditor.actors.editorActor}
|
|
94
|
+
>
|
|
75
95
|
{props.children}
|
|
76
96
|
</PortableTextEditorSelectionProvider>
|
|
77
97
|
</PortableTextEditorContext.Provider>
|
|
@@ -13,9 +13,12 @@ import {
|
|
|
13
13
|
stateIn,
|
|
14
14
|
type AnyEventObject,
|
|
15
15
|
} from 'xstate'
|
|
16
|
+
import type {ActorRefFrom} from 'xstate'
|
|
16
17
|
import type {PortableTextSlateEditor} from '../types/editor'
|
|
17
18
|
import type {EditorSchema} from './editor-schema'
|
|
18
19
|
|
|
20
|
+
export type MutationActor = ActorRefFrom<typeof mutationMachine>
|
|
21
|
+
|
|
19
22
|
/**
|
|
20
23
|
* Makes sure editor mutation events are debounced
|
|
21
24
|
*/
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
type AnyEventObject,
|
|
15
15
|
type CallbackLogicFunction,
|
|
16
16
|
} from 'xstate'
|
|
17
|
+
import type {ActorRefFrom} from 'xstate'
|
|
17
18
|
import {debugWithName} from '../internal-utils/debug'
|
|
18
19
|
import {validateValue} from '../internal-utils/validateValue'
|
|
19
20
|
import {toSlateValue, VOID_CHILD_KEY} from '../internal-utils/values'
|
|
@@ -77,6 +78,8 @@ const syncValueCallback: CallbackLogicFunction<
|
|
|
77
78
|
|
|
78
79
|
const syncValueLogic = fromCallback(syncValueCallback)
|
|
79
80
|
|
|
81
|
+
export type SyncActor = ActorRefFrom<typeof syncMachine>
|
|
82
|
+
|
|
80
83
|
/**
|
|
81
84
|
* Sync value with the editor state
|
|
82
85
|
*
|
|
@@ -24,16 +24,16 @@ import type {
|
|
|
24
24
|
} from '@sanity/types'
|
|
25
25
|
import {
|
|
26
26
|
Element,
|
|
27
|
+
Node,
|
|
27
28
|
Text,
|
|
28
29
|
Transforms,
|
|
29
30
|
type Descendant,
|
|
30
|
-
type Node,
|
|
31
31
|
type Path as SlatePath,
|
|
32
32
|
} from 'slate'
|
|
33
33
|
import type {EditorSchema} from '../editor/editor-schema'
|
|
34
34
|
import type {PortableTextSlateEditor} from '../types/editor'
|
|
35
35
|
import {debugWithName} from './debug'
|
|
36
|
-
import {toSlateValue} from './values'
|
|
36
|
+
import {isEqualToEmptyEditor, toSlateValue} from './values'
|
|
37
37
|
import {KEY_TO_SLATE_ELEMENT} from './weakMaps'
|
|
38
38
|
|
|
39
39
|
const debug = debugWithName('applyPatches')
|
|
@@ -173,9 +173,20 @@ function insertPatch(
|
|
|
173
173
|
const targetBlockIndex = targetBlockPath[0]
|
|
174
174
|
const normalizedIdx =
|
|
175
175
|
position === 'after' ? targetBlockIndex + 1 : targetBlockIndex
|
|
176
|
+
|
|
176
177
|
debug(`Inserting blocks at path [${normalizedIdx}]`)
|
|
177
178
|
debugState(editor, 'before')
|
|
179
|
+
|
|
180
|
+
const editorWasEmptyBefore = isEqualToEmptyEditor(editor.children, schema)
|
|
181
|
+
|
|
178
182
|
Transforms.insertNodes(editor, blocksToInsert, {at: [normalizedIdx]})
|
|
183
|
+
|
|
184
|
+
if (editorWasEmptyBefore) {
|
|
185
|
+
Transforms.removeNodes(editor, {
|
|
186
|
+
at: [position === 'after' ? targetBlockIndex + 1 : targetBlockIndex],
|
|
187
|
+
})
|
|
188
|
+
}
|
|
189
|
+
|
|
179
190
|
debugState(editor, 'after')
|
|
180
191
|
return true
|
|
181
192
|
}
|
|
@@ -319,9 +330,15 @@ function unsetPatch(editor: PortableTextSlateEditor, patch: UnsetPatch) {
|
|
|
319
330
|
debugState(editor, 'before')
|
|
320
331
|
const previousSelection = editor.selection
|
|
321
332
|
Transforms.deselect(editor)
|
|
322
|
-
|
|
323
|
-
|
|
333
|
+
|
|
334
|
+
const children = Node.children(editor, [], {
|
|
335
|
+
reverse: true,
|
|
324
336
|
})
|
|
337
|
+
|
|
338
|
+
for (const [_, path] of children) {
|
|
339
|
+
Transforms.removeNodes(editor, {at: path})
|
|
340
|
+
}
|
|
341
|
+
|
|
325
342
|
Transforms.insertNodes(editor, editor.pteCreateTextBlock({decorators: []}))
|
|
326
343
|
if (previousSelection) {
|
|
327
344
|
Transforms.select(editor, {
|