@portabletext/editor 7.6.1 → 7.7.0

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
@@ -2617,46 +2617,29 @@ function getTextContent(editor, path2) {
2617
2617
  return text;
2618
2618
  }
2619
2619
  const EngineString = (props) => {
2620
- const $ = c(6), {
2620
+ "use no memo";
2621
+ const {
2621
2622
  isLast,
2622
2623
  leaf,
2623
2624
  parent,
2624
2625
  path: path2,
2625
2626
  text
2626
2627
  } = props, editor = useEngineStatic(), parentPath$1 = parentPath(path2), leafText = leaf.text ?? "";
2627
- if (leafText === "" && isTextBlock({
2628
+ return leafText === "" && isTextBlock({
2628
2629
  schema: editor.snapshot.context.schema
2629
- }, parent) && parent.children[parent.children.length - 1] === text && getTextContent(editor, parentPath$1) === "") {
2630
- let t02;
2631
- return $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t02 = /* @__PURE__ */ jsx(ZeroWidthString, { isLineBreak: !0 }), $[0] = t02) : t02 = $[0], t02;
2632
- }
2633
- if (leafText === "") {
2634
- let t02;
2635
- return $[1] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t02 = /* @__PURE__ */ jsx(ZeroWidthString, {}), $[1] = t02) : t02 = $[1], t02;
2636
- }
2637
- if (isLast && leafText.slice(-1) === `
2638
- `) {
2639
- let t02;
2640
- return $[2] !== leafText ? (t02 = /* @__PURE__ */ jsx(TextString, { isTrailing: !0, text: leafText }), $[2] = leafText, $[3] = t02) : t02 = $[3], t02;
2641
- }
2642
- let t0;
2643
- return $[4] !== leafText ? (t0 = /* @__PURE__ */ jsx(TextString, { text: leafText }), $[4] = leafText, $[5] = t0) : t0 = $[5], t0;
2630
+ }, parent) && parent.children[parent.children.length - 1] === text && getTextContent(editor, parentPath$1) === "" ? /* @__PURE__ */ jsx(ZeroWidthString, { isLineBreak: !0 }) : leafText === "" ? /* @__PURE__ */ jsx(ZeroWidthString, {}) : isLast && leafText.slice(-1) === `
2631
+ ` ? /* @__PURE__ */ jsx(TextString, { isTrailing: !0, text: leafText }) : /* @__PURE__ */ jsx(TextString, { text: leafText });
2644
2632
  }, TextString = (props) => {
2645
- const $ = c(8), {
2633
+ "use no memo";
2634
+ const {
2646
2635
  text,
2647
- isTrailing: t0
2648
- } = props, isTrailing = t0 === void 0 ? !1 : t0, isInNewPipeline = useContext(NewPipelineContext), ref = useRef(null);
2649
- let t1;
2650
- $[0] !== isTrailing || $[1] !== text ? (t1 = () => `${text ?? ""}${isTrailing ? `
2651
- ` : ""}`, $[0] = isTrailing, $[1] = text, $[2] = t1) : t1 = $[2];
2652
- const getTextContent2 = t1, [initialText] = useState(getTextContent2);
2653
- let t2;
2654
- $[3] !== getTextContent2 ? (t2 = () => {
2636
+ isTrailing = !1
2637
+ } = props, isInNewPipeline = useContext(NewPipelineContext), ref = useRef(null), getTextContent2 = () => `${text ?? ""}${isTrailing ? `
2638
+ ` : ""}`, [initialText] = useState(getTextContent2);
2639
+ return useIsomorphicLayoutEffect(() => {
2655
2640
  const textWithTrailing = getTextContent2();
2656
2641
  ref.current && ref.current.textContent !== textWithTrailing && (ref.current.textContent = textWithTrailing);
2657
- }, $[3] = getTextContent2, $[4] = t2) : t2 = $[4], useIsomorphicLayoutEffect(t2);
2658
- let t3;
2659
- return $[5] !== initialText || $[6] !== isInNewPipeline ? (t3 = /* @__PURE__ */ jsx(MemoizedText$1, { ref, isInNewPipeline, children: initialText }), $[5] = initialText, $[6] = isInNewPipeline, $[7] = t3) : t3 = $[7], t3;
2642
+ }), /* @__PURE__ */ jsx(MemoizedText$1, { ref, isInNewPipeline, children: initialText });
2660
2643
  }, MemoizedText$1 = memo(forwardRef((props, ref) => {
2661
2644
  const $ = c(6);
2662
2645
  if (props.isInNewPipeline) {
@@ -5072,6 +5055,23 @@ function getSelectionState(snapshot, selection) {
5072
5055
  selectedContainerPaths: selectedContainerPaths.size > 0 ? selectedContainerPaths : emptySet$1
5073
5056
  };
5074
5057
  }
5058
+ function subscribeCoalesced(actor, observer) {
5059
+ let scheduled = !1, active = !0;
5060
+ const subscription = actor.subscribe({
5061
+ next: observer.next ? () => {
5062
+ scheduled || !active || (scheduled = !0, queueMicrotask(() => {
5063
+ scheduled = !1, active && observer.next?.();
5064
+ }));
5065
+ } : void 0,
5066
+ error: observer.error,
5067
+ complete: observer.complete
5068
+ });
5069
+ return {
5070
+ unsubscribe: () => {
5071
+ active = !1, subscription.unsubscribe();
5072
+ }
5073
+ };
5074
+ }
5075
5075
  const emptySet = /* @__PURE__ */ new Set(), defaultSelectionState = {
5076
5076
  focusedLeafPath: void 0,
5077
5077
  selectedLeafPaths: emptySet,
@@ -5132,17 +5132,15 @@ function SelectionStateProvider(t0) {
5132
5132
  for (const cb of subscribersRef.current)
5133
5133
  cb();
5134
5134
  }
5135
- let pendingRecompute = !1;
5136
- const subscription = editorActor.subscribe(() => {
5137
- pendingRecompute || (pendingRecompute = !0, queueMicrotask(() => {
5138
- pendingRecompute = !1;
5135
+ const subscription = subscribeCoalesced(editorActor, {
5136
+ next: () => {
5139
5137
  const newState = computeCurrent();
5140
5138
  if (!selectionStatesEqual(stateRef.current, newState)) {
5141
5139
  stateRef.current = newState;
5142
5140
  for (const cb_0 of subscribersRef.current)
5143
5141
  cb_0();
5144
5142
  }
5145
- }));
5143
+ }
5146
5144
  });
5147
5145
  return () => subscription.unsubscribe();
5148
5146
  }, t3 = [editorActor, computeCurrent], $[3] = computeCurrent, $[4] = editorActor, $[5] = t2, $[6] = t3) : (t2 = $[5], t3 = $[6]), useEffect(t2, t3);
@@ -5402,6 +5400,90 @@ function RenderChild$1({
5402
5400
  value
5403
5401
  });
5404
5402
  }
5403
+ const levelIndexMaps = /* @__PURE__ */ new Map();
5404
+ function buildIndexMaps(context, {
5405
+ blockIndexMap,
5406
+ listIndexMap
5407
+ }) {
5408
+ blockIndexMap.clear();
5409
+ for (let blockIndex = 0; blockIndex < context.value.length; blockIndex++) {
5410
+ const block = context.value.at(blockIndex);
5411
+ if (block === void 0 || block._key === void 0)
5412
+ continue;
5413
+ const blockPath = [{
5414
+ _key: block._key
5415
+ }], blockKey = serializePath(blockPath);
5416
+ blockIndexMap.has(blockKey) || blockIndexMap.set(blockKey, blockIndex), collectDescendantIndexes(context, block, blockPath, void 0, blockIndexMap);
5417
+ }
5418
+ buildListIndexMap(context, listIndexMap);
5419
+ }
5420
+ function buildListIndexMap(context, listIndexMap) {
5421
+ listIndexMap.clear(), levelIndexMaps.clear();
5422
+ let previousListItem;
5423
+ for (let blockIndex = 0; blockIndex < context.value.length; blockIndex++) {
5424
+ const block = context.value.at(blockIndex);
5425
+ if (block === void 0)
5426
+ continue;
5427
+ const blockPath = [{
5428
+ _key: block._key
5429
+ }];
5430
+ if (!isTextBlockNode(context, block)) {
5431
+ levelIndexMaps.clear(), previousListItem = void 0;
5432
+ continue;
5433
+ }
5434
+ if (block.listItem === void 0 || block.level === void 0) {
5435
+ levelIndexMaps.clear(), previousListItem = void 0;
5436
+ continue;
5437
+ }
5438
+ if (!previousListItem) {
5439
+ const levelIndexMap2 = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
5440
+ levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath(blockPath), 1), previousListItem = {
5441
+ listItem: block.listItem,
5442
+ level: block.level
5443
+ };
5444
+ continue;
5445
+ }
5446
+ if (previousListItem.listItem === block.listItem && previousListItem.level < block.level) {
5447
+ const levelIndexMap2 = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
5448
+ levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath(blockPath), 1), previousListItem = {
5449
+ listItem: block.listItem,
5450
+ level: block.level
5451
+ };
5452
+ continue;
5453
+ }
5454
+ levelIndexMaps.forEach((levelIndexMap2, listItem) => {
5455
+ if (listItem === block.listItem)
5456
+ return;
5457
+ const levelsToDelete = [];
5458
+ levelIndexMap2.forEach((_, level) => {
5459
+ level >= block.level && levelsToDelete.push(level);
5460
+ }), levelsToDelete.forEach((level) => {
5461
+ levelIndexMap2.delete(level);
5462
+ });
5463
+ });
5464
+ const levelIndexMap = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map(), levelCounter = levelIndexMap.get(block.level) ?? 0;
5465
+ levelIndexMap.set(block.level, levelCounter + 1), levelIndexMaps.set(block.listItem, levelIndexMap), listIndexMap.set(serializePath(blockPath), levelCounter + 1), previousListItem = {
5466
+ listItem: block.listItem,
5467
+ level: block.level
5468
+ };
5469
+ }
5470
+ }
5471
+ function getListIndexMap(editor) {
5472
+ return editor.listIndexMapDirty && (buildListIndexMap(editor.snapshot.context, editor.listIndexMap), editor.listIndexMapDirty = !1), editor.listIndexMap;
5473
+ }
5474
+ function collectDescendantIndexes(context, node, nodePath, parent, blockIndexMap) {
5475
+ const result = getNodeChildren(context, node, parent);
5476
+ if (result)
5477
+ for (let i = 0; i < result.children.length; i++) {
5478
+ const child = result.children[i];
5479
+ if (!child._key)
5480
+ continue;
5481
+ const childSegment = {
5482
+ _key: child._key
5483
+ }, childPath = [...nodePath, result.fieldName, childSegment], childKey = serializePath(childPath);
5484
+ blockIndexMap.has(childKey) || blockIndexMap.set(childKey, i), collectDescendantIndexes(context, child, childPath, result.parent, blockIndexMap);
5485
+ }
5486
+ }
5405
5487
  function RenderTextBlock(props) {
5406
5488
  const $ = c(79), blockRef = useRef(null);
5407
5489
  let t0;
@@ -5416,7 +5498,7 @@ function RenderTextBlock(props) {
5416
5498
  $[5] !== props.path ? (t2 = serializePath(props.path), $[5] = props.path, $[6] = t2) : t2 = $[6];
5417
5499
  const serializedPath = t2, selected = useIsSelectedContainer(serializedPath), focused = useIsFocusedContainer(serializedPath), dropPosition = useElementDropPosition(props.path);
5418
5500
  let t3;
5419
- $[7] !== serializedPath ? (t3 = (editor) => editor.listIndexMap.get(serializedPath), $[7] = serializedPath, $[8] = t3) : t3 = $[8];
5501
+ $[7] !== serializedPath ? (t3 = (editor) => getListIndexMap(editor).get(serializedPath), $[7] = serializedPath, $[8] = t3) : t3 = $[8];
5420
5502
  const listIndex = useEngineSelector(t3), subSchema = useBlockSubSchema(props.path);
5421
5503
  let children = props.children;
5422
5504
  if (props.legacy.renderStyle && props.textBlock.style) {
@@ -9225,87 +9307,6 @@ class BlockIndexMap extends Map {
9225
9307
  }]));
9226
9308
  }
9227
9309
  }
9228
- const levelIndexMaps = /* @__PURE__ */ new Map();
9229
- function buildIndexMaps(context, {
9230
- blockIndexMap,
9231
- listIndexMap
9232
- }) {
9233
- blockIndexMap.clear();
9234
- for (let blockIndex = 0; blockIndex < context.value.length; blockIndex++) {
9235
- const block = context.value.at(blockIndex);
9236
- if (block === void 0 || block._key === void 0)
9237
- continue;
9238
- const blockPath = [{
9239
- _key: block._key
9240
- }], blockKey = serializePath(blockPath);
9241
- blockIndexMap.has(blockKey) || blockIndexMap.set(blockKey, blockIndex), collectDescendantIndexes(context, block, blockPath, void 0, blockIndexMap);
9242
- }
9243
- buildListIndexMap(context, listIndexMap);
9244
- }
9245
- function buildListIndexMap(context, listIndexMap) {
9246
- listIndexMap.clear(), levelIndexMaps.clear();
9247
- let previousListItem;
9248
- for (let blockIndex = 0; blockIndex < context.value.length; blockIndex++) {
9249
- const block = context.value.at(blockIndex);
9250
- if (block === void 0)
9251
- continue;
9252
- const blockPath = [{
9253
- _key: block._key
9254
- }];
9255
- if (!isTextBlockNode(context, block)) {
9256
- levelIndexMaps.clear(), previousListItem = void 0;
9257
- continue;
9258
- }
9259
- if (block.listItem === void 0 || block.level === void 0) {
9260
- levelIndexMaps.clear(), previousListItem = void 0;
9261
- continue;
9262
- }
9263
- if (!previousListItem) {
9264
- const levelIndexMap2 = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
9265
- levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath(blockPath), 1), previousListItem = {
9266
- listItem: block.listItem,
9267
- level: block.level
9268
- };
9269
- continue;
9270
- }
9271
- if (previousListItem.listItem === block.listItem && previousListItem.level < block.level) {
9272
- const levelIndexMap2 = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
9273
- levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath(blockPath), 1), previousListItem = {
9274
- listItem: block.listItem,
9275
- level: block.level
9276
- };
9277
- continue;
9278
- }
9279
- levelIndexMaps.forEach((levelIndexMap2, listItem) => {
9280
- if (listItem === block.listItem)
9281
- return;
9282
- const levelsToDelete = [];
9283
- levelIndexMap2.forEach((_, level) => {
9284
- level >= block.level && levelsToDelete.push(level);
9285
- }), levelsToDelete.forEach((level) => {
9286
- levelIndexMap2.delete(level);
9287
- });
9288
- });
9289
- const levelIndexMap = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map(), levelCounter = levelIndexMap.get(block.level) ?? 0;
9290
- levelIndexMap.set(block.level, levelCounter + 1), levelIndexMaps.set(block.listItem, levelIndexMap), listIndexMap.set(serializePath(blockPath), levelCounter + 1), previousListItem = {
9291
- listItem: block.listItem,
9292
- level: block.level
9293
- };
9294
- }
9295
- }
9296
- function collectDescendantIndexes(context, node, nodePath, parent, blockIndexMap) {
9297
- const result = getNodeChildren(context, node, parent);
9298
- if (result)
9299
- for (let i = 0; i < result.children.length; i++) {
9300
- const child = result.children[i];
9301
- if (!child._key)
9302
- continue;
9303
- const childSegment = {
9304
- _key: child._key
9305
- }, childPath = [...nodePath, result.fieldName, childSegment], childKey = serializePath(childPath);
9306
- blockIndexMap.has(childKey) || blockIndexMap.set(childKey, i), collectDescendantIndexes(context, child, childPath, result.parent, blockIndexMap);
9307
- }
9308
- }
9309
9310
  function withRemoteChanges(editor, fn) {
9310
9311
  const prev = editor.isProcessingRemoteChanges;
9311
9312
  editor.isProcessingRemoteChanges = !0, fn(), editor.isProcessingRemoteChanges = prev;
@@ -10624,10 +10625,7 @@ ${safeStringify(event.operation, 2)}`);
10624
10625
  operation.type !== "set.selection" && (operation.type === "insert.text" || operation.type === "remove.text" || (transformBlockIndexMap(editor.blockIndexMap, operation, event.beforeValue, editor.snapshot.context.value, {
10625
10626
  schema: context.schema,
10626
10627
  containers: editor.snapshot.context.containers
10627
- }), operation.path.length <= 2 && buildListIndexMap({
10628
- schema: context.schema,
10629
- value: editor.snapshot.context.value
10630
- }, editor.listIndexMap)));
10628
+ }), editor.listIndexMapDirty = !0));
10631
10629
  });
10632
10630
  return () => {
10633
10631
  unsubscribeNormalizationLog?.(), unsubscribeIndexMaps();
@@ -10661,7 +10659,7 @@ function createEditorEngine(config) {
10661
10659
  }, editor.containers = /* @__PURE__ */ new Map(), editor.blockObjects = /* @__PURE__ */ new Map(), editor.inlineObjects = /* @__PURE__ */ new Map(), editor.spans = /* @__PURE__ */ new Map(), editor.textBlocks = /* @__PURE__ */ new Map(), editor.decoratedRanges = [], editor.blockIndexMap = blockIndexMap, editor.history = {
10662
10660
  undos: [],
10663
10661
  redos: []
10664
- }, editor.listIndexMap = /* @__PURE__ */ new Map(), editor.remotePatches = [], editor.undoStepId = void 0, editor.isDeferringMutations = !1, editor.isNormalizingNode = !1, editor.isPatching = !0, editor.isPerformingBehaviorOperation = !1, editor.isProcessingRemoteChanges = !1, editor.isRedoing = !1, editor.isUndoing = !1, editor.withHistory = !0;
10662
+ }, editor.listIndexMap = /* @__PURE__ */ new Map(), editor.listIndexMapDirty = !1, editor.remotePatches = [], editor.undoStepId = void 0, editor.isDeferringMutations = !1, editor.isNormalizingNode = !1, editor.isPatching = !0, editor.isPerformingBehaviorOperation = !1, editor.isProcessingRemoteChanges = !1, editor.isRedoing = !1, editor.isUndoing = !1, editor.withHistory = !0;
10665
10663
  const editorEngine = plugins(withDOM(editor), {
10666
10664
  editorActor: config.editorActor
10667
10665
  });
@@ -13285,13 +13283,15 @@ function removeLeadingChildrenOf(editor, blockPath, endChildPath) {
13285
13283
  removeNodeAt(editor, firstChild.path), firstChild = getFirstChild(editor.snapshot, blockPath);
13286
13284
  }
13287
13285
  function removeBlocksBetween(editor, startBlockPath, endBlockPath) {
13288
- let cursor = getSibling(editor.snapshot, startBlockPath, {
13289
- direction: "next"
13286
+ let cursor = getSibling(editor.snapshot, endBlockPath, {
13287
+ direction: "previous"
13290
13288
  });
13291
- for (; cursor && !pathEquals(cursor.path, endBlockPath); )
13292
- removeNodeAt(editor, cursor.path), cursor = getSibling(editor.snapshot, startBlockPath, {
13293
- direction: "next"
13289
+ for (; cursor && !pathEquals(cursor.path, startBlockPath); ) {
13290
+ const previous = getSibling(editor.snapshot, cursor.path, {
13291
+ direction: "previous"
13294
13292
  });
13293
+ removeNodeAt(editor, cursor.path), cursor = previous;
13294
+ }
13295
13295
  }
13296
13296
  function mergeBlock(editor, startBlockPath, endBlockPath, removeEmptyStartBlock) {
13297
13297
  if (pathEquals(startBlockPath, endBlockPath))
@@ -17385,7 +17385,7 @@ const editorMachine = setup({
17385
17385
  }
17386
17386
  }), TYPE_DEBOUNCE = 250, FLUSH_INTERVAL = (
17387
17387
  // @ts-expect-error - dot notation required for Vite to replace at build time
17388
- process.env.NODE_ENV === "test" ? 250 : 1e3
17388
+ process.env.NODE_ENV === "test" ? 500 : 1e3
17389
17389
  );
17390
17390
  function createMutationBatcher({
17391
17391
  editorActor,
@@ -17501,12 +17501,36 @@ function createRelay() {
17501
17501
  send: (event) => {
17502
17502
  status !== "stopped" && (mailbox.push(event), status === "started" && drainMailbox());
17503
17503
  },
17504
- on: (type, listener) => (listeners.set(type, [...listeners.get(type) ?? [], listener]), {
17505
- unsubscribe: () => {
17506
- const current = listeners.get(type) ?? [], index = current.indexOf(listener);
17507
- index !== -1 && listeners.set(type, [...current.slice(0, index), ...current.slice(index + 1)]);
17508
- }
17509
- }),
17504
+ on: (type, listener, options) => {
17505
+ let stored, unsubscribed = !1;
17506
+ if (options?.batch) {
17507
+ let scheduled = !1;
17508
+ const pendingEvents = [];
17509
+ stored = (event) => {
17510
+ pendingEvents.push(event), !scheduled && (scheduled = !0, queueMicrotask(() => {
17511
+ if (scheduled = !1, unsubscribed || status === "stopped") {
17512
+ pendingEvents.length = 0;
17513
+ return;
17514
+ }
17515
+ const events = pendingEvents.slice();
17516
+ pendingEvents.length = 0;
17517
+ try {
17518
+ listener(events);
17519
+ } catch (error) {
17520
+ console.error(error);
17521
+ }
17522
+ }));
17523
+ };
17524
+ } else
17525
+ stored = listener;
17526
+ return listeners.set(type, [...listeners.get(type) ?? [], stored]), {
17527
+ unsubscribe: () => {
17528
+ unsubscribed = !0;
17529
+ const current = listeners.get(type) ?? [], index = current.indexOf(stored);
17530
+ index !== -1 && listeners.set(type, [...current.slice(0, index), ...current.slice(index + 1)]);
17531
+ }
17532
+ };
17533
+ },
17510
17534
  start: () => {
17511
17535
  status = "started", drainMailbox();
17512
17536
  },
@@ -18566,8 +18590,12 @@ function createInternalEditor(config) {
18566
18590
  }));
18567
18591
  }
18568
18592
  },
18569
- on: (event, listener) => relay.on(event, (event2) => {
18570
- switch (event2.type) {
18593
+ on: (type, listener, options) => options?.batch ? relay.on(type, (events) => {
18594
+ listener(events);
18595
+ }, {
18596
+ batch: !0
18597
+ }) : relay.on(type, (event) => {
18598
+ switch (event.type) {
18571
18599
  case "blurred":
18572
18600
  case "done loading":
18573
18601
  case "editable":
@@ -18581,19 +18609,16 @@ function createInternalEditor(config) {
18581
18609
  case "ready":
18582
18610
  case "selection":
18583
18611
  case "value changed":
18584
- listener(event2);
18612
+ listener(event);
18585
18613
  break;
18586
18614
  }
18587
18615
  }),
18588
18616
  subscribe(observer) {
18589
- const actorSubscription = editorActor.subscribe({
18617
+ return subscribeCoalesced(editorActor, {
18590
18618
  next: () => observer.next?.(editor.getSnapshot()),
18591
18619
  error: observer.error,
18592
18620
  complete: observer.complete
18593
18621
  });
18594
- return {
18595
- unsubscribe: () => actorSubscription.unsubscribe()
18596
- };
18597
18622
  }
18598
18623
  };
18599
18624
  return {