@portabletext/editor 1.1.1 → 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 (51) hide show
  1. package/README.md +3 -0
  2. package/lib/index.d.mts +1667 -0
  3. package/lib/index.d.ts +1667 -0
  4. package/lib/index.esm.js +305 -153
  5. package/lib/index.esm.js.map +1 -1
  6. package/lib/index.js +305 -154
  7. package/lib/index.js.map +1 -1
  8. package/lib/index.mjs +305 -153
  9. package/lib/index.mjs.map +1 -1
  10. package/package.json +23 -22
  11. package/src/editor/Editable.tsx +30 -31
  12. package/src/editor/PortableTextEditor.tsx +23 -6
  13. package/src/editor/__tests__/PortableTextEditor.test.tsx +9 -9
  14. package/src/editor/__tests__/PortableTextEditorTester.tsx +2 -5
  15. package/src/editor/__tests__/RangeDecorations.test.tsx +2 -2
  16. package/src/editor/__tests__/handleClick.test.tsx +27 -7
  17. package/src/editor/__tests__/insert-block.test.tsx +4 -4
  18. package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +7 -7
  19. package/src/editor/__tests__/self-solving.test.tsx +176 -0
  20. package/src/editor/components/Leaf.tsx +28 -23
  21. package/src/editor/components/Synchronizer.tsx +60 -32
  22. package/src/editor/editor-machine.ts +195 -0
  23. package/src/editor/hooks/usePortableTextEditorSelection.tsx +11 -13
  24. package/src/editor/hooks/useSyncValue.test.tsx +9 -9
  25. package/src/editor/hooks/useSyncValue.ts +14 -13
  26. package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +1 -1
  27. package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +28 -28
  28. package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +17 -17
  29. package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +8 -8
  30. package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +5 -5
  31. package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +2 -2
  32. package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +46 -46
  33. package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +22 -11
  34. package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +9 -9
  35. package/src/editor/plugins/createWithInsertData.ts +4 -8
  36. package/src/editor/plugins/createWithObjectKeys.ts +7 -0
  37. package/src/editor/plugins/createWithPatches.ts +5 -6
  38. package/src/editor/plugins/createWithPortableTextBlockStyle.ts +10 -2
  39. package/src/editor/plugins/createWithPortableTextMarkModel.ts +20 -4
  40. package/src/editor/plugins/createWithPortableTextSelections.ts +4 -5
  41. package/src/editor/plugins/createWithSchemaTypes.ts +9 -0
  42. package/src/editor/plugins/index.ts +18 -8
  43. package/src/index.ts +9 -3
  44. package/src/utils/__tests__/dmpToOperations.test.ts +1 -1
  45. package/src/utils/__tests__/operationToPatches.test.ts +61 -61
  46. package/src/utils/__tests__/patchToOperations.test.ts +39 -39
  47. package/src/utils/__tests__/ranges.test.ts +1 -1
  48. package/src/utils/__tests__/valueNormalization.test.tsx +14 -2
  49. package/src/utils/__tests__/values.test.ts +17 -17
  50. package/src/utils/validateValue.ts +0 -22
  51. package/src/editor/__tests__/utils.ts +0 -44
package/lib/index.mjs CHANGED
@@ -9,6 +9,7 @@ import { isKeySegment, isPortableTextSpan as isPortableTextSpan$1, isPortableTex
9
9
  import { styled } from "styled-components";
10
10
  import uniq from "lodash/uniq.js";
11
11
  import { Subject } from "rxjs";
12
+ import { fromCallback, setup, emit, assertEvent, assign, enqueueActions, createActor } from "xstate";
12
13
  import { Schema } from "@sanity/schema";
13
14
  import { diffMatchPatch as diffMatchPatch$1, set, insert, setIfMissing, unset, applyAll } from "@portabletext/patches";
14
15
  import get from "lodash/get.js";
@@ -126,7 +127,7 @@ function normalizeSelection(selection, value) {
126
127
  const { anchor, focus } = selection;
127
128
  return anchor && value.find((blk) => isEqual({ _key: blk._key }, anchor.path[0])) && (newAnchor = normalizePoint(anchor, value)), focus && value.find((blk) => isEqual({ _key: blk._key }, focus.path[0])) && (newFocus = normalizePoint(focus, value)), newAnchor && newFocus ? { anchor: newAnchor, focus: newFocus, backward: selection.backward } : null;
128
129
  }
129
- const EMPTY_MARKDEFS = [], VOID_CHILD_KEY = "void-child";
130
+ const VOID_CHILD_KEY = "void-child";
130
131
  function keepObjectEquality(object, keyMap) {
131
132
  const value = keyMap[object._key];
132
133
  return value && isEqual(object, value) ? value : (keyMap[object._key] = object, object);
@@ -1710,7 +1711,7 @@ function createWithMaxBlocks(maxBlocks) {
1710
1711
  }, editor;
1711
1712
  };
1712
1713
  }
1713
- function createWithObjectKeys(schemaTypes, keyGenerator) {
1714
+ function createWithObjectKeys(editorActor, schemaTypes, keyGenerator) {
1714
1715
  return function(editor) {
1715
1716
  const { apply: apply2, normalizeNode } = editor;
1716
1717
  return editor.apply = (operation) => {
@@ -1746,10 +1747,13 @@ function createWithObjectKeys(schemaTypes, keyGenerator) {
1746
1747
  }, editor.normalizeNode = (entry) => {
1747
1748
  const [node, path] = entry;
1748
1749
  if (Element$1.isElement(node) && node._type === schemaTypes.block.name) {
1749
- node._key || Transforms.setNodes(editor, { _key: keyGenerator() }, { at: path });
1750
+ if (!node._key) {
1751
+ editorActor.send({ type: "normalizing" }), Transforms.setNodes(editor, { _key: keyGenerator() }, { at: path }), editorActor.send({ type: "done normalizing" });
1752
+ return;
1753
+ }
1750
1754
  for (const [child, childPath] of Node.children(editor, path))
1751
1755
  if (!child._key) {
1752
- Transforms.setNodes(editor, { _key: keyGenerator() }, { at: childPath });
1756
+ editorActor.send({ type: "normalizing" }), Transforms.setNodes(editor, { _key: keyGenerator() }, { at: childPath }), editorActor.send({ type: "done normalizing" });
1753
1757
  return;
1754
1758
  }
1755
1759
  }
@@ -2906,7 +2910,7 @@ function findOperationTargetBlock(editor, operation) {
2906
2910
  }
2907
2911
  const debug$g = debugWithName("plugin:withPatches");
2908
2912
  function createWithPatches({
2909
- change$,
2913
+ editorActor,
2910
2914
  patches$,
2911
2915
  patchFunctions,
2912
2916
  readOnly,
@@ -3035,7 +3039,7 @@ function createWithPatches({
3035
3039
  }
3036
3040
  return !editorWasEmpty && editorIsEmpty && ["merge_node", "set_node", "remove_text", "remove_node"].includes(
3037
3041
  operation.type
3038
- ) && (patches = [...patches, unset([])], change$.next({
3042
+ ) && (patches = [...patches, unset([])], editorActor.send({
3039
3043
  type: "unset",
3040
3044
  previousValue: fromSlateValue(
3041
3045
  previousChildren,
@@ -3043,7 +3047,7 @@ function createWithPatches({
3043
3047
  KEY_TO_VALUE_ELEMENT.get(editor)
3044
3048
  )
3045
3049
  })), editorWasEmpty && patches.length > 0 && (patches = [setIfMissing([], []), ...patches]), patches.length > 0 && patches.forEach((patch) => {
3046
- change$.next({
3050
+ editorActor.send({
3047
3051
  type: "patch",
3048
3052
  patch: { ...patch, origin: "local" }
3049
3053
  });
@@ -3079,25 +3083,25 @@ function createWithPlaceholderBlock() {
3079
3083
  };
3080
3084
  }
3081
3085
  const debug$e = debugWithName("plugin:withPortableTextBlockStyle");
3082
- function createWithPortableTextBlockStyle(types) {
3086
+ function createWithPortableTextBlockStyle(editorActor, types) {
3083
3087
  const defaultStyle = types.styles[0].value;
3084
3088
  return function(editor) {
3085
3089
  const { normalizeNode } = editor;
3086
3090
  return editor.normalizeNode = (nodeEntry) => {
3087
- normalizeNode(nodeEntry);
3088
3091
  const [, path] = nodeEntry;
3089
3092
  for (const op of editor.operations)
3090
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)) {
3091
3094
  const [child] = Editor.node(editor, [op.path[0] + 1, 0]);
3092
3095
  if (Text.isText(child) && child.text === "") {
3093
- 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(
3094
3097
  editor,
3095
3098
  { style: defaultStyle },
3096
3099
  { at: [op.path[0] + 1], voids: !1 }
3097
- );
3098
- break;
3100
+ ), editorActor.send({ type: "done normalizing" });
3101
+ return;
3099
3102
  }
3100
3103
  }
3104
+ normalizeNode(nodeEntry);
3101
3105
  }, editor.pteHasBlockStyle = (style) => editor.selection ? [
3102
3106
  ...Editor.nodes(editor, {
3103
3107
  at: editor.selection,
@@ -3242,7 +3246,7 @@ function isPortableTextBlock(node) {
3242
3246
  );
3243
3247
  }
3244
3248
  const debug$c = debugWithName("plugin:withPortableTextMarkModel");
3245
- function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3249
+ function createWithPortableTextMarkModel(editorActor, types, keyGenerator) {
3246
3250
  return function(editor) {
3247
3251
  const { apply: apply2, normalizeNode } = editor, decorators = types.decorators.map((t) => t.value), forceNewSelection = () => {
3248
3252
  editor.selection && (Transforms.select(editor, { ...editor.selection }), editor.selection = { ...editor.selection });
@@ -3251,7 +3255,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3251
3255
  editor.selection,
3252
3256
  types
3253
3257
  );
3254
- change$.next({ type: "selection", selection: ptRange });
3258
+ editorActor.send({ type: "selection", selection: ptRange });
3255
3259
  };
3256
3260
  return editor.normalizeNode = (nodeEntry) => {
3257
3261
  const [node, path] = nodeEntry;
@@ -3264,20 +3268,20 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3264
3268
  "Merging spans",
3265
3269
  JSON.stringify(child, null, 2),
3266
3270
  JSON.stringify(nextNode, null, 2)
3267
- ), Transforms.mergeNodes(editor, {
3271
+ ), editorActor.send({ type: "normalizing" }), Transforms.mergeNodes(editor, {
3268
3272
  at: [childPath[0], childPath[1] + 1],
3269
3273
  voids: !0
3270
- });
3274
+ }), editorActor.send({ type: "done normalizing" });
3271
3275
  return;
3272
3276
  }
3273
3277
  }
3274
3278
  }
3275
3279
  if (editor.isTextBlock(node) && !Array.isArray(node.markDefs)) {
3276
- 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" });
3277
3281
  return;
3278
3282
  }
3279
3283
  if (editor.isTextSpan(node) && !Array.isArray(node.marks)) {
3280
- 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" });
3281
3285
  return;
3282
3286
  }
3283
3287
  if (editor.isTextSpan(node)) {
@@ -3285,11 +3289,11 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3285
3289
  (mark) => !decorators2.includes(mark)
3286
3290
  );
3287
3291
  if (editor.isTextBlock(block) && node.text === "" && annotations && annotations.length > 0) {
3288
- 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(
3289
3293
  editor,
3290
3294
  { marks: node.marks?.filter((mark) => decorators2.includes(mark)) },
3291
3295
  { at: path }
3292
- );
3296
+ ), editorActor.send({ type: "done normalizing" });
3293
3297
  return;
3294
3298
  }
3295
3299
  }
@@ -3299,7 +3303,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3299
3303
  if (editor.isTextSpan(child)) {
3300
3304
  const marks = child.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators2.includes(mark) && !node.markDefs?.find((def) => def._key === mark));
3301
3305
  if (orphanedAnnotations.length > 0) {
3302
- 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(
3303
3307
  editor,
3304
3308
  {
3305
3309
  marks: marks.filter(
@@ -3307,7 +3311,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3307
3311
  )
3308
3312
  },
3309
3313
  { at: childPath }
3310
- );
3314
+ ), editorActor.send({ type: "done normalizing" });
3311
3315
  return;
3312
3316
  }
3313
3317
  }
@@ -3319,7 +3323,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3319
3323
  (decorator) => decorator.value
3320
3324
  ), marks = node.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators2.includes(mark) && !block.markDefs?.find((def) => def._key === mark));
3321
3325
  if (orphanedAnnotations.length > 0) {
3322
- 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(
3323
3327
  editor,
3324
3328
  {
3325
3329
  marks: marks.filter(
@@ -3327,7 +3331,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3327
3331
  )
3328
3332
  },
3329
3333
  { at: path }
3330
- );
3334
+ ), editorActor.send({ type: "done normalizing" });
3331
3335
  return;
3332
3336
  }
3333
3337
  }
@@ -3336,20 +3340,23 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3336
3340
  const markDefs = node.markDefs ?? [], markDefKeys = /* @__PURE__ */ new Set(), newMarkDefs = [];
3337
3341
  for (const markDef of markDefs)
3338
3342
  markDefKeys.has(markDef._key) || (markDefKeys.add(markDef._key), newMarkDefs.push(markDef));
3339
- markDefs.length !== newMarkDefs.length && (debug$c("Removing duplicate markDefs"), Transforms.setNodes(editor, { markDefs: newMarkDefs }, { at: path }));
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
+ }
3340
3347
  }
3341
3348
  if (editor.isTextBlock(node) && !editor.operations.some(
3342
3349
  (op) => op.type === "merge_node" && "markDefs" in op.properties && op.path.length === 1
3343
3350
  )) {
3344
3351
  const newMarkDefs = (node.markDefs || []).filter((def) => node.children.find((child) => Text.isText(child) && Array.isArray(child.marks) && child.marks.includes(def._key)));
3345
3352
  if (node.markDefs && !isEqual(newMarkDefs, node.markDefs)) {
3346
- debug$c("Removing markDef not in use"), Transforms.setNodes(
3353
+ debug$c("Removing markDef not in use"), editorActor.send({ type: "normalizing" }), Transforms.setNodes(
3347
3354
  editor,
3348
3355
  {
3349
3356
  markDefs: newMarkDefs
3350
3357
  },
3351
3358
  { at: path }
3352
- );
3359
+ ), editorActor.send({ type: "done normalizing" });
3353
3360
  return;
3354
3361
  }
3355
3362
  }
@@ -3582,7 +3589,7 @@ function createWithPortableTextMarkModel(types, change$, keyGenerator) {
3582
3589
  };
3583
3590
  }
3584
3591
  const debug$b = debugWithName("plugin:withPortableTextSelections"), debugVerbose$2 = debug$b.enabled && !1;
3585
- function createWithPortableTextSelections(change$, types) {
3592
+ function createWithPortableTextSelections(editorActor, types) {
3586
3593
  let prevSelection = null;
3587
3594
  return function(editor) {
3588
3595
  const emitPortableTextSelection = () => {
@@ -3601,7 +3608,7 @@ function createWithPortableTextSelections(change$, types) {
3601
3608
  `Emitting selection ${JSON.stringify(ptRange || null)} (${JSON.stringify(
3602
3609
  editor.selection
3603
3610
  )})`
3604
- ), 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 });
3605
3612
  }
3606
3613
  prevSelection = editor.selection;
3607
3614
  }, { onChange } = editor;
@@ -3613,6 +3620,7 @@ function createWithPortableTextSelections(change$, types) {
3613
3620
  }
3614
3621
  const debug$a = debugWithName("plugin:withSchemaTypes");
3615
3622
  function createWithSchemaTypes({
3623
+ editorActor,
3616
3624
  schemaTypes,
3617
3625
  keyGenerator
3618
3626
  }) {
@@ -3624,16 +3632,18 @@ function createWithSchemaTypes({
3624
3632
  if (node._type === void 0 && path.length === 2) {
3625
3633
  debug$a("Setting span type on text node without a type");
3626
3634
  const span = node, key = span._key || keyGenerator();
3627
- Transforms.setNodes(
3635
+ editorActor.send({ type: "normalizing" }), Transforms.setNodes(
3628
3636
  editor,
3629
3637
  { ...span, _type: schemaTypes.span.name, _key: key },
3630
3638
  { at: path }
3631
- );
3639
+ ), editorActor.send({ type: "done normalizing" });
3640
+ return;
3632
3641
  }
3633
3642
  if (node._key === void 0 && (path.length === 1 || path.length === 2)) {
3634
3643
  debug$a("Setting missing key on child node without a key");
3635
3644
  const key = keyGenerator();
3636
- 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;
3637
3647
  }
3638
3648
  normalizeNode(entry);
3639
3649
  }, editor;
@@ -3941,22 +3951,6 @@ function validateValue(value, types, keyGenerator) {
3941
3951
  }
3942
3952
  }, !0;
3943
3953
  }
3944
- if (blk.markDefs && !Array.isArray(blk.markDefs))
3945
- return resolution = {
3946
- patches: [
3947
- set({ ...textBlock, markDefs: EMPTY_MARKDEFS }, [
3948
- { _key: textBlock._key }
3949
- ])
3950
- ],
3951
- description: "Block has invalid required property 'markDefs'.",
3952
- action: "Add empty markDefs array",
3953
- item: textBlock,
3954
- i18n: {
3955
- description: "inputs.portable-text.invalid-value.missing-or-invalid-markdefs.description",
3956
- action: "inputs.portable-text.invalid-value.missing-or-invalid-markdefs.action",
3957
- values: { key: textBlock._key }
3958
- }
3959
- }, !0;
3960
3954
  const allUsedMarks = uniq(
3961
3955
  flatten(
3962
3956
  textBlock.children.filter((cld) => cld._type === types.span.name).map((cld) => cld.marks || [])
@@ -4101,7 +4095,7 @@ function validateValue(value, types, keyGenerator) {
4101
4095
  }) && (valid = !1), { valid, resolution, value });
4102
4096
  }
4103
4097
  const debug$7 = debugWithName("plugin:withInsertData");
4104
- function createWithInsertData(change$, schemaTypes, keyGenerator) {
4098
+ function createWithInsertData(editorActor, schemaTypes, keyGenerator) {
4105
4099
  return function(editor) {
4106
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(`
4107
4101
 
@@ -4155,9 +4149,8 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
4155
4149
  ), validation = validateValue(parsed, schemaTypes, keyGenerator);
4156
4150
  if (!validation.valid && !validation.resolution?.autoResolve) {
4157
4151
  const errorDescription = `${validation.resolution?.description}`;
4158
- return change$.next({
4152
+ return editorActor.send({
4159
4153
  type: "error",
4160
- level: "warning",
4161
4154
  name: "pasteError",
4162
4155
  description: errorDescription,
4163
4156
  data: validation
@@ -4170,7 +4163,6 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
4170
4163
  }, editor.insertTextOrHTMLData = (data) => {
4171
4164
  if (!editor.selection)
4172
4165
  return debug$7("No selection, not inserting"), !1;
4173
- change$.next({ type: "loading", isLoading: !0 });
4174
4166
  const html = data.getData("text/html"), text = data.getData("text/plain");
4175
4167
  if (html || text) {
4176
4168
  debug$7("Inserting data", data);
@@ -4201,9 +4193,8 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
4201
4193
  const errorDescription = `Could not validate the resulting portable text to insert.
4202
4194
  ${validation.resolution?.description}
4203
4195
  Try to insert as plain text (shift-paste) instead.`;
4204
- return change$.next({
4196
+ return editorActor.send({
4205
4197
  type: "error",
4206
- level: "warning",
4207
4198
  name: "pasteError",
4208
4199
  description: errorDescription,
4209
4200
  data: validation
@@ -4211,9 +4202,9 @@ Try to insert as plain text (shift-paste) instead.`;
4211
4202
  }
4212
4203
  return debug$7(
4213
4204
  `Inserting ${insertedType} fragment at ${JSON.stringify(editor.selection)}`
4214
- ), _insertFragment(editor, fragment, schemaTypes), change$.next({ type: "loading", isLoading: !1 }), !0;
4205
+ ), _insertFragment(editor, fragment, schemaTypes), !0;
4215
4206
  }
4216
- return change$.next({ type: "loading", isLoading: !1 }), !1;
4207
+ return !1;
4217
4208
  }, editor.insertData = (data) => {
4218
4209
  editor.insertPortableTextData(data) || editor.insertTextOrHTMLData(data);
4219
4210
  }, editor.insertFragmentData = (data) => {
@@ -4300,18 +4291,26 @@ function _insertFragment(editor, fragment, schemaTypes) {
4300
4291
  }), editor.onChange();
4301
4292
  }
4302
4293
  const originalFnMap = /* @__PURE__ */ new WeakMap(), withPlugins = (editor, options) => {
4303
- 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;
4304
4295
  e.subscriptions = [], e.destroy ? e.destroy() : originalFnMap.set(e, {
4305
4296
  apply: e.apply,
4306
4297
  onChange: e.onChange,
4307
4298
  normalizeNode: e.normalizeNode
4308
4299
  });
4309
- 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(
4310
4309
  portableTextEditor,
4311
4310
  schemaTypes,
4312
4311
  keyGenerator
4313
4312
  ), withPatches = createWithPatches({
4314
- change$,
4313
+ editorActor,
4315
4314
  keyGenerator,
4316
4315
  patches$,
4317
4316
  patchFunctions: operationToPatches,
@@ -4322,15 +4321,18 @@ const originalFnMap = /* @__PURE__ */ new WeakMap(), withPlugins = (editor, opti
4322
4321
  patches$,
4323
4322
  blockSchemaType: schemaTypes.block
4324
4323
  }), withPortableTextMarkModel = createWithPortableTextMarkModel(
4324
+ editorActor,
4325
4325
  schemaTypes,
4326
- change$,
4327
4326
  keyGenerator
4328
- ), 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({
4329
4331
  keyGenerator,
4330
4332
  schemaTypes,
4331
4333
  portableTextEditor
4332
4334
  }), withPortableTextSelections = createWithPortableTextSelections(
4333
- change$,
4335
+ editorActor,
4334
4336
  schemaTypes
4335
4337
  );
4336
4338
  return e.destroy = () => {
@@ -4447,7 +4449,7 @@ const defaultKeyGenerator = () => randomKey(12), PortableTextEditorKeyGeneratorC
4447
4449
  return readOnly;
4448
4450
  }, debug$5 = debugWithName("hook:useSyncValue"), CURRENT_VALUE = /* @__PURE__ */ new WeakMap();
4449
4451
  function useSyncValue(props) {
4450
- 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(() => {
4451
4453
  const currentValue = CURRENT_VALUE.get(portableTextEditor);
4452
4454
  if (previousValue.current === currentValue) {
4453
4455
  debug$5("Value is the same object as previous, not need to sync");
@@ -4518,7 +4520,7 @@ function useSyncValue(props) {
4518
4520
  !validation.valid && validation.resolution?.autoResolve && validation.resolution?.patches.length > 0 && !readOnly && previousValue.current && previousValue.current !== value && (console.warn(
4519
4521
  `${validation.resolution.action} for block with _key '${validationValue[0]._key}'. ${validation.resolution?.description}`
4520
4522
  ), validation.resolution.patches.forEach((patch) => {
4521
- change$.next({ type: "patch", patch });
4523
+ editorActor.send({ type: "patch", patch });
4522
4524
  })), validation.valid || validation.resolution?.autoResolve ? (oldBlock._key === currentBlock._key ? (debug$5.enabled && debug$5("Updating block", oldBlock, currentBlock), _updateBlock(
4523
4525
  slateEditor,
4524
4526
  currentBlock,
@@ -4528,8 +4530,8 @@ function useSyncValue(props) {
4528
4530
  slateEditor,
4529
4531
  currentBlock,
4530
4532
  currentBlockIndex
4531
- )), isChanged = !0) : (change$.next({
4532
- type: "invalidValue",
4533
+ )), isChanged = !0) : (editorActor.send({
4534
+ type: "invalid value",
4533
4535
  resolution: validation.resolution,
4534
4536
  value
4535
4537
  }), isValid = !1);
@@ -4545,8 +4547,8 @@ function useSyncValue(props) {
4545
4547
  currentBlock
4546
4548
  ), validation.valid || validation.resolution?.autoResolve ? Transforms.insertNodes(slateEditor, currentBlock, {
4547
4549
  at: [currentBlockIndex]
4548
- }) : (debug$5("Invalid", validation), change$.next({
4549
- type: "invalidValue",
4550
+ }) : (debug$5("Invalid", validation), editorActor.send({
4551
+ type: "invalid value",
4550
4552
  resolution: validation.resolution,
4551
4553
  value
4552
4554
  }), isValid = !1);
@@ -4567,8 +4569,8 @@ function useSyncValue(props) {
4567
4569
  try {
4568
4570
  slateEditor.onChange();
4569
4571
  } catch (err) {
4570
- console.error(err), change$.next({
4571
- type: "invalidValue",
4572
+ console.error(err), editorActor.send({
4573
+ type: "invalid value",
4572
4574
  resolution: null,
4573
4575
  value
4574
4576
  });
@@ -4577,14 +4579,14 @@ function useSyncValue(props) {
4577
4579
  hadSelection && !slateEditor.selection && (Transforms.select(slateEditor, {
4578
4580
  anchor: { path: [0, 0], offset: 0 },
4579
4581
  focus: { path: [0, 0], offset: 0 }
4580
- }), slateEditor.onChange()), change$.next({ type: "value", value });
4582
+ }), slateEditor.onChange()), editorActor.send({ type: "value changed", value });
4581
4583
  } else
4582
4584
  debug$5("Server value and editor value is equal, no need to sync.");
4583
4585
  previousValue.current = value;
4584
4586
  };
4585
4587
  return updateValueFunctionRef.current = updateFunction, updateFunction;
4586
4588
  }, [
4587
- change$,
4589
+ editorActor,
4588
4590
  keyGenerator,
4589
4591
  portableTextEditor,
4590
4592
  readOnly,
@@ -4653,9 +4655,9 @@ function _updateBlock(slateEditor, currentBlock, oldBlock, currentBlockIndex) {
4653
4655
  }
4654
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;
4655
4657
  function Synchronizer(props) {
4656
- 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,
4657
4660
  keyGenerator,
4658
- onChange,
4659
4661
  portableTextEditor,
4660
4662
  readOnly
4661
4663
  }), slateEditor = useSlate();
@@ -4667,14 +4669,14 @@ function Synchronizer(props) {
4667
4669
  debug$4("Flushing pending patches"), debugVerbose$1 && debug$4(`Patches:
4668
4670
  ${JSON.stringify(pendingPatches.current, null, 2)}`);
4669
4671
  const snapshot = getValue();
4670
- change$.next({
4672
+ editorActor.send({
4671
4673
  type: "mutation",
4672
4674
  patches: pendingPatches.current,
4673
4675
  snapshot
4674
4676
  }), pendingPatches.current = [];
4675
4677
  }
4676
4678
  IS_PROCESSING_LOCAL_CHANGES.set(slateEditor, !1);
4677
- }, [slateEditor, getValue, change$]), onFlushPendingPatchesThrottled = useMemo(() => throttle(
4679
+ }, [editorActor, slateEditor, getValue]), onFlushPendingPatchesThrottled = useMemo(() => throttle(
4678
4680
  () => {
4679
4681
  if (Editor.isNormalizing(slateEditor)) {
4680
4682
  onFlushPendingPatches();
@@ -4691,34 +4693,174 @@ ${JSON.stringify(pendingPatches.current, null, 2)}`);
4691
4693
  useEffect(() => () => {
4692
4694
  onFlushPendingPatches();
4693
4695
  }, [onFlushPendingPatches]), useEffect(() => {
4694
- debug$4("Subscribing to editor changes$");
4695
- const sub = change$.subscribe((next) => {
4696
- switch (next.type) {
4696
+ debug$4("Subscribing to editor changes");
4697
+ const sub = editorActor.on("*", (event) => {
4698
+ switch (event.type) {
4697
4699
  case "patch":
4698
- 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
+ });
4699
4728
  break;
4729
+ }
4730
+ case "error": {
4731
+ onChange({
4732
+ ...event,
4733
+ level: "warning"
4734
+ });
4735
+ break;
4736
+ }
4700
4737
  default:
4701
- onChange(next);
4738
+ onChange(event);
4702
4739
  }
4703
4740
  });
4704
4741
  return () => {
4705
- debug$4("Unsubscribing to changes$"), sub.unsubscribe();
4742
+ debug$4("Unsubscribing to changes"), sub.unsubscribe();
4706
4743
  };
4707
- }, [change$, onChange, onFlushPendingPatchesThrottled, slateEditor]);
4744
+ }, [editorActor, onFlushPendingPatchesThrottled, slateEditor]);
4708
4745
  const handleOnline = useCallback(() => {
4709
- debug$4("Editor is online, syncing from props.value"), change$.next({ type: "connection", value: "online" }), syncValue(value);
4710
- }, [change$, syncValue, value]), handleOffline = useCallback(() => {
4711
- debug$4("Editor is offline"), change$.next({ type: "connection", value: "offline" });
4712
- }, [change$]);
4713
- useEffect(() => (portableTextEditor.props.patches$ && (window.addEventListener("online", handleOnline), window.addEventListener("offline", handleOffline)), () => {
4714
- portableTextEditor.props.patches$ && (window.removeEventListener("online", handleOnline), window.removeEventListener("offline", handleOffline));
4715
- }));
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]);
4716
4756
  const isInitialValueFromProps = useRef(!0);
4717
4757
  return useEffect(() => {
4718
- debug$4("Value from props changed, syncing new value"), syncValue(value), isInitialValueFromProps.current && (change$.next({ type: "loading", isLoading: !1 }), change$.next({ type: "ready" }), isInitialValueFromProps.current = !1);
4719
- }, [change$, syncValue, value]), null;
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;
4720
4760
  }
4721
- 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 = () => {
4722
4864
  const selection = useContext(PortableTextEditorSelectionContext);
4723
4865
  if (selection === void 0)
4724
4866
  throw new Error(
@@ -4727,21 +4869,26 @@ const PortableTextEditorSelectionContext = createContext(null), usePortableTextE
4727
4869
  return selection;
4728
4870
  }, debug$3 = debugWithName("component:PortableTextEditor:SelectionProvider"), debugVerbose = debug$3.enabled && !1;
4729
4871
  function PortableTextEditorSelectionProvider(props) {
4730
- const { change$ } = props, [selection, setSelection] = useState(null);
4872
+ const [selection, setSelection] = useState(null);
4731
4873
  return useEffect(() => {
4732
- debug$3("Subscribing to selection changes$");
4733
- const subscription = change$.subscribe((next) => {
4734
- next.type === "selection" && startTransition(() => {
4735
- debugVerbose && debug$3("Setting selection"), setSelection(next.selection);
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);
4736
4878
  });
4737
4879
  });
4738
4880
  return () => {
4739
- debug$3("Unsubscribing to selection changes$"), subscription.unsubscribe();
4881
+ debug$3("Unsubscribing to selection changes"), subscription.unsubscribe();
4740
4882
  };
4741
- }, [change$]), /* @__PURE__ */ jsx(PortableTextEditorSelectionContext.Provider, { value: selection, children: props.children });
4883
+ }, [props.editorActor]), /* @__PURE__ */ jsx(PortableTextEditorSelectionContext.Provider, { value: selection, children: props.children });
4742
4884
  }
4743
4885
  const debug$2 = debugWithName("component:PortableTextEditor");
4744
4886
  class PortableTextEditor extends Component {
4887
+ /**
4888
+ * @internal
4889
+ * Don't use this API directly. It's subject to change.
4890
+ */
4891
+ editorActor;
4745
4892
  /**
4746
4893
  * An observable of all the editor changes.
4747
4894
  */
@@ -4759,7 +4906,7 @@ class PortableTextEditor extends Component {
4759
4906
  throw new Error('PortableTextEditor: missing "schemaType" property');
4760
4907
  props.incomingPatches$ && console.warn(
4761
4908
  "The prop 'incomingPatches$' is deprecated and renamed to 'patches$'"
4762
- ), this.change$.next({ type: "loading", isLoading: !0 }), this.schemaTypes = getPortableTextMemberSchemaTypes(
4909
+ ), this.editorActor = createActor(editorMachine), this.editorActor.start(), this.schemaTypes = getPortableTextMemberSchemaTypes(
4763
4910
  props.schemaType.hasOwnProperty("jsonType") ? props.schemaType : compileType(props.schemaType)
4764
4911
  );
4765
4912
  }
@@ -4776,7 +4923,7 @@ class PortableTextEditor extends Component {
4776
4923
  return this.editable.getValue();
4777
4924
  };
4778
4925
  render() {
4779
- const { onChange, value, children, patches$, incomingPatches$ } = this.props, { change$ } = this, _patches$ = incomingPatches$ || patches$, maxBlocks = typeof this.props.maxBlocks > "u" ? void 0 : Number.parseInt(this.props.maxBlocks.toString(), 10) || void 0, readOnly = !!this.props.readOnly, keyGenerator = this.props.keyGenerator || defaultKeyGenerator;
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;
4780
4927
  return /* @__PURE__ */ jsx(
4781
4928
  SlateContainer,
4782
4929
  {
@@ -4785,18 +4932,26 @@ class PortableTextEditor extends Component {
4785
4932
  patches$: _patches$,
4786
4933
  portableTextEditor: this,
4787
4934
  readOnly,
4788
- children: /* @__PURE__ */ jsx(PortableTextEditorKeyGeneratorContext.Provider, { value: keyGenerator, children: /* @__PURE__ */ jsx(PortableTextEditorContext.Provider, { value: this, children: /* @__PURE__ */ jsx(PortableTextEditorReadOnlyContext.Provider, { value: readOnly, children: /* @__PURE__ */ jsxs(PortableTextEditorSelectionProvider, { change$, children: [
4789
- /* @__PURE__ */ jsx(
4790
- Synchronizer,
4791
- {
4792
- change$,
4793
- getValue: this.getValue,
4794
- onChange,
4795
- value
4796
- }
4797
- ),
4798
- children
4799
- ] }) }) }) })
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
+ ) }) }) })
4800
4955
  }
4801
4956
  );
4802
4957
  }
@@ -4906,20 +5061,19 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
4906
5061
  useEffect(() => {
4907
5062
  if (!shouldTrackSelectionAndFocus)
4908
5063
  return;
4909
- const sub = portableTextEditor.change$.subscribe((next) => {
4910
- if (next.type === "blur") {
4911
- setFocused(!1), setSelected(!1);
4912
- 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();
4913
5073
  }
4914
- if (next.type === "focus") {
4915
- const sel = PortableTextEditor.getSelection(portableTextEditor);
4916
- sel && isEqual(sel.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) && setFocused(!0), setSelectedFromRange();
4917
- return;
4918
- }
4919
- next.type === "selection" && (next.selection && isEqual(next.selection.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) ? setFocused(!0) : setFocused(!1), setSelectedFromRange());
4920
- });
5074
+ );
4921
5075
  return () => {
4922
- sub.unsubscribe();
5076
+ onBlur.unsubscribe(), onFocus.unsubscribe(), onSelection.unsubscribe();
4923
5077
  };
4924
5078
  }, [
4925
5079
  path,
@@ -5070,9 +5224,9 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5070
5224
  forwardedRef,
5071
5225
  () => ref.current
5072
5226
  );
5073
- const rangeDecorationsRef = useRef(rangeDecorations), { change$, schemaTypes } = portableTextEditor, slateEditor = useSlate(), blockTypeName = schemaTypes.block.name, withInsertData = useMemo(
5074
- () => createWithInsertData(change$, schemaTypes, keyGenerator),
5075
- [change$, keyGenerator, schemaTypes]
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]
5076
5230
  ), withHotKeys = useMemo(
5077
5231
  () => createWithHotkeys(schemaTypes, portableTextEditor, hotkeys),
5078
5232
  [hotkeys, portableTextEditor, schemaTypes]
@@ -5145,10 +5299,13 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5145
5299
  `Normalized selection from props ${JSON.stringify(normalizedSelection)}`
5146
5300
  );
5147
5301
  const slateRange = toSlateRange(normalizedSelection, slateEditor);
5148
- slateRange && (Transforms.select(slateEditor, slateRange), slateEditor.operations.some((o) => o.type === "set_selection") || change$.next({ type: "selection", selection: normalizedSelection }), slateEditor.onChange());
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());
5149
5306
  }
5150
5307
  }
5151
- }, [propsSelection, slateEditor, blockTypeName, change$]), syncRangeDecorations = useCallback(
5308
+ }, [editorActor, propsSelection, slateEditor]), syncRangeDecorations = useCallback(
5152
5309
  (operation) => {
5153
5310
  if (rangeDecorations && rangeDecorations.length > 0) {
5154
5311
  const newSlateRanges = [];
@@ -5192,23 +5349,17 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5192
5349
  [portableTextEditor, rangeDecorations, schemaTypes, slateEditor]
5193
5350
  );
5194
5351
  useEffect(() => {
5195
- const sub = change$.subscribe((next) => {
5196
- switch (next.type) {
5197
- case "ready":
5198
- restoreSelectionFromProps();
5199
- break;
5200
- case "invalidValue":
5201
- setHasInvalidValue(!0);
5202
- break;
5203
- case "value":
5204
- setHasInvalidValue(!1);
5205
- break;
5206
- }
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);
5207
5358
  });
5208
5359
  return () => {
5209
- sub.unsubscribe();
5360
+ onReady.unsubscribe(), onInvalidValue.unsubscribe(), onValueChanged.unsubscribe();
5210
5361
  };
5211
- }, [change$, restoreSelectionFromProps]), useEffect(() => {
5362
+ }, [editorActor, restoreSelectionFromProps]), useEffect(() => {
5212
5363
  propsSelection && !hasInvalidValue && restoreSelectionFromProps();
5213
5364
  }, [hasInvalidValue, propsSelection, restoreSelectionFromProps]);
5214
5365
  const originalApply = useMemo(() => slateEditor.apply, [slateEditor]), [syncedRangeDecorations, setSyncedRangeDecorations] = useState(!1);
@@ -5239,7 +5390,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5239
5390
  slateEditor.selection,
5240
5391
  schemaTypes
5241
5392
  )?.focus.path || [], onPasteResult = onPaste({ event, value, path, schemaTypes });
5242
- onPasteResult === void 0 ? (debug("No result from custom paste handler, pasting normally"), slateEditor.insertData(event.clipboardData)) : (change$.next({ type: "loading", isLoading: !0 }), Promise.resolve(onPasteResult).then((result) => {
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) => {
5243
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(
5244
5395
  toSlateValue(result.insert, {
5245
5396
  schemaTypes
@@ -5249,23 +5400,23 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5249
5400
  result
5250
5401
  );
5251
5402
  }).catch((error) => (console.error(error), error)).finally(() => {
5252
- change$.next({ type: "loading", isLoading: !1 });
5403
+ editorActor.send({ type: "done loading" });
5253
5404
  }));
5254
5405
  },
5255
- [change$, onPaste, portableTextEditor, schemaTypes, slateEditor]
5406
+ [onPaste, portableTextEditor, schemaTypes, slateEditor]
5256
5407
  ), handleOnFocus = useCallback(
5257
5408
  (event) => {
5258
5409
  if (onFocus && onFocus(event), !event.isDefaultPrevented()) {
5259
5410
  const selection = PortableTextEditor.getSelection(portableTextEditor);
5260
- 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 });
5261
5412
  const newSelection = PortableTextEditor.getSelection(portableTextEditor);
5262
- selection === newSelection && change$.next({
5413
+ selection === newSelection && editorActor.send({
5263
5414
  type: "selection",
5264
5415
  selection
5265
5416
  });
5266
5417
  }
5267
5418
  },
5268
- [onFocus, portableTextEditor, change$, slateEditor]
5419
+ [editorActor, onFocus, portableTextEditor, slateEditor]
5269
5420
  ), handleClick = useCallback(
5270
5421
  (event) => {
5271
5422
  if (onClick && onClick(event), slateEditor.selection && event.target === event.currentTarget) {
@@ -5282,9 +5433,9 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5282
5433
  [onClick, slateEditor]
5283
5434
  ), handleOnBlur = useCallback(
5284
5435
  (event) => {
5285
- onBlur && onBlur(event), event.isPropagationStopped() || change$.next({ type: "blur", event });
5436
+ onBlur && onBlur(event), event.isPropagationStopped() || editorActor.send({ type: "blur", event });
5286
5437
  },
5287
- [change$, onBlur]
5438
+ [editorActor, onBlur]
5288
5439
  ), handleOnBeforeInput = useCallback(
5289
5440
  (event) => {
5290
5441
  onBeforeInput && onBeforeInput(event);
@@ -5390,6 +5541,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5390
5541
  export {
5391
5542
  PortableTextEditable,
5392
5543
  PortableTextEditor,
5544
+ editorMachine,
5393
5545
  defaultKeyGenerator as keyGenerator,
5394
5546
  usePortableTextEditor,
5395
5547
  usePortableTextEditorSelection