@portabletext/editor 1.1.1 → 1.1.3

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 (53) hide show
  1. package/README.md +3 -0
  2. package/lib/index.d.mts +1668 -1
  3. package/lib/index.d.ts +1668 -1
  4. package/lib/index.esm.js +320 -172
  5. package/lib/index.esm.js.map +1 -1
  6. package/lib/index.js +320 -173
  7. package/lib/index.js.map +1 -1
  8. package/lib/index.mjs +320 -172
  9. package/lib/index.mjs.map +1 -1
  10. package/package.json +23 -23
  11. package/src/editor/Editable.tsx +32 -34
  12. package/src/editor/PortableTextEditor.tsx +23 -7
  13. package/src/editor/__tests__/PortableTextEditor.test.tsx +9 -9
  14. package/src/editor/__tests__/PortableTextEditorTester.tsx +2 -5
  15. package/src/editor/__tests__/RangeDecorations.test.tsx +2 -2
  16. package/src/editor/__tests__/handleClick.test.tsx +27 -7
  17. package/src/editor/__tests__/insert-block.test.tsx +4 -4
  18. package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +7 -7
  19. package/src/editor/__tests__/self-solving.test.tsx +176 -0
  20. package/src/editor/components/Leaf.tsx +28 -23
  21. package/src/editor/components/Synchronizer.tsx +60 -32
  22. package/src/editor/editor-machine.ts +195 -0
  23. package/src/editor/hooks/usePortableTextEditorSelection.tsx +12 -14
  24. package/src/editor/hooks/useSyncValue.test.tsx +9 -9
  25. package/src/editor/hooks/useSyncValue.ts +14 -13
  26. package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +1 -1
  27. package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +28 -28
  28. package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +17 -17
  29. package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +8 -8
  30. package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +5 -5
  31. package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +2 -2
  32. package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +46 -46
  33. package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +22 -11
  34. package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +9 -9
  35. package/src/editor/plugins/createWithEditableAPI.ts +5 -7
  36. package/src/editor/plugins/createWithInsertData.ts +4 -9
  37. package/src/editor/plugins/createWithObjectKeys.ts +7 -0
  38. package/src/editor/plugins/createWithPatches.ts +5 -6
  39. package/src/editor/plugins/createWithPortableTextBlockStyle.ts +10 -2
  40. package/src/editor/plugins/createWithPortableTextMarkModel.ts +40 -36
  41. package/src/editor/plugins/createWithPortableTextSelections.ts +4 -5
  42. package/src/editor/plugins/createWithSchemaTypes.ts +9 -0
  43. package/src/editor/plugins/index.ts +18 -8
  44. package/src/index.ts +9 -3
  45. package/src/utils/__tests__/dmpToOperations.test.ts +1 -1
  46. package/src/utils/__tests__/operationToPatches.test.ts +61 -61
  47. package/src/utils/__tests__/patchToOperations.test.ts +39 -39
  48. package/src/utils/__tests__/ranges.test.ts +1 -1
  49. package/src/utils/__tests__/valueNormalization.test.tsx +13 -2
  50. package/src/utils/__tests__/values.test.ts +17 -17
  51. package/src/utils/applyPatch.ts +4 -10
  52. package/src/utils/validateValue.ts +0 -22
  53. package/src/editor/__tests__/utils.ts +0 -44
package/lib/index.mjs CHANGED
@@ -9,6 +9,7 @@ import { isKeySegment, isPortableTextSpan as isPortableTextSpan$1, isPortableTex
9
9
  import { styled } from "styled-components";
10
10
  import uniq from "lodash/uniq.js";
11
11
  import { Subject } from "rxjs";
12
+ import { fromCallback, setup, emit, assertEvent, assign, enqueueActions, createActor } from "xstate";
12
13
  import { Schema } from "@sanity/schema";
13
14
  import { diffMatchPatch as diffMatchPatch$1, set, insert, setIfMissing, unset, applyAll } from "@portabletext/patches";
14
15
  import get from "lodash/get.js";
@@ -126,7 +127,7 @@ function normalizeSelection(selection, value) {
126
127
  const { anchor, focus } = selection;
127
128
  return anchor && value.find((blk) => isEqual({ _key: blk._key }, anchor.path[0])) && (newAnchor = normalizePoint(anchor, value)), focus && value.find((blk) => isEqual({ _key: blk._key }, focus.path[0])) && (newFocus = normalizePoint(focus, value)), newAnchor && newFocus ? { anchor: newAnchor, focus: newFocus, backward: selection.backward } : null;
128
129
  }
129
- const EMPTY_MARKDEFS = [], VOID_CHILD_KEY = "void-child";
130
+ const VOID_CHILD_KEY = "void-child";
130
131
  function keepObjectEquality(object, keyMap) {
131
132
  const value = keyMap[object._key];
132
133
  return value && isEqual(object, value) ? value : (keyMap[object._key] = object, object);
@@ -1710,7 +1711,7 @@ function createWithMaxBlocks(maxBlocks) {
1710
1711
  }, editor;
1711
1712
  };
1712
1713
  }
1713
- function createWithObjectKeys(schemaTypes, keyGenerator) {
1714
+ function createWithObjectKeys(editorActor, schemaTypes, keyGenerator) {
1714
1715
  return function(editor) {
1715
1716
  const { apply: apply2, normalizeNode } = editor;
1716
1717
  return editor.apply = (operation) => {
@@ -1746,10 +1747,13 @@ function createWithObjectKeys(schemaTypes, keyGenerator) {
1746
1747
  }, editor.normalizeNode = (entry) => {
1747
1748
  const [node, path] = entry;
1748
1749
  if (Element$1.isElement(node) && node._type === schemaTypes.block.name) {
1749
- node._key || Transforms.setNodes(editor, { _key: keyGenerator() }, { at: path });
1750
+ if (!node._key) {
1751
+ editorActor.send({ type: "normalizing" }), Transforms.setNodes(editor, { _key: keyGenerator() }, { at: path }), editorActor.send({ type: "done normalizing" });
1752
+ return;
1753
+ }
1750
1754
  for (const [child, childPath] of Node.children(editor, path))
1751
1755
  if (!child._key) {
1752
- Transforms.setNodes(editor, { _key: keyGenerator() }, { at: childPath });
1756
+ editorActor.send({ type: "normalizing" }), Transforms.setNodes(editor, { _key: keyGenerator() }, { at: childPath }), editorActor.send({ type: "done normalizing" });
1753
1757
  return;
1754
1758
  }
1755
1759
  }
@@ -2454,7 +2458,6 @@ function toInt(num) {
2454
2458
  }
2455
2459
  const debug$i = debugWithName("applyPatches"), debugVerbose$4 = debug$i.enabled && !0;
2456
2460
  function createApplyPatch(schemaTypes) {
2457
- let previousPatch;
2458
2461
  return (editor, patch) => {
2459
2462
  let changed = !1;
2460
2463
  debugVerbose$4 && (debug$i(
@@ -2468,7 +2471,7 @@ NEW PATCH =============================================================`
2468
2471
  changed = insertPatch(editor, patch, schemaTypes);
2469
2472
  break;
2470
2473
  case "unset":
2471
- changed = unsetPatch(editor, patch, previousPatch);
2474
+ changed = unsetPatch(editor, patch);
2472
2475
  break;
2473
2476
  case "set":
2474
2477
  changed = setPatch(editor, patch);
@@ -2482,7 +2485,7 @@ NEW PATCH =============================================================`
2482
2485
  } catch (err) {
2483
2486
  console.error(err);
2484
2487
  }
2485
- return previousPatch = patch, changed;
2488
+ return changed;
2486
2489
  };
2487
2490
  }
2488
2491
  function diffMatchPatch(editor, patch) {
@@ -2597,11 +2600,11 @@ function setPatch(editor, patch) {
2597
2600
  }
2598
2601
  return debugState(editor, "after"), !0;
2599
2602
  }
2600
- function unsetPatch(editor, patch, previousPatch) {
2603
+ function unsetPatch(editor, patch) {
2601
2604
  if (patch.path.length === 0) {
2602
2605
  debug$i("Removing everything"), debugState(editor, "before");
2603
2606
  const previousSelection = editor.selection;
2604
- return Transforms.deselect(editor), editor.children.forEach((c, i) => {
2607
+ return Transforms.deselect(editor), editor.children.forEach((_child, i) => {
2605
2608
  Transforms.removeNodes(editor, { at: [i] });
2606
2609
  }), Transforms.insertNodes(editor, editor.pteCreateTextBlock({ decorators: [] })), previousSelection && Transforms.select(editor, {
2607
2610
  anchor: { path: [0, 0], offset: 0 },
@@ -2906,7 +2909,7 @@ function findOperationTargetBlock(editor, operation) {
2906
2909
  }
2907
2910
  const debug$g = debugWithName("plugin:withPatches");
2908
2911
  function createWithPatches({
2909
- change$,
2912
+ editorActor,
2910
2913
  patches$,
2911
2914
  patchFunctions,
2912
2915
  readOnly,
@@ -3035,7 +3038,7 @@ function createWithPatches({
3035
3038
  }
3036
3039
  return !editorWasEmpty && editorIsEmpty && ["merge_node", "set_node", "remove_text", "remove_node"].includes(
3037
3040
  operation.type
3038
- ) && (patches = [...patches, unset([])], change$.next({
3041
+ ) && (patches = [...patches, unset([])], editorActor.send({
3039
3042
  type: "unset",
3040
3043
  previousValue: fromSlateValue(
3041
3044
  previousChildren,
@@ -3043,7 +3046,7 @@ function createWithPatches({
3043
3046
  KEY_TO_VALUE_ELEMENT.get(editor)
3044
3047
  )
3045
3048
  })), editorWasEmpty && patches.length > 0 && (patches = [setIfMissing([], []), ...patches]), patches.length > 0 && patches.forEach((patch) => {
3046
- change$.next({
3049
+ editorActor.send({
3047
3050
  type: "patch",
3048
3051
  patch: { ...patch, origin: "local" }
3049
3052
  });
@@ -3079,25 +3082,25 @@ function createWithPlaceholderBlock() {
3079
3082
  };
3080
3083
  }
3081
3084
  const debug$e = debugWithName("plugin:withPortableTextBlockStyle");
3082
- function createWithPortableTextBlockStyle(types) {
3085
+ function createWithPortableTextBlockStyle(editorActor, types) {
3083
3086
  const defaultStyle = types.styles[0].value;
3084
3087
  return function(editor) {
3085
3088
  const { normalizeNode } = editor;
3086
3089
  return editor.normalizeNode = (nodeEntry) => {
3087
- normalizeNode(nodeEntry);
3088
3090
  const [, path] = nodeEntry;
3089
3091
  for (const op of editor.operations)
3090
3092
  if (op.type === "split_node" && op.path.length === 1 && editor.isTextBlock(op.properties) && op.properties.style !== defaultStyle && op.path[0] === path[0] && !Path.equals(path, op.path)) {
3091
3093
  const [child] = Editor.node(editor, [op.path[0] + 1, 0]);
3092
3094
  if (Text.isText(child) && child.text === "") {
3093
- debug$e(`Normalizing split node to ${defaultStyle} style`, op), Transforms.setNodes(
3095
+ debug$e(`Normalizing split node to ${defaultStyle} style`, op), editorActor.send({ type: "normalizing" }), Transforms.setNodes(
3094
3096
  editor,
3095
3097
  { style: defaultStyle },
3096
3098
  { at: [op.path[0] + 1], voids: !1 }
3097
- );
3098
- break;
3099
+ ), editorActor.send({ type: "done normalizing" });
3100
+ return;
3099
3101
  }
3100
3102
  }
3103
+ normalizeNode(nodeEntry);
3101
3104
  }, editor.pteHasBlockStyle = (style) => editor.selection ? [
3102
3105
  ...Editor.nodes(editor, {
3103
3106
  at: editor.selection,
@@ -3242,7 +3245,7 @@ function isPortableTextBlock(node) {
3242
3245
  );
3243
3246
  }
3244
3247
  const debug$c = debugWithName("plugin:withPortableTextMarkModel");
3245
- function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3248
+ function createWithPortableTextMarkModel(editorActor, types, keyGenerator) {
3246
3249
  return function(editor) {
3247
3250
  const { apply: apply2, normalizeNode } = editor, decorators = types.decorators.map((t) => t.value), forceNewSelection = () => {
3248
3251
  editor.selection && (Transforms.select(editor, { ...editor.selection }), editor.selection = { ...editor.selection });
@@ -3251,7 +3254,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3251
3254
  editor.selection,
3252
3255
  types
3253
3256
  );
3254
- change$.next({ type: "selection", selection: ptRange });
3257
+ editorActor.send({ type: "selection", selection: ptRange });
3255
3258
  };
3256
3259
  return editor.normalizeNode = (nodeEntry) => {
3257
3260
  const [node, path] = nodeEntry;
@@ -3264,20 +3267,20 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3264
3267
  "Merging spans",
3265
3268
  JSON.stringify(child, null, 2),
3266
3269
  JSON.stringify(nextNode, null, 2)
3267
- ), Transforms.mergeNodes(editor, {
3270
+ ), editorActor.send({ type: "normalizing" }), Transforms.mergeNodes(editor, {
3268
3271
  at: [childPath[0], childPath[1] + 1],
3269
3272
  voids: !0
3270
- });
3273
+ }), editorActor.send({ type: "done normalizing" });
3271
3274
  return;
3272
3275
  }
3273
3276
  }
3274
3277
  }
3275
3278
  if (editor.isTextBlock(node) && !Array.isArray(node.markDefs)) {
3276
- debug$c("Adding .markDefs to block node"), Transforms.setNodes(editor, { markDefs: [] }, { at: path });
3279
+ debug$c("Adding .markDefs to block node"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(editor, { markDefs: [] }, { at: path }), editorActor.send({ type: "done normalizing" });
3277
3280
  return;
3278
3281
  }
3279
3282
  if (editor.isTextSpan(node) && !Array.isArray(node.marks)) {
3280
- debug$c("Adding .marks to span node"), Transforms.setNodes(editor, { marks: [] }, { at: path });
3283
+ debug$c("Adding .marks to span node"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(editor, { marks: [] }, { at: path }), editorActor.send({ type: "done normalizing" });
3281
3284
  return;
3282
3285
  }
3283
3286
  if (editor.isTextSpan(node)) {
@@ -3285,11 +3288,11 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3285
3288
  (mark) => !decorators2.includes(mark)
3286
3289
  );
3287
3290
  if (editor.isTextBlock(block) && node.text === "" && annotations && annotations.length > 0) {
3288
- debug$c("Removing annotations from empty span node"), Transforms.setNodes(
3291
+ debug$c("Removing annotations from empty span node"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(
3289
3292
  editor,
3290
3293
  { marks: node.marks?.filter((mark) => decorators2.includes(mark)) },
3291
3294
  { at: path }
3292
- );
3295
+ ), editorActor.send({ type: "done normalizing" });
3293
3296
  return;
3294
3297
  }
3295
3298
  }
@@ -3299,7 +3302,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3299
3302
  if (editor.isTextSpan(child)) {
3300
3303
  const marks = child.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators2.includes(mark) && !node.markDefs?.find((def) => def._key === mark));
3301
3304
  if (orphanedAnnotations.length > 0) {
3302
- debug$c("Removing orphaned annotations from span node"), Transforms.setNodes(
3305
+ debug$c("Removing orphaned annotations from span node"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(
3303
3306
  editor,
3304
3307
  {
3305
3308
  marks: marks.filter(
@@ -3307,7 +3310,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3307
3310
  )
3308
3311
  },
3309
3312
  { at: childPath }
3310
- );
3313
+ ), editorActor.send({ type: "done normalizing" });
3311
3314
  return;
3312
3315
  }
3313
3316
  }
@@ -3319,7 +3322,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3319
3322
  (decorator) => decorator.value
3320
3323
  ), marks = node.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators2.includes(mark) && !block.markDefs?.find((def) => def._key === mark));
3321
3324
  if (orphanedAnnotations.length > 0) {
3322
- debug$c("Removing orphaned annotations from span node"), Transforms.setNodes(
3325
+ debug$c("Removing orphaned annotations from span node"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(
3323
3326
  editor,
3324
3327
  {
3325
3328
  marks: marks.filter(
@@ -3327,7 +3330,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3327
3330
  )
3328
3331
  },
3329
3332
  { at: path }
3330
- );
3333
+ ), editorActor.send({ type: "done normalizing" });
3331
3334
  return;
3332
3335
  }
3333
3336
  }
@@ -3336,20 +3339,23 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3336
3339
  const markDefs = node.markDefs ?? [], markDefKeys = /* @__PURE__ */ new Set(), newMarkDefs = [];
3337
3340
  for (const markDef of markDefs)
3338
3341
  markDefKeys.has(markDef._key) || (markDefKeys.add(markDef._key), newMarkDefs.push(markDef));
3339
- markDefs.length !== newMarkDefs.length && (debug$c("Removing duplicate markDefs"), Transforms.setNodes(editor, { markDefs: newMarkDefs }, { at: path }));
3342
+ if (markDefs.length !== newMarkDefs.length) {
3343
+ debug$c("Removing duplicate markDefs"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(editor, { markDefs: newMarkDefs }, { at: path }), editorActor.send({ type: "done normalizing" });
3344
+ return;
3345
+ }
3340
3346
  }
3341
3347
  if (editor.isTextBlock(node) && !editor.operations.some(
3342
3348
  (op) => op.type === "merge_node" && "markDefs" in op.properties && op.path.length === 1
3343
3349
  )) {
3344
3350
  const newMarkDefs = (node.markDefs || []).filter((def) => node.children.find((child) => Text.isText(child) && Array.isArray(child.marks) && child.marks.includes(def._key)));
3345
3351
  if (node.markDefs && !isEqual(newMarkDefs, node.markDefs)) {
3346
- debug$c("Removing markDef not in use"), Transforms.setNodes(
3352
+ debug$c("Removing markDef not in use"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(
3347
3353
  editor,
3348
3354
  {
3349
3355
  markDefs: newMarkDefs
3350
3356
  },
3351
3357
  { at: path }
3352
- );
3358
+ ), editorActor.send({ type: "done normalizing" });
3353
3359
  return;
3354
3360
  }
3355
3361
  }
@@ -3364,27 +3370,24 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3364
3370
  return;
3365
3371
  }
3366
3372
  if (op.type === "insert_text") {
3367
- const { selection } = editor;
3368
- if (selection && Range.isCollapsed(selection) && Editor.marks(editor)?.marks?.some(
3369
- (mark) => !decorators.includes(mark)
3370
- )) {
3371
- const [node] = Array.from(
3373
+ const { selection } = editor, collapsedSelection = selection ? Range.isCollapsed(selection) : !1;
3374
+ if (selection && collapsedSelection) {
3375
+ const [span] = Array.from(
3372
3376
  Editor.nodes(editor, {
3373
3377
  mode: "lowest",
3374
3378
  at: selection.focus,
3375
- match: (n) => n._type === types.span.name,
3379
+ match: (n) => editor.isTextSpan(n),
3376
3380
  voids: !1
3377
3381
  })
3378
- )[0] || [void 0];
3379
- if (Text.isText(node) && node.text.length === selection.focus.offset && Array.isArray(node.marks) && node.marks.length > 0) {
3380
- const marksWithoutAnnotationMarks = ({
3381
- ...Editor.marks(editor) || {}
3382
- }.marks || []).filter((mark) => decorators.includes(mark));
3382
+ )[0], marks = span.marks ?? [], marksWithoutAnnotations = marks.filter(
3383
+ (mark) => decorators.includes(mark)
3384
+ );
3385
+ if (marks.length > marksWithoutAnnotations.length && (selection.anchor.offset === 0 || span.text.length === selection.focus.offset)) {
3383
3386
  Transforms.insertNodes(editor, {
3384
3387
  _type: "span",
3385
3388
  _key: keyGenerator(),
3386
3389
  text: op.text,
3387
- marks: marksWithoutAnnotationMarks
3390
+ marks: marksWithoutAnnotations
3388
3391
  }), debug$c("Inserting text at end of annotation");
3389
3392
  return;
3390
3393
  }
@@ -3582,7 +3585,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3582
3585
  };
3583
3586
  }
3584
3587
  const debug$b = debugWithName("plugin:withPortableTextSelections"), debugVerbose$2 = debug$b.enabled && !1;
3585
- function createWithPortableTextSelections(change$, types) {
3588
+ function createWithPortableTextSelections(editorActor, types) {
3586
3589
  let prevSelection = null;
3587
3590
  return function(editor) {
3588
3591
  const emitPortableTextSelection = () => {
@@ -3601,7 +3604,7 @@ function createWithPortableTextSelections(change$, types) {
3601
3604
  `Emitting selection ${JSON.stringify(ptRange || null)} (${JSON.stringify(
3602
3605
  editor.selection
3603
3606
  )})`
3604
- ), ptRange ? change$.next({ type: "selection", selection: ptRange }) : change$.next({ type: "selection", selection: null });
3607
+ ), ptRange ? editorActor.send({ type: "selection", selection: ptRange }) : editorActor.send({ type: "selection", selection: null });
3605
3608
  }
3606
3609
  prevSelection = editor.selection;
3607
3610
  }, { onChange } = editor;
@@ -3613,6 +3616,7 @@ function createWithPortableTextSelections(change$, types) {
3613
3616
  }
3614
3617
  const debug$a = debugWithName("plugin:withSchemaTypes");
3615
3618
  function createWithSchemaTypes({
3619
+ editorActor,
3616
3620
  schemaTypes,
3617
3621
  keyGenerator
3618
3622
  }) {
@@ -3624,16 +3628,18 @@ function createWithSchemaTypes({
3624
3628
  if (node._type === void 0 && path.length === 2) {
3625
3629
  debug$a("Setting span type on text node without a type");
3626
3630
  const span = node, key = span._key || keyGenerator();
3627
- Transforms.setNodes(
3631
+ editorActor.send({ type: "normalizing" }), Transforms.setNodes(
3628
3632
  editor,
3629
3633
  { ...span, _type: schemaTypes.span.name, _key: key },
3630
3634
  { at: path }
3631
- );
3635
+ ), editorActor.send({ type: "done normalizing" });
3636
+ return;
3632
3637
  }
3633
3638
  if (node._key === void 0 && (path.length === 1 || path.length === 2)) {
3634
3639
  debug$a("Setting missing key on child node without a key");
3635
3640
  const key = keyGenerator();
3636
- Transforms.setNodes(editor, { _key: key }, { at: path });
3641
+ editorActor.send({ type: "normalizing" }), Transforms.setNodes(editor, { _key: key }, { at: path }), editorActor.send({ type: "done normalizing" });
3642
+ return;
3637
3643
  }
3638
3644
  normalizeNode(entry);
3639
3645
  }, editor;
@@ -3941,22 +3947,6 @@ function validateValue(value, types, keyGenerator) {
3941
3947
  }
3942
3948
  }, !0;
3943
3949
  }
3944
- if (blk.markDefs && !Array.isArray(blk.markDefs))
3945
- return resolution = {
3946
- patches: [
3947
- set({ ...textBlock, markDefs: EMPTY_MARKDEFS }, [
3948
- { _key: textBlock._key }
3949
- ])
3950
- ],
3951
- description: "Block has invalid required property 'markDefs'.",
3952
- action: "Add empty markDefs array",
3953
- item: textBlock,
3954
- i18n: {
3955
- description: "inputs.portable-text.invalid-value.missing-or-invalid-markdefs.description",
3956
- action: "inputs.portable-text.invalid-value.missing-or-invalid-markdefs.action",
3957
- values: { key: textBlock._key }
3958
- }
3959
- }, !0;
3960
3950
  const allUsedMarks = uniq(
3961
3951
  flatten(
3962
3952
  textBlock.children.filter((cld) => cld._type === types.span.name).map((cld) => cld.marks || [])
@@ -4101,7 +4091,7 @@ function validateValue(value, types, keyGenerator) {
4101
4091
  }) && (valid = !1), { valid, resolution, value });
4102
4092
  }
4103
4093
  const debug$7 = debugWithName("plugin:withInsertData");
4104
- function createWithInsertData(change$, schemaTypes, keyGenerator) {
4094
+ function createWithInsertData(editorActor, schemaTypes, keyGenerator) {
4105
4095
  return function(editor) {
4106
4096
  const blockTypeName = schemaTypes.block.name, spanTypeName = schemaTypes.span.name, whitespaceOnPasteMode = schemaTypes.block.options.unstable_whitespaceOnPasteMode, toPlainText = (blocks) => blocks.map((block) => editor.isTextBlock(block) ? block.children.map((child) => child._type === spanTypeName ? child.text : `[${schemaTypes.inlineObjects.find((t) => t.name === child._type)?.title || "Object"}]`).join("") : `[${schemaTypes.blockObjects.find((t) => t.name === block._type)?.title || "Object"}]`).join(`
4107
4097
 
@@ -4155,9 +4145,8 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
4155
4145
  ), validation = validateValue(parsed, schemaTypes, keyGenerator);
4156
4146
  if (!validation.valid && !validation.resolution?.autoResolve) {
4157
4147
  const errorDescription = `${validation.resolution?.description}`;
4158
- return change$.next({
4148
+ return editorActor.send({
4159
4149
  type: "error",
4160
- level: "warning",
4161
4150
  name: "pasteError",
4162
4151
  description: errorDescription,
4163
4152
  data: validation
@@ -4170,7 +4159,6 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
4170
4159
  }, editor.insertTextOrHTMLData = (data) => {
4171
4160
  if (!editor.selection)
4172
4161
  return debug$7("No selection, not inserting"), !1;
4173
- change$.next({ type: "loading", isLoading: !0 });
4174
4162
  const html = data.getData("text/html"), text = data.getData("text/plain");
4175
4163
  if (html || text) {
4176
4164
  debug$7("Inserting data", data);
@@ -4201,9 +4189,8 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
4201
4189
  const errorDescription = `Could not validate the resulting portable text to insert.
4202
4190
  ${validation.resolution?.description}
4203
4191
  Try to insert as plain text (shift-paste) instead.`;
4204
- return change$.next({
4192
+ return editorActor.send({
4205
4193
  type: "error",
4206
- level: "warning",
4207
4194
  name: "pasteError",
4208
4195
  description: errorDescription,
4209
4196
  data: validation
@@ -4211,9 +4198,9 @@ Try to insert as plain text (shift-paste) instead.`;
4211
4198
  }
4212
4199
  return debug$7(
4213
4200
  `Inserting ${insertedType} fragment at ${JSON.stringify(editor.selection)}`
4214
- ), _insertFragment(editor, fragment, schemaTypes), change$.next({ type: "loading", isLoading: !1 }), !0;
4201
+ ), _insertFragment(editor, fragment, schemaTypes), !0;
4215
4202
  }
4216
- return change$.next({ type: "loading", isLoading: !1 }), !1;
4203
+ return !1;
4217
4204
  }, editor.insertData = (data) => {
4218
4205
  editor.insertPortableTextData(data) || editor.insertTextOrHTMLData(data);
4219
4206
  }, editor.insertFragmentData = (data) => {
@@ -4300,18 +4287,26 @@ function _insertFragment(editor, fragment, schemaTypes) {
4300
4287
  }), editor.onChange();
4301
4288
  }
4302
4289
  const originalFnMap = /* @__PURE__ */ new WeakMap(), withPlugins = (editor, options) => {
4303
- const e = editor, { keyGenerator, portableTextEditor, patches$, readOnly, maxBlocks } = options, { schemaTypes, change$ } = portableTextEditor;
4290
+ const e = editor, { keyGenerator, portableTextEditor, patches$, readOnly, maxBlocks } = options, { editorActor, schemaTypes } = portableTextEditor;
4304
4291
  e.subscriptions = [], e.destroy ? e.destroy() : originalFnMap.set(e, {
4305
4292
  apply: e.apply,
4306
4293
  onChange: e.onChange,
4307
4294
  normalizeNode: e.normalizeNode
4308
4295
  });
4309
- const operationToPatches = createOperationToPatches(schemaTypes), withObjectKeys = createWithObjectKeys(schemaTypes, keyGenerator), withSchemaTypes = createWithSchemaTypes({ schemaTypes, keyGenerator }), withEditableAPI = createWithEditableAPI(
4296
+ const operationToPatches = createOperationToPatches(schemaTypes), withObjectKeys = createWithObjectKeys(
4297
+ editorActor,
4298
+ schemaTypes,
4299
+ keyGenerator
4300
+ ), withSchemaTypes = createWithSchemaTypes({
4301
+ editorActor,
4302
+ schemaTypes,
4303
+ keyGenerator
4304
+ }), withEditableAPI = createWithEditableAPI(
4310
4305
  portableTextEditor,
4311
4306
  schemaTypes,
4312
4307
  keyGenerator
4313
4308
  ), withPatches = createWithPatches({
4314
- change$,
4309
+ editorActor,
4315
4310
  keyGenerator,
4316
4311
  patches$,
4317
4312
  patchFunctions: operationToPatches,
@@ -4322,15 +4317,18 @@ const originalFnMap = /* @__PURE__ */ new WeakMap(), withPlugins = (editor, opti
4322
4317
  patches$,
4323
4318
  blockSchemaType: schemaTypes.block
4324
4319
  }), withPortableTextMarkModel = createWithPortableTextMarkModel(
4320
+ editorActor,
4325
4321
  schemaTypes,
4326
- change$,
4327
4322
  keyGenerator
4328
- ), withPortableTextBlockStyle = createWithPortableTextBlockStyle(schemaTypes), withPlaceholderBlock = createWithPlaceholderBlock(), withInsertBreak = createWithInsertBreak(schemaTypes, keyGenerator), withUtils = createWithUtils({
4323
+ ), withPortableTextBlockStyle = createWithPortableTextBlockStyle(
4324
+ editorActor,
4325
+ schemaTypes
4326
+ ), withPlaceholderBlock = createWithPlaceholderBlock(), withInsertBreak = createWithInsertBreak(schemaTypes, keyGenerator), withUtils = createWithUtils({
4329
4327
  keyGenerator,
4330
4328
  schemaTypes,
4331
4329
  portableTextEditor
4332
4330
  }), withPortableTextSelections = createWithPortableTextSelections(
4333
- change$,
4331
+ editorActor,
4334
4332
  schemaTypes
4335
4333
  );
4336
4334
  return e.destroy = () => {
@@ -4447,7 +4445,7 @@ const defaultKeyGenerator = () => randomKey(12), PortableTextEditorKeyGeneratorC
4447
4445
  return readOnly;
4448
4446
  }, debug$5 = debugWithName("hook:useSyncValue"), CURRENT_VALUE = /* @__PURE__ */ new WeakMap();
4449
4447
  function useSyncValue(props) {
4450
- const { portableTextEditor, readOnly, keyGenerator } = props, { change$, schemaTypes } = portableTextEditor, previousValue = useRef(), slateEditor = useSlate(), updateValueFunctionRef = useRef(), updateFromCurrentValue = useCallback(() => {
4448
+ const { editorActor, portableTextEditor, readOnly, keyGenerator } = props, { schemaTypes } = portableTextEditor, previousValue = useRef(), slateEditor = useSlate(), updateValueFunctionRef = useRef(), updateFromCurrentValue = useCallback(() => {
4451
4449
  const currentValue = CURRENT_VALUE.get(portableTextEditor);
4452
4450
  if (previousValue.current === currentValue) {
4453
4451
  debug$5("Value is the same object as previous, not need to sync");
@@ -4518,7 +4516,7 @@ function useSyncValue(props) {
4518
4516
  !validation.valid && validation.resolution?.autoResolve && validation.resolution?.patches.length > 0 && !readOnly && previousValue.current && previousValue.current !== value && (console.warn(
4519
4517
  `${validation.resolution.action} for block with _key '${validationValue[0]._key}'. ${validation.resolution?.description}`
4520
4518
  ), validation.resolution.patches.forEach((patch) => {
4521
- change$.next({ type: "patch", patch });
4519
+ editorActor.send({ type: "patch", patch });
4522
4520
  })), validation.valid || validation.resolution?.autoResolve ? (oldBlock._key === currentBlock._key ? (debug$5.enabled && debug$5("Updating block", oldBlock, currentBlock), _updateBlock(
4523
4521
  slateEditor,
4524
4522
  currentBlock,
@@ -4528,8 +4526,8 @@ function useSyncValue(props) {
4528
4526
  slateEditor,
4529
4527
  currentBlock,
4530
4528
  currentBlockIndex
4531
- )), isChanged = !0) : (change$.next({
4532
- type: "invalidValue",
4529
+ )), isChanged = !0) : (editorActor.send({
4530
+ type: "invalid value",
4533
4531
  resolution: validation.resolution,
4534
4532
  value
4535
4533
  }), isValid = !1);
@@ -4545,8 +4543,8 @@ function useSyncValue(props) {
4545
4543
  currentBlock
4546
4544
  ), validation.valid || validation.resolution?.autoResolve ? Transforms.insertNodes(slateEditor, currentBlock, {
4547
4545
  at: [currentBlockIndex]
4548
- }) : (debug$5("Invalid", validation), change$.next({
4549
- type: "invalidValue",
4546
+ }) : (debug$5("Invalid", validation), editorActor.send({
4547
+ type: "invalid value",
4550
4548
  resolution: validation.resolution,
4551
4549
  value
4552
4550
  }), isValid = !1);
@@ -4567,8 +4565,8 @@ function useSyncValue(props) {
4567
4565
  try {
4568
4566
  slateEditor.onChange();
4569
4567
  } catch (err) {
4570
- console.error(err), change$.next({
4571
- type: "invalidValue",
4568
+ console.error(err), editorActor.send({
4569
+ type: "invalid value",
4572
4570
  resolution: null,
4573
4571
  value
4574
4572
  });
@@ -4577,14 +4575,14 @@ function useSyncValue(props) {
4577
4575
  hadSelection && !slateEditor.selection && (Transforms.select(slateEditor, {
4578
4576
  anchor: { path: [0, 0], offset: 0 },
4579
4577
  focus: { path: [0, 0], offset: 0 }
4580
- }), slateEditor.onChange()), change$.next({ type: "value", value });
4578
+ }), slateEditor.onChange()), editorActor.send({ type: "value changed", value });
4581
4579
  } else
4582
4580
  debug$5("Server value and editor value is equal, no need to sync.");
4583
4581
  previousValue.current = value;
4584
4582
  };
4585
4583
  return updateValueFunctionRef.current = updateFunction, updateFunction;
4586
4584
  }, [
4587
- change$,
4585
+ editorActor,
4588
4586
  keyGenerator,
4589
4587
  portableTextEditor,
4590
4588
  readOnly,
@@ -4653,9 +4651,9 @@ function _updateBlock(slateEditor, currentBlock, oldBlock, currentBlockIndex) {
4653
4651
  }
4654
4652
  const debug$4 = debugWithName("component:PortableTextEditor:Synchronizer"), debugVerbose$1 = debug$4.enabled && !1, FLUSH_PATCHES_THROTTLED_MS = process.env.NODE_ENV === "test" ? 500 : 1e3;
4655
4653
  function Synchronizer(props) {
4656
- const portableTextEditor = usePortableTextEditor(), keyGenerator = usePortableTextEditorKeyGenerator(), readOnly = usePortableTextEditorReadOnlyStatus(), { change$, getValue, onChange, value } = props, pendingPatches = useRef([]), syncValue = useSyncValue({
4654
+ const portableTextEditor = usePortableTextEditor(), keyGenerator = usePortableTextEditorKeyGenerator(), readOnly = usePortableTextEditorReadOnlyStatus(), { editorActor, getValue, onChange, value } = props, pendingPatches = useRef([]), syncValue = useSyncValue({
4655
+ editorActor,
4657
4656
  keyGenerator,
4658
- onChange,
4659
4657
  portableTextEditor,
4660
4658
  readOnly
4661
4659
  }), slateEditor = useSlate();
@@ -4667,14 +4665,14 @@ function Synchronizer(props) {
4667
4665
  debug$4("Flushing pending patches"), debugVerbose$1 && debug$4(`Patches:
4668
4666
  ${JSON.stringify(pendingPatches.current, null, 2)}`);
4669
4667
  const snapshot = getValue();
4670
- change$.next({
4668
+ editorActor.send({
4671
4669
  type: "mutation",
4672
4670
  patches: pendingPatches.current,
4673
4671
  snapshot
4674
4672
  }), pendingPatches.current = [];
4675
4673
  }
4676
4674
  IS_PROCESSING_LOCAL_CHANGES.set(slateEditor, !1);
4677
- }, [slateEditor, getValue, change$]), onFlushPendingPatchesThrottled = useMemo(() => throttle(
4675
+ }, [editorActor, slateEditor, getValue]), onFlushPendingPatchesThrottled = useMemo(() => throttle(
4678
4676
  () => {
4679
4677
  if (Editor.isNormalizing(slateEditor)) {
4680
4678
  onFlushPendingPatches();
@@ -4691,34 +4689,174 @@ ${JSON.stringify(pendingPatches.current, null, 2)}`);
4691
4689
  useEffect(() => () => {
4692
4690
  onFlushPendingPatches();
4693
4691
  }, [onFlushPendingPatches]), useEffect(() => {
4694
- debug$4("Subscribing to editor changes$");
4695
- const sub = change$.subscribe((next) => {
4696
- switch (next.type) {
4692
+ debug$4("Subscribing to editor changes");
4693
+ const sub = editorActor.on("*", (event) => {
4694
+ switch (event.type) {
4697
4695
  case "patch":
4698
- IS_PROCESSING_LOCAL_CHANGES.set(slateEditor, !0), pendingPatches.current.push(next.patch), onFlushPendingPatchesThrottled(), onChange(next);
4696
+ IS_PROCESSING_LOCAL_CHANGES.set(slateEditor, !0), pendingPatches.current.push(event.patch), onFlushPendingPatchesThrottled(), onChange(event);
4697
+ break;
4698
+ case "loading": {
4699
+ onChange({ type: "loading", isLoading: !0 });
4700
+ break;
4701
+ }
4702
+ case "done loading": {
4703
+ onChange({ type: "loading", isLoading: !1 });
4704
+ break;
4705
+ }
4706
+ case "offline": {
4707
+ onChange({ type: "connection", value: "offline" });
4708
+ break;
4709
+ }
4710
+ case "online": {
4711
+ onChange({ type: "connection", value: "online" });
4712
+ break;
4713
+ }
4714
+ case "value changed": {
4715
+ onChange({ type: "value", value: event.value });
4716
+ break;
4717
+ }
4718
+ case "invalid value": {
4719
+ onChange({
4720
+ type: "invalidValue",
4721
+ resolution: event.resolution,
4722
+ value: event.value
4723
+ });
4724
+ break;
4725
+ }
4726
+ case "error": {
4727
+ onChange({
4728
+ ...event,
4729
+ level: "warning"
4730
+ });
4699
4731
  break;
4732
+ }
4700
4733
  default:
4701
- onChange(next);
4734
+ onChange(event);
4702
4735
  }
4703
4736
  });
4704
4737
  return () => {
4705
- debug$4("Unsubscribing to changes$"), sub.unsubscribe();
4738
+ debug$4("Unsubscribing to changes"), sub.unsubscribe();
4706
4739
  };
4707
- }, [change$, onChange, onFlushPendingPatchesThrottled, slateEditor]);
4740
+ }, [editorActor, onFlushPendingPatchesThrottled, slateEditor]);
4708
4741
  const handleOnline = useCallback(() => {
4709
- debug$4("Editor is online, syncing from props.value"), change$.next({ type: "connection", value: "online" }), syncValue(value);
4710
- }, [change$, syncValue, value]), handleOffline = useCallback(() => {
4711
- debug$4("Editor is offline"), change$.next({ type: "connection", value: "offline" });
4712
- }, [change$]);
4713
- useEffect(() => (portableTextEditor.props.patches$ && (window.addEventListener("online", handleOnline), window.addEventListener("offline", handleOffline)), () => {
4714
- portableTextEditor.props.patches$ && (window.removeEventListener("online", handleOnline), window.removeEventListener("offline", handleOffline));
4715
- }));
4742
+ debug$4("Editor is online, syncing from props.value"), syncValue(value);
4743
+ }, [syncValue, value]);
4744
+ useEffect(() => {
4745
+ const subscription = editorActor.on("online", () => {
4746
+ portableTextEditor.props.patches$ && handleOnline();
4747
+ });
4748
+ return () => {
4749
+ subscription.unsubscribe();
4750
+ };
4751
+ }, [editorActor]);
4716
4752
  const isInitialValueFromProps = useRef(!0);
4717
4753
  return useEffect(() => {
4718
- debug$4("Value from props changed, syncing new value"), syncValue(value), isInitialValueFromProps.current && (change$.next({ type: "loading", isLoading: !1 }), change$.next({ type: "ready" }), isInitialValueFromProps.current = !1);
4719
- }, [change$, syncValue, value]), null;
4754
+ debug$4("Value from props changed, syncing new value"), syncValue(value), isInitialValueFromProps.current && (editorActor.send({ type: "ready" }), isInitialValueFromProps.current = !1);
4755
+ }, [editorActor, syncValue, value]), null;
4720
4756
  }
4721
- const PortableTextEditorSelectionContext = createContext(null), usePortableTextEditorSelection = () => {
4757
+ const networkLogic = fromCallback(({ sendBack }) => {
4758
+ const onlineHandler = () => {
4759
+ sendBack({ type: "online" });
4760
+ }, offlineHandler = () => {
4761
+ sendBack({ type: "offline" });
4762
+ };
4763
+ return window.addEventListener("online", onlineHandler), window.addEventListener("offline", offlineHandler), () => {
4764
+ window.removeEventListener("online", onlineHandler), window.removeEventListener("offline", offlineHandler);
4765
+ };
4766
+ }), editorMachine = setup({
4767
+ types: {
4768
+ context: {},
4769
+ events: {},
4770
+ emitted: {}
4771
+ },
4772
+ actions: {
4773
+ "emit patch event": emit(({ event }) => (assertEvent(event, "patch"), event)),
4774
+ "emit mutation event": emit(({ event }) => (assertEvent(event, "mutation"), event)),
4775
+ "defer event": assign({
4776
+ pendingEvents: ({ context, event }) => (assertEvent(event, ["patch", "mutation"]), [...context.pendingEvents, event])
4777
+ }),
4778
+ "emit pending events": enqueueActions(({ context, enqueue }) => {
4779
+ for (const event of context.pendingEvents)
4780
+ enqueue(emit(event));
4781
+ }),
4782
+ "clear pending events": assign({
4783
+ pendingEvents: []
4784
+ })
4785
+ },
4786
+ actors: {
4787
+ networkLogic
4788
+ }
4789
+ }).createMachine({
4790
+ id: "editor",
4791
+ context: {
4792
+ pendingEvents: []
4793
+ },
4794
+ invoke: {
4795
+ id: "networkLogic",
4796
+ src: "networkLogic"
4797
+ },
4798
+ on: {
4799
+ ready: { actions: emit(({ event }) => event) },
4800
+ unset: { actions: emit(({ event }) => event) },
4801
+ "value changed": { actions: emit(({ event }) => event) },
4802
+ "invalid value": { actions: emit(({ event }) => event) },
4803
+ error: { actions: emit(({ event }) => event) },
4804
+ selection: { actions: emit(({ event }) => event) },
4805
+ blur: { actions: emit(({ event }) => event) },
4806
+ focus: { actions: emit(({ event }) => event) },
4807
+ online: { actions: emit({ type: "online" }) },
4808
+ offline: { actions: emit({ type: "offline" }) },
4809
+ loading: { actions: emit({ type: "loading" }) },
4810
+ "done loading": { actions: emit({ type: "done loading" }) }
4811
+ },
4812
+ initial: "pristine",
4813
+ states: {
4814
+ pristine: {
4815
+ initial: "idle",
4816
+ states: {
4817
+ idle: {
4818
+ on: {
4819
+ normalizing: {
4820
+ target: "normalizing"
4821
+ },
4822
+ patch: {
4823
+ actions: "defer event",
4824
+ target: "#editor.dirty"
4825
+ },
4826
+ mutation: {
4827
+ actions: "defer event",
4828
+ target: "#editor.dirty"
4829
+ }
4830
+ }
4831
+ },
4832
+ normalizing: {
4833
+ on: {
4834
+ "done normalizing": {
4835
+ target: "idle"
4836
+ },
4837
+ patch: {
4838
+ actions: "defer event"
4839
+ },
4840
+ mutation: {
4841
+ actions: "defer event"
4842
+ }
4843
+ }
4844
+ }
4845
+ }
4846
+ },
4847
+ dirty: {
4848
+ entry: ["emit pending events", "clear pending events"],
4849
+ on: {
4850
+ patch: {
4851
+ actions: "emit patch event"
4852
+ },
4853
+ mutation: {
4854
+ actions: "emit mutation event"
4855
+ }
4856
+ }
4857
+ }
4858
+ }
4859
+ }), PortableTextEditorSelectionContext = createContext(null), usePortableTextEditorSelection = () => {
4722
4860
  const selection = useContext(PortableTextEditorSelectionContext);
4723
4861
  if (selection === void 0)
4724
4862
  throw new Error(
@@ -4727,21 +4865,26 @@ const PortableTextEditorSelectionContext = createContext(null), usePortableTextE
4727
4865
  return selection;
4728
4866
  }, debug$3 = debugWithName("component:PortableTextEditor:SelectionProvider"), debugVerbose = debug$3.enabled && !1;
4729
4867
  function PortableTextEditorSelectionProvider(props) {
4730
- const { change$ } = props, [selection, setSelection] = useState(null);
4868
+ const [selection, setSelection] = useState(null);
4731
4869
  return useEffect(() => {
4732
- debug$3("Subscribing to selection changes$");
4733
- const subscription = change$.subscribe((next) => {
4734
- next.type === "selection" && startTransition(() => {
4735
- debugVerbose && debug$3("Setting selection"), setSelection(next.selection);
4870
+ debug$3("Subscribing to selection changes");
4871
+ const subscription = props.editorActor.on("selection", (event) => {
4872
+ startTransition(() => {
4873
+ debugVerbose && debug$3("Setting selection"), setSelection(event.selection);
4736
4874
  });
4737
4875
  });
4738
4876
  return () => {
4739
- debug$3("Unsubscribing to selection changes$"), subscription.unsubscribe();
4877
+ debug$3("Unsubscribing to selection changes"), subscription.unsubscribe();
4740
4878
  };
4741
- }, [change$]), /* @__PURE__ */ jsx(PortableTextEditorSelectionContext.Provider, { value: selection, children: props.children });
4879
+ }, [props.editorActor]), /* @__PURE__ */ jsx(PortableTextEditorSelectionContext.Provider, { value: selection, children: props.children });
4742
4880
  }
4743
4881
  const debug$2 = debugWithName("component:PortableTextEditor");
4744
4882
  class PortableTextEditor extends Component {
4883
+ /**
4884
+ * @internal
4885
+ * Don't use this API directly. It's subject to change.
4886
+ */
4887
+ editorActor;
4745
4888
  /**
4746
4889
  * An observable of all the editor changes.
4747
4890
  */
@@ -4759,7 +4902,7 @@ class PortableTextEditor extends Component {
4759
4902
  throw new Error('PortableTextEditor: missing "schemaType" property');
4760
4903
  props.incomingPatches$ && console.warn(
4761
4904
  "The prop 'incomingPatches$' is deprecated and renamed to 'patches$'"
4762
- ), this.change$.next({ type: "loading", isLoading: !0 }), this.schemaTypes = getPortableTextMemberSchemaTypes(
4905
+ ), this.editorActor = createActor(editorMachine), this.editorActor.start(), this.schemaTypes = getPortableTextMemberSchemaTypes(
4763
4906
  props.schemaType.hasOwnProperty("jsonType") ? props.schemaType : compileType(props.schemaType)
4764
4907
  );
4765
4908
  }
@@ -4776,7 +4919,7 @@ class PortableTextEditor extends Component {
4776
4919
  return this.editable.getValue();
4777
4920
  };
4778
4921
  render() {
4779
- const { onChange, value, children, patches$, incomingPatches$ } = this.props, { change$ } = this, _patches$ = incomingPatches$ || patches$, maxBlocks = typeof this.props.maxBlocks > "u" ? void 0 : Number.parseInt(this.props.maxBlocks.toString(), 10) || void 0, readOnly = !!this.props.readOnly, keyGenerator = this.props.keyGenerator || defaultKeyGenerator;
4922
+ const { value, children, patches$, incomingPatches$ } = this.props, _patches$ = incomingPatches$ || patches$, maxBlocks = typeof this.props.maxBlocks > "u" ? void 0 : Number.parseInt(this.props.maxBlocks.toString(), 10) || void 0, readOnly = !!this.props.readOnly, keyGenerator = this.props.keyGenerator || defaultKeyGenerator;
4780
4923
  return /* @__PURE__ */ jsx(
4781
4924
  SlateContainer,
4782
4925
  {
@@ -4785,18 +4928,26 @@ class PortableTextEditor extends Component {
4785
4928
  patches$: _patches$,
4786
4929
  portableTextEditor: this,
4787
4930
  readOnly,
4788
- children: /* @__PURE__ */ jsx(PortableTextEditorKeyGeneratorContext.Provider, { value: keyGenerator, children: /* @__PURE__ */ jsx(PortableTextEditorContext.Provider, { value: this, children: /* @__PURE__ */ jsx(PortableTextEditorReadOnlyContext.Provider, { value: readOnly, children: /* @__PURE__ */ jsxs(PortableTextEditorSelectionProvider, { change$, children: [
4789
- /* @__PURE__ */ jsx(
4790
- Synchronizer,
4791
- {
4792
- change$,
4793
- getValue: this.getValue,
4794
- onChange,
4795
- value
4796
- }
4797
- ),
4798
- children
4799
- ] }) }) }) })
4931
+ children: /* @__PURE__ */ jsx(PortableTextEditorKeyGeneratorContext.Provider, { value: keyGenerator, children: /* @__PURE__ */ jsx(PortableTextEditorContext.Provider, { value: this, children: /* @__PURE__ */ jsx(PortableTextEditorReadOnlyContext.Provider, { value: readOnly, children: /* @__PURE__ */ jsxs(
4932
+ PortableTextEditorSelectionProvider,
4933
+ {
4934
+ editorActor: this.editorActor,
4935
+ children: [
4936
+ /* @__PURE__ */ jsx(
4937
+ Synchronizer,
4938
+ {
4939
+ editorActor: this.editorActor,
4940
+ getValue: this.getValue,
4941
+ onChange: (change) => {
4942
+ this.props.onChange(change), this.change$.next(change);
4943
+ },
4944
+ value
4945
+ }
4946
+ ),
4947
+ children
4948
+ ]
4949
+ }
4950
+ ) }) }) })
4800
4951
  }
4801
4952
  );
4802
4953
  }
@@ -4826,7 +4977,7 @@ class PortableTextEditor extends Component {
4826
4977
  static insertBlock = (editor, type, value) => editor.editable?.insertBlock(type, value);
4827
4978
  static insertBreak = (editor) => editor.editable?.insertBreak();
4828
4979
  static isVoid = (editor, element) => editor.editable?.isVoid(element);
4829
- static isObjectPath = (editor, path) => {
4980
+ static isObjectPath = (_editor, path) => {
4830
4981
  if (!path || !Array.isArray(path)) return !1;
4831
4982
  const isChildObjectEditPath = path.length > 3 && path[1] === "children";
4832
4983
  return path.length > 1 && path[1] !== "children" || isChildObjectEditPath;
@@ -4906,20 +5057,19 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
4906
5057
  useEffect(() => {
4907
5058
  if (!shouldTrackSelectionAndFocus)
4908
5059
  return;
4909
- const sub = portableTextEditor.change$.subscribe((next) => {
4910
- if (next.type === "blur") {
4911
- setFocused(!1), setSelected(!1);
4912
- return;
5060
+ const onBlur = portableTextEditor.editorActor.on("blur", () => {
5061
+ setFocused(!1), setSelected(!1);
5062
+ }), onFocus = portableTextEditor.editorActor.on("focus", () => {
5063
+ const sel = PortableTextEditor.getSelection(portableTextEditor);
5064
+ sel && isEqual(sel.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) && setFocused(!0), setSelectedFromRange();
5065
+ }), onSelection = portableTextEditor.editorActor.on(
5066
+ "selection",
5067
+ (event) => {
5068
+ event.selection && isEqual(event.selection.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) ? setFocused(!0) : setFocused(!1), setSelectedFromRange();
4913
5069
  }
4914
- if (next.type === "focus") {
4915
- const sel = PortableTextEditor.getSelection(portableTextEditor);
4916
- sel && isEqual(sel.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) && setFocused(!0), setSelectedFromRange();
4917
- return;
4918
- }
4919
- next.type === "selection" && (next.selection && isEqual(next.selection.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) ? setFocused(!0) : setFocused(!1), setSelectedFromRange());
4920
- });
5070
+ );
4921
5071
  return () => {
4922
- sub.unsubscribe();
5072
+ onBlur.unsubscribe(), onFocus.unsubscribe(), onSelection.unsubscribe();
4923
5073
  };
4924
5074
  }, [
4925
5075
  path,
@@ -5070,9 +5220,9 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5070
5220
  forwardedRef,
5071
5221
  () => ref.current
5072
5222
  );
5073
- const rangeDecorationsRef = useRef(rangeDecorations), { change$, schemaTypes } = portableTextEditor, slateEditor = useSlate(), blockTypeName = schemaTypes.block.name, withInsertData = useMemo(
5074
- () => createWithInsertData(change$, schemaTypes, keyGenerator),
5075
- [change$, keyGenerator, schemaTypes]
5223
+ const rangeDecorationsRef = useRef(rangeDecorations), { editorActor, schemaTypes } = portableTextEditor, slateEditor = useSlate(), blockTypeName = schemaTypes.block.name, withInsertData = useMemo(
5224
+ () => createWithInsertData(editorActor, schemaTypes, keyGenerator),
5225
+ [editorActor, keyGenerator, schemaTypes]
5076
5226
  ), withHotKeys = useMemo(
5077
5227
  () => createWithHotkeys(schemaTypes, portableTextEditor, hotkeys),
5078
5228
  [hotkeys, portableTextEditor, schemaTypes]
@@ -5145,10 +5295,13 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5145
5295
  `Normalized selection from props ${JSON.stringify(normalizedSelection)}`
5146
5296
  );
5147
5297
  const slateRange = toSlateRange(normalizedSelection, slateEditor);
5148
- slateRange && (Transforms.select(slateEditor, slateRange), slateEditor.operations.some((o) => o.type === "set_selection") || change$.next({ type: "selection", selection: normalizedSelection }), slateEditor.onChange());
5298
+ slateRange && (Transforms.select(slateEditor, slateRange), slateEditor.operations.some((o) => o.type === "set_selection") || editorActor.send({
5299
+ type: "selection",
5300
+ selection: normalizedSelection
5301
+ }), slateEditor.onChange());
5149
5302
  }
5150
5303
  }
5151
- }, [propsSelection, slateEditor, blockTypeName, change$]), syncRangeDecorations = useCallback(
5304
+ }, [editorActor, propsSelection, slateEditor]), syncRangeDecorations = useCallback(
5152
5305
  (operation) => {
5153
5306
  if (rangeDecorations && rangeDecorations.length > 0) {
5154
5307
  const newSlateRanges = [];
@@ -5192,23 +5345,17 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5192
5345
  [portableTextEditor, rangeDecorations, schemaTypes, slateEditor]
5193
5346
  );
5194
5347
  useEffect(() => {
5195
- const sub = change$.subscribe((next) => {
5196
- switch (next.type) {
5197
- case "ready":
5198
- restoreSelectionFromProps();
5199
- break;
5200
- case "invalidValue":
5201
- setHasInvalidValue(!0);
5202
- break;
5203
- case "value":
5204
- setHasInvalidValue(!1);
5205
- break;
5206
- }
5348
+ const onReady = editorActor.on("ready", () => {
5349
+ restoreSelectionFromProps();
5350
+ }), onInvalidValue = editorActor.on("invalid value", () => {
5351
+ setHasInvalidValue(!0);
5352
+ }), onValueChanged = editorActor.on("value changed", () => {
5353
+ setHasInvalidValue(!1);
5207
5354
  });
5208
5355
  return () => {
5209
- sub.unsubscribe();
5356
+ onReady.unsubscribe(), onInvalidValue.unsubscribe(), onValueChanged.unsubscribe();
5210
5357
  };
5211
- }, [change$, restoreSelectionFromProps]), useEffect(() => {
5358
+ }, [editorActor, restoreSelectionFromProps]), useEffect(() => {
5212
5359
  propsSelection && !hasInvalidValue && restoreSelectionFromProps();
5213
5360
  }, [hasInvalidValue, propsSelection, restoreSelectionFromProps]);
5214
5361
  const originalApply = useMemo(() => slateEditor.apply, [slateEditor]), [syncedRangeDecorations, setSyncedRangeDecorations] = useState(!1);
@@ -5239,7 +5386,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5239
5386
  slateEditor.selection,
5240
5387
  schemaTypes
5241
5388
  )?.focus.path || [], onPasteResult = onPaste({ event, value, path, schemaTypes });
5242
- onPasteResult === void 0 ? (debug("No result from custom paste handler, pasting normally"), slateEditor.insertData(event.clipboardData)) : (change$.next({ type: "loading", isLoading: !0 }), Promise.resolve(onPasteResult).then((result) => {
5389
+ onPasteResult === void 0 ? (debug("No result from custom paste handler, pasting normally"), slateEditor.insertData(event.clipboardData)) : (editorActor.send({ type: "loading" }), Promise.resolve(onPasteResult).then((result) => {
5243
5390
  debug("Custom paste function from client resolved", result), !result || !result.insert ? (debug("No result from custom paste handler, pasting normally"), slateEditor.insertData(event.clipboardData)) : result.insert ? slateEditor.insertFragment(
5244
5391
  toSlateValue(result.insert, {
5245
5392
  schemaTypes
@@ -5249,23 +5396,23 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5249
5396
  result
5250
5397
  );
5251
5398
  }).catch((error) => (console.error(error), error)).finally(() => {
5252
- change$.next({ type: "loading", isLoading: !1 });
5399
+ editorActor.send({ type: "done loading" });
5253
5400
  }));
5254
5401
  },
5255
- [change$, onPaste, portableTextEditor, schemaTypes, slateEditor]
5402
+ [onPaste, portableTextEditor, schemaTypes, slateEditor]
5256
5403
  ), handleOnFocus = useCallback(
5257
5404
  (event) => {
5258
5405
  if (onFocus && onFocus(event), !event.isDefaultPrevented()) {
5259
5406
  const selection = PortableTextEditor.getSelection(portableTextEditor);
5260
- selection === null && (Transforms.select(slateEditor, Editor.start(slateEditor, [])), slateEditor.onChange()), change$.next({ type: "focus", event });
5407
+ selection === null && (Transforms.select(slateEditor, Editor.start(slateEditor, [])), slateEditor.onChange()), editorActor.send({ type: "focus", event });
5261
5408
  const newSelection = PortableTextEditor.getSelection(portableTextEditor);
5262
- selection === newSelection && change$.next({
5409
+ selection === newSelection && editorActor.send({
5263
5410
  type: "selection",
5264
5411
  selection
5265
5412
  });
5266
5413
  }
5267
5414
  },
5268
- [onFocus, portableTextEditor, change$, slateEditor]
5415
+ [editorActor, onFocus, portableTextEditor, slateEditor]
5269
5416
  ), handleClick = useCallback(
5270
5417
  (event) => {
5271
5418
  if (onClick && onClick(event), slateEditor.selection && event.target === event.currentTarget) {
@@ -5282,9 +5429,9 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5282
5429
  [onClick, slateEditor]
5283
5430
  ), handleOnBlur = useCallback(
5284
5431
  (event) => {
5285
- onBlur && onBlur(event), event.isPropagationStopped() || change$.next({ type: "blur", event });
5432
+ onBlur && onBlur(event), event.isPropagationStopped() || editorActor.send({ type: "blur", event });
5286
5433
  },
5287
- [change$, onBlur]
5434
+ [editorActor, onBlur]
5288
5435
  ), handleOnBeforeInput = useCallback(
5289
5436
  (event) => {
5290
5437
  onBeforeInput && onBeforeInput(event);
@@ -5331,7 +5478,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5331
5478
  [props, slateEditor]
5332
5479
  ), scrollSelectionIntoViewToSlate = useMemo(() => {
5333
5480
  if (scrollSelectionIntoView !== void 0)
5334
- return scrollSelectionIntoView === null ? noop : (editor, domRange) => {
5481
+ return scrollSelectionIntoView === null ? noop : (_editor, domRange) => {
5335
5482
  scrollSelectionIntoView(portableTextEditor, domRange);
5336
5483
  };
5337
5484
  }, [portableTextEditor, scrollSelectionIntoView]), decorate = useCallback(
@@ -5390,6 +5537,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5390
5537
  export {
5391
5538
  PortableTextEditable,
5392
5539
  PortableTextEditor,
5540
+ editorMachine,
5393
5541
  defaultKeyGenerator as keyGenerator,
5394
5542
  usePortableTextEditor,
5395
5543
  usePortableTextEditorSelection