@portabletext/editor 1.1.0 → 1.1.2

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 (79) hide show
  1. package/README.md +3 -0
  2. package/lib/index.d.mts +1680 -12
  3. package/lib/index.d.ts +1680 -12
  4. package/lib/index.esm.js +310 -162
  5. package/lib/index.esm.js.map +1 -1
  6. package/lib/index.js +310 -163
  7. package/lib/index.js.map +1 -1
  8. package/lib/index.mjs +310 -162
  9. package/lib/index.mjs.map +1 -1
  10. package/package.json +25 -38
  11. package/src/editor/Editable.tsx +51 -50
  12. package/src/editor/PortableTextEditor.tsx +42 -26
  13. package/src/editor/__tests__/PortableTextEditor.test.tsx +11 -12
  14. package/src/editor/__tests__/PortableTextEditorTester.tsx +2 -5
  15. package/src/editor/__tests__/RangeDecorations.test.tsx +6 -7
  16. package/src/editor/__tests__/handleClick.test.tsx +27 -7
  17. package/src/editor/__tests__/insert-block.test.tsx +6 -6
  18. package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +8 -8
  19. package/src/editor/__tests__/self-solving.test.tsx +176 -0
  20. package/src/editor/components/Element.tsx +15 -17
  21. package/src/editor/components/Leaf.tsx +40 -35
  22. package/src/editor/components/SlateContainer.tsx +2 -2
  23. package/src/editor/components/Synchronizer.tsx +62 -34
  24. package/src/editor/editor-machine.ts +195 -0
  25. package/src/editor/hooks/usePortableTextEditor.ts +1 -1
  26. package/src/editor/hooks/usePortableTextEditorSelection.tsx +12 -14
  27. package/src/editor/hooks/useSyncValue.test.tsx +9 -9
  28. package/src/editor/hooks/useSyncValue.ts +16 -19
  29. package/src/editor/nodes/DefaultAnnotation.tsx +1 -2
  30. package/src/editor/nodes/DefaultObject.tsx +1 -1
  31. package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +2 -5
  32. package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +28 -28
  33. package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +17 -17
  34. package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +8 -8
  35. package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +6 -6
  36. package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +2 -2
  37. package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +47 -49
  38. package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +22 -11
  39. package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +9 -9
  40. package/src/editor/plugins/createWithEditableAPI.ts +8 -8
  41. package/src/editor/plugins/createWithHotKeys.ts +8 -12
  42. package/src/editor/plugins/createWithInsertBreak.ts +4 -4
  43. package/src/editor/plugins/createWithInsertData.ts +11 -16
  44. package/src/editor/plugins/createWithMaxBlocks.ts +1 -1
  45. package/src/editor/plugins/createWithObjectKeys.ts +10 -3
  46. package/src/editor/plugins/createWithPatches.ts +9 -12
  47. package/src/editor/plugins/createWithPlaceholderBlock.ts +2 -2
  48. package/src/editor/plugins/createWithPortableTextBlockStyle.ts +13 -5
  49. package/src/editor/plugins/createWithPortableTextLists.ts +3 -4
  50. package/src/editor/plugins/createWithPortableTextMarkModel.ts +24 -10
  51. package/src/editor/plugins/createWithPortableTextSelections.ts +9 -10
  52. package/src/editor/plugins/createWithSchemaTypes.ts +13 -4
  53. package/src/editor/plugins/createWithUndoRedo.ts +3 -7
  54. package/src/editor/plugins/createWithUtils.ts +6 -6
  55. package/src/editor/plugins/index.ts +21 -11
  56. package/src/index.ts +9 -3
  57. package/src/types/editor.ts +33 -33
  58. package/src/types/options.ts +3 -3
  59. package/src/types/slate.ts +4 -4
  60. package/src/utils/__tests__/dmpToOperations.test.ts +4 -4
  61. package/src/utils/__tests__/operationToPatches.test.ts +62 -62
  62. package/src/utils/__tests__/patchToOperations.test.ts +40 -40
  63. package/src/utils/__tests__/ranges.test.ts +2 -2
  64. package/src/utils/__tests__/valueNormalization.test.tsx +14 -2
  65. package/src/utils/__tests__/values.test.ts +17 -17
  66. package/src/utils/applyPatch.ts +10 -12
  67. package/src/utils/getPortableTextMemberSchemaTypes.ts +8 -8
  68. package/src/utils/operationToPatches.ts +5 -9
  69. package/src/utils/paths.ts +5 -5
  70. package/src/utils/ranges.ts +4 -5
  71. package/src/utils/selection.ts +2 -2
  72. package/src/utils/ucs2Indices.ts +2 -2
  73. package/src/utils/validateValue.ts +3 -25
  74. package/src/utils/values.ts +7 -8
  75. package/src/utils/weakMaps.ts +2 -2
  76. package/src/utils/withChanges.ts +1 -1
  77. package/src/utils/withUndoRedo.ts +1 -1
  78. package/src/utils/withoutPatching.ts +1 -1
  79. package/src/editor/__tests__/utils.ts +0 -45
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);
@@ -724,7 +725,6 @@ const EMPTY_ANNOTATIONS = [], inlineBlockStyle = { display: "inline-block" }, El
724
725
  };
725
726
  function DefaultAnnotation(props) {
726
727
  const handleClick = useCallback(
727
- // eslint-disable-next-line no-alert
728
728
  () => alert(JSON.stringify(props.annotation)),
729
729
  [props.annotation]
730
730
  );
@@ -1711,7 +1711,7 @@ function createWithMaxBlocks(maxBlocks) {
1711
1711
  }, editor;
1712
1712
  };
1713
1713
  }
1714
- function createWithObjectKeys(schemaTypes, keyGenerator) {
1714
+ function createWithObjectKeys(editorActor, schemaTypes, keyGenerator) {
1715
1715
  return function(editor) {
1716
1716
  const { apply: apply2, normalizeNode } = editor;
1717
1717
  return editor.apply = (operation) => {
@@ -1747,10 +1747,13 @@ function createWithObjectKeys(schemaTypes, keyGenerator) {
1747
1747
  }, editor.normalizeNode = (entry) => {
1748
1748
  const [node, path] = entry;
1749
1749
  if (Element$1.isElement(node) && node._type === schemaTypes.block.name) {
1750
- 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
+ }
1751
1754
  for (const [child, childPath] of Node.children(editor, path))
1752
1755
  if (!child._key) {
1753
- Transforms.setNodes(editor, { _key: keyGenerator() }, { at: childPath });
1756
+ editorActor.send({ type: "normalizing" }), Transforms.setNodes(editor, { _key: keyGenerator() }, { at: childPath }), editorActor.send({ type: "done normalizing" });
1754
1757
  return;
1755
1758
  }
1756
1759
  }
@@ -2456,7 +2459,7 @@ function toInt(num) {
2456
2459
  const debug$i = debugWithName("applyPatches"), debugVerbose$4 = debug$i.enabled && !0;
2457
2460
  function createApplyPatch(schemaTypes) {
2458
2461
  let previousPatch;
2459
- return function(editor, patch) {
2462
+ return (editor, patch) => {
2460
2463
  let changed = !1;
2461
2464
  debugVerbose$4 && (debug$i(
2462
2465
  `
@@ -2907,7 +2910,7 @@ function findOperationTargetBlock(editor, operation) {
2907
2910
  }
2908
2911
  const debug$g = debugWithName("plugin:withPatches");
2909
2912
  function createWithPatches({
2910
- change$,
2913
+ editorActor,
2911
2914
  patches$,
2912
2915
  patchFunctions,
2913
2916
  readOnly,
@@ -3036,7 +3039,7 @@ function createWithPatches({
3036
3039
  }
3037
3040
  return !editorWasEmpty && editorIsEmpty && ["merge_node", "set_node", "remove_text", "remove_node"].includes(
3038
3041
  operation.type
3039
- ) && (patches = [...patches, unset([])], change$.next({
3042
+ ) && (patches = [...patches, unset([])], editorActor.send({
3040
3043
  type: "unset",
3041
3044
  previousValue: fromSlateValue(
3042
3045
  previousChildren,
@@ -3044,7 +3047,7 @@ function createWithPatches({
3044
3047
  KEY_TO_VALUE_ELEMENT.get(editor)
3045
3048
  )
3046
3049
  })), editorWasEmpty && patches.length > 0 && (patches = [setIfMissing([], []), ...patches]), patches.length > 0 && patches.forEach((patch) => {
3047
- change$.next({
3050
+ editorActor.send({
3048
3051
  type: "patch",
3049
3052
  patch: { ...patch, origin: "local" }
3050
3053
  });
@@ -3080,25 +3083,25 @@ function createWithPlaceholderBlock() {
3080
3083
  };
3081
3084
  }
3082
3085
  const debug$e = debugWithName("plugin:withPortableTextBlockStyle");
3083
- function createWithPortableTextBlockStyle(types) {
3086
+ function createWithPortableTextBlockStyle(editorActor, types) {
3084
3087
  const defaultStyle = types.styles[0].value;
3085
3088
  return function(editor) {
3086
3089
  const { normalizeNode } = editor;
3087
3090
  return editor.normalizeNode = (nodeEntry) => {
3088
- normalizeNode(nodeEntry);
3089
3091
  const [, path] = nodeEntry;
3090
3092
  for (const op of editor.operations)
3091
3093
  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)) {
3092
3094
  const [child] = Editor.node(editor, [op.path[0] + 1, 0]);
3093
3095
  if (Text.isText(child) && child.text === "") {
3094
- debug$e(`Normalizing split node to ${defaultStyle} style`, op), Transforms.setNodes(
3096
+ debug$e(`Normalizing split node to ${defaultStyle} style`, op), editorActor.send({ type: "normalizing" }), Transforms.setNodes(
3095
3097
  editor,
3096
3098
  { style: defaultStyle },
3097
3099
  { at: [op.path[0] + 1], voids: !1 }
3098
- );
3099
- break;
3100
+ ), editorActor.send({ type: "done normalizing" });
3101
+ return;
3100
3102
  }
3101
3103
  }
3104
+ normalizeNode(nodeEntry);
3102
3105
  }, editor.pteHasBlockStyle = (style) => editor.selection ? [
3103
3106
  ...Editor.nodes(editor, {
3104
3107
  at: editor.selection,
@@ -3243,7 +3246,7 @@ function isPortableTextBlock(node) {
3243
3246
  );
3244
3247
  }
3245
3248
  const debug$c = debugWithName("plugin:withPortableTextMarkModel");
3246
- function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3249
+ function createWithPortableTextMarkModel(editorActor, types, keyGenerator) {
3247
3250
  return function(editor) {
3248
3251
  const { apply: apply2, normalizeNode } = editor, decorators = types.decorators.map((t) => t.value), forceNewSelection = () => {
3249
3252
  editor.selection && (Transforms.select(editor, { ...editor.selection }), editor.selection = { ...editor.selection });
@@ -3252,7 +3255,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3252
3255
  editor.selection,
3253
3256
  types
3254
3257
  );
3255
- change$.next({ type: "selection", selection: ptRange });
3258
+ editorActor.send({ type: "selection", selection: ptRange });
3256
3259
  };
3257
3260
  return editor.normalizeNode = (nodeEntry) => {
3258
3261
  const [node, path] = nodeEntry;
@@ -3265,20 +3268,20 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3265
3268
  "Merging spans",
3266
3269
  JSON.stringify(child, null, 2),
3267
3270
  JSON.stringify(nextNode, null, 2)
3268
- ), Transforms.mergeNodes(editor, {
3271
+ ), editorActor.send({ type: "normalizing" }), Transforms.mergeNodes(editor, {
3269
3272
  at: [childPath[0], childPath[1] + 1],
3270
3273
  voids: !0
3271
- });
3274
+ }), editorActor.send({ type: "done normalizing" });
3272
3275
  return;
3273
3276
  }
3274
3277
  }
3275
3278
  }
3276
3279
  if (editor.isTextBlock(node) && !Array.isArray(node.markDefs)) {
3277
- debug$c("Adding .markDefs to block node"), Transforms.setNodes(editor, { markDefs: [] }, { at: path });
3280
+ debug$c("Adding .markDefs to block node"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(editor, { markDefs: [] }, { at: path }), editorActor.send({ type: "done normalizing" });
3278
3281
  return;
3279
3282
  }
3280
3283
  if (editor.isTextSpan(node) && !Array.isArray(node.marks)) {
3281
- debug$c("Adding .marks to span node"), Transforms.setNodes(editor, { marks: [] }, { at: path });
3284
+ debug$c("Adding .marks to span node"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(editor, { marks: [] }, { at: path }), editorActor.send({ type: "done normalizing" });
3282
3285
  return;
3283
3286
  }
3284
3287
  if (editor.isTextSpan(node)) {
@@ -3286,11 +3289,11 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3286
3289
  (mark) => !decorators2.includes(mark)
3287
3290
  );
3288
3291
  if (editor.isTextBlock(block) && node.text === "" && annotations && annotations.length > 0) {
3289
- debug$c("Removing annotations from empty span node"), Transforms.setNodes(
3292
+ debug$c("Removing annotations from empty span node"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(
3290
3293
  editor,
3291
3294
  { marks: node.marks?.filter((mark) => decorators2.includes(mark)) },
3292
3295
  { at: path }
3293
- );
3296
+ ), editorActor.send({ type: "done normalizing" });
3294
3297
  return;
3295
3298
  }
3296
3299
  }
@@ -3300,7 +3303,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3300
3303
  if (editor.isTextSpan(child)) {
3301
3304
  const marks = child.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators2.includes(mark) && !node.markDefs?.find((def) => def._key === mark));
3302
3305
  if (orphanedAnnotations.length > 0) {
3303
- debug$c("Removing orphaned annotations from span node"), Transforms.setNodes(
3306
+ debug$c("Removing orphaned annotations from span node"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(
3304
3307
  editor,
3305
3308
  {
3306
3309
  marks: marks.filter(
@@ -3308,7 +3311,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3308
3311
  )
3309
3312
  },
3310
3313
  { at: childPath }
3311
- );
3314
+ ), editorActor.send({ type: "done normalizing" });
3312
3315
  return;
3313
3316
  }
3314
3317
  }
@@ -3320,7 +3323,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3320
3323
  (decorator) => decorator.value
3321
3324
  ), marks = node.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators2.includes(mark) && !block.markDefs?.find((def) => def._key === mark));
3322
3325
  if (orphanedAnnotations.length > 0) {
3323
- debug$c("Removing orphaned annotations from span node"), Transforms.setNodes(
3326
+ debug$c("Removing orphaned annotations from span node"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(
3324
3327
  editor,
3325
3328
  {
3326
3329
  marks: marks.filter(
@@ -3328,7 +3331,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3328
3331
  )
3329
3332
  },
3330
3333
  { at: path }
3331
- );
3334
+ ), editorActor.send({ type: "done normalizing" });
3332
3335
  return;
3333
3336
  }
3334
3337
  }
@@ -3337,20 +3340,23 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3337
3340
  const markDefs = node.markDefs ?? [], markDefKeys = /* @__PURE__ */ new Set(), newMarkDefs = [];
3338
3341
  for (const markDef of markDefs)
3339
3342
  markDefKeys.has(markDef._key) || (markDefKeys.add(markDef._key), newMarkDefs.push(markDef));
3340
- markDefs.length !== newMarkDefs.length && (debug$c("Removing duplicate markDefs"), Transforms.setNodes(editor, { markDefs: newMarkDefs }, { at: path }));
3343
+ if (markDefs.length !== newMarkDefs.length) {
3344
+ debug$c("Removing duplicate markDefs"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(editor, { markDefs: newMarkDefs }, { at: path }), editorActor.send({ type: "done normalizing" });
3345
+ return;
3346
+ }
3341
3347
  }
3342
3348
  if (editor.isTextBlock(node) && !editor.operations.some(
3343
3349
  (op) => op.type === "merge_node" && "markDefs" in op.properties && op.path.length === 1
3344
3350
  )) {
3345
3351
  const newMarkDefs = (node.markDefs || []).filter((def) => node.children.find((child) => Text.isText(child) && Array.isArray(child.marks) && child.marks.includes(def._key)));
3346
3352
  if (node.markDefs && !isEqual(newMarkDefs, node.markDefs)) {
3347
- debug$c("Removing markDef not in use"), Transforms.setNodes(
3353
+ debug$c("Removing markDef not in use"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(
3348
3354
  editor,
3349
3355
  {
3350
3356
  markDefs: newMarkDefs
3351
3357
  },
3352
3358
  { at: path }
3353
- );
3359
+ ), editorActor.send({ type: "done normalizing" });
3354
3360
  return;
3355
3361
  }
3356
3362
  }
@@ -3583,7 +3589,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3583
3589
  };
3584
3590
  }
3585
3591
  const debug$b = debugWithName("plugin:withPortableTextSelections"), debugVerbose$2 = debug$b.enabled && !1;
3586
- function createWithPortableTextSelections(change$, types) {
3592
+ function createWithPortableTextSelections(editorActor, types) {
3587
3593
  let prevSelection = null;
3588
3594
  return function(editor) {
3589
3595
  const emitPortableTextSelection = () => {
@@ -3602,7 +3608,7 @@ function createWithPortableTextSelections(change$, types) {
3602
3608
  `Emitting selection ${JSON.stringify(ptRange || null)} (${JSON.stringify(
3603
3609
  editor.selection
3604
3610
  )})`
3605
- ), ptRange ? change$.next({ type: "selection", selection: ptRange }) : change$.next({ type: "selection", selection: null });
3611
+ ), ptRange ? editorActor.send({ type: "selection", selection: ptRange }) : editorActor.send({ type: "selection", selection: null });
3606
3612
  }
3607
3613
  prevSelection = editor.selection;
3608
3614
  }, { onChange } = editor;
@@ -3614,27 +3620,30 @@ function createWithPortableTextSelections(change$, types) {
3614
3620
  }
3615
3621
  const debug$a = debugWithName("plugin:withSchemaTypes");
3616
3622
  function createWithSchemaTypes({
3623
+ editorActor,
3617
3624
  schemaTypes,
3618
3625
  keyGenerator
3619
3626
  }) {
3620
3627
  return function(editor) {
3621
- editor.isTextBlock = (value) => isPortableTextTextBlock(value) && value._type === schemaTypes.block.name, editor.isTextSpan = (value) => isPortableTextSpan$1(value) && value._type == schemaTypes.span.name, editor.isListBlock = (value) => isPortableTextListBlock(value) && value._type === schemaTypes.block.name, editor.isVoid = (element) => schemaTypes.block.name !== element._type && (schemaTypes.blockObjects.map((obj) => obj.name).includes(element._type) || schemaTypes.inlineObjects.map((obj) => obj.name).includes(element._type)), editor.isInline = (element) => schemaTypes.inlineObjects.map((obj) => obj.name).includes(element._type) && "__inline" in element && element.__inline === !0;
3628
+ editor.isTextBlock = (value) => isPortableTextTextBlock(value) && value._type === schemaTypes.block.name, editor.isTextSpan = (value) => isPortableTextSpan$1(value) && value._type === schemaTypes.span.name, editor.isListBlock = (value) => isPortableTextListBlock(value) && value._type === schemaTypes.block.name, editor.isVoid = (element) => schemaTypes.block.name !== element._type && (schemaTypes.blockObjects.map((obj) => obj.name).includes(element._type) || schemaTypes.inlineObjects.map((obj) => obj.name).includes(element._type)), editor.isInline = (element) => schemaTypes.inlineObjects.map((obj) => obj.name).includes(element._type) && "__inline" in element && element.__inline === !0;
3622
3629
  const { normalizeNode } = editor;
3623
3630
  return editor.normalizeNode = (entry) => {
3624
3631
  const [node, path] = entry;
3625
3632
  if (node._type === void 0 && path.length === 2) {
3626
3633
  debug$a("Setting span type on text node without a type");
3627
3634
  const span = node, key = span._key || keyGenerator();
3628
- Transforms.setNodes(
3635
+ editorActor.send({ type: "normalizing" }), Transforms.setNodes(
3629
3636
  editor,
3630
3637
  { ...span, _type: schemaTypes.span.name, _key: key },
3631
3638
  { at: path }
3632
- );
3639
+ ), editorActor.send({ type: "done normalizing" });
3640
+ return;
3633
3641
  }
3634
3642
  if (node._key === void 0 && (path.length === 1 || path.length === 2)) {
3635
3643
  debug$a("Setting missing key on child node without a key");
3636
3644
  const key = keyGenerator();
3637
- Transforms.setNodes(editor, { _key: key }, { at: path });
3645
+ editorActor.send({ type: "normalizing" }), Transforms.setNodes(editor, { _key: key }, { at: path }), editorActor.send({ type: "done normalizing" });
3646
+ return;
3638
3647
  }
3639
3648
  normalizeNode(entry);
3640
3649
  }, editor;
@@ -3656,7 +3665,7 @@ function createWithUtils({
3656
3665
  return;
3657
3666
  }
3658
3667
  const { focus } = selection, focusOffset = focus.offset, charsBefore = textNode.text.slice(0, focusOffset), charsAfter = textNode.text.slice(focusOffset, -1), isEmpty = (str) => str.match(/\s/g), whiteSpaceBeforeIndex = charsBefore.split("").reverse().findIndex((str) => isEmpty(str)), newStartOffset = whiteSpaceBeforeIndex > -1 ? charsBefore.length - whiteSpaceBeforeIndex : 0, whiteSpaceAfterIndex = charsAfter.split("").findIndex((obj) => isEmpty(obj)), newEndOffset = charsBefore.length + (whiteSpaceAfterIndex > -1 ? whiteSpaceAfterIndex : charsAfter.length + 1);
3659
- if (!(newStartOffset === newEndOffset || isNaN(newStartOffset) || isNaN(newEndOffset))) {
3668
+ if (!(newStartOffset === newEndOffset || Number.isNaN(newStartOffset) || Number.isNaN(newEndOffset))) {
3660
3669
  debug$9("pteExpandToWord: Expanding to focused word"), Transforms.setSelection(editor, {
3661
3670
  anchor: { ...selection.anchor, offset: newStartOffset },
3662
3671
  focus: { ...selection.focus, offset: newEndOffset }
@@ -3942,22 +3951,6 @@ function validateValue(value, types, keyGenerator) {
3942
3951
  }
3943
3952
  }, !0;
3944
3953
  }
3945
- if (blk.markDefs && !Array.isArray(blk.markDefs))
3946
- return resolution = {
3947
- patches: [
3948
- set({ ...textBlock, markDefs: EMPTY_MARKDEFS }, [
3949
- { _key: textBlock._key }
3950
- ])
3951
- ],
3952
- description: "Block has invalid required property 'markDefs'.",
3953
- action: "Add empty markDefs array",
3954
- item: textBlock,
3955
- i18n: {
3956
- description: "inputs.portable-text.invalid-value.missing-or-invalid-markdefs.description",
3957
- action: "inputs.portable-text.invalid-value.missing-or-invalid-markdefs.action",
3958
- values: { key: textBlock._key }
3959
- }
3960
- }, !0;
3961
3954
  const allUsedMarks = uniq(
3962
3955
  flatten(
3963
3956
  textBlock.children.filter((cld) => cld._type === types.span.name).map((cld) => cld.marks || [])
@@ -4102,7 +4095,7 @@ function validateValue(value, types, keyGenerator) {
4102
4095
  }) && (valid = !1), { valid, resolution, value });
4103
4096
  }
4104
4097
  const debug$7 = debugWithName("plugin:withInsertData");
4105
- function createWithInsertData(change$, schemaTypes, keyGenerator) {
4098
+ function createWithInsertData(editorActor, schemaTypes, keyGenerator) {
4106
4099
  return function(editor) {
4107
4100
  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(`
4108
4101
 
@@ -4156,9 +4149,8 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
4156
4149
  ), validation = validateValue(parsed, schemaTypes, keyGenerator);
4157
4150
  if (!validation.valid && !validation.resolution?.autoResolve) {
4158
4151
  const errorDescription = `${validation.resolution?.description}`;
4159
- return change$.next({
4152
+ return editorActor.send({
4160
4153
  type: "error",
4161
- level: "warning",
4162
4154
  name: "pasteError",
4163
4155
  description: errorDescription,
4164
4156
  data: validation
@@ -4171,7 +4163,6 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
4171
4163
  }, editor.insertTextOrHTMLData = (data) => {
4172
4164
  if (!editor.selection)
4173
4165
  return debug$7("No selection, not inserting"), !1;
4174
- change$.next({ type: "loading", isLoading: !0 });
4175
4166
  const html = data.getData("text/html"), text = data.getData("text/plain");
4176
4167
  if (html || text) {
4177
4168
  debug$7("Inserting data", data);
@@ -4202,9 +4193,8 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
4202
4193
  const errorDescription = `Could not validate the resulting portable text to insert.
4203
4194
  ${validation.resolution?.description}
4204
4195
  Try to insert as plain text (shift-paste) instead.`;
4205
- return change$.next({
4196
+ return editorActor.send({
4206
4197
  type: "error",
4207
- level: "warning",
4208
4198
  name: "pasteError",
4209
4199
  description: errorDescription,
4210
4200
  data: validation
@@ -4212,9 +4202,9 @@ Try to insert as plain text (shift-paste) instead.`;
4212
4202
  }
4213
4203
  return debug$7(
4214
4204
  `Inserting ${insertedType} fragment at ${JSON.stringify(editor.selection)}`
4215
- ), _insertFragment(editor, fragment, schemaTypes), change$.next({ type: "loading", isLoading: !1 }), !0;
4205
+ ), _insertFragment(editor, fragment, schemaTypes), !0;
4216
4206
  }
4217
- return change$.next({ type: "loading", isLoading: !1 }), !1;
4207
+ return !1;
4218
4208
  }, editor.insertData = (data) => {
4219
4209
  editor.insertPortableTextData(data) || editor.insertTextOrHTMLData(data);
4220
4210
  }, editor.insertFragmentData = (data) => {
@@ -4258,10 +4248,7 @@ function _regenerateKeys(editor, fragment, keyGenerator, spanTypeName, editorTyp
4258
4248
  return newNode.children = newNode.children.map(
4259
4249
  (child) => child._type === spanTypeName && editor.isTextSpan(child) ? {
4260
4250
  ...child,
4261
- marks: child.marks && child.marks.includes(oldKey) ? (
4262
- // eslint-disable-next-line max-nested-callbacks
4263
- [...child.marks].filter((mark) => mark !== oldKey).concat(newKey)
4264
- ) : child.marks
4251
+ marks: child.marks && child.marks.includes(oldKey) ? [...child.marks].filter((mark) => mark !== oldKey).concat(newKey) : child.marks
4265
4252
  } : child
4266
4253
  ), { ...def, _key: newKey };
4267
4254
  });
@@ -4304,18 +4291,26 @@ function _insertFragment(editor, fragment, schemaTypes) {
4304
4291
  }), editor.onChange();
4305
4292
  }
4306
4293
  const originalFnMap = /* @__PURE__ */ new WeakMap(), withPlugins = (editor, options) => {
4307
- const e = editor, { keyGenerator, portableTextEditor, patches$, readOnly, maxBlocks } = options, { schemaTypes, change$ } = portableTextEditor;
4294
+ const e = editor, { keyGenerator, portableTextEditor, patches$, readOnly, maxBlocks } = options, { editorActor, schemaTypes } = portableTextEditor;
4308
4295
  e.subscriptions = [], e.destroy ? e.destroy() : originalFnMap.set(e, {
4309
4296
  apply: e.apply,
4310
4297
  onChange: e.onChange,
4311
4298
  normalizeNode: e.normalizeNode
4312
4299
  });
4313
- const operationToPatches = createOperationToPatches(schemaTypes), withObjectKeys = createWithObjectKeys(schemaTypes, keyGenerator), withSchemaTypes = createWithSchemaTypes({ schemaTypes, keyGenerator }), withEditableAPI = createWithEditableAPI(
4300
+ const operationToPatches = createOperationToPatches(schemaTypes), withObjectKeys = createWithObjectKeys(
4301
+ editorActor,
4302
+ schemaTypes,
4303
+ keyGenerator
4304
+ ), withSchemaTypes = createWithSchemaTypes({
4305
+ editorActor,
4306
+ schemaTypes,
4307
+ keyGenerator
4308
+ }), withEditableAPI = createWithEditableAPI(
4314
4309
  portableTextEditor,
4315
4310
  schemaTypes,
4316
4311
  keyGenerator
4317
4312
  ), withPatches = createWithPatches({
4318
- change$,
4313
+ editorActor,
4319
4314
  keyGenerator,
4320
4315
  patches$,
4321
4316
  patchFunctions: operationToPatches,
@@ -4326,15 +4321,18 @@ const originalFnMap = /* @__PURE__ */ new WeakMap(), withPlugins = (editor, opti
4326
4321
  patches$,
4327
4322
  blockSchemaType: schemaTypes.block
4328
4323
  }), withPortableTextMarkModel = createWithPortableTextMarkModel(
4324
+ editorActor,
4329
4325
  schemaTypes,
4330
- change$,
4331
4326
  keyGenerator
4332
- ), withPortableTextBlockStyle = createWithPortableTextBlockStyle(schemaTypes), withPlaceholderBlock = createWithPlaceholderBlock(), withInsertBreak = createWithInsertBreak(schemaTypes, keyGenerator), withUtils = createWithUtils({
4327
+ ), withPortableTextBlockStyle = createWithPortableTextBlockStyle(
4328
+ editorActor,
4329
+ schemaTypes
4330
+ ), withPlaceholderBlock = createWithPlaceholderBlock(), withInsertBreak = createWithInsertBreak(schemaTypes, keyGenerator), withUtils = createWithUtils({
4333
4331
  keyGenerator,
4334
4332
  schemaTypes,
4335
4333
  portableTextEditor
4336
4334
  }), withPortableTextSelections = createWithPortableTextSelections(
4337
- change$,
4335
+ editorActor,
4338
4336
  schemaTypes
4339
4337
  );
4340
4338
  return e.destroy = () => {
@@ -4451,7 +4449,7 @@ const defaultKeyGenerator = () => randomKey(12), PortableTextEditorKeyGeneratorC
4451
4449
  return readOnly;
4452
4450
  }, debug$5 = debugWithName("hook:useSyncValue"), CURRENT_VALUE = /* @__PURE__ */ new WeakMap();
4453
4451
  function useSyncValue(props) {
4454
- const { portableTextEditor, readOnly, keyGenerator } = props, { change$, schemaTypes } = portableTextEditor, previousValue = useRef(), slateEditor = useSlate(), updateValueFunctionRef = useRef(), updateFromCurrentValue = useCallback(() => {
4452
+ const { editorActor, portableTextEditor, readOnly, keyGenerator } = props, { schemaTypes } = portableTextEditor, previousValue = useRef(), slateEditor = useSlate(), updateValueFunctionRef = useRef(), updateFromCurrentValue = useCallback(() => {
4455
4453
  const currentValue = CURRENT_VALUE.get(portableTextEditor);
4456
4454
  if (previousValue.current === currentValue) {
4457
4455
  debug$5("Value is the same object as previous, not need to sync");
@@ -4522,7 +4520,7 @@ function useSyncValue(props) {
4522
4520
  !validation.valid && validation.resolution?.autoResolve && validation.resolution?.patches.length > 0 && !readOnly && previousValue.current && previousValue.current !== value && (console.warn(
4523
4521
  `${validation.resolution.action} for block with _key '${validationValue[0]._key}'. ${validation.resolution?.description}`
4524
4522
  ), validation.resolution.patches.forEach((patch) => {
4525
- change$.next({ type: "patch", patch });
4523
+ editorActor.send({ type: "patch", patch });
4526
4524
  })), validation.valid || validation.resolution?.autoResolve ? (oldBlock._key === currentBlock._key ? (debug$5.enabled && debug$5("Updating block", oldBlock, currentBlock), _updateBlock(
4527
4525
  slateEditor,
4528
4526
  currentBlock,
@@ -4532,8 +4530,8 @@ function useSyncValue(props) {
4532
4530
  slateEditor,
4533
4531
  currentBlock,
4534
4532
  currentBlockIndex
4535
- )), isChanged = !0) : (change$.next({
4536
- type: "invalidValue",
4533
+ )), isChanged = !0) : (editorActor.send({
4534
+ type: "invalid value",
4537
4535
  resolution: validation.resolution,
4538
4536
  value
4539
4537
  }), isValid = !1);
@@ -4549,8 +4547,8 @@ function useSyncValue(props) {
4549
4547
  currentBlock
4550
4548
  ), validation.valid || validation.resolution?.autoResolve ? Transforms.insertNodes(slateEditor, currentBlock, {
4551
4549
  at: [currentBlockIndex]
4552
- }) : (debug$5("Invalid", validation), change$.next({
4553
- type: "invalidValue",
4550
+ }) : (debug$5("Invalid", validation), editorActor.send({
4551
+ type: "invalid value",
4554
4552
  resolution: validation.resolution,
4555
4553
  value
4556
4554
  }), isValid = !1);
@@ -4571,8 +4569,8 @@ function useSyncValue(props) {
4571
4569
  try {
4572
4570
  slateEditor.onChange();
4573
4571
  } catch (err) {
4574
- console.error(err), change$.next({
4575
- type: "invalidValue",
4572
+ console.error(err), editorActor.send({
4573
+ type: "invalid value",
4576
4574
  resolution: null,
4577
4575
  value
4578
4576
  });
@@ -4581,14 +4579,14 @@ function useSyncValue(props) {
4581
4579
  hadSelection && !slateEditor.selection && (Transforms.select(slateEditor, {
4582
4580
  anchor: { path: [0, 0], offset: 0 },
4583
4581
  focus: { path: [0, 0], offset: 0 }
4584
- }), slateEditor.onChange()), change$.next({ type: "value", value });
4582
+ }), slateEditor.onChange()), editorActor.send({ type: "value changed", value });
4585
4583
  } else
4586
4584
  debug$5("Server value and editor value is equal, no need to sync.");
4587
4585
  previousValue.current = value;
4588
4586
  };
4589
4587
  return updateValueFunctionRef.current = updateFunction, updateFunction;
4590
4588
  }, [
4591
- change$,
4589
+ editorActor,
4592
4590
  keyGenerator,
4593
4591
  portableTextEditor,
4594
4592
  readOnly,
@@ -4657,9 +4655,9 @@ function _updateBlock(slateEditor, currentBlock, oldBlock, currentBlockIndex) {
4657
4655
  }
4658
4656
  const debug$4 = debugWithName("component:PortableTextEditor:Synchronizer"), debugVerbose$1 = debug$4.enabled && !1, FLUSH_PATCHES_THROTTLED_MS = process.env.NODE_ENV === "test" ? 500 : 1e3;
4659
4657
  function Synchronizer(props) {
4660
- const portableTextEditor = usePortableTextEditor(), keyGenerator = usePortableTextEditorKeyGenerator(), readOnly = usePortableTextEditorReadOnlyStatus(), { change$, getValue, onChange, value } = props, pendingPatches = useRef([]), syncValue = useSyncValue({
4658
+ const portableTextEditor = usePortableTextEditor(), keyGenerator = usePortableTextEditorKeyGenerator(), readOnly = usePortableTextEditorReadOnlyStatus(), { editorActor, getValue, onChange, value } = props, pendingPatches = useRef([]), syncValue = useSyncValue({
4659
+ editorActor,
4661
4660
  keyGenerator,
4662
- onChange,
4663
4661
  portableTextEditor,
4664
4662
  readOnly
4665
4663
  }), slateEditor = useSlate();
@@ -4671,14 +4669,14 @@ function Synchronizer(props) {
4671
4669
  debug$4("Flushing pending patches"), debugVerbose$1 && debug$4(`Patches:
4672
4670
  ${JSON.stringify(pendingPatches.current, null, 2)}`);
4673
4671
  const snapshot = getValue();
4674
- change$.next({
4672
+ editorActor.send({
4675
4673
  type: "mutation",
4676
4674
  patches: pendingPatches.current,
4677
4675
  snapshot
4678
4676
  }), pendingPatches.current = [];
4679
4677
  }
4680
4678
  IS_PROCESSING_LOCAL_CHANGES.set(slateEditor, !1);
4681
- }, [slateEditor, getValue, change$]), onFlushPendingPatchesThrottled = useMemo(() => throttle(
4679
+ }, [editorActor, slateEditor, getValue]), onFlushPendingPatchesThrottled = useMemo(() => throttle(
4682
4680
  () => {
4683
4681
  if (Editor.isNormalizing(slateEditor)) {
4684
4682
  onFlushPendingPatches();
@@ -4695,34 +4693,174 @@ ${JSON.stringify(pendingPatches.current, null, 2)}`);
4695
4693
  useEffect(() => () => {
4696
4694
  onFlushPendingPatches();
4697
4695
  }, [onFlushPendingPatches]), useEffect(() => {
4698
- debug$4("Subscribing to editor changes$");
4699
- const sub = change$.subscribe((next) => {
4700
- switch (next.type) {
4696
+ debug$4("Subscribing to editor changes");
4697
+ const sub = editorActor.on("*", (event) => {
4698
+ switch (event.type) {
4701
4699
  case "patch":
4702
- IS_PROCESSING_LOCAL_CHANGES.set(slateEditor, !0), pendingPatches.current.push(next.patch), onFlushPendingPatchesThrottled(), onChange(next);
4700
+ IS_PROCESSING_LOCAL_CHANGES.set(slateEditor, !0), pendingPatches.current.push(event.patch), onFlushPendingPatchesThrottled(), onChange(event);
4701
+ break;
4702
+ case "loading": {
4703
+ onChange({ type: "loading", isLoading: !0 });
4704
+ break;
4705
+ }
4706
+ case "done loading": {
4707
+ onChange({ type: "loading", isLoading: !1 });
4708
+ break;
4709
+ }
4710
+ case "offline": {
4711
+ onChange({ type: "connection", value: "offline" });
4712
+ break;
4713
+ }
4714
+ case "online": {
4715
+ onChange({ type: "connection", value: "online" });
4716
+ break;
4717
+ }
4718
+ case "value changed": {
4719
+ onChange({ type: "value", value: event.value });
4720
+ break;
4721
+ }
4722
+ case "invalid value": {
4723
+ onChange({
4724
+ type: "invalidValue",
4725
+ resolution: event.resolution,
4726
+ value: event.value
4727
+ });
4703
4728
  break;
4729
+ }
4730
+ case "error": {
4731
+ onChange({
4732
+ ...event,
4733
+ level: "warning"
4734
+ });
4735
+ break;
4736
+ }
4704
4737
  default:
4705
- onChange(next);
4738
+ onChange(event);
4706
4739
  }
4707
4740
  });
4708
4741
  return () => {
4709
- debug$4("Unsubscribing to changes$"), sub.unsubscribe();
4742
+ debug$4("Unsubscribing to changes"), sub.unsubscribe();
4710
4743
  };
4711
- }, [change$, onChange, onFlushPendingPatchesThrottled, slateEditor]);
4744
+ }, [editorActor, onFlushPendingPatchesThrottled, slateEditor]);
4712
4745
  const handleOnline = useCallback(() => {
4713
- debug$4("Editor is online, syncing from props.value"), change$.next({ type: "connection", value: "online" }), syncValue(value);
4714
- }, [change$, syncValue, value]), handleOffline = useCallback(() => {
4715
- debug$4("Editor is offline"), change$.next({ type: "connection", value: "offline" });
4716
- }, [change$]);
4717
- useEffect(() => (portableTextEditor.props.patches$ && (window.addEventListener("online", handleOnline), window.addEventListener("offline", handleOffline)), () => {
4718
- portableTextEditor.props.patches$ && (window.removeEventListener("online", handleOnline), window.removeEventListener("offline", handleOffline));
4719
- }));
4746
+ debug$4("Editor is online, syncing from props.value"), syncValue(value);
4747
+ }, [syncValue, value]);
4748
+ useEffect(() => {
4749
+ const subscription = editorActor.on("online", () => {
4750
+ portableTextEditor.props.patches$ && handleOnline();
4751
+ });
4752
+ return () => {
4753
+ subscription.unsubscribe();
4754
+ };
4755
+ }, [editorActor]);
4720
4756
  const isInitialValueFromProps = useRef(!0);
4721
4757
  return useEffect(() => {
4722
- 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);
4723
- }, [change$, syncValue, value]), null;
4758
+ debug$4("Value from props changed, syncing new value"), syncValue(value), isInitialValueFromProps.current && (editorActor.send({ type: "ready" }), isInitialValueFromProps.current = !1);
4759
+ }, [editorActor, syncValue, value]), null;
4724
4760
  }
4725
- const PortableTextEditorSelectionContext = createContext(null), usePortableTextEditorSelection = () => {
4761
+ const networkLogic = fromCallback(({ sendBack }) => {
4762
+ const onlineHandler = () => {
4763
+ sendBack({ type: "online" });
4764
+ }, offlineHandler = () => {
4765
+ sendBack({ type: "offline" });
4766
+ };
4767
+ return window.addEventListener("online", onlineHandler), window.addEventListener("offline", offlineHandler), () => {
4768
+ window.removeEventListener("online", onlineHandler), window.removeEventListener("offline", offlineHandler);
4769
+ };
4770
+ }), editorMachine = setup({
4771
+ types: {
4772
+ context: {},
4773
+ events: {},
4774
+ emitted: {}
4775
+ },
4776
+ actions: {
4777
+ "emit patch event": emit(({ event }) => (assertEvent(event, "patch"), event)),
4778
+ "emit mutation event": emit(({ event }) => (assertEvent(event, "mutation"), event)),
4779
+ "defer event": assign({
4780
+ pendingEvents: ({ context, event }) => (assertEvent(event, ["patch", "mutation"]), [...context.pendingEvents, event])
4781
+ }),
4782
+ "emit pending events": enqueueActions(({ context, enqueue }) => {
4783
+ for (const event of context.pendingEvents)
4784
+ enqueue(emit(event));
4785
+ }),
4786
+ "clear pending events": assign({
4787
+ pendingEvents: []
4788
+ })
4789
+ },
4790
+ actors: {
4791
+ networkLogic
4792
+ }
4793
+ }).createMachine({
4794
+ id: "editor",
4795
+ context: {
4796
+ pendingEvents: []
4797
+ },
4798
+ invoke: {
4799
+ id: "networkLogic",
4800
+ src: "networkLogic"
4801
+ },
4802
+ on: {
4803
+ ready: { actions: emit(({ event }) => event) },
4804
+ unset: { actions: emit(({ event }) => event) },
4805
+ "value changed": { actions: emit(({ event }) => event) },
4806
+ "invalid value": { actions: emit(({ event }) => event) },
4807
+ error: { actions: emit(({ event }) => event) },
4808
+ selection: { actions: emit(({ event }) => event) },
4809
+ blur: { actions: emit(({ event }) => event) },
4810
+ focus: { actions: emit(({ event }) => event) },
4811
+ online: { actions: emit({ type: "online" }) },
4812
+ offline: { actions: emit({ type: "offline" }) },
4813
+ loading: { actions: emit({ type: "loading" }) },
4814
+ "done loading": { actions: emit({ type: "done loading" }) }
4815
+ },
4816
+ initial: "pristine",
4817
+ states: {
4818
+ pristine: {
4819
+ initial: "idle",
4820
+ states: {
4821
+ idle: {
4822
+ on: {
4823
+ normalizing: {
4824
+ target: "normalizing"
4825
+ },
4826
+ patch: {
4827
+ actions: "defer event",
4828
+ target: "#editor.dirty"
4829
+ },
4830
+ mutation: {
4831
+ actions: "defer event",
4832
+ target: "#editor.dirty"
4833
+ }
4834
+ }
4835
+ },
4836
+ normalizing: {
4837
+ on: {
4838
+ "done normalizing": {
4839
+ target: "idle"
4840
+ },
4841
+ patch: {
4842
+ actions: "defer event"
4843
+ },
4844
+ mutation: {
4845
+ actions: "defer event"
4846
+ }
4847
+ }
4848
+ }
4849
+ }
4850
+ },
4851
+ dirty: {
4852
+ entry: ["emit pending events", "clear pending events"],
4853
+ on: {
4854
+ patch: {
4855
+ actions: "emit patch event"
4856
+ },
4857
+ mutation: {
4858
+ actions: "emit mutation event"
4859
+ }
4860
+ }
4861
+ }
4862
+ }
4863
+ }), PortableTextEditorSelectionContext = createContext(null), usePortableTextEditorSelection = () => {
4726
4864
  const selection = useContext(PortableTextEditorSelectionContext);
4727
4865
  if (selection === void 0)
4728
4866
  throw new Error(
@@ -4731,21 +4869,26 @@ const PortableTextEditorSelectionContext = createContext(null), usePortableTextE
4731
4869
  return selection;
4732
4870
  }, debug$3 = debugWithName("component:PortableTextEditor:SelectionProvider"), debugVerbose = debug$3.enabled && !1;
4733
4871
  function PortableTextEditorSelectionProvider(props) {
4734
- const { change$ } = props, [selection, setSelection] = useState(null);
4872
+ const [selection, setSelection] = useState(null);
4735
4873
  return useEffect(() => {
4736
- debug$3("Subscribing to selection changes$");
4737
- const subscription = change$.subscribe((next) => {
4738
- next.type === "selection" && startTransition(() => {
4739
- debugVerbose && debug$3("Setting selection"), setSelection(next.selection);
4874
+ debug$3("Subscribing to selection changes");
4875
+ const subscription = props.editorActor.on("selection", (event) => {
4876
+ startTransition(() => {
4877
+ debugVerbose && debug$3("Setting selection"), setSelection(event.selection);
4740
4878
  });
4741
4879
  });
4742
4880
  return () => {
4743
- debug$3("Unsubscribing to selection changes$"), subscription.unsubscribe();
4881
+ debug$3("Unsubscribing to selection changes"), subscription.unsubscribe();
4744
4882
  };
4745
- }, [change$]), /* @__PURE__ */ jsx(PortableTextEditorSelectionContext.Provider, { value: selection, children: props.children });
4883
+ }, [props.editorActor]), /* @__PURE__ */ jsx(PortableTextEditorSelectionContext.Provider, { value: selection, children: props.children });
4746
4884
  }
4747
4885
  const debug$2 = debugWithName("component:PortableTextEditor");
4748
4886
  class PortableTextEditor extends Component {
4887
+ /**
4888
+ * @internal
4889
+ * Don't use this API directly. It's subject to change.
4890
+ */
4891
+ editorActor;
4749
4892
  /**
4750
4893
  * An observable of all the editor changes.
4751
4894
  */
@@ -4763,7 +4906,7 @@ class PortableTextEditor extends Component {
4763
4906
  throw new Error('PortableTextEditor: missing "schemaType" property');
4764
4907
  props.incomingPatches$ && console.warn(
4765
4908
  "The prop 'incomingPatches$' is deprecated and renamed to 'patches$'"
4766
- ), this.change$.next({ type: "loading", isLoading: !0 }), this.schemaTypes = getPortableTextMemberSchemaTypes(
4909
+ ), this.editorActor = createActor(editorMachine), this.editorActor.start(), this.schemaTypes = getPortableTextMemberSchemaTypes(
4767
4910
  props.schemaType.hasOwnProperty("jsonType") ? props.schemaType : compileType(props.schemaType)
4768
4911
  );
4769
4912
  }
@@ -4780,7 +4923,7 @@ class PortableTextEditor extends Component {
4780
4923
  return this.editable.getValue();
4781
4924
  };
4782
4925
  render() {
4783
- const { onChange, value, children, patches$, incomingPatches$ } = this.props, { change$ } = this, _patches$ = incomingPatches$ || patches$, maxBlocks = typeof this.props.maxBlocks > "u" ? void 0 : parseInt(this.props.maxBlocks.toString(), 10) || void 0, readOnly = !!this.props.readOnly, keyGenerator = this.props.keyGenerator || defaultKeyGenerator;
4926
+ 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;
4784
4927
  return /* @__PURE__ */ jsx(
4785
4928
  SlateContainer,
4786
4929
  {
@@ -4789,18 +4932,26 @@ class PortableTextEditor extends Component {
4789
4932
  patches$: _patches$,
4790
4933
  portableTextEditor: this,
4791
4934
  readOnly,
4792
- 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: [
4793
- /* @__PURE__ */ jsx(
4794
- Synchronizer,
4795
- {
4796
- change$,
4797
- getValue: this.getValue,
4798
- onChange,
4799
- value
4800
- }
4801
- ),
4802
- children
4803
- ] }) }) }) })
4935
+ children: /* @__PURE__ */ jsx(PortableTextEditorKeyGeneratorContext.Provider, { value: keyGenerator, children: /* @__PURE__ */ jsx(PortableTextEditorContext.Provider, { value: this, children: /* @__PURE__ */ jsx(PortableTextEditorReadOnlyContext.Provider, { value: readOnly, children: /* @__PURE__ */ jsxs(
4936
+ PortableTextEditorSelectionProvider,
4937
+ {
4938
+ editorActor: this.editorActor,
4939
+ children: [
4940
+ /* @__PURE__ */ jsx(
4941
+ Synchronizer,
4942
+ {
4943
+ editorActor: this.editorActor,
4944
+ getValue: this.getValue,
4945
+ onChange: (change) => {
4946
+ this.props.onChange(change), this.change$.next(change);
4947
+ },
4948
+ value
4949
+ }
4950
+ ),
4951
+ children
4952
+ ]
4953
+ }
4954
+ ) }) }) })
4804
4955
  }
4805
4956
  );
4806
4957
  }
@@ -4910,20 +5061,19 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
4910
5061
  useEffect(() => {
4911
5062
  if (!shouldTrackSelectionAndFocus)
4912
5063
  return;
4913
- const sub = portableTextEditor.change$.subscribe((next) => {
4914
- if (next.type === "blur") {
4915
- setFocused(!1), setSelected(!1);
4916
- return;
5064
+ const onBlur = portableTextEditor.editorActor.on("blur", () => {
5065
+ setFocused(!1), setSelected(!1);
5066
+ }), onFocus = portableTextEditor.editorActor.on("focus", () => {
5067
+ const sel = PortableTextEditor.getSelection(portableTextEditor);
5068
+ sel && isEqual(sel.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) && setFocused(!0), setSelectedFromRange();
5069
+ }), onSelection = portableTextEditor.editorActor.on(
5070
+ "selection",
5071
+ (event) => {
5072
+ event.selection && isEqual(event.selection.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) ? setFocused(!0) : setFocused(!1), setSelectedFromRange();
4917
5073
  }
4918
- if (next.type === "focus") {
4919
- const sel = PortableTextEditor.getSelection(portableTextEditor);
4920
- sel && isEqual(sel.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) && setFocused(!0), setSelectedFromRange();
4921
- return;
4922
- }
4923
- next.type === "selection" && (next.selection && isEqual(next.selection.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) ? setFocused(!0) : setFocused(!1), setSelectedFromRange());
4924
- });
5074
+ );
4925
5075
  return () => {
4926
- sub.unsubscribe();
5076
+ onBlur.unsubscribe(), onFocus.unsubscribe(), onSelection.unsubscribe();
4927
5077
  };
4928
5078
  }, [
4929
5079
  path,
@@ -5074,9 +5224,9 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5074
5224
  forwardedRef,
5075
5225
  () => ref.current
5076
5226
  );
5077
- const rangeDecorationsRef = useRef(rangeDecorations), { change$, schemaTypes } = portableTextEditor, slateEditor = useSlate(), blockTypeName = schemaTypes.block.name, withInsertData = useMemo(
5078
- () => createWithInsertData(change$, schemaTypes, keyGenerator),
5079
- [change$, keyGenerator, schemaTypes]
5227
+ const rangeDecorationsRef = useRef(rangeDecorations), { editorActor, schemaTypes } = portableTextEditor, slateEditor = useSlate(), blockTypeName = schemaTypes.block.name, withInsertData = useMemo(
5228
+ () => createWithInsertData(editorActor, schemaTypes, keyGenerator),
5229
+ [editorActor, keyGenerator, schemaTypes]
5080
5230
  ), withHotKeys = useMemo(
5081
5231
  () => createWithHotkeys(schemaTypes, portableTextEditor, hotkeys),
5082
5232
  [hotkeys, portableTextEditor, schemaTypes]
@@ -5149,10 +5299,13 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5149
5299
  `Normalized selection from props ${JSON.stringify(normalizedSelection)}`
5150
5300
  );
5151
5301
  const slateRange = toSlateRange(normalizedSelection, slateEditor);
5152
- slateRange && (Transforms.select(slateEditor, slateRange), slateEditor.operations.some((o) => o.type === "set_selection") || change$.next({ type: "selection", selection: normalizedSelection }), slateEditor.onChange());
5302
+ slateRange && (Transforms.select(slateEditor, slateRange), slateEditor.operations.some((o) => o.type === "set_selection") || editorActor.send({
5303
+ type: "selection",
5304
+ selection: normalizedSelection
5305
+ }), slateEditor.onChange());
5153
5306
  }
5154
5307
  }
5155
- }, [propsSelection, slateEditor, blockTypeName, change$]), syncRangeDecorations = useCallback(
5308
+ }, [editorActor, propsSelection, slateEditor]), syncRangeDecorations = useCallback(
5156
5309
  (operation) => {
5157
5310
  if (rangeDecorations && rangeDecorations.length > 0) {
5158
5311
  const newSlateRanges = [];
@@ -5191,28 +5344,22 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5191
5344
  return;
5192
5345
  }
5193
5346
  }
5194
- setRangeDecorationsState([]);
5347
+ rangeDecorationState.length > 0 && setRangeDecorationsState([]);
5195
5348
  },
5196
5349
  [portableTextEditor, rangeDecorations, schemaTypes, slateEditor]
5197
5350
  );
5198
5351
  useEffect(() => {
5199
- const sub = change$.subscribe((next) => {
5200
- switch (next.type) {
5201
- case "ready":
5202
- restoreSelectionFromProps();
5203
- break;
5204
- case "invalidValue":
5205
- setHasInvalidValue(!0);
5206
- break;
5207
- case "value":
5208
- setHasInvalidValue(!1);
5209
- break;
5210
- }
5352
+ const onReady = editorActor.on("ready", () => {
5353
+ restoreSelectionFromProps();
5354
+ }), onInvalidValue = editorActor.on("invalid value", () => {
5355
+ setHasInvalidValue(!0);
5356
+ }), onValueChanged = editorActor.on("value changed", () => {
5357
+ setHasInvalidValue(!1);
5211
5358
  });
5212
5359
  return () => {
5213
- sub.unsubscribe();
5360
+ onReady.unsubscribe(), onInvalidValue.unsubscribe(), onValueChanged.unsubscribe();
5214
5361
  };
5215
- }, [change$, restoreSelectionFromProps]), useEffect(() => {
5362
+ }, [editorActor, restoreSelectionFromProps]), useEffect(() => {
5216
5363
  propsSelection && !hasInvalidValue && restoreSelectionFromProps();
5217
5364
  }, [hasInvalidValue, propsSelection, restoreSelectionFromProps]);
5218
5365
  const originalApply = useMemo(() => slateEditor.apply, [slateEditor]), [syncedRangeDecorations, setSyncedRangeDecorations] = useState(!1);
@@ -5243,7 +5390,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5243
5390
  slateEditor.selection,
5244
5391
  schemaTypes
5245
5392
  )?.focus.path || [], onPasteResult = onPaste({ event, value, path, schemaTypes });
5246
- 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) => {
5393
+ 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) => {
5247
5394
  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(
5248
5395
  toSlateValue(result.insert, {
5249
5396
  schemaTypes
@@ -5253,23 +5400,23 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5253
5400
  result
5254
5401
  );
5255
5402
  }).catch((error) => (console.error(error), error)).finally(() => {
5256
- change$.next({ type: "loading", isLoading: !1 });
5403
+ editorActor.send({ type: "done loading" });
5257
5404
  }));
5258
5405
  },
5259
- [change$, onPaste, portableTextEditor, schemaTypes, slateEditor]
5406
+ [onPaste, portableTextEditor, schemaTypes, slateEditor]
5260
5407
  ), handleOnFocus = useCallback(
5261
5408
  (event) => {
5262
5409
  if (onFocus && onFocus(event), !event.isDefaultPrevented()) {
5263
5410
  const selection = PortableTextEditor.getSelection(portableTextEditor);
5264
- selection === null && (Transforms.select(slateEditor, Editor.start(slateEditor, [])), slateEditor.onChange()), change$.next({ type: "focus", event });
5411
+ selection === null && (Transforms.select(slateEditor, Editor.start(slateEditor, [])), slateEditor.onChange()), editorActor.send({ type: "focus", event });
5265
5412
  const newSelection = PortableTextEditor.getSelection(portableTextEditor);
5266
- selection === newSelection && change$.next({
5413
+ selection === newSelection && editorActor.send({
5267
5414
  type: "selection",
5268
5415
  selection
5269
5416
  });
5270
5417
  }
5271
5418
  },
5272
- [onFocus, portableTextEditor, change$, slateEditor]
5419
+ [editorActor, onFocus, portableTextEditor, slateEditor]
5273
5420
  ), handleClick = useCallback(
5274
5421
  (event) => {
5275
5422
  if (onClick && onClick(event), slateEditor.selection && event.target === event.currentTarget) {
@@ -5286,9 +5433,9 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5286
5433
  [onClick, slateEditor]
5287
5434
  ), handleOnBlur = useCallback(
5288
5435
  (event) => {
5289
- onBlur && onBlur(event), event.isPropagationStopped() || change$.next({ type: "blur", event });
5436
+ onBlur && onBlur(event), event.isPropagationStopped() || editorActor.send({ type: "blur", event });
5290
5437
  },
5291
- [change$, onBlur]
5438
+ [editorActor, onBlur]
5292
5439
  ), handleOnBeforeInput = useCallback(
5293
5440
  (event) => {
5294
5441
  onBeforeInput && onBeforeInput(event);
@@ -5394,6 +5541,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5394
5541
  export {
5395
5542
  PortableTextEditable,
5396
5543
  PortableTextEditor,
5544
+ editorMachine,
5397
5545
  defaultKeyGenerator as keyGenerator,
5398
5546
  usePortableTextEditor,
5399
5547
  usePortableTextEditorSelection