@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.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: !0 });
3
- var jsxRuntime = require("react/jsx-runtime"), isEqual = require("lodash/isEqual.js"), noop = require("lodash/noop.js"), react = require("react"), slate = require("slate"), slateReact = require("slate-react"), debug$m = require("debug"), types = require("@sanity/types"), styledComponents = require("styled-components"), uniq = require("lodash/uniq.js"), rxjs = require("rxjs"), schema = require("@sanity/schema"), patches = require("@portabletext/patches"), get = require("lodash/get.js"), isUndefined = require("lodash/isUndefined.js"), omitBy = require("lodash/omitBy.js"), flatten = require("lodash/flatten.js"), isHotkeyEsm = require("is-hotkey-esm"), blockTools = require("@sanity/block-tools"), isPlainObject = require("lodash/isPlainObject.js"), throttle = require("lodash/throttle.js"), content = require("@sanity/util/content"), debounce = require("lodash/debounce.js");
3
+ var jsxRuntime = require("react/jsx-runtime"), isEqual = require("lodash/isEqual.js"), noop = require("lodash/noop.js"), react = require("react"), slate = require("slate"), slateReact = require("slate-react"), debug$m = require("debug"), types = require("@sanity/types"), styledComponents = require("styled-components"), uniq = require("lodash/uniq.js"), rxjs = require("rxjs"), xstate = require("xstate"), schema = require("@sanity/schema"), patches = require("@portabletext/patches"), get = require("lodash/get.js"), isUndefined = require("lodash/isUndefined.js"), omitBy = require("lodash/omitBy.js"), flatten = require("lodash/flatten.js"), isHotkeyEsm = require("is-hotkey-esm"), blockTools = require("@sanity/block-tools"), isPlainObject = require("lodash/isPlainObject.js"), throttle = require("lodash/throttle.js"), content = require("@sanity/util/content"), debounce = require("lodash/debounce.js");
4
4
  function _interopDefaultCompat(e) {
5
5
  return e && typeof e == "object" && "default" in e ? e : { default: e };
6
6
  }
@@ -110,7 +110,7 @@ function normalizeSelection(selection, value) {
110
110
  const { anchor, focus } = selection;
111
111
  return anchor && value.find((blk) => isEqual__default.default({ _key: blk._key }, anchor.path[0])) && (newAnchor = normalizePoint(anchor, value)), focus && value.find((blk) => isEqual__default.default({ _key: blk._key }, focus.path[0])) && (newFocus = normalizePoint(focus, value)), newAnchor && newFocus ? { anchor: newAnchor, focus: newFocus, backward: selection.backward } : null;
112
112
  }
113
- const EMPTY_MARKDEFS = [], VOID_CHILD_KEY = "void-child";
113
+ const VOID_CHILD_KEY = "void-child";
114
114
  function keepObjectEquality(object, keyMap) {
115
115
  const value = keyMap[object._key];
116
116
  return value && isEqual__default.default(object, value) ? value : (keyMap[object._key] = object, object);
@@ -708,7 +708,6 @@ const EMPTY_ANNOTATIONS = [], inlineBlockStyle = { display: "inline-block" }, El
708
708
  };
709
709
  function DefaultAnnotation(props) {
710
710
  const handleClick = react.useCallback(
711
- // eslint-disable-next-line no-alert
712
711
  () => alert(JSON.stringify(props.annotation)),
713
712
  [props.annotation]
714
713
  );
@@ -1695,7 +1694,7 @@ function createWithMaxBlocks(maxBlocks) {
1695
1694
  }, editor;
1696
1695
  };
1697
1696
  }
1698
- function createWithObjectKeys(schemaTypes, keyGenerator) {
1697
+ function createWithObjectKeys(editorActor, schemaTypes, keyGenerator) {
1699
1698
  return function(editor) {
1700
1699
  const { apply: apply2, normalizeNode } = editor;
1701
1700
  return editor.apply = (operation) => {
@@ -1731,10 +1730,13 @@ function createWithObjectKeys(schemaTypes, keyGenerator) {
1731
1730
  }, editor.normalizeNode = (entry) => {
1732
1731
  const [node, path] = entry;
1733
1732
  if (slate.Element.isElement(node) && node._type === schemaTypes.block.name) {
1734
- node._key || slate.Transforms.setNodes(editor, { _key: keyGenerator() }, { at: path });
1733
+ if (!node._key) {
1734
+ editorActor.send({ type: "normalizing" }), slate.Transforms.setNodes(editor, { _key: keyGenerator() }, { at: path }), editorActor.send({ type: "done normalizing" });
1735
+ return;
1736
+ }
1735
1737
  for (const [child, childPath] of slate.Node.children(editor, path))
1736
1738
  if (!child._key) {
1737
- slate.Transforms.setNodes(editor, { _key: keyGenerator() }, { at: childPath });
1739
+ editorActor.send({ type: "normalizing" }), slate.Transforms.setNodes(editor, { _key: keyGenerator() }, { at: childPath }), editorActor.send({ type: "done normalizing" });
1738
1740
  return;
1739
1741
  }
1740
1742
  }
@@ -2440,7 +2442,7 @@ function toInt(num) {
2440
2442
  const debug$i = debugWithName("applyPatches"), debugVerbose$4 = debug$i.enabled && !0;
2441
2443
  function createApplyPatch(schemaTypes) {
2442
2444
  let previousPatch;
2443
- return function(editor, patch) {
2445
+ return (editor, patch) => {
2444
2446
  let changed = !1;
2445
2447
  debugVerbose$4 && (debug$i(
2446
2448
  `
@@ -2891,7 +2893,7 @@ function findOperationTargetBlock(editor, operation) {
2891
2893
  }
2892
2894
  const debug$g = debugWithName("plugin:withPatches");
2893
2895
  function createWithPatches({
2894
- change$,
2896
+ editorActor,
2895
2897
  patches$,
2896
2898
  patchFunctions,
2897
2899
  readOnly,
@@ -3020,7 +3022,7 @@ function createWithPatches({
3020
3022
  }
3021
3023
  return !editorWasEmpty && editorIsEmpty && ["merge_node", "set_node", "remove_text", "remove_node"].includes(
3022
3024
  operation.type
3023
- ) && (patches$1 = [...patches$1, patches.unset([])], change$.next({
3025
+ ) && (patches$1 = [...patches$1, patches.unset([])], editorActor.send({
3024
3026
  type: "unset",
3025
3027
  previousValue: fromSlateValue(
3026
3028
  previousChildren,
@@ -3028,7 +3030,7 @@ function createWithPatches({
3028
3030
  KEY_TO_VALUE_ELEMENT.get(editor)
3029
3031
  )
3030
3032
  })), editorWasEmpty && patches$1.length > 0 && (patches$1 = [patches.setIfMissing([], []), ...patches$1]), patches$1.length > 0 && patches$1.forEach((patch) => {
3031
- change$.next({
3033
+ editorActor.send({
3032
3034
  type: "patch",
3033
3035
  patch: { ...patch, origin: "local" }
3034
3036
  });
@@ -3064,25 +3066,25 @@ function createWithPlaceholderBlock() {
3064
3066
  };
3065
3067
  }
3066
3068
  const debug$e = debugWithName("plugin:withPortableTextBlockStyle");
3067
- function createWithPortableTextBlockStyle(types2) {
3069
+ function createWithPortableTextBlockStyle(editorActor, types2) {
3068
3070
  const defaultStyle = types2.styles[0].value;
3069
3071
  return function(editor) {
3070
3072
  const { normalizeNode } = editor;
3071
3073
  return editor.normalizeNode = (nodeEntry) => {
3072
- normalizeNode(nodeEntry);
3073
3074
  const [, path] = nodeEntry;
3074
3075
  for (const op of editor.operations)
3075
3076
  if (op.type === "split_node" && op.path.length === 1 && editor.isTextBlock(op.properties) && op.properties.style !== defaultStyle && op.path[0] === path[0] && !slate.Path.equals(path, op.path)) {
3076
3077
  const [child] = slate.Editor.node(editor, [op.path[0] + 1, 0]);
3077
3078
  if (slate.Text.isText(child) && child.text === "") {
3078
- debug$e(`Normalizing split node to ${defaultStyle} style`, op), slate.Transforms.setNodes(
3079
+ debug$e(`Normalizing split node to ${defaultStyle} style`, op), editorActor.send({ type: "normalizing" }), slate.Transforms.setNodes(
3079
3080
  editor,
3080
3081
  { style: defaultStyle },
3081
3082
  { at: [op.path[0] + 1], voids: !1 }
3082
- );
3083
- break;
3083
+ ), editorActor.send({ type: "done normalizing" });
3084
+ return;
3084
3085
  }
3085
3086
  }
3087
+ normalizeNode(nodeEntry);
3086
3088
  }, editor.pteHasBlockStyle = (style) => editor.selection ? [
3087
3089
  ...slate.Editor.nodes(editor, {
3088
3090
  at: editor.selection,
@@ -3227,7 +3229,7 @@ function isPortableTextBlock(node) {
3227
3229
  );
3228
3230
  }
3229
3231
  const debug$c = debugWithName("plugin:withPortableTextMarkModel");
3230
- function createWithPortableTextMarkModel(types2, change$, keyGenerator) {
3232
+ function createWithPortableTextMarkModel(editorActor, types2, keyGenerator) {
3231
3233
  return function(editor) {
3232
3234
  const { apply: apply2, normalizeNode } = editor, decorators = types2.decorators.map((t) => t.value), forceNewSelection = () => {
3233
3235
  editor.selection && (slate.Transforms.select(editor, { ...editor.selection }), editor.selection = { ...editor.selection });
@@ -3236,7 +3238,7 @@ function createWithPortableTextMarkModel(types2, change$, keyGenerator) {
3236
3238
  editor.selection,
3237
3239
  types2
3238
3240
  );
3239
- change$.next({ type: "selection", selection: ptRange });
3241
+ editorActor.send({ type: "selection", selection: ptRange });
3240
3242
  };
3241
3243
  return editor.normalizeNode = (nodeEntry) => {
3242
3244
  const [node, path] = nodeEntry;
@@ -3249,20 +3251,20 @@ function createWithPortableTextMarkModel(types2, change$, keyGenerator) {
3249
3251
  "Merging spans",
3250
3252
  JSON.stringify(child, null, 2),
3251
3253
  JSON.stringify(nextNode, null, 2)
3252
- ), slate.Transforms.mergeNodes(editor, {
3254
+ ), editorActor.send({ type: "normalizing" }), slate.Transforms.mergeNodes(editor, {
3253
3255
  at: [childPath[0], childPath[1] + 1],
3254
3256
  voids: !0
3255
- });
3257
+ }), editorActor.send({ type: "done normalizing" });
3256
3258
  return;
3257
3259
  }
3258
3260
  }
3259
3261
  }
3260
3262
  if (editor.isTextBlock(node) && !Array.isArray(node.markDefs)) {
3261
- debug$c("Adding .markDefs to block node"), slate.Transforms.setNodes(editor, { markDefs: [] }, { at: path });
3263
+ debug$c("Adding .markDefs to block node"), editorActor.send({ type: "normalizing" }), slate.Transforms.setNodes(editor, { markDefs: [] }, { at: path }), editorActor.send({ type: "done normalizing" });
3262
3264
  return;
3263
3265
  }
3264
3266
  if (editor.isTextSpan(node) && !Array.isArray(node.marks)) {
3265
- debug$c("Adding .marks to span node"), slate.Transforms.setNodes(editor, { marks: [] }, { at: path });
3267
+ debug$c("Adding .marks to span node"), editorActor.send({ type: "normalizing" }), slate.Transforms.setNodes(editor, { marks: [] }, { at: path }), editorActor.send({ type: "done normalizing" });
3266
3268
  return;
3267
3269
  }
3268
3270
  if (editor.isTextSpan(node)) {
@@ -3270,11 +3272,11 @@ function createWithPortableTextMarkModel(types2, change$, keyGenerator) {
3270
3272
  (mark) => !decorators2.includes(mark)
3271
3273
  );
3272
3274
  if (editor.isTextBlock(block) && node.text === "" && annotations && annotations.length > 0) {
3273
- debug$c("Removing annotations from empty span node"), slate.Transforms.setNodes(
3275
+ debug$c("Removing annotations from empty span node"), editorActor.send({ type: "normalizing" }), slate.Transforms.setNodes(
3274
3276
  editor,
3275
3277
  { marks: node.marks?.filter((mark) => decorators2.includes(mark)) },
3276
3278
  { at: path }
3277
- );
3279
+ ), editorActor.send({ type: "done normalizing" });
3278
3280
  return;
3279
3281
  }
3280
3282
  }
@@ -3284,7 +3286,7 @@ function createWithPortableTextMarkModel(types2, change$, keyGenerator) {
3284
3286
  if (editor.isTextSpan(child)) {
3285
3287
  const marks = child.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators2.includes(mark) && !node.markDefs?.find((def) => def._key === mark));
3286
3288
  if (orphanedAnnotations.length > 0) {
3287
- debug$c("Removing orphaned annotations from span node"), slate.Transforms.setNodes(
3289
+ debug$c("Removing orphaned annotations from span node"), editorActor.send({ type: "normalizing" }), slate.Transforms.setNodes(
3288
3290
  editor,
3289
3291
  {
3290
3292
  marks: marks.filter(
@@ -3292,7 +3294,7 @@ function createWithPortableTextMarkModel(types2, change$, keyGenerator) {
3292
3294
  )
3293
3295
  },
3294
3296
  { at: childPath }
3295
- );
3297
+ ), editorActor.send({ type: "done normalizing" });
3296
3298
  return;
3297
3299
  }
3298
3300
  }
@@ -3304,7 +3306,7 @@ function createWithPortableTextMarkModel(types2, change$, keyGenerator) {
3304
3306
  (decorator) => decorator.value
3305
3307
  ), marks = node.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators2.includes(mark) && !block.markDefs?.find((def) => def._key === mark));
3306
3308
  if (orphanedAnnotations.length > 0) {
3307
- debug$c("Removing orphaned annotations from span node"), slate.Transforms.setNodes(
3309
+ debug$c("Removing orphaned annotations from span node"), editorActor.send({ type: "normalizing" }), slate.Transforms.setNodes(
3308
3310
  editor,
3309
3311
  {
3310
3312
  marks: marks.filter(
@@ -3312,7 +3314,7 @@ function createWithPortableTextMarkModel(types2, change$, keyGenerator) {
3312
3314
  )
3313
3315
  },
3314
3316
  { at: path }
3315
- );
3317
+ ), editorActor.send({ type: "done normalizing" });
3316
3318
  return;
3317
3319
  }
3318
3320
  }
@@ -3321,20 +3323,23 @@ function createWithPortableTextMarkModel(types2, change$, keyGenerator) {
3321
3323
  const markDefs = node.markDefs ?? [], markDefKeys = /* @__PURE__ */ new Set(), newMarkDefs = [];
3322
3324
  for (const markDef of markDefs)
3323
3325
  markDefKeys.has(markDef._key) || (markDefKeys.add(markDef._key), newMarkDefs.push(markDef));
3324
- markDefs.length !== newMarkDefs.length && (debug$c("Removing duplicate markDefs"), slate.Transforms.setNodes(editor, { markDefs: newMarkDefs }, { at: path }));
3326
+ if (markDefs.length !== newMarkDefs.length) {
3327
+ debug$c("Removing duplicate markDefs"), editorActor.send({ type: "normalizing" }), slate.Transforms.setNodes(editor, { markDefs: newMarkDefs }, { at: path }), editorActor.send({ type: "done normalizing" });
3328
+ return;
3329
+ }
3325
3330
  }
3326
3331
  if (editor.isTextBlock(node) && !editor.operations.some(
3327
3332
  (op) => op.type === "merge_node" && "markDefs" in op.properties && op.path.length === 1
3328
3333
  )) {
3329
3334
  const newMarkDefs = (node.markDefs || []).filter((def) => node.children.find((child) => slate.Text.isText(child) && Array.isArray(child.marks) && child.marks.includes(def._key)));
3330
3335
  if (node.markDefs && !isEqual__default.default(newMarkDefs, node.markDefs)) {
3331
- debug$c("Removing markDef not in use"), slate.Transforms.setNodes(
3336
+ debug$c("Removing markDef not in use"), editorActor.send({ type: "normalizing" }), slate.Transforms.setNodes(
3332
3337
  editor,
3333
3338
  {
3334
3339
  markDefs: newMarkDefs
3335
3340
  },
3336
3341
  { at: path }
3337
- );
3342
+ ), editorActor.send({ type: "done normalizing" });
3338
3343
  return;
3339
3344
  }
3340
3345
  }
@@ -3567,7 +3572,7 @@ function createWithPortableTextMarkModel(types2, change$, keyGenerator) {
3567
3572
  };
3568
3573
  }
3569
3574
  const debug$b = debugWithName("plugin:withPortableTextSelections"), debugVerbose$2 = debug$b.enabled && !1;
3570
- function createWithPortableTextSelections(change$, types2) {
3575
+ function createWithPortableTextSelections(editorActor, types2) {
3571
3576
  let prevSelection = null;
3572
3577
  return function(editor) {
3573
3578
  const emitPortableTextSelection = () => {
@@ -3586,7 +3591,7 @@ function createWithPortableTextSelections(change$, types2) {
3586
3591
  `Emitting selection ${JSON.stringify(ptRange || null)} (${JSON.stringify(
3587
3592
  editor.selection
3588
3593
  )})`
3589
- ), ptRange ? change$.next({ type: "selection", selection: ptRange }) : change$.next({ type: "selection", selection: null });
3594
+ ), ptRange ? editorActor.send({ type: "selection", selection: ptRange }) : editorActor.send({ type: "selection", selection: null });
3590
3595
  }
3591
3596
  prevSelection = editor.selection;
3592
3597
  }, { onChange } = editor;
@@ -3598,27 +3603,30 @@ function createWithPortableTextSelections(change$, types2) {
3598
3603
  }
3599
3604
  const debug$a = debugWithName("plugin:withSchemaTypes");
3600
3605
  function createWithSchemaTypes({
3606
+ editorActor,
3601
3607
  schemaTypes,
3602
3608
  keyGenerator
3603
3609
  }) {
3604
3610
  return function(editor) {
3605
- editor.isTextBlock = (value) => types.isPortableTextTextBlock(value) && value._type === schemaTypes.block.name, editor.isTextSpan = (value) => types.isPortableTextSpan(value) && value._type == schemaTypes.span.name, editor.isListBlock = (value) => types.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;
3611
+ editor.isTextBlock = (value) => types.isPortableTextTextBlock(value) && value._type === schemaTypes.block.name, editor.isTextSpan = (value) => types.isPortableTextSpan(value) && value._type === schemaTypes.span.name, editor.isListBlock = (value) => types.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;
3606
3612
  const { normalizeNode } = editor;
3607
3613
  return editor.normalizeNode = (entry) => {
3608
3614
  const [node, path] = entry;
3609
3615
  if (node._type === void 0 && path.length === 2) {
3610
3616
  debug$a("Setting span type on text node without a type");
3611
3617
  const span = node, key = span._key || keyGenerator();
3612
- slate.Transforms.setNodes(
3618
+ editorActor.send({ type: "normalizing" }), slate.Transforms.setNodes(
3613
3619
  editor,
3614
3620
  { ...span, _type: schemaTypes.span.name, _key: key },
3615
3621
  { at: path }
3616
- );
3622
+ ), editorActor.send({ type: "done normalizing" });
3623
+ return;
3617
3624
  }
3618
3625
  if (node._key === void 0 && (path.length === 1 || path.length === 2)) {
3619
3626
  debug$a("Setting missing key on child node without a key");
3620
3627
  const key = keyGenerator();
3621
- slate.Transforms.setNodes(editor, { _key: key }, { at: path });
3628
+ editorActor.send({ type: "normalizing" }), slate.Transforms.setNodes(editor, { _key: key }, { at: path }), editorActor.send({ type: "done normalizing" });
3629
+ return;
3622
3630
  }
3623
3631
  normalizeNode(entry);
3624
3632
  }, editor;
@@ -3640,7 +3648,7 @@ function createWithUtils({
3640
3648
  return;
3641
3649
  }
3642
3650
  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);
3643
- if (!(newStartOffset === newEndOffset || isNaN(newStartOffset) || isNaN(newEndOffset))) {
3651
+ if (!(newStartOffset === newEndOffset || Number.isNaN(newStartOffset) || Number.isNaN(newEndOffset))) {
3644
3652
  debug$9("pteExpandToWord: Expanding to focused word"), slate.Transforms.setSelection(editor, {
3645
3653
  anchor: { ...selection.anchor, offset: newStartOffset },
3646
3654
  focus: { ...selection.focus, offset: newEndOffset }
@@ -3926,22 +3934,6 @@ function validateValue(value, types$1, keyGenerator) {
3926
3934
  }
3927
3935
  }, !0;
3928
3936
  }
3929
- if (blk.markDefs && !Array.isArray(blk.markDefs))
3930
- return resolution = {
3931
- patches: [
3932
- patches.set({ ...textBlock, markDefs: EMPTY_MARKDEFS }, [
3933
- { _key: textBlock._key }
3934
- ])
3935
- ],
3936
- description: "Block has invalid required property 'markDefs'.",
3937
- action: "Add empty markDefs array",
3938
- item: textBlock,
3939
- i18n: {
3940
- description: "inputs.portable-text.invalid-value.missing-or-invalid-markdefs.description",
3941
- action: "inputs.portable-text.invalid-value.missing-or-invalid-markdefs.action",
3942
- values: { key: textBlock._key }
3943
- }
3944
- }, !0;
3945
3937
  const allUsedMarks = uniq__default.default(
3946
3938
  flatten__default.default(
3947
3939
  textBlock.children.filter((cld) => cld._type === types$1.span.name).map((cld) => cld.marks || [])
@@ -4086,7 +4078,7 @@ function validateValue(value, types$1, keyGenerator) {
4086
4078
  }) && (valid = !1), { valid, resolution, value });
4087
4079
  }
4088
4080
  const debug$7 = debugWithName("plugin:withInsertData");
4089
- function createWithInsertData(change$, schemaTypes, keyGenerator) {
4081
+ function createWithInsertData(editorActor, schemaTypes, keyGenerator) {
4090
4082
  return function(editor) {
4091
4083
  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(`
4092
4084
 
@@ -4140,9 +4132,8 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
4140
4132
  ), validation = validateValue(parsed, schemaTypes, keyGenerator);
4141
4133
  if (!validation.valid && !validation.resolution?.autoResolve) {
4142
4134
  const errorDescription = `${validation.resolution?.description}`;
4143
- return change$.next({
4135
+ return editorActor.send({
4144
4136
  type: "error",
4145
- level: "warning",
4146
4137
  name: "pasteError",
4147
4138
  description: errorDescription,
4148
4139
  data: validation
@@ -4155,7 +4146,6 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
4155
4146
  }, editor.insertTextOrHTMLData = (data) => {
4156
4147
  if (!editor.selection)
4157
4148
  return debug$7("No selection, not inserting"), !1;
4158
- change$.next({ type: "loading", isLoading: !0 });
4159
4149
  const html = data.getData("text/html"), text = data.getData("text/plain");
4160
4150
  if (html || text) {
4161
4151
  debug$7("Inserting data", data);
@@ -4186,9 +4176,8 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
4186
4176
  const errorDescription = `Could not validate the resulting portable text to insert.
4187
4177
  ${validation.resolution?.description}
4188
4178
  Try to insert as plain text (shift-paste) instead.`;
4189
- return change$.next({
4179
+ return editorActor.send({
4190
4180
  type: "error",
4191
- level: "warning",
4192
4181
  name: "pasteError",
4193
4182
  description: errorDescription,
4194
4183
  data: validation
@@ -4196,9 +4185,9 @@ Try to insert as plain text (shift-paste) instead.`;
4196
4185
  }
4197
4186
  return debug$7(
4198
4187
  `Inserting ${insertedType} fragment at ${JSON.stringify(editor.selection)}`
4199
- ), _insertFragment(editor, fragment, schemaTypes), change$.next({ type: "loading", isLoading: !1 }), !0;
4188
+ ), _insertFragment(editor, fragment, schemaTypes), !0;
4200
4189
  }
4201
- return change$.next({ type: "loading", isLoading: !1 }), !1;
4190
+ return !1;
4202
4191
  }, editor.insertData = (data) => {
4203
4192
  editor.insertPortableTextData(data) || editor.insertTextOrHTMLData(data);
4204
4193
  }, editor.insertFragmentData = (data) => {
@@ -4242,10 +4231,7 @@ function _regenerateKeys(editor, fragment, keyGenerator, spanTypeName, editorTyp
4242
4231
  return newNode.children = newNode.children.map(
4243
4232
  (child) => child._type === spanTypeName && editor.isTextSpan(child) ? {
4244
4233
  ...child,
4245
- marks: child.marks && child.marks.includes(oldKey) ? (
4246
- // eslint-disable-next-line max-nested-callbacks
4247
- [...child.marks].filter((mark) => mark !== oldKey).concat(newKey)
4248
- ) : child.marks
4234
+ marks: child.marks && child.marks.includes(oldKey) ? [...child.marks].filter((mark) => mark !== oldKey).concat(newKey) : child.marks
4249
4235
  } : child
4250
4236
  ), { ...def, _key: newKey };
4251
4237
  });
@@ -4288,18 +4274,26 @@ function _insertFragment(editor, fragment, schemaTypes) {
4288
4274
  }), editor.onChange();
4289
4275
  }
4290
4276
  const originalFnMap = /* @__PURE__ */ new WeakMap(), withPlugins = (editor, options) => {
4291
- const e = editor, { keyGenerator, portableTextEditor, patches$, readOnly, maxBlocks } = options, { schemaTypes, change$ } = portableTextEditor;
4277
+ const e = editor, { keyGenerator, portableTextEditor, patches$, readOnly, maxBlocks } = options, { editorActor, schemaTypes } = portableTextEditor;
4292
4278
  e.subscriptions = [], e.destroy ? e.destroy() : originalFnMap.set(e, {
4293
4279
  apply: e.apply,
4294
4280
  onChange: e.onChange,
4295
4281
  normalizeNode: e.normalizeNode
4296
4282
  });
4297
- const operationToPatches = createOperationToPatches(schemaTypes), withObjectKeys = createWithObjectKeys(schemaTypes, keyGenerator), withSchemaTypes = createWithSchemaTypes({ schemaTypes, keyGenerator }), withEditableAPI = createWithEditableAPI(
4283
+ const operationToPatches = createOperationToPatches(schemaTypes), withObjectKeys = createWithObjectKeys(
4284
+ editorActor,
4285
+ schemaTypes,
4286
+ keyGenerator
4287
+ ), withSchemaTypes = createWithSchemaTypes({
4288
+ editorActor,
4289
+ schemaTypes,
4290
+ keyGenerator
4291
+ }), withEditableAPI = createWithEditableAPI(
4298
4292
  portableTextEditor,
4299
4293
  schemaTypes,
4300
4294
  keyGenerator
4301
4295
  ), withPatches = createWithPatches({
4302
- change$,
4296
+ editorActor,
4303
4297
  keyGenerator,
4304
4298
  patches$,
4305
4299
  patchFunctions: operationToPatches,
@@ -4310,15 +4304,18 @@ const originalFnMap = /* @__PURE__ */ new WeakMap(), withPlugins = (editor, opti
4310
4304
  patches$,
4311
4305
  blockSchemaType: schemaTypes.block
4312
4306
  }), withPortableTextMarkModel = createWithPortableTextMarkModel(
4307
+ editorActor,
4313
4308
  schemaTypes,
4314
- change$,
4315
4309
  keyGenerator
4316
- ), withPortableTextBlockStyle = createWithPortableTextBlockStyle(schemaTypes), withPlaceholderBlock = createWithPlaceholderBlock(), withInsertBreak = createWithInsertBreak(schemaTypes, keyGenerator), withUtils = createWithUtils({
4310
+ ), withPortableTextBlockStyle = createWithPortableTextBlockStyle(
4311
+ editorActor,
4312
+ schemaTypes
4313
+ ), withPlaceholderBlock = createWithPlaceholderBlock(), withInsertBreak = createWithInsertBreak(schemaTypes, keyGenerator), withUtils = createWithUtils({
4317
4314
  keyGenerator,
4318
4315
  schemaTypes,
4319
4316
  portableTextEditor
4320
4317
  }), withPortableTextSelections = createWithPortableTextSelections(
4321
- change$,
4318
+ editorActor,
4322
4319
  schemaTypes
4323
4320
  );
4324
4321
  return e.destroy = () => {
@@ -4435,7 +4432,7 @@ const defaultKeyGenerator = () => content.randomKey(12), PortableTextEditorKeyGe
4435
4432
  return readOnly;
4436
4433
  }, debug$5 = debugWithName("hook:useSyncValue"), CURRENT_VALUE = /* @__PURE__ */ new WeakMap();
4437
4434
  function useSyncValue(props) {
4438
- const { portableTextEditor, readOnly, keyGenerator } = props, { change$, schemaTypes } = portableTextEditor, previousValue = react.useRef(), slateEditor = slateReact.useSlate(), updateValueFunctionRef = react.useRef(), updateFromCurrentValue = react.useCallback(() => {
4435
+ const { editorActor, portableTextEditor, readOnly, keyGenerator } = props, { schemaTypes } = portableTextEditor, previousValue = react.useRef(), slateEditor = slateReact.useSlate(), updateValueFunctionRef = react.useRef(), updateFromCurrentValue = react.useCallback(() => {
4439
4436
  const currentValue = CURRENT_VALUE.get(portableTextEditor);
4440
4437
  if (previousValue.current === currentValue) {
4441
4438
  debug$5("Value is the same object as previous, not need to sync");
@@ -4506,7 +4503,7 @@ function useSyncValue(props) {
4506
4503
  !validation.valid && validation.resolution?.autoResolve && validation.resolution?.patches.length > 0 && !readOnly && previousValue.current && previousValue.current !== value && (console.warn(
4507
4504
  `${validation.resolution.action} for block with _key '${validationValue[0]._key}'. ${validation.resolution?.description}`
4508
4505
  ), validation.resolution.patches.forEach((patch) => {
4509
- change$.next({ type: "patch", patch });
4506
+ editorActor.send({ type: "patch", patch });
4510
4507
  })), validation.valid || validation.resolution?.autoResolve ? (oldBlock._key === currentBlock._key ? (debug$5.enabled && debug$5("Updating block", oldBlock, currentBlock), _updateBlock(
4511
4508
  slateEditor,
4512
4509
  currentBlock,
@@ -4516,8 +4513,8 @@ function useSyncValue(props) {
4516
4513
  slateEditor,
4517
4514
  currentBlock,
4518
4515
  currentBlockIndex
4519
- )), isChanged = !0) : (change$.next({
4520
- type: "invalidValue",
4516
+ )), isChanged = !0) : (editorActor.send({
4517
+ type: "invalid value",
4521
4518
  resolution: validation.resolution,
4522
4519
  value
4523
4520
  }), isValid = !1);
@@ -4533,8 +4530,8 @@ function useSyncValue(props) {
4533
4530
  currentBlock
4534
4531
  ), validation.valid || validation.resolution?.autoResolve ? slate.Transforms.insertNodes(slateEditor, currentBlock, {
4535
4532
  at: [currentBlockIndex]
4536
- }) : (debug$5("Invalid", validation), change$.next({
4537
- type: "invalidValue",
4533
+ }) : (debug$5("Invalid", validation), editorActor.send({
4534
+ type: "invalid value",
4538
4535
  resolution: validation.resolution,
4539
4536
  value
4540
4537
  }), isValid = !1);
@@ -4555,8 +4552,8 @@ function useSyncValue(props) {
4555
4552
  try {
4556
4553
  slateEditor.onChange();
4557
4554
  } catch (err) {
4558
- console.error(err), change$.next({
4559
- type: "invalidValue",
4555
+ console.error(err), editorActor.send({
4556
+ type: "invalid value",
4560
4557
  resolution: null,
4561
4558
  value
4562
4559
  });
@@ -4565,14 +4562,14 @@ function useSyncValue(props) {
4565
4562
  hadSelection && !slateEditor.selection && (slate.Transforms.select(slateEditor, {
4566
4563
  anchor: { path: [0, 0], offset: 0 },
4567
4564
  focus: { path: [0, 0], offset: 0 }
4568
- }), slateEditor.onChange()), change$.next({ type: "value", value });
4565
+ }), slateEditor.onChange()), editorActor.send({ type: "value changed", value });
4569
4566
  } else
4570
4567
  debug$5("Server value and editor value is equal, no need to sync.");
4571
4568
  previousValue.current = value;
4572
4569
  };
4573
4570
  return updateValueFunctionRef.current = updateFunction, updateFunction;
4574
4571
  }, [
4575
- change$,
4572
+ editorActor,
4576
4573
  keyGenerator,
4577
4574
  portableTextEditor,
4578
4575
  readOnly,
@@ -4641,9 +4638,9 @@ function _updateBlock(slateEditor, currentBlock, oldBlock, currentBlockIndex) {
4641
4638
  }
4642
4639
  const debug$4 = debugWithName("component:PortableTextEditor:Synchronizer"), debugVerbose$1 = debug$4.enabled && !1, FLUSH_PATCHES_THROTTLED_MS = process.env.NODE_ENV === "test" ? 500 : 1e3;
4643
4640
  function Synchronizer(props) {
4644
- const portableTextEditor = usePortableTextEditor(), keyGenerator = usePortableTextEditorKeyGenerator(), readOnly = usePortableTextEditorReadOnlyStatus(), { change$, getValue, onChange, value } = props, pendingPatches = react.useRef([]), syncValue = useSyncValue({
4641
+ const portableTextEditor = usePortableTextEditor(), keyGenerator = usePortableTextEditorKeyGenerator(), readOnly = usePortableTextEditorReadOnlyStatus(), { editorActor, getValue, onChange, value } = props, pendingPatches = react.useRef([]), syncValue = useSyncValue({
4642
+ editorActor,
4645
4643
  keyGenerator,
4646
- onChange,
4647
4644
  portableTextEditor,
4648
4645
  readOnly
4649
4646
  }), slateEditor = slateReact.useSlate();
@@ -4655,14 +4652,14 @@ function Synchronizer(props) {
4655
4652
  debug$4("Flushing pending patches"), debugVerbose$1 && debug$4(`Patches:
4656
4653
  ${JSON.stringify(pendingPatches.current, null, 2)}`);
4657
4654
  const snapshot = getValue();
4658
- change$.next({
4655
+ editorActor.send({
4659
4656
  type: "mutation",
4660
4657
  patches: pendingPatches.current,
4661
4658
  snapshot
4662
4659
  }), pendingPatches.current = [];
4663
4660
  }
4664
4661
  IS_PROCESSING_LOCAL_CHANGES.set(slateEditor, !1);
4665
- }, [slateEditor, getValue, change$]), onFlushPendingPatchesThrottled = react.useMemo(() => throttle__default.default(
4662
+ }, [editorActor, slateEditor, getValue]), onFlushPendingPatchesThrottled = react.useMemo(() => throttle__default.default(
4666
4663
  () => {
4667
4664
  if (slate.Editor.isNormalizing(slateEditor)) {
4668
4665
  onFlushPendingPatches();
@@ -4679,34 +4676,174 @@ ${JSON.stringify(pendingPatches.current, null, 2)}`);
4679
4676
  react.useEffect(() => () => {
4680
4677
  onFlushPendingPatches();
4681
4678
  }, [onFlushPendingPatches]), react.useEffect(() => {
4682
- debug$4("Subscribing to editor changes$");
4683
- const sub = change$.subscribe((next) => {
4684
- switch (next.type) {
4679
+ debug$4("Subscribing to editor changes");
4680
+ const sub = editorActor.on("*", (event) => {
4681
+ switch (event.type) {
4685
4682
  case "patch":
4686
- IS_PROCESSING_LOCAL_CHANGES.set(slateEditor, !0), pendingPatches.current.push(next.patch), onFlushPendingPatchesThrottled(), onChange(next);
4683
+ IS_PROCESSING_LOCAL_CHANGES.set(slateEditor, !0), pendingPatches.current.push(event.patch), onFlushPendingPatchesThrottled(), onChange(event);
4684
+ break;
4685
+ case "loading": {
4686
+ onChange({ type: "loading", isLoading: !0 });
4687
+ break;
4688
+ }
4689
+ case "done loading": {
4690
+ onChange({ type: "loading", isLoading: !1 });
4691
+ break;
4692
+ }
4693
+ case "offline": {
4694
+ onChange({ type: "connection", value: "offline" });
4695
+ break;
4696
+ }
4697
+ case "online": {
4698
+ onChange({ type: "connection", value: "online" });
4699
+ break;
4700
+ }
4701
+ case "value changed": {
4702
+ onChange({ type: "value", value: event.value });
4703
+ break;
4704
+ }
4705
+ case "invalid value": {
4706
+ onChange({
4707
+ type: "invalidValue",
4708
+ resolution: event.resolution,
4709
+ value: event.value
4710
+ });
4687
4711
  break;
4712
+ }
4713
+ case "error": {
4714
+ onChange({
4715
+ ...event,
4716
+ level: "warning"
4717
+ });
4718
+ break;
4719
+ }
4688
4720
  default:
4689
- onChange(next);
4721
+ onChange(event);
4690
4722
  }
4691
4723
  });
4692
4724
  return () => {
4693
- debug$4("Unsubscribing to changes$"), sub.unsubscribe();
4725
+ debug$4("Unsubscribing to changes"), sub.unsubscribe();
4694
4726
  };
4695
- }, [change$, onChange, onFlushPendingPatchesThrottled, slateEditor]);
4727
+ }, [editorActor, onFlushPendingPatchesThrottled, slateEditor]);
4696
4728
  const handleOnline = react.useCallback(() => {
4697
- debug$4("Editor is online, syncing from props.value"), change$.next({ type: "connection", value: "online" }), syncValue(value);
4698
- }, [change$, syncValue, value]), handleOffline = react.useCallback(() => {
4699
- debug$4("Editor is offline"), change$.next({ type: "connection", value: "offline" });
4700
- }, [change$]);
4701
- react.useEffect(() => (portableTextEditor.props.patches$ && (window.addEventListener("online", handleOnline), window.addEventListener("offline", handleOffline)), () => {
4702
- portableTextEditor.props.patches$ && (window.removeEventListener("online", handleOnline), window.removeEventListener("offline", handleOffline));
4703
- }));
4729
+ debug$4("Editor is online, syncing from props.value"), syncValue(value);
4730
+ }, [syncValue, value]);
4731
+ react.useEffect(() => {
4732
+ const subscription = editorActor.on("online", () => {
4733
+ portableTextEditor.props.patches$ && handleOnline();
4734
+ });
4735
+ return () => {
4736
+ subscription.unsubscribe();
4737
+ };
4738
+ }, [editorActor]);
4704
4739
  const isInitialValueFromProps = react.useRef(!0);
4705
4740
  return react.useEffect(() => {
4706
- 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);
4707
- }, [change$, syncValue, value]), null;
4741
+ debug$4("Value from props changed, syncing new value"), syncValue(value), isInitialValueFromProps.current && (editorActor.send({ type: "ready" }), isInitialValueFromProps.current = !1);
4742
+ }, [editorActor, syncValue, value]), null;
4708
4743
  }
4709
- const PortableTextEditorSelectionContext = react.createContext(null), usePortableTextEditorSelection = () => {
4744
+ const networkLogic = xstate.fromCallback(({ sendBack }) => {
4745
+ const onlineHandler = () => {
4746
+ sendBack({ type: "online" });
4747
+ }, offlineHandler = () => {
4748
+ sendBack({ type: "offline" });
4749
+ };
4750
+ return window.addEventListener("online", onlineHandler), window.addEventListener("offline", offlineHandler), () => {
4751
+ window.removeEventListener("online", onlineHandler), window.removeEventListener("offline", offlineHandler);
4752
+ };
4753
+ }), editorMachine = xstate.setup({
4754
+ types: {
4755
+ context: {},
4756
+ events: {},
4757
+ emitted: {}
4758
+ },
4759
+ actions: {
4760
+ "emit patch event": xstate.emit(({ event }) => (xstate.assertEvent(event, "patch"), event)),
4761
+ "emit mutation event": xstate.emit(({ event }) => (xstate.assertEvent(event, "mutation"), event)),
4762
+ "defer event": xstate.assign({
4763
+ pendingEvents: ({ context, event }) => (xstate.assertEvent(event, ["patch", "mutation"]), [...context.pendingEvents, event])
4764
+ }),
4765
+ "emit pending events": xstate.enqueueActions(({ context, enqueue }) => {
4766
+ for (const event of context.pendingEvents)
4767
+ enqueue(xstate.emit(event));
4768
+ }),
4769
+ "clear pending events": xstate.assign({
4770
+ pendingEvents: []
4771
+ })
4772
+ },
4773
+ actors: {
4774
+ networkLogic
4775
+ }
4776
+ }).createMachine({
4777
+ id: "editor",
4778
+ context: {
4779
+ pendingEvents: []
4780
+ },
4781
+ invoke: {
4782
+ id: "networkLogic",
4783
+ src: "networkLogic"
4784
+ },
4785
+ on: {
4786
+ ready: { actions: xstate.emit(({ event }) => event) },
4787
+ unset: { actions: xstate.emit(({ event }) => event) },
4788
+ "value changed": { actions: xstate.emit(({ event }) => event) },
4789
+ "invalid value": { actions: xstate.emit(({ event }) => event) },
4790
+ error: { actions: xstate.emit(({ event }) => event) },
4791
+ selection: { actions: xstate.emit(({ event }) => event) },
4792
+ blur: { actions: xstate.emit(({ event }) => event) },
4793
+ focus: { actions: xstate.emit(({ event }) => event) },
4794
+ online: { actions: xstate.emit({ type: "online" }) },
4795
+ offline: { actions: xstate.emit({ type: "offline" }) },
4796
+ loading: { actions: xstate.emit({ type: "loading" }) },
4797
+ "done loading": { actions: xstate.emit({ type: "done loading" }) }
4798
+ },
4799
+ initial: "pristine",
4800
+ states: {
4801
+ pristine: {
4802
+ initial: "idle",
4803
+ states: {
4804
+ idle: {
4805
+ on: {
4806
+ normalizing: {
4807
+ target: "normalizing"
4808
+ },
4809
+ patch: {
4810
+ actions: "defer event",
4811
+ target: "#editor.dirty"
4812
+ },
4813
+ mutation: {
4814
+ actions: "defer event",
4815
+ target: "#editor.dirty"
4816
+ }
4817
+ }
4818
+ },
4819
+ normalizing: {
4820
+ on: {
4821
+ "done normalizing": {
4822
+ target: "idle"
4823
+ },
4824
+ patch: {
4825
+ actions: "defer event"
4826
+ },
4827
+ mutation: {
4828
+ actions: "defer event"
4829
+ }
4830
+ }
4831
+ }
4832
+ }
4833
+ },
4834
+ dirty: {
4835
+ entry: ["emit pending events", "clear pending events"],
4836
+ on: {
4837
+ patch: {
4838
+ actions: "emit patch event"
4839
+ },
4840
+ mutation: {
4841
+ actions: "emit mutation event"
4842
+ }
4843
+ }
4844
+ }
4845
+ }
4846
+ }), PortableTextEditorSelectionContext = react.createContext(null), usePortableTextEditorSelection = () => {
4710
4847
  const selection = react.useContext(PortableTextEditorSelectionContext);
4711
4848
  if (selection === void 0)
4712
4849
  throw new Error(
@@ -4715,21 +4852,26 @@ const PortableTextEditorSelectionContext = react.createContext(null), usePortabl
4715
4852
  return selection;
4716
4853
  }, debug$3 = debugWithName("component:PortableTextEditor:SelectionProvider"), debugVerbose = debug$3.enabled && !1;
4717
4854
  function PortableTextEditorSelectionProvider(props) {
4718
- const { change$ } = props, [selection, setSelection] = react.useState(null);
4855
+ const [selection, setSelection] = react.useState(null);
4719
4856
  return react.useEffect(() => {
4720
- debug$3("Subscribing to selection changes$");
4721
- const subscription = change$.subscribe((next) => {
4722
- next.type === "selection" && react.startTransition(() => {
4723
- debugVerbose && debug$3("Setting selection"), setSelection(next.selection);
4857
+ debug$3("Subscribing to selection changes");
4858
+ const subscription = props.editorActor.on("selection", (event) => {
4859
+ react.startTransition(() => {
4860
+ debugVerbose && debug$3("Setting selection"), setSelection(event.selection);
4724
4861
  });
4725
4862
  });
4726
4863
  return () => {
4727
- debug$3("Unsubscribing to selection changes$"), subscription.unsubscribe();
4864
+ debug$3("Unsubscribing to selection changes"), subscription.unsubscribe();
4728
4865
  };
4729
- }, [change$]), /* @__PURE__ */ jsxRuntime.jsx(PortableTextEditorSelectionContext.Provider, { value: selection, children: props.children });
4866
+ }, [props.editorActor]), /* @__PURE__ */ jsxRuntime.jsx(PortableTextEditorSelectionContext.Provider, { value: selection, children: props.children });
4730
4867
  }
4731
4868
  const debug$2 = debugWithName("component:PortableTextEditor");
4732
4869
  class PortableTextEditor extends react.Component {
4870
+ /**
4871
+ * @internal
4872
+ * Don't use this API directly. It's subject to change.
4873
+ */
4874
+ editorActor;
4733
4875
  /**
4734
4876
  * An observable of all the editor changes.
4735
4877
  */
@@ -4747,7 +4889,7 @@ class PortableTextEditor extends react.Component {
4747
4889
  throw new Error('PortableTextEditor: missing "schemaType" property');
4748
4890
  props.incomingPatches$ && console.warn(
4749
4891
  "The prop 'incomingPatches$' is deprecated and renamed to 'patches$'"
4750
- ), this.change$.next({ type: "loading", isLoading: !0 }), this.schemaTypes = getPortableTextMemberSchemaTypes(
4892
+ ), this.editorActor = xstate.createActor(editorMachine), this.editorActor.start(), this.schemaTypes = getPortableTextMemberSchemaTypes(
4751
4893
  props.schemaType.hasOwnProperty("jsonType") ? props.schemaType : compileType(props.schemaType)
4752
4894
  );
4753
4895
  }
@@ -4764,7 +4906,7 @@ class PortableTextEditor extends react.Component {
4764
4906
  return this.editable.getValue();
4765
4907
  };
4766
4908
  render() {
4767
- 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;
4909
+ 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;
4768
4910
  return /* @__PURE__ */ jsxRuntime.jsx(
4769
4911
  SlateContainer,
4770
4912
  {
@@ -4773,18 +4915,26 @@ class PortableTextEditor extends react.Component {
4773
4915
  patches$: _patches$,
4774
4916
  portableTextEditor: this,
4775
4917
  readOnly,
4776
- children: /* @__PURE__ */ jsxRuntime.jsx(PortableTextEditorKeyGeneratorContext.Provider, { value: keyGenerator, children: /* @__PURE__ */ jsxRuntime.jsx(PortableTextEditorContext.Provider, { value: this, children: /* @__PURE__ */ jsxRuntime.jsx(PortableTextEditorReadOnlyContext.Provider, { value: readOnly, children: /* @__PURE__ */ jsxRuntime.jsxs(PortableTextEditorSelectionProvider, { change$, children: [
4777
- /* @__PURE__ */ jsxRuntime.jsx(
4778
- Synchronizer,
4779
- {
4780
- change$,
4781
- getValue: this.getValue,
4782
- onChange,
4783
- value
4784
- }
4785
- ),
4786
- children
4787
- ] }) }) }) })
4918
+ children: /* @__PURE__ */ jsxRuntime.jsx(PortableTextEditorKeyGeneratorContext.Provider, { value: keyGenerator, children: /* @__PURE__ */ jsxRuntime.jsx(PortableTextEditorContext.Provider, { value: this, children: /* @__PURE__ */ jsxRuntime.jsx(PortableTextEditorReadOnlyContext.Provider, { value: readOnly, children: /* @__PURE__ */ jsxRuntime.jsxs(
4919
+ PortableTextEditorSelectionProvider,
4920
+ {
4921
+ editorActor: this.editorActor,
4922
+ children: [
4923
+ /* @__PURE__ */ jsxRuntime.jsx(
4924
+ Synchronizer,
4925
+ {
4926
+ editorActor: this.editorActor,
4927
+ getValue: this.getValue,
4928
+ onChange: (change) => {
4929
+ this.props.onChange(change), this.change$.next(change);
4930
+ },
4931
+ value
4932
+ }
4933
+ ),
4934
+ children
4935
+ ]
4936
+ }
4937
+ ) }) }) })
4788
4938
  }
4789
4939
  );
4790
4940
  }
@@ -4894,20 +5044,19 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
4894
5044
  react.useEffect(() => {
4895
5045
  if (!shouldTrackSelectionAndFocus)
4896
5046
  return;
4897
- const sub = portableTextEditor.change$.subscribe((next) => {
4898
- if (next.type === "blur") {
4899
- setFocused(!1), setSelected(!1);
4900
- return;
5047
+ const onBlur = portableTextEditor.editorActor.on("blur", () => {
5048
+ setFocused(!1), setSelected(!1);
5049
+ }), onFocus = portableTextEditor.editorActor.on("focus", () => {
5050
+ const sel = PortableTextEditor.getSelection(portableTextEditor);
5051
+ sel && isEqual__default.default(sel.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) && setFocused(!0), setSelectedFromRange();
5052
+ }), onSelection = portableTextEditor.editorActor.on(
5053
+ "selection",
5054
+ (event) => {
5055
+ event.selection && isEqual__default.default(event.selection.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) ? setFocused(!0) : setFocused(!1), setSelectedFromRange();
4901
5056
  }
4902
- if (next.type === "focus") {
4903
- const sel = PortableTextEditor.getSelection(portableTextEditor);
4904
- sel && isEqual__default.default(sel.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) && setFocused(!0), setSelectedFromRange();
4905
- return;
4906
- }
4907
- next.type === "selection" && (next.selection && isEqual__default.default(next.selection.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) ? setFocused(!0) : setFocused(!1), setSelectedFromRange());
4908
- });
5057
+ );
4909
5058
  return () => {
4910
- sub.unsubscribe();
5059
+ onBlur.unsubscribe(), onFocus.unsubscribe(), onSelection.unsubscribe();
4911
5060
  };
4912
5061
  }, [
4913
5062
  path,
@@ -5058,9 +5207,9 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5058
5207
  forwardedRef,
5059
5208
  () => ref.current
5060
5209
  );
5061
- const rangeDecorationsRef = react.useRef(rangeDecorations), { change$, schemaTypes } = portableTextEditor, slateEditor = slateReact.useSlate(), blockTypeName = schemaTypes.block.name, withInsertData = react.useMemo(
5062
- () => createWithInsertData(change$, schemaTypes, keyGenerator),
5063
- [change$, keyGenerator, schemaTypes]
5210
+ const rangeDecorationsRef = react.useRef(rangeDecorations), { editorActor, schemaTypes } = portableTextEditor, slateEditor = slateReact.useSlate(), blockTypeName = schemaTypes.block.name, withInsertData = react.useMemo(
5211
+ () => createWithInsertData(editorActor, schemaTypes, keyGenerator),
5212
+ [editorActor, keyGenerator, schemaTypes]
5064
5213
  ), withHotKeys = react.useMemo(
5065
5214
  () => createWithHotkeys(schemaTypes, portableTextEditor, hotkeys),
5066
5215
  [hotkeys, portableTextEditor, schemaTypes]
@@ -5133,10 +5282,13 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5133
5282
  `Normalized selection from props ${JSON.stringify(normalizedSelection)}`
5134
5283
  );
5135
5284
  const slateRange = toSlateRange(normalizedSelection, slateEditor);
5136
- slateRange && (slate.Transforms.select(slateEditor, slateRange), slateEditor.operations.some((o) => o.type === "set_selection") || change$.next({ type: "selection", selection: normalizedSelection }), slateEditor.onChange());
5285
+ slateRange && (slate.Transforms.select(slateEditor, slateRange), slateEditor.operations.some((o) => o.type === "set_selection") || editorActor.send({
5286
+ type: "selection",
5287
+ selection: normalizedSelection
5288
+ }), slateEditor.onChange());
5137
5289
  }
5138
5290
  }
5139
- }, [propsSelection, slateEditor, blockTypeName, change$]), syncRangeDecorations = react.useCallback(
5291
+ }, [editorActor, propsSelection, slateEditor]), syncRangeDecorations = react.useCallback(
5140
5292
  (operation) => {
5141
5293
  if (rangeDecorations && rangeDecorations.length > 0) {
5142
5294
  const newSlateRanges = [];
@@ -5175,28 +5327,22 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5175
5327
  return;
5176
5328
  }
5177
5329
  }
5178
- setRangeDecorationsState([]);
5330
+ rangeDecorationState.length > 0 && setRangeDecorationsState([]);
5179
5331
  },
5180
5332
  [portableTextEditor, rangeDecorations, schemaTypes, slateEditor]
5181
5333
  );
5182
5334
  react.useEffect(() => {
5183
- const sub = change$.subscribe((next) => {
5184
- switch (next.type) {
5185
- case "ready":
5186
- restoreSelectionFromProps();
5187
- break;
5188
- case "invalidValue":
5189
- setHasInvalidValue(!0);
5190
- break;
5191
- case "value":
5192
- setHasInvalidValue(!1);
5193
- break;
5194
- }
5335
+ const onReady = editorActor.on("ready", () => {
5336
+ restoreSelectionFromProps();
5337
+ }), onInvalidValue = editorActor.on("invalid value", () => {
5338
+ setHasInvalidValue(!0);
5339
+ }), onValueChanged = editorActor.on("value changed", () => {
5340
+ setHasInvalidValue(!1);
5195
5341
  });
5196
5342
  return () => {
5197
- sub.unsubscribe();
5343
+ onReady.unsubscribe(), onInvalidValue.unsubscribe(), onValueChanged.unsubscribe();
5198
5344
  };
5199
- }, [change$, restoreSelectionFromProps]), react.useEffect(() => {
5345
+ }, [editorActor, restoreSelectionFromProps]), react.useEffect(() => {
5200
5346
  propsSelection && !hasInvalidValue && restoreSelectionFromProps();
5201
5347
  }, [hasInvalidValue, propsSelection, restoreSelectionFromProps]);
5202
5348
  const originalApply = react.useMemo(() => slateEditor.apply, [slateEditor]), [syncedRangeDecorations, setSyncedRangeDecorations] = react.useState(!1);
@@ -5227,7 +5373,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5227
5373
  slateEditor.selection,
5228
5374
  schemaTypes
5229
5375
  )?.focus.path || [], onPasteResult = onPaste({ event, value, path, schemaTypes });
5230
- 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) => {
5376
+ 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) => {
5231
5377
  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(
5232
5378
  toSlateValue(result.insert, {
5233
5379
  schemaTypes
@@ -5237,23 +5383,23 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5237
5383
  result
5238
5384
  );
5239
5385
  }).catch((error) => (console.error(error), error)).finally(() => {
5240
- change$.next({ type: "loading", isLoading: !1 });
5386
+ editorActor.send({ type: "done loading" });
5241
5387
  }));
5242
5388
  },
5243
- [change$, onPaste, portableTextEditor, schemaTypes, slateEditor]
5389
+ [onPaste, portableTextEditor, schemaTypes, slateEditor]
5244
5390
  ), handleOnFocus = react.useCallback(
5245
5391
  (event) => {
5246
5392
  if (onFocus && onFocus(event), !event.isDefaultPrevented()) {
5247
5393
  const selection = PortableTextEditor.getSelection(portableTextEditor);
5248
- selection === null && (slate.Transforms.select(slateEditor, slate.Editor.start(slateEditor, [])), slateEditor.onChange()), change$.next({ type: "focus", event });
5394
+ selection === null && (slate.Transforms.select(slateEditor, slate.Editor.start(slateEditor, [])), slateEditor.onChange()), editorActor.send({ type: "focus", event });
5249
5395
  const newSelection = PortableTextEditor.getSelection(portableTextEditor);
5250
- selection === newSelection && change$.next({
5396
+ selection === newSelection && editorActor.send({
5251
5397
  type: "selection",
5252
5398
  selection
5253
5399
  });
5254
5400
  }
5255
5401
  },
5256
- [onFocus, portableTextEditor, change$, slateEditor]
5402
+ [editorActor, onFocus, portableTextEditor, slateEditor]
5257
5403
  ), handleClick = react.useCallback(
5258
5404
  (event) => {
5259
5405
  if (onClick && onClick(event), slateEditor.selection && event.target === event.currentTarget) {
@@ -5270,9 +5416,9 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5270
5416
  [onClick, slateEditor]
5271
5417
  ), handleOnBlur = react.useCallback(
5272
5418
  (event) => {
5273
- onBlur && onBlur(event), event.isPropagationStopped() || change$.next({ type: "blur", event });
5419
+ onBlur && onBlur(event), event.isPropagationStopped() || editorActor.send({ type: "blur", event });
5274
5420
  },
5275
- [change$, onBlur]
5421
+ [editorActor, onBlur]
5276
5422
  ), handleOnBeforeInput = react.useCallback(
5277
5423
  (event) => {
5278
5424
  onBeforeInput && onBeforeInput(event);
@@ -5377,6 +5523,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5377
5523
  });
5378
5524
  exports.PortableTextEditable = PortableTextEditable;
5379
5525
  exports.PortableTextEditor = PortableTextEditor;
5526
+ exports.editorMachine = editorMachine;
5380
5527
  exports.keyGenerator = defaultKeyGenerator;
5381
5528
  exports.usePortableTextEditor = usePortableTextEditor;
5382
5529
  exports.usePortableTextEditorSelection = usePortableTextEditorSelection;