@portabletext/editor 1.44.4 → 1.44.6

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.cjs CHANGED
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: !0 });
3
- var editorProvider = require("./_chunks-cjs/editor-provider.cjs"), jsxRuntime = require("react/jsx-runtime"), react = require("@xstate/react"), isEqual = require("lodash/isEqual.js"), noop = require("lodash/noop.js"), React = require("react"), slate = require("slate"), slateReact = require("slate-react"), selector_isOverlappingSelection = require("./_chunks-cjs/selector.is-overlapping-selection.cjs"), util_sliceBlocks = require("./_chunks-cjs/util.slice-blocks.cjs"), selector_getFocusInlineObject = require("./_chunks-cjs/selector.get-focus-inline-object.cjs"), slateDom = require("slate-dom"), util_isSelectionCollapsed = require("./_chunks-cjs/util.is-selection-collapsed.cjs"), parseBlocks = require("./_chunks-cjs/parse-blocks.cjs"), selector_isSelectingEntireBlocks = require("./_chunks-cjs/selector.is-selecting-entire-blocks.cjs"), behavior_core = require("./_chunks-cjs/behavior.core.cjs"), reactCompilerRuntime = require("react-compiler-runtime"), uniq = require("lodash/uniq.js"), useEffectEvent = require("use-effect-event");
3
+ var editorProvider = require("./_chunks-cjs/editor-provider.cjs"), jsxRuntime = require("react/jsx-runtime"), react = require("@xstate/react"), noop = require("lodash/noop.js"), React = require("react"), slate = require("slate"), slateReact = require("slate-react"), selector_isOverlappingSelection = require("./_chunks-cjs/selector.is-overlapping-selection.cjs"), util_sliceBlocks = require("./_chunks-cjs/util.slice-blocks.cjs"), selector_getFocusInlineObject = require("./_chunks-cjs/selector.get-focus-inline-object.cjs"), slateDom = require("slate-dom"), util_isSelectionCollapsed = require("./_chunks-cjs/util.is-selection-collapsed.cjs"), parseBlocks = require("./_chunks-cjs/parse-blocks.cjs"), isEqual = require("lodash/isEqual.js"), selector_isSelectingEntireBlocks = require("./_chunks-cjs/selector.is-selecting-entire-blocks.cjs"), behavior_core = require("./_chunks-cjs/behavior.core.cjs"), reactCompilerRuntime = require("react-compiler-runtime"), uniq = require("lodash/uniq.js"), xstate = require("xstate"), useEffectEvent = require("use-effect-event");
4
4
  function _interopDefaultCompat(e) {
5
5
  return e && typeof e == "object" && "default" in e ? e : { default: e };
6
6
  }
7
- var isEqual__default = /* @__PURE__ */ _interopDefaultCompat(isEqual), noop__default = /* @__PURE__ */ _interopDefaultCompat(noop), uniq__default = /* @__PURE__ */ _interopDefaultCompat(uniq);
7
+ var noop__default = /* @__PURE__ */ _interopDefaultCompat(noop), isEqual__default = /* @__PURE__ */ _interopDefaultCompat(isEqual), uniq__default = /* @__PURE__ */ _interopDefaultCompat(uniq);
8
8
  function getCompoundClientRect(nodes) {
9
9
  if (nodes.length === 0)
10
10
  return new DOMRect(0, 0, 0, 0);
@@ -710,18 +710,232 @@ function createWithHotkeys(editorActor, portableTextEditor, hotkeysFromOptions)
710
710
  }, editor;
711
711
  };
712
712
  }
713
- function withSyncRangeDecorations({
714
- editorActor,
715
- slateEditor,
716
- syncRangeDecorations
717
- }) {
718
- const originalApply = slateEditor.apply;
719
- return slateEditor.apply = (op) => {
720
- originalApply(op), !editorActor.getSnapshot().matches({
721
- "edit mode": "read only"
722
- }) && op.type !== "set_selection" && syncRangeDecorations(op);
713
+ const slateOperationCallback = ({
714
+ input,
715
+ sendBack
716
+ }) => {
717
+ const originalApply = input.slateEditor.apply;
718
+ return input.slateEditor.apply = (op) => {
719
+ op.type !== "set_selection" && sendBack({
720
+ type: "slate operation",
721
+ operation: op
722
+ }), originalApply(op);
723
723
  }, () => {
724
- slateEditor.apply = originalApply;
724
+ input.slateEditor.apply = originalApply;
725
+ };
726
+ }, rangeDecorationsMachine = xstate.setup({
727
+ types: {
728
+ context: {},
729
+ input: {},
730
+ events: {}
731
+ },
732
+ actions: {
733
+ "update pending range decorations": xstate.assign({
734
+ pendingRangeDecorations: ({
735
+ event
736
+ }) => (xstate.assertEvent(event, "range decorations updated"), event.rangeDecorations)
737
+ }),
738
+ "set up initial range decorations": xstate.assign({
739
+ decoratedRanges: ({
740
+ context,
741
+ event
742
+ }) => {
743
+ xstate.assertEvent(event, "ready");
744
+ const rangeDecorationState = [];
745
+ for (const rangeDecoration of context.pendingRangeDecorations) {
746
+ const slateRange = editorProvider.toSlateRange(rangeDecoration.selection, context.slateEditor);
747
+ if (!slate.Range.isRange(slateRange)) {
748
+ rangeDecoration.onMoved?.({
749
+ newSelection: null,
750
+ rangeDecoration,
751
+ origin: "local"
752
+ });
753
+ continue;
754
+ }
755
+ rangeDecorationState.push({
756
+ rangeDecoration,
757
+ ...slateRange
758
+ });
759
+ }
760
+ return rangeDecorationState;
761
+ }
762
+ }),
763
+ "update range decorations": xstate.assign({
764
+ decoratedRanges: ({
765
+ context,
766
+ event
767
+ }) => {
768
+ xstate.assertEvent(event, "range decorations updated");
769
+ const rangeDecorationState = [];
770
+ for (const rangeDecoration of event.rangeDecorations) {
771
+ const slateRange = editorProvider.toSlateRange(rangeDecoration.selection, context.slateEditor);
772
+ if (!slate.Range.isRange(slateRange)) {
773
+ rangeDecoration.onMoved?.({
774
+ newSelection: null,
775
+ rangeDecoration,
776
+ origin: "local"
777
+ });
778
+ continue;
779
+ }
780
+ rangeDecorationState.push({
781
+ rangeDecoration,
782
+ ...slateRange
783
+ });
784
+ }
785
+ return rangeDecorationState;
786
+ }
787
+ }),
788
+ "move range decorations": xstate.assign({
789
+ decoratedRanges: ({
790
+ context,
791
+ event
792
+ }) => {
793
+ xstate.assertEvent(event, "slate operation");
794
+ const rangeDecorationState = [];
795
+ for (const decoratedRange of context.decoratedRanges) {
796
+ const slateRange = editorProvider.toSlateRange(decoratedRange.rangeDecoration.selection, context.slateEditor);
797
+ if (!slate.Range.isRange(slateRange)) {
798
+ decoratedRange.rangeDecoration.onMoved?.({
799
+ newSelection: null,
800
+ rangeDecoration: decoratedRange.rangeDecoration,
801
+ origin: "local"
802
+ });
803
+ continue;
804
+ }
805
+ let newRange;
806
+ if (newRange = editorProvider.moveRangeByOperation(slateRange, event.operation), newRange && newRange !== slateRange || newRange === null && slateRange) {
807
+ const newRangeSelection = newRange ? editorProvider.slateRangeToSelection({
808
+ schema: context.schema,
809
+ editor: context.slateEditor,
810
+ range: newRange
811
+ }) : null;
812
+ decoratedRange.rangeDecoration.onMoved?.({
813
+ newSelection: newRangeSelection,
814
+ rangeDecoration: decoratedRange.rangeDecoration,
815
+ origin: "local"
816
+ });
817
+ }
818
+ newRange !== null && rangeDecorationState.push({
819
+ ...newRange || slateRange,
820
+ rangeDecoration: decoratedRange.rangeDecoration
821
+ });
822
+ }
823
+ return rangeDecorationState;
824
+ }
825
+ }),
826
+ "assign readOnly": xstate.assign({
827
+ readOnly: ({
828
+ event
829
+ }) => (xstate.assertEvent(event, "update read only"), event.readOnly)
830
+ })
831
+ },
832
+ actors: {
833
+ "slate operation listener": xstate.fromCallback(slateOperationCallback)
834
+ },
835
+ guards: {
836
+ "has range decorations": ({
837
+ context
838
+ }) => context.decoratedRanges.length > 0,
839
+ "has different decorations": ({
840
+ context,
841
+ event
842
+ }) => (xstate.assertEvent(event, "range decorations updated"), !isEqual__default.default(context.pendingRangeDecorations, event.rangeDecorations)),
843
+ "not read only": ({
844
+ context
845
+ }) => !context.readOnly
846
+ }
847
+ }).createMachine({
848
+ id: "range decorations",
849
+ context: ({
850
+ input
851
+ }) => ({
852
+ readOnly: input.readOnly,
853
+ pendingRangeDecorations: input.rangeDecorations,
854
+ decoratedRanges: [],
855
+ schema: input.schema,
856
+ slateEditor: input.slateEditor
857
+ }),
858
+ invoke: {
859
+ src: "slate operation listener",
860
+ input: ({
861
+ context
862
+ }) => ({
863
+ slateEditor: context.slateEditor
864
+ })
865
+ },
866
+ on: {
867
+ "update read only": {
868
+ actions: ["assign readOnly"]
869
+ }
870
+ },
871
+ initial: "idle",
872
+ states: {
873
+ idle: {
874
+ on: {
875
+ "range decorations updated": {
876
+ actions: ["update pending range decorations"]
877
+ },
878
+ ready: {
879
+ target: "ready",
880
+ actions: ["set up initial range decorations"]
881
+ }
882
+ }
883
+ },
884
+ ready: {
885
+ initial: "idle",
886
+ on: {
887
+ "range decorations updated": {
888
+ target: ".idle",
889
+ guard: "has different decorations",
890
+ actions: ["update range decorations", "update pending range decorations"]
891
+ }
892
+ },
893
+ states: {
894
+ idle: {
895
+ on: {
896
+ "slate operation": {
897
+ target: "moving range decorations",
898
+ guard: xstate.and(["has range decorations", "not read only"])
899
+ }
900
+ }
901
+ },
902
+ "moving range decorations": {
903
+ entry: ["move range decorations"],
904
+ always: {
905
+ target: "idle"
906
+ }
907
+ }
908
+ }
909
+ }
910
+ }
911
+ });
912
+ function createDecorate(rangeDecorationActor) {
913
+ return function([, path]) {
914
+ if (editorProvider.isEqualToEmptyEditor(rangeDecorationActor.getSnapshot().context.slateEditor.children, rangeDecorationActor.getSnapshot().context.schema))
915
+ return [{
916
+ anchor: {
917
+ path: [0, 0],
918
+ offset: 0
919
+ },
920
+ focus: {
921
+ path: [0, 0],
922
+ offset: 0
923
+ },
924
+ placeholder: !0
925
+ }];
926
+ if (path.length === 0)
927
+ return [];
928
+ const result = rangeDecorationActor.getSnapshot().context.decoratedRanges.filter((item) => slate.Range.isCollapsed(item) ? path.length !== 2 ? !1 : slate.Path.equals(item.focus.path, path) && slate.Path.equals(item.anchor.path, path) : slate.Range.intersection(item, {
929
+ anchor: {
930
+ path,
931
+ offset: 0
932
+ },
933
+ focus: {
934
+ path,
935
+ offset: 0
936
+ }
937
+ }) || slate.Range.includes(item, path));
938
+ return result.length > 0 ? result : [];
725
939
  };
726
940
  }
727
941
  const debug = editorProvider.debugWithName("component:Editable"), PLACEHOLDER_STYLE = {
@@ -759,11 +973,30 @@ const debug = editorProvider.debugWithName("component:Editable"), PLACEHOLDER_ST
759
973
  scrollSelectionIntoView,
760
974
  spellCheck,
761
975
  ...restProps
762
- } = props, portableTextEditor = editorProvider.usePortableTextEditor(), ref = React.useRef(null), [editableElement, setEditableElement] = React.useState(null), [hasInvalidValue, setHasInvalidValue] = React.useState(!1), [rangeDecorationState, setRangeDecorationsState] = React.useState([]);
976
+ } = props, portableTextEditor = editorProvider.usePortableTextEditor(), ref = React.useRef(null), [editableElement, setEditableElement] = React.useState(null), [hasInvalidValue, setHasInvalidValue] = React.useState(!1);
763
977
  React.useImperativeHandle(forwardedRef, () => ref.current);
764
- const rangeDecorationsRef = React.useRef(rangeDecorations), editorActor = React.useContext(editorProvider.EditorActorContext), readOnly = react.useSelector(editorActor, (s) => s.matches({
978
+ const editorActor = React.useContext(editorProvider.EditorActorContext), readOnly = react.useSelector(editorActor, (s) => s.matches({
765
979
  "edit mode": "read only"
766
- })), schemaTypes = react.useSelector(editorActor, (s_0) => s_0.context.schema), slateEditor = slateReact.useSlate(), blockTypeName = schemaTypes.block.name;
980
+ })), schemaTypes = react.useSelector(editorActor, (s_0) => s_0.context.schema), slateEditor = slateReact.useSlate(), rangeDecorationsActor = react.useActorRef(rangeDecorationsMachine, {
981
+ input: {
982
+ readOnly,
983
+ slateEditor,
984
+ schema: schemaTypes,
985
+ rangeDecorations: rangeDecorations ?? []
986
+ }
987
+ }), decorate = React.useMemo(() => createDecorate(rangeDecorationsActor), [rangeDecorationsActor]);
988
+ React.useEffect(() => {
989
+ rangeDecorationsActor.send({
990
+ type: "update read only",
991
+ readOnly
992
+ });
993
+ }, [rangeDecorationsActor, readOnly]), React.useEffect(() => {
994
+ rangeDecorationsActor.send({
995
+ type: "range decorations updated",
996
+ rangeDecorations: rangeDecorations ?? []
997
+ });
998
+ }, [rangeDecorationsActor, rangeDecorations]);
999
+ const blockTypeName = schemaTypes.block.name;
767
1000
  React.useMemo(() => {
768
1001
  if (readOnly)
769
1002
  return debug("Editable is in read only mode"), slateEditor;
@@ -797,46 +1030,12 @@ const debug = editorProvider.debugWithName("component:Editable"), PLACEHOLDER_ST
797
1030
  }), slateEditor.onChange());
798
1031
  }
799
1032
  }
800
- }, [blockTypeName, editorActor, propsSelection, slateEditor]), syncRangeDecorations = React.useCallback((operation) => {
801
- if (rangeDecorations && rangeDecorations.length > 0) {
802
- const newSlateRanges = [];
803
- if (rangeDecorations.forEach((rangeDecorationItem) => {
804
- const slateRange_0 = editorProvider.toSlateRange(rangeDecorationItem.selection, slateEditor);
805
- if (!slate.Range.isRange(slateRange_0)) {
806
- rangeDecorationItem.onMoved && rangeDecorationItem.onMoved({
807
- newSelection: null,
808
- rangeDecoration: rangeDecorationItem,
809
- origin: "local"
810
- });
811
- return;
812
- }
813
- let newRange;
814
- if (operation && (newRange = editorProvider.moveRangeByOperation(slateRange_0, operation), newRange && newRange !== slateRange_0 || newRange === null && slateRange_0)) {
815
- const newRangeSelection = newRange ? editorProvider.slateRangeToSelection({
816
- schema: schemaTypes,
817
- editor: slateEditor,
818
- range: newRange
819
- }) : null;
820
- rangeDecorationItem.onMoved && rangeDecorationItem.onMoved({
821
- newSelection: newRangeSelection,
822
- rangeDecoration: rangeDecorationItem,
823
- origin: "local"
824
- });
825
- }
826
- newRange !== null && newSlateRanges.push({
827
- ...newRange || slateRange_0,
828
- rangeDecoration: rangeDecorationItem
829
- });
830
- }), newSlateRanges.length > 0) {
831
- setRangeDecorationsState(newSlateRanges);
832
- return;
833
- }
834
- }
835
- setRangeDecorationsState((rangeDecorationState_0) => rangeDecorationState_0.length > 0 ? [] : rangeDecorationState_0);
836
- }, [rangeDecorations, schemaTypes, slateEditor]);
1033
+ }, [blockTypeName, editorActor, propsSelection, slateEditor]);
837
1034
  React.useEffect(() => {
838
1035
  const onReady = editorActor.on("ready", () => {
839
- syncRangeDecorations(), restoreSelectionFromProps();
1036
+ rangeDecorationsActor.send({
1037
+ type: "ready"
1038
+ }), restoreSelectionFromProps();
840
1039
  }), onInvalidValue = editorActor.on("invalid value", () => {
841
1040
  setHasInvalidValue(!0);
842
1041
  }), onValueChanged = editorActor.on("value changed", () => {
@@ -845,22 +1044,9 @@ const debug = editorProvider.debugWithName("component:Editable"), PLACEHOLDER_ST
845
1044
  return () => {
846
1045
  onReady.unsubscribe(), onInvalidValue.unsubscribe(), onValueChanged.unsubscribe();
847
1046
  };
848
- }, [editorActor, restoreSelectionFromProps, syncRangeDecorations]), React.useEffect(() => {
1047
+ }, [rangeDecorationsActor, editorActor, restoreSelectionFromProps]), React.useEffect(() => {
849
1048
  propsSelection && !hasInvalidValue && restoreSelectionFromProps();
850
1049
  }, [hasInvalidValue, propsSelection, restoreSelectionFromProps]);
851
- const [syncedRangeDecorations, setSyncedRangeDecorations] = React.useState(!1);
852
- React.useEffect(() => {
853
- syncedRangeDecorations || (setSyncedRangeDecorations(!0), syncRangeDecorations());
854
- }, [syncRangeDecorations, syncedRangeDecorations]), React.useEffect(() => {
855
- isEqual__default.default(rangeDecorations, rangeDecorationsRef.current) || syncRangeDecorations(), rangeDecorationsRef.current = rangeDecorations;
856
- }, [rangeDecorations, syncRangeDecorations]), React.useEffect(() => {
857
- const teardown = withSyncRangeDecorations({
858
- editorActor,
859
- slateEditor,
860
- syncRangeDecorations
861
- });
862
- return () => teardown();
863
- }, [editorActor, slateEditor, syncRangeDecorations]);
864
1050
  const handleCopy = React.useCallback((event) => {
865
1051
  if (onCopy)
866
1052
  onCopy(event) !== void 0 && event.preventDefault();
@@ -1106,33 +1292,7 @@ const debug = editorProvider.debugWithName("component:Editable"), PLACEHOLDER_ST
1106
1292
  return scrollSelectionIntoView === null ? noop__default.default : (_editor, domRange) => {
1107
1293
  scrollSelectionIntoView(portableTextEditor, domRange);
1108
1294
  };
1109
- }, [portableTextEditor, scrollSelectionIntoView]), decorate = React.useCallback(([, path_0]) => {
1110
- if (editorProvider.isEqualToEmptyEditor(slateEditor.children, schemaTypes))
1111
- return [{
1112
- anchor: {
1113
- path: [0, 0],
1114
- offset: 0
1115
- },
1116
- focus: {
1117
- path: [0, 0],
1118
- offset: 0
1119
- },
1120
- placeholder: !0
1121
- }];
1122
- if (path_0.length === 0)
1123
- return [];
1124
- const result_2 = rangeDecorationState.filter((item) => slate.Range.isCollapsed(item) ? path_0.length !== 2 ? !1 : slate.Path.equals(item.focus.path, path_0) && slate.Path.equals(item.anchor.path, path_0) : slate.Range.intersection(item, {
1125
- anchor: {
1126
- path: path_0,
1127
- offset: 0
1128
- },
1129
- focus: {
1130
- path: path_0,
1131
- offset: 0
1132
- }
1133
- }) || slate.Range.includes(item, path_0));
1134
- return result_2.length > 0 ? result_2 : [];
1135
- }, [slateEditor, schemaTypes, rangeDecorationState]);
1295
+ }, [portableTextEditor, scrollSelectionIntoView]);
1136
1296
  React.useEffect(() => {
1137
1297
  ref.current = slateReact.ReactEditor.toDOMNode(slateEditor, slateEditor), setEditableElement(ref.current);
1138
1298
  }, [slateEditor, ref]), React.useEffect(() => {