@portabletext/editor 1.1.9 → 1.1.11

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.
package/lib/index.esm.js CHANGED
@@ -2,7 +2,7 @@ import { jsx, Fragment, jsxs } from "react/jsx-runtime";
2
2
  import isEqual from "lodash/isEqual.js";
3
3
  import noop from "lodash/noop.js";
4
4
  import { useRef, useState, useMemo, useEffect, useCallback, createContext, useContext, startTransition, Component, forwardRef, useImperativeHandle } from "react";
5
- import { Editor, Element as Element$1, Range, Point, Text, Path, Transforms, Node, Operation, createEditor } from "slate";
5
+ import { Editor, Element as Element$1, Range, Point, Text, Path, Transforms, Node, Operation, createEditor, deleteBackward, insertText } from "slate";
6
6
  import { useSlateStatic, ReactEditor, useSelected, withReact, Slate, useSlate, Editable } from "slate-react";
7
7
  import debug$m from "debug";
8
8
  import { isKeySegment, isPortableTextTextBlock, isPortableTextSpan, isPortableTextListBlock } from "@sanity/types";
@@ -11,12 +11,12 @@ import uniq from "lodash/uniq.js";
11
11
  import { Subject } from "rxjs";
12
12
  import { fromCallback, setup, assign, assertEvent, emit, enqueueActions, createActor } from "xstate";
13
13
  import { Schema } from "@sanity/schema";
14
- import { isHotkey } from "is-hotkey-esm";
15
14
  import { diffMatchPatch as diffMatchPatch$1, set, insert, setIfMissing, unset, applyAll } from "@portabletext/patches";
16
15
  import get from "lodash/get.js";
17
16
  import isUndefined from "lodash/isUndefined.js";
18
17
  import omitBy from "lodash/omitBy.js";
19
18
  import flatten from "lodash/flatten.js";
19
+ import { isHotkey } from "is-hotkey-esm";
20
20
  import { htmlToBlocks, normalizeBlock } from "@sanity/block-tools";
21
21
  import isPlainObject from "lodash/isPlainObject.js";
22
22
  import throttle from "lodash/throttle.js";
@@ -816,20 +816,15 @@ function getFocusBlockObject(context) {
816
816
  const focusBlock = getFocusBlock(context);
817
817
  return focusBlock && !isPortableTextTextBlock(focusBlock.node) ? { node: focusBlock.node, path: focusBlock.path } : void 0;
818
818
  }
819
- const overwriteSoftReturn = {
820
- on: "key down",
821
- guard: ({ event }) => isHotkey("shift+enter", event.nativeEvent),
822
- actions: [
823
- ({ event }) => (event.nativeEvent.preventDefault(), { type: "insert text", text: `
824
- ` })
825
- ]
826
- }, enterOnVoidBlock = {
827
- on: "key down",
828
- guard: ({ context, event }) => isHotkey("enter", event.nativeEvent) ? !!getFocusBlockObject(context) : !1,
829
- actions: [
830
- ({ event }) => (event.nativeEvent.preventDefault(), { type: "insert text block", decorators: [] })
831
- ]
832
- }, coreBehaviors = [overwriteSoftReturn, enterOnVoidBlock], debug$k = debugWithName("operationToPatches");
819
+ const softReturn = {
820
+ on: "insert soft break",
821
+ actions: [() => [{ type: "insert text", text: `
822
+ ` }]]
823
+ }, breakingVoidBlock = {
824
+ on: "insert break",
825
+ guard: ({ context }) => !!getFocusBlockObject(context),
826
+ actions: [() => [{ type: "insert text block", decorators: [] }]]
827
+ }, coreBehaviors = [softReturn, breakingVoidBlock], debug$k = debugWithName("operationToPatches");
833
828
  function createOperationToPatches(types) {
834
829
  const textBlockName = types.block.name;
835
830
  function insertTextPatch(editor, operation, beforeValue) {
@@ -1104,6 +1099,46 @@ function createOperationToPatches(types) {
1104
1099
  splitNodePatch
1105
1100
  };
1106
1101
  }
1102
+ function createWithEventListeners(editorActor) {
1103
+ return function(editor) {
1104
+ return editor.deleteBackward = (unit) => {
1105
+ editorActor.send({
1106
+ type: "behavior event",
1107
+ behaviorEvent: {
1108
+ type: "delete backward",
1109
+ unit
1110
+ },
1111
+ editor
1112
+ });
1113
+ }, editor.insertBreak = () => {
1114
+ editorActor.send({
1115
+ type: "behavior event",
1116
+ behaviorEvent: {
1117
+ type: "insert break"
1118
+ },
1119
+ editor
1120
+ });
1121
+ }, editor.insertSoftBreak = () => {
1122
+ editorActor.send({
1123
+ type: "behavior event",
1124
+ behaviorEvent: {
1125
+ type: "insert soft break"
1126
+ },
1127
+ editor
1128
+ });
1129
+ }, editor.insertText = (text, options) => {
1130
+ editorActor.send({
1131
+ type: "behavior event",
1132
+ behaviorEvent: {
1133
+ type: "insert text",
1134
+ text,
1135
+ options
1136
+ },
1137
+ editor
1138
+ });
1139
+ }, editor;
1140
+ };
1141
+ }
1107
1142
  const debug$j = debugWithName("API:editable");
1108
1143
  function createWithEditableAPI(editorActor, portableTextEditor, types) {
1109
1144
  return function(editor) {
@@ -1590,127 +1625,6 @@ function createWithEditableAPI(editorActor, portableTextEditor, types) {
1590
1625
  }), editor;
1591
1626
  };
1592
1627
  }
1593
- function createWithInsertBreak(editorActor, types) {
1594
- return function(editor) {
1595
- const { insertBreak } = editor;
1596
- return editor.insertBreak = () => {
1597
- if (!editor.selection) {
1598
- insertBreak();
1599
- return;
1600
- }
1601
- const [focusSpan] = Array.from(
1602
- Editor.nodes(editor, {
1603
- mode: "lowest",
1604
- at: editor.selection.focus,
1605
- match: (n) => editor.isTextSpan(n),
1606
- voids: !1
1607
- })
1608
- )[0] ?? [void 0], focusDecorators = focusSpan.marks?.filter(
1609
- (mark) => types.decorators.some((decorator) => decorator.value === mark)
1610
- ) ?? [], focusAnnotations = focusSpan.marks?.filter(
1611
- (mark) => !types.decorators.some((decorator) => decorator.value === mark)
1612
- ) ?? [], focusBlockPath = editor.selection.focus.path.slice(0, 1), focusBlock = Node.descendant(editor, focusBlockPath);
1613
- if (editor.isTextBlock(focusBlock)) {
1614
- const [start, end] = Range.edges(editor.selection), atTheStartOfBlock = isEqual(end, {
1615
- path: [...focusBlockPath, 0],
1616
- offset: 0
1617
- });
1618
- if (atTheStartOfBlock && Range.isCollapsed(editor.selection)) {
1619
- Editor.insertNode(
1620
- editor,
1621
- editor.pteCreateTextBlock({
1622
- decorators: focusAnnotations.length === 0 ? focusDecorators : []
1623
- })
1624
- );
1625
- const [nextBlockPath] = Path.next(focusBlockPath);
1626
- Transforms.select(editor, {
1627
- anchor: { path: [nextBlockPath, 0], offset: 0 },
1628
- focus: { path: [nextBlockPath, 0], offset: 0 }
1629
- });
1630
- return;
1631
- }
1632
- const lastFocusBlockChild = focusBlock.children[focusBlock.children.length - 1], atTheEndOfBlock = isEqual(start, {
1633
- path: [...focusBlockPath, focusBlock.children.length - 1],
1634
- offset: editor.isTextSpan(lastFocusBlockChild) ? lastFocusBlockChild.text.length : 0
1635
- });
1636
- if (atTheEndOfBlock && Range.isCollapsed(editor.selection)) {
1637
- Editor.insertNode(
1638
- editor,
1639
- editor.pteCreateTextBlock({
1640
- decorators: []
1641
- })
1642
- );
1643
- const [nextBlockPath] = Path.next(focusBlockPath);
1644
- Transforms.setSelection(editor, {
1645
- anchor: { path: [nextBlockPath, 0], offset: 0 },
1646
- focus: { path: [nextBlockPath, 0], offset: 0 }
1647
- });
1648
- return;
1649
- }
1650
- if (!atTheStartOfBlock && !atTheEndOfBlock) {
1651
- Editor.withoutNormalizing(editor, () => {
1652
- if (!editor.selection)
1653
- return;
1654
- Transforms.splitNodes(editor, {
1655
- at: editor.selection
1656
- });
1657
- const [nextNode, nextNodePath] = Editor.node(
1658
- editor,
1659
- Path.next(focusBlockPath),
1660
- { depth: 1 }
1661
- );
1662
- if (Transforms.setSelection(editor, {
1663
- anchor: { path: [...nextNodePath, 0], offset: 0 },
1664
- focus: { path: [...nextNodePath, 0], offset: 0 }
1665
- }), editor.isTextBlock(nextNode) && nextNode.markDefs && nextNode.markDefs.length > 0) {
1666
- const newMarkDefKeys = /* @__PURE__ */ new Map(), prevNodeSpans = Array.from(
1667
- Node.children(editor, focusBlockPath)
1668
- ).map((entry) => entry[0]).filter((node) => editor.isTextSpan(node)), children = Node.children(editor, nextNodePath);
1669
- for (const [child, childPath] of children) {
1670
- if (!editor.isTextSpan(child))
1671
- continue;
1672
- const marks = child.marks ?? [];
1673
- for (const mark of marks)
1674
- types.decorators.some(
1675
- (decorator) => decorator.value === mark
1676
- ) || prevNodeSpans.some(
1677
- (prevNodeSpan) => prevNodeSpan.marks?.includes(mark)
1678
- ) && !newMarkDefKeys.has(mark) && newMarkDefKeys.set(
1679
- mark,
1680
- editorActor.getSnapshot().context.keyGenerator()
1681
- );
1682
- const newMarks = marks.map(
1683
- (mark) => newMarkDefKeys.get(mark) ?? mark
1684
- );
1685
- isEqual(marks, newMarks) || Transforms.setNodes(
1686
- editor,
1687
- { marks: newMarks },
1688
- {
1689
- at: childPath
1690
- }
1691
- );
1692
- }
1693
- const newMarkDefs = nextNode.markDefs.map((markDef) => ({
1694
- ...markDef,
1695
- _key: newMarkDefKeys.get(markDef._key) ?? markDef._key
1696
- }));
1697
- isEqual(nextNode.markDefs, newMarkDefs) || Transforms.setNodes(
1698
- editor,
1699
- { markDefs: newMarkDefs },
1700
- {
1701
- at: nextNodePath,
1702
- match: (node) => editor.isTextBlock(node)
1703
- }
1704
- );
1705
- }
1706
- }), editor.onChange();
1707
- return;
1708
- }
1709
- }
1710
- insertBreak();
1711
- }, editor;
1712
- };
1713
- }
1714
1628
  function withRemoteChanges(editor, fn) {
1715
1629
  const prev = isChangingRemotely(editor) || !1;
1716
1630
  IS_PROCESSING_REMOTE_CHANGES.set(editor, !0), fn(), IS_PROCESSING_REMOTE_CHANGES.set(editor, prev);
@@ -2187,8 +2101,8 @@ function deisolateChar(diffs, i, dir) {
2187
2101
  }
2188
2102
  }
2189
2103
  if (insertIdx !== null && deleteIdx !== null && hasSharedChar(diffs, insertIdx, deleteIdx, dir)) {
2190
- const [insertText, insertChar] = splitChar(diffs[insertIdx][1], inv), [deleteText] = splitChar(diffs[deleteIdx][1], inv);
2191
- diffs[insertIdx][1] = insertText, diffs[deleteIdx][1] = deleteText, diffs[i][1] = combineChar(diffs[i][1], insertChar, dir);
2104
+ const [insertText2, insertChar] = splitChar(diffs[insertIdx][1], inv), [deleteText] = splitChar(diffs[deleteIdx][1], inv);
2105
+ diffs[insertIdx][1] = insertText2, diffs[deleteIdx][1] = deleteText, diffs[i][1] = combineChar(diffs[i][1], insertChar, dir);
2192
2106
  return;
2193
2107
  }
2194
2108
  const [text, char] = splitChar(diffs[i][1], dir);
@@ -3795,6 +3709,8 @@ function createWithUtils({
3795
3709
  _type: schemaTypes.block.name,
3796
3710
  _key: editorActor.getSnapshot().context.keyGenerator(),
3797
3711
  style: schemaTypes.styles[0].value || "normal",
3712
+ ...options.listItem ? { listItem: options.listItem } : {},
3713
+ ...options.level ? { level: options.level } : {},
3798
3714
  markDefs: [],
3799
3715
  children: [
3800
3716
  {
@@ -4414,14 +4330,14 @@ const originalFnMap = /* @__PURE__ */ new WeakMap(), withPlugins = (editor, opti
4414
4330
  ), withPortableTextBlockStyle = createWithPortableTextBlockStyle(
4415
4331
  editorActor,
4416
4332
  schemaTypes
4417
- ), withPlaceholderBlock = createWithPlaceholderBlock(), withInsertBreak = createWithInsertBreak(editorActor, schemaTypes), withUtils = createWithUtils({
4333
+ ), withPlaceholderBlock = createWithPlaceholderBlock(), withUtils = createWithUtils({
4418
4334
  editorActor,
4419
4335
  schemaTypes,
4420
4336
  portableTextEditor
4421
4337
  }), withPortableTextSelections = createWithPortableTextSelections(
4422
4338
  editorActor,
4423
4339
  schemaTypes
4424
- );
4340
+ ), withEventListeners = createWithEventListeners(editorActor);
4425
4341
  return e.destroy = () => {
4426
4342
  const originalFunctions = originalFnMap.get(e);
4427
4343
  if (!originalFunctions)
@@ -4435,9 +4351,7 @@ const originalFnMap = /* @__PURE__ */ new WeakMap(), withPlugins = (editor, opti
4435
4351
  withUtils(
4436
4352
  withPlaceholderBlock(
4437
4353
  withPortableTextLists(
4438
- withPortableTextSelections(
4439
- withEditableAPI(withInsertBreak(e))
4440
- )
4354
+ withPortableTextSelections(withEditableAPI(e))
4441
4355
  )
4442
4356
  )
4443
4357
  )
@@ -4447,18 +4361,18 @@ const originalFnMap = /* @__PURE__ */ new WeakMap(), withPlugins = (editor, opti
4447
4361
  ),
4448
4362
  subscribe: () => noop
4449
4363
  } : {
4450
- editor: withSchemaTypes(
4451
- withObjectKeys(
4452
- withPortableTextMarkModel(
4453
- withPortableTextBlockStyle(
4454
- withPortableTextLists(
4455
- withPlaceholderBlock(
4456
- withUtils(
4457
- withMaxBlocks(
4458
- withUndoRedo(
4459
- withPatches(
4460
- withPortableTextSelections(
4461
- withEditableAPI(withInsertBreak(e))
4364
+ editor: withEventListeners(
4365
+ withSchemaTypes(
4366
+ withObjectKeys(
4367
+ withPortableTextMarkModel(
4368
+ withPortableTextBlockStyle(
4369
+ withPortableTextLists(
4370
+ withPlaceholderBlock(
4371
+ withUtils(
4372
+ withMaxBlocks(
4373
+ withUndoRedo(
4374
+ withPatches(
4375
+ withPortableTextSelections(withEditableAPI(e))
4462
4376
  )
4463
4377
  )
4464
4378
  )
@@ -4829,26 +4743,162 @@ ${JSON.stringify(pendingPatches.current, null, 2)}`);
4829
4743
  debug$4("Value from props changed, syncing new value"), syncValue(value), isInitialValueFromProps.current && (editorActor.send({ type: "ready" }), isInitialValueFromProps.current = !1);
4830
4744
  }, [editorActor, syncValue, value]), null;
4831
4745
  }
4832
- const EditorActorContext = createContext({}), behaviorActionImplementations = {
4833
- "apply block style": ({ event }) => {
4834
- for (const path of event.paths) {
4746
+ const EditorActorContext = createContext({}), insertBreakActionImplementation = ({ context, action }) => {
4747
+ const keyGenerator = context.keyGenerator, schema = context.schema, editor = action.editor;
4748
+ if (!editor.selection)
4749
+ return;
4750
+ const [focusSpan] = Array.from(
4751
+ Editor.nodes(editor, {
4752
+ mode: "lowest",
4753
+ at: editor.selection.focus,
4754
+ match: (n) => editor.isTextSpan(n),
4755
+ voids: !1
4756
+ })
4757
+ )[0] ?? [void 0], focusDecorators = focusSpan.marks?.filter(
4758
+ (mark) => schema.decorators.some((decorator) => decorator.value === mark)
4759
+ ) ?? [], focusAnnotations = focusSpan.marks?.filter(
4760
+ (mark) => !schema.decorators.some((decorator) => decorator.value === mark)
4761
+ ) ?? [], focusBlockPath = editor.selection.focus.path.slice(0, 1), focusBlock = Node.descendant(editor, focusBlockPath);
4762
+ if (editor.isTextBlock(focusBlock)) {
4763
+ const [start, end] = Range.edges(editor.selection), atTheStartOfBlock = isEqual(end, {
4764
+ path: [...focusBlockPath, 0],
4765
+ offset: 0
4766
+ });
4767
+ if (atTheStartOfBlock && Range.isCollapsed(editor.selection)) {
4768
+ Editor.insertNode(
4769
+ editor,
4770
+ editor.pteCreateTextBlock({
4771
+ decorators: focusAnnotations.length === 0 ? focusDecorators : [],
4772
+ listItem: focusBlock.listItem,
4773
+ level: focusBlock.level
4774
+ })
4775
+ );
4776
+ const [nextBlockPath] = Path.next(focusBlockPath);
4777
+ Transforms.select(editor, {
4778
+ anchor: { path: [nextBlockPath, 0], offset: 0 },
4779
+ focus: { path: [nextBlockPath, 0], offset: 0 }
4780
+ });
4781
+ return;
4782
+ }
4783
+ const lastFocusBlockChild = focusBlock.children[focusBlock.children.length - 1], atTheEndOfBlock = isEqual(start, {
4784
+ path: [...focusBlockPath, focusBlock.children.length - 1],
4785
+ offset: editor.isTextSpan(lastFocusBlockChild) ? lastFocusBlockChild.text.length : 0
4786
+ });
4787
+ if (atTheEndOfBlock && Range.isCollapsed(editor.selection)) {
4788
+ Editor.insertNode(
4789
+ editor,
4790
+ editor.pteCreateTextBlock({
4791
+ decorators: [],
4792
+ listItem: focusBlock.listItem,
4793
+ level: focusBlock.level
4794
+ })
4795
+ );
4796
+ const [nextBlockPath] = Path.next(focusBlockPath);
4797
+ Transforms.setSelection(editor, {
4798
+ anchor: { path: [nextBlockPath, 0], offset: 0 },
4799
+ focus: { path: [nextBlockPath, 0], offset: 0 }
4800
+ });
4801
+ return;
4802
+ }
4803
+ if (!atTheStartOfBlock && !atTheEndOfBlock) {
4804
+ Editor.withoutNormalizing(editor, () => {
4805
+ if (!editor.selection)
4806
+ return;
4807
+ Transforms.splitNodes(editor, {
4808
+ at: editor.selection
4809
+ });
4810
+ const [nextNode, nextNodePath] = Editor.node(
4811
+ editor,
4812
+ Path.next(focusBlockPath),
4813
+ { depth: 1 }
4814
+ );
4815
+ if (Transforms.setSelection(editor, {
4816
+ anchor: { path: [...nextNodePath, 0], offset: 0 },
4817
+ focus: { path: [...nextNodePath, 0], offset: 0 }
4818
+ }), editor.isTextBlock(nextNode) && nextNode.markDefs && nextNode.markDefs.length > 0) {
4819
+ const newMarkDefKeys = /* @__PURE__ */ new Map(), prevNodeSpans = Array.from(
4820
+ Node.children(editor, focusBlockPath)
4821
+ ).map((entry) => entry[0]).filter((node) => editor.isTextSpan(node)), children = Node.children(editor, nextNodePath);
4822
+ for (const [child, childPath] of children) {
4823
+ if (!editor.isTextSpan(child))
4824
+ continue;
4825
+ const marks = child.marks ?? [];
4826
+ for (const mark of marks)
4827
+ schema.decorators.some((decorator) => decorator.value === mark) || prevNodeSpans.some(
4828
+ (prevNodeSpan) => prevNodeSpan.marks?.includes(mark)
4829
+ ) && !newMarkDefKeys.has(mark) && newMarkDefKeys.set(mark, keyGenerator());
4830
+ const newMarks = marks.map(
4831
+ (mark) => newMarkDefKeys.get(mark) ?? mark
4832
+ );
4833
+ isEqual(marks, newMarks) || Transforms.setNodes(
4834
+ editor,
4835
+ { marks: newMarks },
4836
+ {
4837
+ at: childPath
4838
+ }
4839
+ );
4840
+ }
4841
+ const newMarkDefs = nextNode.markDefs.map((markDef) => ({
4842
+ ...markDef,
4843
+ _key: newMarkDefKeys.get(markDef._key) ?? markDef._key
4844
+ }));
4845
+ isEqual(nextNode.markDefs, newMarkDefs) || Transforms.setNodes(
4846
+ editor,
4847
+ { markDefs: newMarkDefs },
4848
+ {
4849
+ at: nextNodePath,
4850
+ match: (node) => editor.isTextBlock(node)
4851
+ }
4852
+ );
4853
+ }
4854
+ }), editor.onChange();
4855
+ return;
4856
+ }
4857
+ }
4858
+ }, behaviorActionImplementations = {
4859
+ "set block": ({ action }) => {
4860
+ for (const path of action.paths) {
4861
+ const at = toSlateRange(
4862
+ { anchor: { path, offset: 0 }, focus: { path, offset: 0 } },
4863
+ action.editor
4864
+ );
4865
+ Transforms.setNodes(
4866
+ action.editor,
4867
+ {
4868
+ ...action.style ? { style: action.style } : {},
4869
+ ...action.listItem ? { listItem: action.listItem } : {},
4870
+ ...action.level ? { level: action.level } : {}
4871
+ },
4872
+ { at }
4873
+ );
4874
+ }
4875
+ },
4876
+ "unset block": ({ action }) => {
4877
+ for (const path of action.paths) {
4835
4878
  const at = toSlateRange(
4836
4879
  { anchor: { path, offset: 0 }, focus: { path, offset: 0 } },
4837
- event.editor
4880
+ action.editor
4838
4881
  );
4839
- Transforms.setNodes(event.editor, { style: event.style }, { at });
4882
+ Transforms.unsetNodes(action.editor, action.props, { at });
4840
4883
  }
4841
4884
  },
4842
- "delete text": ({ event }) => {
4843
- Transforms.delete(event.editor, {
4844
- at: toSlateRange(event.selection, event.editor)
4885
+ "delete backward": ({ action }) => {
4886
+ deleteBackward(action.editor, action.unit);
4887
+ },
4888
+ "delete text": ({ action }) => {
4889
+ Transforms.delete(action.editor, {
4890
+ at: toSlateRange(action.selection, action.editor)
4845
4891
  });
4846
4892
  },
4847
- "insert text": ({ event }) => {
4848
- Editor.insertText(event.editor, event.text);
4893
+ "insert break": insertBreakActionImplementation,
4894
+ // This mimics Slate's internal which also just does a regular insert break
4895
+ // when on soft break
4896
+ "insert soft break": insertBreakActionImplementation,
4897
+ "insert text": ({ action }) => {
4898
+ insertText(action.editor, action.text);
4849
4899
  },
4850
- "insert text block": ({ context, event }) => {
4851
- Editor.insertNode(event.editor, {
4900
+ "insert text block": ({ context, action }) => {
4901
+ Editor.insertNode(action.editor, {
4852
4902
  _key: context.keyGenerator(),
4853
4903
  _type: context.schema.block.name,
4854
4904
  style: context.schema.styles[0].value ?? "normal",
@@ -4861,8 +4911,47 @@ const EditorActorContext = createContext({}), behaviorActionImplementations = {
4861
4911
  }
4862
4912
  ]
4863
4913
  });
4914
+ },
4915
+ effect: ({ action }) => {
4916
+ action.effect();
4864
4917
  }
4865
- }, networkLogic = fromCallback(({ sendBack }) => {
4918
+ };
4919
+ function performDefaultAction({
4920
+ context,
4921
+ action
4922
+ }) {
4923
+ switch (action.type) {
4924
+ case "delete backward": {
4925
+ behaviorActionImplementations["delete backward"]({
4926
+ context,
4927
+ action
4928
+ });
4929
+ break;
4930
+ }
4931
+ case "insert break": {
4932
+ behaviorActionImplementations["insert break"]({
4933
+ context,
4934
+ action
4935
+ });
4936
+ break;
4937
+ }
4938
+ case "insert soft break": {
4939
+ behaviorActionImplementations["insert soft break"]({
4940
+ context,
4941
+ action
4942
+ });
4943
+ break;
4944
+ }
4945
+ case "insert text": {
4946
+ behaviorActionImplementations["insert text"]({
4947
+ context,
4948
+ action
4949
+ });
4950
+ break;
4951
+ }
4952
+ }
4953
+ }
4954
+ const networkLogic = fromCallback(({ sendBack }) => {
4866
4955
  const onlineHandler = () => {
4867
4956
  sendBack({ type: "online" });
4868
4957
  }, offlineHandler = () => {
@@ -4895,12 +4984,17 @@ const EditorActorContext = createContext({}), behaviorActionImplementations = {
4895
4984
  pendingEvents: []
4896
4985
  }),
4897
4986
  "handle behavior event": enqueueActions(({ context, event, enqueue }) => {
4898
- assertEvent(event, ["key down", "before insert text"]);
4899
- const eventBehaviors = context.behaviors.filter(
4900
- (behavior) => behavior.on === event.type
4987
+ assertEvent(event, ["behavior event"]);
4988
+ const defaultAction = {
4989
+ ...event.behaviorEvent,
4990
+ editor: event.editor
4991
+ }, eventBehaviors = context.behaviors.filter(
4992
+ (behavior) => behavior.on === event.behaviorEvent.type
4901
4993
  );
4902
- if (eventBehaviors.length === 0)
4994
+ if (eventBehaviors.length === 0) {
4995
+ performDefaultAction({ context, action: defaultAction });
4903
4996
  return;
4997
+ }
4904
4998
  const value = fromSlateValue(
4905
4999
  event.editor.children,
4906
5000
  context.schema.block.name,
@@ -4913,7 +5007,7 @@ const EditorActorContext = createContext({}), behaviorActionImplementations = {
4913
5007
  if (!selection) {
4914
5008
  console.warn(
4915
5009
  `Unable to handle event ${event.type} due to missing selection`
4916
- );
5010
+ ), performDefaultAction({ context, action: defaultAction });
4917
5011
  return;
4918
5012
  }
4919
5013
  const behaviorContext = {
@@ -4921,22 +5015,28 @@ const EditorActorContext = createContext({}), behaviorActionImplementations = {
4921
5015
  value,
4922
5016
  selection
4923
5017
  };
5018
+ let behaviorOverwritten = !1;
4924
5019
  for (const eventBehavior of eventBehaviors) {
4925
5020
  const shouldRun = eventBehavior.guard?.({
4926
5021
  context: behaviorContext,
4927
- event
5022
+ event: event.behaviorEvent
4928
5023
  }) ?? !0;
4929
5024
  if (!shouldRun)
4930
5025
  continue;
4931
- const actions = eventBehavior.actions.map(
4932
- (action) => action({ context: behaviorContext, event }, shouldRun)
5026
+ const actionIntendSets = eventBehavior.actions.map(
5027
+ (actionSet) => actionSet(
5028
+ { context: behaviorContext, event: event.behaviorEvent },
5029
+ shouldRun
5030
+ )
4933
5031
  );
4934
- for (const action of actions)
4935
- typeof action == "object" && enqueue.raise({
4936
- ...action,
4937
- editor: event.editor
5032
+ for (const actionIntends of actionIntendSets)
5033
+ behaviorOverwritten = actionIntends.length > 0 && actionIntends.some((actionIntend) => actionIntend.type !== "effect"), enqueue.raise({
5034
+ type: "behavior action intends",
5035
+ editor: event.editor,
5036
+ actionIntends
4938
5037
  });
4939
5038
  }
5039
+ behaviorOverwritten || performDefaultAction({ context, action: defaultAction });
4940
5040
  })
4941
5041
  },
4942
5042
  actors: {
@@ -4968,23 +5068,83 @@ const EditorActorContext = createContext({}), behaviorActionImplementations = {
4968
5068
  loading: { actions: emit({ type: "loading" }) },
4969
5069
  "done loading": { actions: emit({ type: "done loading" }) },
4970
5070
  "update schema": { actions: "assign schema" },
4971
- "key down": {
4972
- actions: ["handle behavior event"]
4973
- },
4974
- "before insert text": {
4975
- actions: ["handle behavior event"]
4976
- },
4977
- "apply block style": {
4978
- actions: [behaviorActionImplementations["apply block style"]]
4979
- },
4980
- "delete text": {
4981
- actions: [behaviorActionImplementations["delete text"]]
4982
- },
4983
- "insert text": {
4984
- actions: [behaviorActionImplementations["insert text"]]
4985
- },
4986
- "insert text block": {
4987
- actions: [behaviorActionImplementations["insert text block"]]
5071
+ "behavior event": { actions: "handle behavior event" },
5072
+ "behavior action intends": {
5073
+ actions: [
5074
+ ({ context, event }) => {
5075
+ Editor.withoutNormalizing(event.editor, () => {
5076
+ for (const actionIntend of event.actionIntends) {
5077
+ const action = {
5078
+ ...actionIntend,
5079
+ editor: event.editor
5080
+ };
5081
+ switch (action.type) {
5082
+ case "delete backward": {
5083
+ behaviorActionImplementations["delete backward"]({
5084
+ context,
5085
+ action
5086
+ });
5087
+ break;
5088
+ }
5089
+ case "delete text": {
5090
+ behaviorActionImplementations["delete text"]({
5091
+ context,
5092
+ action
5093
+ });
5094
+ break;
5095
+ }
5096
+ case "insert break": {
5097
+ behaviorActionImplementations["insert break"]({
5098
+ context,
5099
+ action
5100
+ });
5101
+ break;
5102
+ }
5103
+ case "insert soft break": {
5104
+ behaviorActionImplementations["insert soft break"]({
5105
+ context,
5106
+ action
5107
+ });
5108
+ break;
5109
+ }
5110
+ case "insert text": {
5111
+ behaviorActionImplementations["insert text"]({
5112
+ context,
5113
+ action
5114
+ });
5115
+ break;
5116
+ }
5117
+ case "insert text block": {
5118
+ behaviorActionImplementations["insert text block"]({
5119
+ context,
5120
+ action
5121
+ });
5122
+ break;
5123
+ }
5124
+ case "set block": {
5125
+ behaviorActionImplementations["set block"]({
5126
+ context,
5127
+ action
5128
+ });
5129
+ break;
5130
+ }
5131
+ case "unset block": {
5132
+ behaviorActionImplementations["unset block"]({
5133
+ context,
5134
+ action
5135
+ });
5136
+ break;
5137
+ }
5138
+ default:
5139
+ behaviorActionImplementations.effect({
5140
+ context,
5141
+ action
5142
+ });
5143
+ }
5144
+ }
5145
+ }), event.editor.onChange();
5146
+ }
5147
+ ]
4988
5148
  }
4989
5149
  },
4990
5150
  initial: "pristine",
@@ -5616,11 +5776,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5616
5776
  [editorActor, onBlur]
5617
5777
  ), handleOnBeforeInput = useCallback(
5618
5778
  (event) => {
5619
- onBeforeInput && onBeforeInput(event), !event.defaultPrevented && event.inputType === "insertText" && editorActor.send({
5620
- type: "before insert text",
5621
- nativeEvent: event,
5622
- editor: slateEditor
5623
- });
5779
+ onBeforeInput && onBeforeInput(event);
5624
5780
  },
5625
5781
  [onBeforeInput]
5626
5782
  ), validateSelection = useCallback(() => {
@@ -5659,11 +5815,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5659
5815
  }, [validateSelection, editableElement]);
5660
5816
  const handleKeyDown = useCallback(
5661
5817
  (event) => {
5662
- props.onKeyDown && props.onKeyDown(event), event.isDefaultPrevented() || (editorActor.send({
5663
- type: "key down",
5664
- nativeEvent: event.nativeEvent,
5665
- editor: slateEditor
5666
- }), slateEditor.pteWithHotKeys(event));
5818
+ props.onKeyDown && props.onKeyDown(event), event.isDefaultPrevented() || slateEditor.pteWithHotKeys(event);
5667
5819
  },
5668
5820
  [props, slateEditor]
5669
5821
  ), scrollSelectionIntoViewToSlate = useMemo(() => {