@portabletext/editor 1.49.4 → 1.49.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.
@@ -200,7 +200,6 @@ export const PortableTextEditable = forwardRef<
200
200
  useMemo(() => {
201
201
  // React/UI-specific plugins
202
202
  if (readOnly) {
203
- debug('Editable is in read only mode')
204
203
  return slateEditor
205
204
  }
206
205
  const withHotKeys = createWithHotkeys(
@@ -209,7 +208,6 @@ export const PortableTextEditable = forwardRef<
209
208
  hotkeys,
210
209
  )
211
210
 
212
- debug('Editable is in edit mode')
213
211
  return withHotKeys(slateEditor)
214
212
  }, [editorActor, hotkeys, portableTextEditor, readOnly, slateEditor])
215
213
 
@@ -16,6 +16,7 @@ import {coreBehaviorsConfig} from '../behaviors/behavior.core'
16
16
  import {performEvent} from '../behaviors/behavior.perform-event'
17
17
  import type {BehaviorEvent} from '../behaviors/behavior.types.event'
18
18
  import type {Converter} from '../converters/converter.types'
19
+ import {debugWithName} from '../internal-utils/debug'
19
20
  import type {EventPosition} from '../internal-utils/event-position'
20
21
  import {sortByPriority} from '../priority/priority.sort'
21
22
  import type {NamespaceEvent} from '../type-utils'
@@ -30,6 +31,8 @@ import {createEditorSnapshot} from './editor-snapshot'
30
31
 
31
32
  export * from 'xstate/guards'
32
33
 
34
+ const debug = debugWithName('editor machine')
35
+
33
36
  /**
34
37
  * @public
35
38
  */
@@ -459,6 +462,20 @@ export const editorMachine = setup({
459
462
  },
460
463
  states: {
461
464
  'determine initial edit mode': {
465
+ entry: [
466
+ () => {
467
+ debug(
468
+ 'entry: edit mode->read only->determine initial edit mode',
469
+ )
470
+ },
471
+ ],
472
+ exit: [
473
+ () => {
474
+ debug(
475
+ 'exit: edit mode->read only->determine initial edit mode',
476
+ )
477
+ },
478
+ ],
462
479
  on: {
463
480
  'done syncing value': [
464
481
  {
@@ -472,6 +489,16 @@ export const editorMachine = setup({
472
489
  },
473
490
  },
474
491
  'read only': {
492
+ entry: [
493
+ () => {
494
+ debug('entry: edit mode->read only->read only')
495
+ },
496
+ ],
497
+ exit: [
498
+ () => {
499
+ debug('exit: edit mode->read only->read only')
500
+ },
501
+ ],
475
502
  on: {
476
503
  'update readOnly': {
477
504
  guard: ({event}) => !event.readOnly,
@@ -503,6 +530,16 @@ export const editorMachine = setup({
503
530
  initial: 'idle',
504
531
  states: {
505
532
  'idle': {
533
+ entry: [
534
+ () => {
535
+ debug('entry: edit mode->editable->idle')
536
+ },
537
+ ],
538
+ exit: [
539
+ () => {
540
+ debug('exit: edit mode->editable-idle')
541
+ },
542
+ ],
506
543
  on: {
507
544
  dragstart: {
508
545
  actions: [
@@ -521,6 +558,20 @@ export const editorMachine = setup({
521
558
  initial: 'checking if busy',
522
559
  states: {
523
560
  'checking if busy': {
561
+ entry: [
562
+ () => {
563
+ debug(
564
+ 'entry: edit mode->editable->focusing->checking if busy',
565
+ )
566
+ },
567
+ ],
568
+ exit: [
569
+ () => {
570
+ debug(
571
+ 'exit: edit mode->editable->focusing->checking if busy',
572
+ )
573
+ },
574
+ ],
524
575
  always: [
525
576
  {
526
577
  guard: 'slate is busy',
@@ -533,6 +584,16 @@ export const editorMachine = setup({
533
584
  ],
534
585
  },
535
586
  'busy': {
587
+ entry: [
588
+ () => {
589
+ debug('entry: edit mode->editable->focusing-busy')
590
+ },
591
+ ],
592
+ exit: [
593
+ () => {
594
+ debug('exit: edit mode->editable->focusing->busy')
595
+ },
596
+ ],
536
597
  after: {
537
598
  10: {
538
599
  target: 'checking if busy',
@@ -542,7 +603,15 @@ export const editorMachine = setup({
542
603
  },
543
604
  },
544
605
  'dragging internally': {
606
+ entry: [
607
+ () => {
608
+ debug('entry: edit mode->editable->dragging internally')
609
+ },
610
+ ],
545
611
  exit: [
612
+ () => {
613
+ debug('exit: edit mode->editable->dragging internally')
614
+ },
546
615
  ({context}) => {
547
616
  if (context.internalDrag?.ghost) {
548
617
  try {
@@ -574,7 +643,15 @@ export const editorMachine = setup({
574
643
  initial: 'setting up',
575
644
  states: {
576
645
  'setting up': {
646
+ entry: [
647
+ () => {
648
+ debug('entry: setup->setting up')
649
+ },
650
+ ],
577
651
  exit: [
652
+ () => {
653
+ debug('exit: setup->setting up')
654
+ },
578
655
  'emit ready',
579
656
  'emit pending incoming patches',
580
657
  'clear pending incoming patches',
@@ -601,6 +678,16 @@ export const editorMachine = setup({
601
678
  initial: 'idle',
602
679
  states: {
603
680
  'idle': {
681
+ entry: [
682
+ () => {
683
+ debug('entry: setup->set up->value sync->idle')
684
+ },
685
+ ],
686
+ exit: [
687
+ () => {
688
+ debug('exit: setup->set up->value sync->idle')
689
+ },
690
+ ],
604
691
  on: {
605
692
  'patches': {
606
693
  actions: [emit(({event}) => event)],
@@ -611,7 +698,15 @@ export const editorMachine = setup({
611
698
  },
612
699
  },
613
700
  'syncing value': {
701
+ entry: [
702
+ () => {
703
+ debug('entry: setup->set up->value sync->syncing value')
704
+ },
705
+ ],
614
706
  exit: [
707
+ () => {
708
+ debug('exit: setup->set up->value sync->syncing value')
709
+ },
615
710
  'emit pending incoming patches',
616
711
  'clear pending incoming patches',
617
712
  ],
@@ -633,6 +728,16 @@ export const editorMachine = setup({
633
728
  initial: 'idle',
634
729
  states: {
635
730
  idle: {
731
+ entry: [
732
+ () => {
733
+ debug('entry: setup->set up->writing->pristine->idle')
734
+ },
735
+ ],
736
+ exit: [
737
+ () => {
738
+ debug('exit: setup->set up->writing->pristine->idle')
739
+ },
740
+ ],
636
741
  on: {
637
742
  'normalizing': {
638
743
  target: 'normalizing',
@@ -648,6 +753,20 @@ export const editorMachine = setup({
648
753
  },
649
754
  },
650
755
  normalizing: {
756
+ entry: [
757
+ () => {
758
+ debug(
759
+ 'entry: setup->set up->writing->pristine->normalizing',
760
+ )
761
+ },
762
+ ],
763
+ exit: [
764
+ () => {
765
+ debug(
766
+ 'exit: setup->set up->writing->pristine->normalizing',
767
+ )
768
+ },
769
+ ],
651
770
  on: {
652
771
  'done normalizing': {
653
772
  target: 'idle',
@@ -663,7 +782,18 @@ export const editorMachine = setup({
663
782
  },
664
783
  },
665
784
  dirty: {
666
- entry: ['emit pending events', 'clear pending events'],
785
+ entry: [
786
+ () => {
787
+ debug('entry: setup->set up->writing->dirty')
788
+ },
789
+ 'emit pending events',
790
+ 'clear pending events',
791
+ ],
792
+ exit: [
793
+ () => {
794
+ debug('exit: setup->set up->writing->dirty')
795
+ },
796
+ ],
667
797
  on: {
668
798
  'internal.patch': {
669
799
  actions: 'emit patch event',
@@ -3,10 +3,12 @@ import type {PortableTextBlock} from '@sanity/types'
3
3
  import {isEqual} from 'lodash'
4
4
  import {Editor, Text, Transforms, type Descendant, type Node} from 'slate'
5
5
  import {
6
+ and,
6
7
  assertEvent,
7
8
  assign,
8
9
  emit,
9
10
  fromCallback,
11
+ not,
10
12
  setup,
11
13
  type AnyEventObject,
12
14
  type CallbackLogicFunction,
@@ -173,6 +175,11 @@ export const syncMachine = setup({
173
175
 
174
176
  return isBusy
175
177
  },
178
+ 'is new value': ({context, event}) => {
179
+ return (
180
+ event.type === 'update value' && context.previousValue !== event.value
181
+ )
182
+ },
176
183
  'value changed while syncing': ({context, event}) => {
177
184
  assertEvent(event, 'done syncing')
178
185
  return context.pendingValue !== event.value
@@ -211,176 +218,148 @@ export const syncMachine = setup({
211
218
  actions: ['assign readOnly'],
212
219
  },
213
220
  },
214
- type: 'parallel',
221
+ initial: 'idle',
215
222
  states: {
216
- 'setting up': {
217
- initial: 'syncing initial value',
218
- states: {
219
- 'syncing initial value': {
220
- entry: [
221
- () => {
222
- debug('entry: syncing initial value')
223
- },
224
- ],
225
- exit: [
226
- () => {
227
- debug('exit: syncing initial value')
228
- },
229
- ],
230
- always: {
231
- guard: 'initial value synced',
232
- target: 'done syncing initial value',
233
- },
223
+ idle: {
224
+ entry: [
225
+ () => {
226
+ debug('entry: syncing->idle')
234
227
  },
235
- 'done syncing initial value': {
236
- entry: [
237
- 'emit done syncing value',
238
- () => {
239
- debug('entry: done syncing initial value')
240
- },
241
- ],
242
- exit: [
243
- () => {
244
- debug('exit: done syncing initial value')
245
- },
246
- ],
247
- type: 'final',
228
+ ],
229
+ exit: [
230
+ () => {
231
+ debug('exit: syncing->idle')
248
232
  },
249
- },
250
- },
251
- 'syncing': {
252
- initial: 'idle',
253
- states: {
254
- idle: {
255
- entry: [
256
- () => {
257
- debug('entry: syncing->idle')
258
- },
259
- ],
260
- exit: [
261
- () => {
262
- debug('exit: syncing->idle')
263
- },
264
- ],
265
- on: {
266
- 'update value': [
267
- {
268
- guard: 'is busy',
269
- target: 'busy',
270
- actions: ['assign pending value'],
271
- },
272
- {
273
- target: 'syncing',
274
- actions: ['assign pending value'],
233
+ ],
234
+ on: {
235
+ 'update value': [
236
+ {
237
+ guard: and(['is busy', 'is new value']),
238
+ target: 'busy',
239
+ actions: ['assign pending value'],
240
+ },
241
+ {
242
+ guard: 'is new value',
243
+ target: 'syncing',
244
+ actions: ['assign pending value'],
245
+ },
246
+ {
247
+ guard: not('initial value synced'),
248
+ actions: [
249
+ () => {
250
+ debug('no new value – setting initial value as synced')
275
251
  },
252
+ 'assign initial value synced',
253
+ 'emit done syncing value',
276
254
  ],
277
255
  },
278
- },
279
- busy: {
280
- entry: [
281
- () => {
282
- debug('entry: syncing->busy')
283
- },
284
- ],
285
- exit: [
286
- () => {
287
- debug('exit: syncing->busy')
288
- },
289
- ],
290
- after: {
291
- 1000: [
292
- {
293
- guard: 'is busy',
294
- target: '.',
295
- reenter: true,
296
- actions: [
297
- () => {
298
- debug('reenter: syncing->busy')
299
- },
300
- ],
301
- },
302
- {
303
- target: 'syncing',
256
+ {
257
+ actions: [
258
+ () => {
259
+ debug('no new value and initial value already synced')
304
260
  },
305
261
  ],
306
262
  },
307
- on: {
308
- 'update value': [
309
- {
310
- actions: ['assign pending value'],
263
+ ],
264
+ },
265
+ },
266
+ busy: {
267
+ entry: [
268
+ () => {
269
+ debug('entry: syncing->busy')
270
+ },
271
+ ],
272
+ exit: [
273
+ () => {
274
+ debug('exit: syncing->busy')
275
+ },
276
+ ],
277
+ after: {
278
+ 1000: [
279
+ {
280
+ guard: 'is busy',
281
+ target: '.',
282
+ reenter: true,
283
+ actions: [
284
+ () => {
285
+ debug('reenter: syncing->busy')
311
286
  },
312
287
  ],
313
288
  },
314
- },
315
- syncing: {
316
- entry: [
317
- () => {
318
- debug('entry: syncing->syncing')
319
- },
320
- 'emit syncing value',
321
- ],
322
- exit: [
323
- () => {
324
- debug('exit: syncing->syncing')
325
- },
326
- 'emit done syncing value',
327
- ],
328
- always: {
329
- guard: 'pending value equals previous value',
330
- target: 'idle',
331
- actions: ['clear pending value', 'assign initial value synced'],
289
+ {
290
+ target: 'syncing',
332
291
  },
333
- invoke: {
334
- src: 'sync value',
335
- id: 'sync value',
336
- input: ({context}) => {
337
- return {
338
- context: {
339
- keyGenerator: context.keyGenerator,
340
- previousValue: context.previousValue,
341
- readOnly: context.readOnly,
342
- schema: context.schema,
343
- },
344
- slateEditor: context.slateEditor,
345
- streamBlocks: !context.initialValueSynced,
346
- value: context.pendingValue,
347
- }
348
- },
292
+ ],
293
+ },
294
+ on: {
295
+ 'update value': [
296
+ {
297
+ guard: 'is new value',
298
+ actions: ['assign pending value'],
349
299
  },
350
- on: {
351
- 'update value': {
352
- actions: ['assign pending value'],
353
- },
354
- 'patch': {
355
- actions: [emit(({event}) => event)],
356
- },
357
- 'invalid value': {
358
- actions: [emit(({event}) => event)],
359
- },
360
- 'value changed': {
361
- actions: [emit(({event}) => event)],
300
+ ],
301
+ },
302
+ },
303
+ syncing: {
304
+ entry: [
305
+ () => {
306
+ debug('entry: syncing->syncing')
307
+ },
308
+ 'emit syncing value',
309
+ ],
310
+ exit: [
311
+ () => {
312
+ debug('exit: syncing->syncing')
313
+ },
314
+ 'emit done syncing value',
315
+ ],
316
+ invoke: {
317
+ src: 'sync value',
318
+ id: 'sync value',
319
+ input: ({context}) => {
320
+ return {
321
+ context: {
322
+ keyGenerator: context.keyGenerator,
323
+ previousValue: context.previousValue,
324
+ readOnly: context.readOnly,
325
+ schema: context.schema,
362
326
  },
363
- 'done syncing': [
364
- {
365
- guard: 'value changed while syncing',
366
- actions: [
367
- 'assign previous value',
368
- 'assign initial value synced',
369
- ],
370
- target: 'syncing',
371
- reenter: true,
372
- },
373
- {
374
- target: 'idle',
375
- actions: [
376
- 'clear pending value',
377
- 'assign previous value',
378
- 'assign initial value synced',
379
- ],
380
- },
327
+ slateEditor: context.slateEditor,
328
+ streamBlocks: !context.initialValueSynced,
329
+ value: context.pendingValue,
330
+ }
331
+ },
332
+ },
333
+ on: {
334
+ 'update value': {
335
+ guard: 'is new value',
336
+ actions: ['assign pending value'],
337
+ },
338
+ 'patch': {
339
+ actions: [emit(({event}) => event)],
340
+ },
341
+ 'invalid value': {
342
+ actions: [emit(({event}) => event)],
343
+ },
344
+ 'value changed': {
345
+ actions: [emit(({event}) => event)],
346
+ },
347
+ 'done syncing': [
348
+ {
349
+ guard: 'value changed while syncing',
350
+ actions: ['assign previous value', 'assign initial value synced'],
351
+ target: 'syncing',
352
+ reenter: true,
353
+ },
354
+ {
355
+ target: 'idle',
356
+ actions: [
357
+ 'clear pending value',
358
+ 'assign previous value',
359
+ 'assign initial value synced',
381
360
  ],
382
361
  },
383
- },
362
+ ],
384
363
  },
385
364
  },
386
365
  },