@portabletext/editor 7.6.2 → 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
@@ -5055,6 +5055,23 @@ function getSelectionState(snapshot, selection) {
5055
5055
  selectedContainerPaths: selectedContainerPaths.size > 0 ? selectedContainerPaths : emptySet$1
5056
5056
  };
5057
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
+ }
5058
5075
  const emptySet = /* @__PURE__ */ new Set(), defaultSelectionState = {
5059
5076
  focusedLeafPath: void 0,
5060
5077
  selectedLeafPaths: emptySet,
@@ -5115,17 +5132,15 @@ function SelectionStateProvider(t0) {
5115
5132
  for (const cb of subscribersRef.current)
5116
5133
  cb();
5117
5134
  }
5118
- let pendingRecompute = !1;
5119
- const subscription = editorActor.subscribe(() => {
5120
- pendingRecompute || (pendingRecompute = !0, queueMicrotask(() => {
5121
- pendingRecompute = !1;
5135
+ const subscription = subscribeCoalesced(editorActor, {
5136
+ next: () => {
5122
5137
  const newState = computeCurrent();
5123
5138
  if (!selectionStatesEqual(stateRef.current, newState)) {
5124
5139
  stateRef.current = newState;
5125
5140
  for (const cb_0 of subscribersRef.current)
5126
5141
  cb_0();
5127
5142
  }
5128
- }));
5143
+ }
5129
5144
  });
5130
5145
  return () => subscription.unsubscribe();
5131
5146
  }, t3 = [editorActor, computeCurrent], $[3] = computeCurrent, $[4] = editorActor, $[5] = t2, $[6] = t3) : (t2 = $[5], t3 = $[6]), useEffect(t2, t3);
@@ -5385,6 +5400,90 @@ function RenderChild$1({
5385
5400
  value
5386
5401
  });
5387
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
+ }
5388
5487
  function RenderTextBlock(props) {
5389
5488
  const $ = c(79), blockRef = useRef(null);
5390
5489
  let t0;
@@ -5399,7 +5498,7 @@ function RenderTextBlock(props) {
5399
5498
  $[5] !== props.path ? (t2 = serializePath(props.path), $[5] = props.path, $[6] = t2) : t2 = $[6];
5400
5499
  const serializedPath = t2, selected = useIsSelectedContainer(serializedPath), focused = useIsFocusedContainer(serializedPath), dropPosition = useElementDropPosition(props.path);
5401
5500
  let t3;
5402
- $[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];
5403
5502
  const listIndex = useEngineSelector(t3), subSchema = useBlockSubSchema(props.path);
5404
5503
  let children = props.children;
5405
5504
  if (props.legacy.renderStyle && props.textBlock.style) {
@@ -9208,87 +9307,6 @@ class BlockIndexMap extends Map {
9208
9307
  }]));
9209
9308
  }
9210
9309
  }
9211
- const levelIndexMaps = /* @__PURE__ */ new Map();
9212
- function buildIndexMaps(context, {
9213
- blockIndexMap,
9214
- listIndexMap
9215
- }) {
9216
- blockIndexMap.clear();
9217
- for (let blockIndex = 0; blockIndex < context.value.length; blockIndex++) {
9218
- const block = context.value.at(blockIndex);
9219
- if (block === void 0 || block._key === void 0)
9220
- continue;
9221
- const blockPath = [{
9222
- _key: block._key
9223
- }], blockKey = serializePath(blockPath);
9224
- blockIndexMap.has(blockKey) || blockIndexMap.set(blockKey, blockIndex), collectDescendantIndexes(context, block, blockPath, void 0, blockIndexMap);
9225
- }
9226
- buildListIndexMap(context, listIndexMap);
9227
- }
9228
- function buildListIndexMap(context, listIndexMap) {
9229
- listIndexMap.clear(), levelIndexMaps.clear();
9230
- let previousListItem;
9231
- for (let blockIndex = 0; blockIndex < context.value.length; blockIndex++) {
9232
- const block = context.value.at(blockIndex);
9233
- if (block === void 0)
9234
- continue;
9235
- const blockPath = [{
9236
- _key: block._key
9237
- }];
9238
- if (!isTextBlockNode(context, block)) {
9239
- levelIndexMaps.clear(), previousListItem = void 0;
9240
- continue;
9241
- }
9242
- if (block.listItem === void 0 || block.level === void 0) {
9243
- levelIndexMaps.clear(), previousListItem = void 0;
9244
- continue;
9245
- }
9246
- if (!previousListItem) {
9247
- const levelIndexMap2 = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
9248
- levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath(blockPath), 1), previousListItem = {
9249
- listItem: block.listItem,
9250
- level: block.level
9251
- };
9252
- continue;
9253
- }
9254
- if (previousListItem.listItem === block.listItem && previousListItem.level < block.level) {
9255
- const levelIndexMap2 = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
9256
- levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath(blockPath), 1), previousListItem = {
9257
- listItem: block.listItem,
9258
- level: block.level
9259
- };
9260
- continue;
9261
- }
9262
- levelIndexMaps.forEach((levelIndexMap2, listItem) => {
9263
- if (listItem === block.listItem)
9264
- return;
9265
- const levelsToDelete = [];
9266
- levelIndexMap2.forEach((_, level) => {
9267
- level >= block.level && levelsToDelete.push(level);
9268
- }), levelsToDelete.forEach((level) => {
9269
- levelIndexMap2.delete(level);
9270
- });
9271
- });
9272
- const levelIndexMap = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map(), levelCounter = levelIndexMap.get(block.level) ?? 0;
9273
- levelIndexMap.set(block.level, levelCounter + 1), levelIndexMaps.set(block.listItem, levelIndexMap), listIndexMap.set(serializePath(blockPath), levelCounter + 1), previousListItem = {
9274
- listItem: block.listItem,
9275
- level: block.level
9276
- };
9277
- }
9278
- }
9279
- function collectDescendantIndexes(context, node, nodePath, parent, blockIndexMap) {
9280
- const result = getNodeChildren(context, node, parent);
9281
- if (result)
9282
- for (let i = 0; i < result.children.length; i++) {
9283
- const child = result.children[i];
9284
- if (!child._key)
9285
- continue;
9286
- const childSegment = {
9287
- _key: child._key
9288
- }, childPath = [...nodePath, result.fieldName, childSegment], childKey = serializePath(childPath);
9289
- blockIndexMap.has(childKey) || blockIndexMap.set(childKey, i), collectDescendantIndexes(context, child, childPath, result.parent, blockIndexMap);
9290
- }
9291
- }
9292
9310
  function withRemoteChanges(editor, fn) {
9293
9311
  const prev = editor.isProcessingRemoteChanges;
9294
9312
  editor.isProcessingRemoteChanges = !0, fn(), editor.isProcessingRemoteChanges = prev;
@@ -10607,10 +10625,7 @@ ${safeStringify(event.operation, 2)}`);
10607
10625
  operation.type !== "set.selection" && (operation.type === "insert.text" || operation.type === "remove.text" || (transformBlockIndexMap(editor.blockIndexMap, operation, event.beforeValue, editor.snapshot.context.value, {
10608
10626
  schema: context.schema,
10609
10627
  containers: editor.snapshot.context.containers
10610
- }), operation.path.length <= 2 && buildListIndexMap({
10611
- schema: context.schema,
10612
- value: editor.snapshot.context.value
10613
- }, editor.listIndexMap)));
10628
+ }), editor.listIndexMapDirty = !0));
10614
10629
  });
10615
10630
  return () => {
10616
10631
  unsubscribeNormalizationLog?.(), unsubscribeIndexMaps();
@@ -10644,7 +10659,7 @@ function createEditorEngine(config) {
10644
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 = {
10645
10660
  undos: [],
10646
10661
  redos: []
10647
- }, 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;
10648
10663
  const editorEngine = plugins(withDOM(editor), {
10649
10664
  editorActor: config.editorActor
10650
10665
  });
@@ -13268,13 +13283,15 @@ function removeLeadingChildrenOf(editor, blockPath, endChildPath) {
13268
13283
  removeNodeAt(editor, firstChild.path), firstChild = getFirstChild(editor.snapshot, blockPath);
13269
13284
  }
13270
13285
  function removeBlocksBetween(editor, startBlockPath, endBlockPath) {
13271
- let cursor = getSibling(editor.snapshot, startBlockPath, {
13272
- direction: "next"
13286
+ let cursor = getSibling(editor.snapshot, endBlockPath, {
13287
+ direction: "previous"
13273
13288
  });
13274
- for (; cursor && !pathEquals(cursor.path, endBlockPath); )
13275
- removeNodeAt(editor, cursor.path), cursor = getSibling(editor.snapshot, startBlockPath, {
13276
- direction: "next"
13289
+ for (; cursor && !pathEquals(cursor.path, startBlockPath); ) {
13290
+ const previous = getSibling(editor.snapshot, cursor.path, {
13291
+ direction: "previous"
13277
13292
  });
13293
+ removeNodeAt(editor, cursor.path), cursor = previous;
13294
+ }
13278
13295
  }
13279
13296
  function mergeBlock(editor, startBlockPath, endBlockPath, removeEmptyStartBlock) {
13280
13297
  if (pathEquals(startBlockPath, endBlockPath))
@@ -17368,7 +17385,7 @@ const editorMachine = setup({
17368
17385
  }
17369
17386
  }), TYPE_DEBOUNCE = 250, FLUSH_INTERVAL = (
17370
17387
  // @ts-expect-error - dot notation required for Vite to replace at build time
17371
- process.env.NODE_ENV === "test" ? 250 : 1e3
17388
+ process.env.NODE_ENV === "test" ? 500 : 1e3
17372
17389
  );
17373
17390
  function createMutationBatcher({
17374
17391
  editorActor,
@@ -17484,12 +17501,36 @@ function createRelay() {
17484
17501
  send: (event) => {
17485
17502
  status !== "stopped" && (mailbox.push(event), status === "started" && drainMailbox());
17486
17503
  },
17487
- on: (type, listener) => (listeners.set(type, [...listeners.get(type) ?? [], listener]), {
17488
- unsubscribe: () => {
17489
- const current = listeners.get(type) ?? [], index = current.indexOf(listener);
17490
- index !== -1 && listeners.set(type, [...current.slice(0, index), ...current.slice(index + 1)]);
17491
- }
17492
- }),
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
+ },
17493
17534
  start: () => {
17494
17535
  status = "started", drainMailbox();
17495
17536
  },
@@ -18549,8 +18590,12 @@ function createInternalEditor(config) {
18549
18590
  }));
18550
18591
  }
18551
18592
  },
18552
- on: (event, listener) => relay.on(event, (event2) => {
18553
- 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) {
18554
18599
  case "blurred":
18555
18600
  case "done loading":
18556
18601
  case "editable":
@@ -18564,19 +18609,16 @@ function createInternalEditor(config) {
18564
18609
  case "ready":
18565
18610
  case "selection":
18566
18611
  case "value changed":
18567
- listener(event2);
18612
+ listener(event);
18568
18613
  break;
18569
18614
  }
18570
18615
  }),
18571
18616
  subscribe(observer) {
18572
- const actorSubscription = editorActor.subscribe({
18617
+ return subscribeCoalesced(editorActor, {
18573
18618
  next: () => observer.next?.(editor.getSnapshot()),
18574
18619
  error: observer.error,
18575
18620
  complete: observer.complete
18576
18621
  });
18577
- return {
18578
- unsubscribe: () => actorSubscription.unsubscribe()
18579
- };
18580
18622
  }
18581
18623
  };
18582
18624
  return {