@portabletext/editor 1.1.7 → 1.1.9

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.js CHANGED
@@ -1594,11 +1594,11 @@ function createWithInsertBreak(editorActor, types2) {
1594
1594
  (mark) => !types2.decorators.some((decorator) => decorator.value === mark)
1595
1595
  ) ?? [], focusBlockPath = editor.selection.focus.path.slice(0, 1), focusBlock = slate.Node.descendant(editor, focusBlockPath);
1596
1596
  if (editor.isTextBlock(focusBlock)) {
1597
- const [start, end] = slate.Range.edges(editor.selection), isEndAtStartOfBlock = isEqual__default.default(end, {
1597
+ const [start, end] = slate.Range.edges(editor.selection), atTheStartOfBlock = isEqual__default.default(end, {
1598
1598
  path: [...focusBlockPath, 0],
1599
1599
  offset: 0
1600
1600
  });
1601
- if (isEndAtStartOfBlock && slate.Range.isCollapsed(editor.selection)) {
1601
+ if (atTheStartOfBlock && slate.Range.isCollapsed(editor.selection)) {
1602
1602
  slate.Editor.insertNode(
1603
1603
  editor,
1604
1604
  editor.pteCreateTextBlock({
@@ -1609,32 +1609,28 @@ function createWithInsertBreak(editorActor, types2) {
1609
1609
  slate.Transforms.select(editor, {
1610
1610
  anchor: { path: [nextBlockPath, 0], offset: 0 },
1611
1611
  focus: { path: [nextBlockPath, 0], offset: 0 }
1612
- }), editor.onChange();
1612
+ });
1613
1613
  return;
1614
1614
  }
1615
- const lastFocusBlockChild = focusBlock.children[focusBlock.children.length - 1], isStartAtEndOfBlock = isEqual__default.default(start, {
1615
+ const lastFocusBlockChild = focusBlock.children[focusBlock.children.length - 1], atTheEndOfBlock = isEqual__default.default(start, {
1616
1616
  path: [...focusBlockPath, focusBlock.children.length - 1],
1617
1617
  offset: editor.isTextSpan(lastFocusBlockChild) ? lastFocusBlockChild.text.length : 0
1618
1618
  });
1619
- if (isStartAtEndOfBlock && slate.Range.isCollapsed(editor.selection) && focusDecorators.length > 0 && focusAnnotations.length > 0) {
1620
- slate.Editor.withoutNormalizing(editor, () => {
1621
- if (!editor.selection)
1622
- return;
1623
- slate.Editor.insertNode(
1624
- editor,
1625
- editor.pteCreateTextBlock({
1626
- decorators: []
1627
- })
1628
- );
1629
- const [nextBlockPath] = slate.Path.next(focusBlockPath);
1630
- slate.Transforms.setSelection(editor, {
1631
- anchor: { path: [nextBlockPath, 0], offset: 0 },
1632
- focus: { path: [nextBlockPath, 0], offset: 0 }
1633
- });
1634
- }), editor.onChange();
1619
+ if (atTheEndOfBlock && slate.Range.isCollapsed(editor.selection)) {
1620
+ slate.Editor.insertNode(
1621
+ editor,
1622
+ editor.pteCreateTextBlock({
1623
+ decorators: []
1624
+ })
1625
+ );
1626
+ const [nextBlockPath] = slate.Path.next(focusBlockPath);
1627
+ slate.Transforms.setSelection(editor, {
1628
+ anchor: { path: [nextBlockPath, 0], offset: 0 },
1629
+ focus: { path: [nextBlockPath, 0], offset: 0 }
1630
+ });
1635
1631
  return;
1636
1632
  }
1637
- if (!isEndAtStartOfBlock && !isStartAtEndOfBlock) {
1633
+ if (!atTheStartOfBlock && !atTheEndOfBlock) {
1638
1634
  slate.Editor.withoutNormalizing(editor, () => {
1639
1635
  if (!editor.selection)
1640
1636
  return;
@@ -3494,6 +3490,17 @@ function createWithPortableTextMarkModel(editorActor, types2) {
3494
3490
  }
3495
3491
  }
3496
3492
  }
3493
+ if (atTheBeginningOfSpan && !spanIsEmpty && previousSpan) {
3494
+ slate.Transforms.insertNodes(editor, {
3495
+ _type: "span",
3496
+ _key: editorActor.getSnapshot().context.keyGenerator(),
3497
+ text: op.text,
3498
+ marks: (previousSpan.marks ?? []).filter(
3499
+ (mark) => decorators.includes(mark)
3500
+ )
3501
+ });
3502
+ return;
3503
+ }
3497
3504
  }
3498
3505
  }
3499
3506
  if (op.type === "remove_text") {
@@ -3797,7 +3804,7 @@ const debug$8 = debugWithName("plugin:withHotKeys"), DEFAULT_HOTKEYS = {
3797
3804
  },
3798
3805
  custom: {}
3799
3806
  };
3800
- function createWithHotkeys(types$1, portableTextEditor, hotkeysFromOptions) {
3807
+ function createWithHotkeys(portableTextEditor, hotkeysFromOptions) {
3801
3808
  const reservedHotkeys = ["enter", "tab", "shift", "delete", "end"], activeHotkeys = hotkeysFromOptions || DEFAULT_HOTKEYS;
3802
3809
  return function(editor) {
3803
3810
  return editor.pteWithHotKeys = (event) => {
@@ -3878,16 +3885,6 @@ function createWithHotkeys(types$1, portableTextEditor, hotkeysFromOptions) {
3878
3885
  editor.pteEndList() && event.preventDefault();
3879
3886
  return;
3880
3887
  }
3881
- if (editor.isTextBlock(focusBlock) && focusBlock.style && focusBlock.style !== types$1.styles[0].value) {
3882
- const [, end] = slate.Range.edges(editor.selection);
3883
- if (slate.Editor.isEnd(editor, end, end.path)) {
3884
- slate.Editor.insertNode(
3885
- editor,
3886
- editor.pteCreateTextBlock({ decorators: [] })
3887
- ), event.preventDefault(), editor.onChange();
3888
- return;
3889
- }
3890
- }
3891
3888
  }
3892
3889
  }, editor;
3893
3890
  };
@@ -4371,7 +4368,7 @@ function _insertFragment(editor, fragment, schemaTypes) {
4371
4368
  }), editor.onChange();
4372
4369
  }
4373
4370
  const originalFnMap = /* @__PURE__ */ new WeakMap(), withPlugins = (editor, options) => {
4374
- const e = editor, { portableTextEditor, patches$, readOnly, maxBlocks } = options, { editorActor, schemaTypes } = portableTextEditor;
4371
+ const e = editor, { editorActor, portableTextEditor, patches$, readOnly, maxBlocks } = options, { schemaTypes } = portableTextEditor;
4375
4372
  e.subscriptions = [], e.destroy ? e.destroy() : originalFnMap.set(e, {
4376
4373
  apply: e.apply,
4377
4374
  onChange: e.onChange,
@@ -4469,9 +4466,10 @@ const originalFnMap = /* @__PURE__ */ new WeakMap(), withPlugins = (editor, opti
4469
4466
  };
4470
4467
  }, debug$6 = debugWithName("component:PortableTextEditor:SlateContainer");
4471
4468
  function SlateContainer(props) {
4472
- const { patches$, portableTextEditor, readOnly, maxBlocks } = props, [[slateEditor, subscribe]] = react.useState(() => {
4469
+ const { editorActor, patches$, portableTextEditor, readOnly, maxBlocks } = props, [[slateEditor, subscribe]] = react.useState(() => {
4473
4470
  debug$6("Creating new Slate editor instance");
4474
4471
  const { editor, subscribe: _sub } = withPlugins(slateReact.withReact(slate.createEditor()), {
4472
+ editorActor,
4475
4473
  maxBlocks,
4476
4474
  patches$,
4477
4475
  portableTextEditor,
@@ -4486,6 +4484,7 @@ function SlateContainer(props) {
4486
4484
  };
4487
4485
  }, [subscribe]), react.useEffect(() => {
4488
4486
  debug$6("Re-initializing plugin chain"), withPlugins(slateEditor, {
4487
+ editorActor,
4489
4488
  maxBlocks,
4490
4489
  patches$,
4491
4490
  portableTextEditor,
@@ -4506,7 +4505,7 @@ const PortableTextEditorReadOnlyContext = react.createContext(!1), usePortableTe
4506
4505
  return readOnly;
4507
4506
  }, debug$5 = debugWithName("hook:useSyncValue"), CURRENT_VALUE = /* @__PURE__ */ new WeakMap();
4508
4507
  function useSyncValue(props) {
4509
- const { editorActor, portableTextEditor, readOnly } = props, { schemaTypes } = portableTextEditor, previousValue = react.useRef(), slateEditor = slateReact.useSlate(), updateValueFunctionRef = react.useRef(), updateFromCurrentValue = react.useCallback(() => {
4508
+ const { editorActor, portableTextEditor, readOnly } = props, schemaTypes = editorActor.getSnapshot().context.schema, previousValue = react.useRef(), slateEditor = slateReact.useSlate(), updateValueFunctionRef = react.useRef(), updateFromCurrentValue = react.useCallback(() => {
4510
4509
  const currentValue = CURRENT_VALUE.get(portableTextEditor);
4511
4510
  if (previousValue.current === currentValue) {
4512
4511
  debug$5("Value is the same object as previous, not need to sync");
@@ -4813,30 +4812,40 @@ ${JSON.stringify(pendingPatches.current, null, 2)}`);
4813
4812
  debug$4("Value from props changed, syncing new value"), syncValue(value), isInitialValueFromProps.current && (editorActor.send({ type: "ready" }), isInitialValueFromProps.current = !1);
4814
4813
  }, [editorActor, syncValue, value]), null;
4815
4814
  }
4816
- function inserText({
4817
- event
4818
- }) {
4819
- slate.Editor.insertText(event.editor, event.text);
4820
- }
4821
- function inserTextBlock({
4822
- context,
4823
- event
4824
- }) {
4825
- slate.Editor.insertNode(event.editor, {
4826
- _key: context.keyGenerator(),
4827
- _type: context.schema.block.name,
4828
- style: context.schema.styles[0].value ?? "normal",
4829
- markDefs: [],
4830
- children: [
4831
- {
4832
- _key: context.keyGenerator(),
4833
- _type: "span",
4834
- text: ""
4835
- }
4836
- ]
4837
- });
4838
- }
4839
- const networkLogic = xstate.fromCallback(({ sendBack }) => {
4815
+ const EditorActorContext = react.createContext({}), behaviorActionImplementations = {
4816
+ "apply block style": ({ event }) => {
4817
+ for (const path of event.paths) {
4818
+ const at = toSlateRange(
4819
+ { anchor: { path, offset: 0 }, focus: { path, offset: 0 } },
4820
+ event.editor
4821
+ );
4822
+ slate.Transforms.setNodes(event.editor, { style: event.style }, { at });
4823
+ }
4824
+ },
4825
+ "delete text": ({ event }) => {
4826
+ slate.Transforms.delete(event.editor, {
4827
+ at: toSlateRange(event.selection, event.editor)
4828
+ });
4829
+ },
4830
+ "insert text": ({ event }) => {
4831
+ slate.Editor.insertText(event.editor, event.text);
4832
+ },
4833
+ "insert text block": ({ context, event }) => {
4834
+ slate.Editor.insertNode(event.editor, {
4835
+ _key: context.keyGenerator(),
4836
+ _type: context.schema.block.name,
4837
+ style: context.schema.styles[0].value ?? "normal",
4838
+ markDefs: [],
4839
+ children: [
4840
+ {
4841
+ _key: context.keyGenerator(),
4842
+ _type: "span",
4843
+ text: ""
4844
+ }
4845
+ ]
4846
+ });
4847
+ }
4848
+ }, networkLogic = xstate.fromCallback(({ sendBack }) => {
4840
4849
  const onlineHandler = () => {
4841
4850
  sendBack({ type: "online" });
4842
4851
  }, offlineHandler = () => {
@@ -4853,12 +4862,6 @@ const networkLogic = xstate.fromCallback(({ sendBack }) => {
4853
4862
  input: {}
4854
4863
  },
4855
4864
  actions: {
4856
- "apply:insert text": ({ context, event }) => {
4857
- xstate.assertEvent(event, "insert text"), inserText({ context, event });
4858
- },
4859
- "apply:insert text block": ({ context, event }) => {
4860
- xstate.assertEvent(event, "insert text block"), inserTextBlock({ context, event });
4861
- },
4862
4865
  "assign schema": xstate.assign({
4863
4866
  schema: ({ event }) => (xstate.assertEvent(event, "update schema"), event.schema)
4864
4867
  }),
@@ -4875,7 +4878,7 @@ const networkLogic = xstate.fromCallback(({ sendBack }) => {
4875
4878
  pendingEvents: []
4876
4879
  }),
4877
4880
  "handle behavior event": xstate.enqueueActions(({ context, event, enqueue }) => {
4878
- xstate.assertEvent(event, ["key down"]);
4881
+ xstate.assertEvent(event, ["key down", "before insert text"]);
4879
4882
  const eventBehaviors = context.behaviors.filter(
4880
4883
  (behavior) => behavior.on === event.type
4881
4884
  );
@@ -4951,11 +4954,20 @@ const networkLogic = xstate.fromCallback(({ sendBack }) => {
4951
4954
  "key down": {
4952
4955
  actions: ["handle behavior event"]
4953
4956
  },
4957
+ "before insert text": {
4958
+ actions: ["handle behavior event"]
4959
+ },
4960
+ "apply block style": {
4961
+ actions: [behaviorActionImplementations["apply block style"]]
4962
+ },
4963
+ "delete text": {
4964
+ actions: [behaviorActionImplementations["delete text"]]
4965
+ },
4954
4966
  "insert text": {
4955
- actions: ["apply:insert text"]
4967
+ actions: [behaviorActionImplementations["insert text"]]
4956
4968
  },
4957
4969
  "insert text block": {
4958
- actions: ["apply:insert text block"]
4970
+ actions: [behaviorActionImplementations["insert text block"]]
4959
4971
  }
4960
4972
  },
4961
4973
  initial: "pristine",
@@ -5029,11 +5041,6 @@ function PortableTextEditorSelectionProvider(props) {
5029
5041
  }
5030
5042
  const defaultKeyGenerator = () => content.randomKey(12), debug$2 = debugWithName("component:PortableTextEditor");
5031
5043
  class PortableTextEditor extends react.Component {
5032
- /**
5033
- * @internal
5034
- * Don't use this API directly. It's subject to change.
5035
- */
5036
- editorActor;
5037
5044
  /**
5038
5045
  * An observable of all the editor changes.
5039
5046
  */
@@ -5046,6 +5053,7 @@ class PortableTextEditor extends react.Component {
5046
5053
  * The editor API (currently implemented with Slate).
5047
5054
  */
5048
5055
  editable;
5056
+ editorActor;
5049
5057
  constructor(props) {
5050
5058
  if (super(props), !props.schemaType)
5051
5059
  throw new Error('PortableTextEditor: missing "schemaType" property');
@@ -5078,29 +5086,36 @@ class PortableTextEditor extends react.Component {
5078
5086
  };
5079
5087
  render() {
5080
5088
  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;
5081
- return /* @__PURE__ */ jsxRuntime.jsx(
5089
+ return /* @__PURE__ */ jsxRuntime.jsx(EditorActorContext.Provider, { value: this.editorActor, children: /* @__PURE__ */ jsxRuntime.jsx(
5082
5090
  SlateContainer,
5083
5091
  {
5092
+ editorActor: this.editorActor,
5084
5093
  maxBlocks,
5085
5094
  patches$: _patches$,
5086
5095
  portableTextEditor: this,
5087
5096
  readOnly,
5088
- children: /* @__PURE__ */ jsxRuntime.jsx(PortableTextEditorContext.Provider, { value: this, children: /* @__PURE__ */ jsxRuntime.jsx(PortableTextEditorReadOnlyContext.Provider, { value: readOnly, children: /* @__PURE__ */ jsxRuntime.jsxs(PortableTextEditorSelectionProvider, { editorActor: this.editorActor, children: [
5089
- /* @__PURE__ */ jsxRuntime.jsx(
5090
- Synchronizer,
5091
- {
5092
- editorActor: this.editorActor,
5093
- getValue: this.getValue,
5094
- onChange: (change) => {
5095
- this.props.onChange(change), this.change$.next(change);
5096
- },
5097
- value
5098
- }
5099
- ),
5100
- children
5101
- ] }) }) })
5097
+ children: /* @__PURE__ */ jsxRuntime.jsx(PortableTextEditorContext.Provider, { value: this, children: /* @__PURE__ */ jsxRuntime.jsx(PortableTextEditorReadOnlyContext.Provider, { value: readOnly, children: /* @__PURE__ */ jsxRuntime.jsxs(
5098
+ PortableTextEditorSelectionProvider,
5099
+ {
5100
+ editorActor: this.editorActor,
5101
+ children: [
5102
+ /* @__PURE__ */ jsxRuntime.jsx(
5103
+ Synchronizer,
5104
+ {
5105
+ editorActor: this.editorActor,
5106
+ getValue: this.getValue,
5107
+ onChange: (change) => {
5108
+ this.props.onChange(change), this.change$.next(change);
5109
+ },
5110
+ value
5111
+ }
5112
+ ),
5113
+ children
5114
+ ]
5115
+ }
5116
+ ) }) })
5102
5117
  }
5103
- );
5118
+ ) });
5104
5119
  }
5105
5120
  // Static API methods
5106
5121
  static activeAnnotations = (editor) => editor && editor.editable ? editor.editable.activeAnnotations() : [];
@@ -5154,6 +5169,7 @@ class PortableTextEditor extends react.Component {
5154
5169
  }
5155
5170
  const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (props) => {
5156
5171
  const {
5172
+ editorActor,
5157
5173
  attributes,
5158
5174
  children,
5159
5175
  leaf,
@@ -5208,17 +5224,14 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5208
5224
  react.useEffect(() => {
5209
5225
  if (!shouldTrackSelectionAndFocus)
5210
5226
  return;
5211
- const onBlur = portableTextEditor.editorActor.on("blur", () => {
5227
+ const onBlur = editorActor.on("blur", () => {
5212
5228
  setFocused(!1), setSelected(!1);
5213
- }), onFocus = portableTextEditor.editorActor.on("focus", () => {
5229
+ }), onFocus = editorActor.on("focus", () => {
5214
5230
  const sel = PortableTextEditor.getSelection(portableTextEditor);
5215
5231
  sel && isEqual__default.default(sel.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) && setFocused(!0), setSelectedFromRange();
5216
- }), onSelection = portableTextEditor.editorActor.on(
5217
- "selection",
5218
- (event) => {
5219
- event.selection && isEqual__default.default(event.selection.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) ? setFocused(!0) : setFocused(!1), setSelectedFromRange();
5220
- }
5221
- );
5232
+ }), onSelection = editorActor.on("selection", (event) => {
5233
+ event.selection && isEqual__default.default(event.selection.focus.path, path) && PortableTextEditor.isCollapsedSelection(portableTextEditor) ? setFocused(!0) : setFocused(!1), setSelectedFromRange();
5234
+ });
5222
5235
  return () => {
5223
5236
  onBlur.unsubscribe(), onFocus.unsubscribe(), onSelection.unsubscribe();
5224
5237
  };
@@ -5371,12 +5384,12 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5371
5384
  forwardedRef,
5372
5385
  () => ref.current
5373
5386
  );
5374
- const rangeDecorationsRef = react.useRef(rangeDecorations), { editorActor, schemaTypes } = portableTextEditor, slateEditor = slateReact.useSlate(), blockTypeName = schemaTypes.block.name, withInsertData = react.useMemo(
5387
+ const rangeDecorationsRef = react.useRef(rangeDecorations), editorActor = react.useContext(EditorActorContext), { schemaTypes } = portableTextEditor, slateEditor = slateReact.useSlate(), blockTypeName = schemaTypes.block.name, withInsertData = react.useMemo(
5375
5388
  () => createWithInsertData(editorActor, schemaTypes),
5376
5389
  [editorActor, schemaTypes]
5377
5390
  ), withHotKeys = react.useMemo(
5378
- () => createWithHotkeys(schemaTypes, portableTextEditor, hotkeys),
5379
- [hotkeys, portableTextEditor, schemaTypes]
5391
+ () => createWithHotkeys(portableTextEditor, hotkeys),
5392
+ [hotkeys, portableTextEditor]
5380
5393
  );
5381
5394
  react.useMemo(() => readOnly ? (debug("Editable is in read only mode"), withInsertData(slateEditor)) : (debug("Editable is in edit mode"), withInsertData(withHotKeys(slateEditor))), [readOnly, slateEditor, withHotKeys, withInsertData]);
5382
5395
  const renderElement = react.useCallback(
@@ -5409,6 +5422,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5409
5422
  Leaf,
5410
5423
  {
5411
5424
  ...lProps,
5425
+ editorActor,
5412
5426
  schemaTypes,
5413
5427
  renderAnnotation,
5414
5428
  renderChild,
@@ -5585,7 +5599,11 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
5585
5599
  [editorActor, onBlur]
5586
5600
  ), handleOnBeforeInput = react.useCallback(
5587
5601
  (event) => {
5588
- onBeforeInput && onBeforeInput(event);
5602
+ onBeforeInput && onBeforeInput(event), !event.defaultPrevented && event.inputType === "insertText" && editorActor.send({
5603
+ type: "before insert text",
5604
+ nativeEvent: event,
5605
+ editor: slateEditor
5606
+ });
5589
5607
  },
5590
5608
  [onBeforeInput]
5591
5609
  ), validateSelection = react.useCallback(() => {