@portabletext/editor 7.6.2 → 7.8.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
@@ -5,11 +5,11 @@ import React, { createContext, useContext, useRef, useEffect, useLayoutEffect, u
5
5
  import { serializePath, isKeyedSegment, getNode, getParent, parentPath, getChildren, getNodeChildren } from "./_chunks-es/get-parent.js";
6
6
  import { isPath, getLeaf, isRange, isPoint, isObject, isLeafObject, getAncestor, pathContains, getSpan, isBeforePoint, getText, rangeIntersects, getTextBlock, getUnionSchema, getFirstChild } from "./_chunks-es/get-first-child.js";
7
7
  import { rangeEdges, isTextBlockNode, isBackwardRange, hasNode, getNodes, isAncestorPath, isEditableContainer, getSibling, isInline, isObject as isObject$1, isSpanNode, isBlock, getEnclosingBlock, getAncestors, getPathSubSchema, getBlock, resolveContainerAt, comparePaths, getEnclosingContainer, comparePoints$1 as comparePoints, isAfterPoint } from "./_chunks-es/get-path-sub-schema.js";
8
- import { isSpan, isTextBlock, compileSchema } from "@portabletext/schema";
8
+ import { isSpan, isTextBlock, getSubSchema, compileSchema } from "@portabletext/schema";
9
9
  import { defineSchema } from "@portabletext/schema";
10
10
  import scrollIntoView from "scroll-into-view-if-needed";
11
11
  import { createKeyboardShortcut, undo, redo, code, underline, italic as italic$1, bold as bold$1 } from "@portabletext/keyboard-shortcuts";
12
- import { rangesOverlap, getFocusInlineObject, isSelectionCollapsed as isSelectionCollapsed$1, getFocusTextBlock, getFocusSpan, getFragment, isSelectionExpanded, getSelectionStartBlock, getSelectionEndBlock, isOverlappingSelection, getFocusBlock, getSelectedBlocks, isSelectingEntireBlocks, getSelectedValue, isActiveAnnotation, getActiveAnnotationsMarks, getActiveDecorators, getCaretWordSelection, getSelectionStartChild, getSelectionEndChild, getPreviousSpan, getNextSpan, getSelectionStartPoint, getSelectionEndPoint, getFocusBlockObject, getLastBlock, getFirstBlock, isAtTheEndOfBlock, isAtTheStartOfBlock, getMarkState, getFocusListBlock, getNextBlock, getPreviousBlock, getSelectedTextBlocks, getRootAcceptedTypes, isActiveDecorator, getFocusChild, getActiveAnnotations, isActiveListItem, isActiveStyle } from "./_chunks-es/selector.is-at-the-start-of-block.js";
12
+ import { rangesOverlap, getFocusInlineObject, getFocusTextBlock, getFocusSpan, getFragment, isSelectionExpanded, getSelectionStartBlock, getSelectionEndBlock, isOverlappingSelection, isSelectionCollapsed as isSelectionCollapsed$1, getFocusBlock, getSelectedBlocks, isSelectingEntireBlocks, getSelectedValue, isActiveAnnotation, getActiveAnnotationsMarks, getActiveDecorators, getCaretWordSelection, getSelectionStartChild, getSelectionEndChild, getPreviousSpan, getNextSpan, getSelectionStartPoint, getSelectionEndPoint, getFocusBlockObject, getLastBlock, getFirstBlock, isAtTheEndOfBlock, isAtTheStartOfBlock, getRootAcceptedTypes, getMarkState, getFocusListBlock, getNextBlock, getPreviousBlock, getSelectedTextBlocks, isActiveDecorator, getFocusChild, getActiveAnnotations, isActiveListItem, isActiveStyle } from "./_chunks-es/selector.is-at-the-start-of-block.js";
13
13
  import { isEqualSelectionPoints, blockOffsetToSpanSelectionPoint, getBlockKeyFromSelectionPoint, getBlockEndPoint, getBlockStartPoint, isSelectionCollapsed, defaultKeyGenerator, parseBlocks, parseBlock, isListBlock, getSelectionStartPoint as getSelectionStartPoint$1, getSelectionEndPoint as getSelectionEndPoint$1, parseAnnotation, parseMarkDefs, parseSpan, parseInlineObject } from "./_chunks-es/util.slice-blocks.js";
14
14
  import rawDebug from "debug";
15
15
  import { isEmptyTextBlock, getTextBlockText } from "./_chunks-es/util.is-empty-text-block.js";
@@ -4046,6 +4046,9 @@ const debug = {
4046
4046
  syncValue: createDebugger("sync:value"),
4047
4047
  syncPatch: createDebugger("sync:patch")
4048
4048
  };
4049
+ function isDragEvent(event) {
4050
+ return "dataTransfer" in event;
4051
+ }
4049
4052
  function getEventPosition({
4050
4053
  editorActor,
4051
4054
  editorEngine,
@@ -4085,6 +4088,22 @@ function getEventPosition({
4085
4088
  }
4086
4089
  }
4087
4090
  };
4091
+ if (eventPositionBlock && !isEditor(eventNode) && isEditableContainer(editorEngine.snapshot, eventNode, eventPath) && isDragEvent(event))
4092
+ return {
4093
+ block: eventPositionBlock,
4094
+ isEditor: !1,
4095
+ isContainer: !0,
4096
+ selection: {
4097
+ anchor: {
4098
+ path: eventPath,
4099
+ offset: 0
4100
+ },
4101
+ focus: {
4102
+ path: eventPath,
4103
+ offset: 0
4104
+ }
4105
+ }
4106
+ };
4088
4107
  if (eventBlock && eventBlockPath && eventPositionBlock && !eventSelection && !isEventContainer(editorEngine, eventNode, eventPath))
4089
4108
  return {
4090
4109
  block: eventPositionBlock,
@@ -4227,16 +4246,6 @@ function getSelectionFromEvent(editor, event) {
4227
4246
  function isEventContainer(editorEngine, eventNode, eventPath) {
4228
4247
  return isEditor(eventNode) ? !0 : isEditableContainer(editorEngine.snapshot, eventNode, eventPath);
4229
4248
  }
4230
- function createEditorPriority(config) {
4231
- return {
4232
- id: defaultKeyGenerator(),
4233
- name: config?.name,
4234
- reference: config?.reference
4235
- };
4236
- }
4237
- const corePriority = createEditorPriority({
4238
- name: "core"
4239
- });
4240
4249
  function getDragSelection({
4241
4250
  eventSelection,
4242
4251
  snapshot
@@ -4306,6 +4315,16 @@ function getDragSelection({
4306
4315
  }
4307
4316
  return dragSelection;
4308
4317
  }
4318
+ function createEditorPriority(config) {
4319
+ return {
4320
+ id: defaultKeyGenerator(),
4321
+ name: config?.name,
4322
+ reference: config?.reference
4323
+ };
4324
+ }
4325
+ const corePriority = createEditorPriority({
4326
+ name: "core"
4327
+ });
4309
4328
  function createDropPositionBehaviorsConfig({
4310
4329
  setDropPosition
4311
4330
  }) {
@@ -5055,6 +5074,23 @@ function getSelectionState(snapshot, selection) {
5055
5074
  selectedContainerPaths: selectedContainerPaths.size > 0 ? selectedContainerPaths : emptySet$1
5056
5075
  };
5057
5076
  }
5077
+ function subscribeCoalesced(actor, observer) {
5078
+ let scheduled = !1, active = !0;
5079
+ const subscription = actor.subscribe({
5080
+ next: observer.next ? () => {
5081
+ scheduled || !active || (scheduled = !0, queueMicrotask(() => {
5082
+ scheduled = !1, active && observer.next?.();
5083
+ }));
5084
+ } : void 0,
5085
+ error: observer.error,
5086
+ complete: observer.complete
5087
+ });
5088
+ return {
5089
+ unsubscribe: () => {
5090
+ active = !1, subscription.unsubscribe();
5091
+ }
5092
+ };
5093
+ }
5058
5094
  const emptySet = /* @__PURE__ */ new Set(), defaultSelectionState = {
5059
5095
  focusedLeafPath: void 0,
5060
5096
  selectedLeafPaths: emptySet,
@@ -5115,17 +5151,15 @@ function SelectionStateProvider(t0) {
5115
5151
  for (const cb of subscribersRef.current)
5116
5152
  cb();
5117
5153
  }
5118
- let pendingRecompute = !1;
5119
- const subscription = editorActor.subscribe(() => {
5120
- pendingRecompute || (pendingRecompute = !0, queueMicrotask(() => {
5121
- pendingRecompute = !1;
5154
+ const subscription = subscribeCoalesced(editorActor, {
5155
+ next: () => {
5122
5156
  const newState = computeCurrent();
5123
5157
  if (!selectionStatesEqual(stateRef.current, newState)) {
5124
5158
  stateRef.current = newState;
5125
5159
  for (const cb_0 of subscribersRef.current)
5126
5160
  cb_0();
5127
5161
  }
5128
- }));
5162
+ }
5129
5163
  });
5130
5164
  return () => subscription.unsubscribe();
5131
5165
  }, t3 = [editorActor, computeCurrent], $[3] = computeCurrent, $[4] = editorActor, $[5] = t2, $[6] = t3) : (t2 = $[5], t3 = $[6]), useEffect(t2, t3);
@@ -5385,6 +5419,90 @@ function RenderChild$1({
5385
5419
  value
5386
5420
  });
5387
5421
  }
5422
+ const levelIndexMaps = /* @__PURE__ */ new Map();
5423
+ function buildIndexMaps(context, {
5424
+ blockIndexMap,
5425
+ listIndexMap
5426
+ }) {
5427
+ blockIndexMap.clear();
5428
+ for (let blockIndex = 0; blockIndex < context.value.length; blockIndex++) {
5429
+ const block = context.value.at(blockIndex);
5430
+ if (block === void 0 || block._key === void 0)
5431
+ continue;
5432
+ const blockPath = [{
5433
+ _key: block._key
5434
+ }], blockKey = serializePath(blockPath);
5435
+ blockIndexMap.has(blockKey) || blockIndexMap.set(blockKey, blockIndex), collectDescendantIndexes(context, block, blockPath, void 0, blockIndexMap);
5436
+ }
5437
+ buildListIndexMap(context, listIndexMap);
5438
+ }
5439
+ function buildListIndexMap(context, listIndexMap) {
5440
+ listIndexMap.clear(), levelIndexMaps.clear();
5441
+ let previousListItem;
5442
+ for (let blockIndex = 0; blockIndex < context.value.length; blockIndex++) {
5443
+ const block = context.value.at(blockIndex);
5444
+ if (block === void 0)
5445
+ continue;
5446
+ const blockPath = [{
5447
+ _key: block._key
5448
+ }];
5449
+ if (!isTextBlockNode(context, block)) {
5450
+ levelIndexMaps.clear(), previousListItem = void 0;
5451
+ continue;
5452
+ }
5453
+ if (block.listItem === void 0 || block.level === void 0) {
5454
+ levelIndexMaps.clear(), previousListItem = void 0;
5455
+ continue;
5456
+ }
5457
+ if (!previousListItem) {
5458
+ const levelIndexMap2 = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
5459
+ levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath(blockPath), 1), previousListItem = {
5460
+ listItem: block.listItem,
5461
+ level: block.level
5462
+ };
5463
+ continue;
5464
+ }
5465
+ if (previousListItem.listItem === block.listItem && previousListItem.level < block.level) {
5466
+ const levelIndexMap2 = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
5467
+ levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(serializePath(blockPath), 1), previousListItem = {
5468
+ listItem: block.listItem,
5469
+ level: block.level
5470
+ };
5471
+ continue;
5472
+ }
5473
+ levelIndexMaps.forEach((levelIndexMap2, listItem) => {
5474
+ if (listItem === block.listItem)
5475
+ return;
5476
+ const levelsToDelete = [];
5477
+ levelIndexMap2.forEach((_, level) => {
5478
+ level >= block.level && levelsToDelete.push(level);
5479
+ }), levelsToDelete.forEach((level) => {
5480
+ levelIndexMap2.delete(level);
5481
+ });
5482
+ });
5483
+ const levelIndexMap = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map(), levelCounter = levelIndexMap.get(block.level) ?? 0;
5484
+ levelIndexMap.set(block.level, levelCounter + 1), levelIndexMaps.set(block.listItem, levelIndexMap), listIndexMap.set(serializePath(blockPath), levelCounter + 1), previousListItem = {
5485
+ listItem: block.listItem,
5486
+ level: block.level
5487
+ };
5488
+ }
5489
+ }
5490
+ function getListIndexMap(editor) {
5491
+ return editor.listIndexMapDirty && (buildListIndexMap(editor.snapshot.context, editor.listIndexMap), editor.listIndexMapDirty = !1), editor.listIndexMap;
5492
+ }
5493
+ function collectDescendantIndexes(context, node, nodePath, parent, blockIndexMap) {
5494
+ const result = getNodeChildren(context, node, parent);
5495
+ if (result)
5496
+ for (let i = 0; i < result.children.length; i++) {
5497
+ const child = result.children[i];
5498
+ if (!child._key)
5499
+ continue;
5500
+ const childSegment = {
5501
+ _key: child._key
5502
+ }, childPath = [...nodePath, result.fieldName, childSegment], childKey = serializePath(childPath);
5503
+ blockIndexMap.has(childKey) || blockIndexMap.set(childKey, i), collectDescendantIndexes(context, child, childPath, result.parent, blockIndexMap);
5504
+ }
5505
+ }
5388
5506
  function RenderTextBlock(props) {
5389
5507
  const $ = c(79), blockRef = useRef(null);
5390
5508
  let t0;
@@ -5399,7 +5517,7 @@ function RenderTextBlock(props) {
5399
5517
  $[5] !== props.path ? (t2 = serializePath(props.path), $[5] = props.path, $[6] = t2) : t2 = $[6];
5400
5518
  const serializedPath = t2, selected = useIsSelectedContainer(serializedPath), focused = useIsFocusedContainer(serializedPath), dropPosition = useElementDropPosition(props.path);
5401
5519
  let t3;
5402
- $[7] !== serializedPath ? (t3 = (editor) => editor.listIndexMap.get(serializedPath), $[7] = serializedPath, $[8] = t3) : t3 = $[8];
5520
+ $[7] !== serializedPath ? (t3 = (editor) => getListIndexMap(editor).get(serializedPath), $[7] = serializedPath, $[8] = t3) : t3 = $[8];
5403
5521
  const listIndex = useEngineSelector(t3), subSchema = useBlockSubSchema(props.path);
5404
5522
  let children = props.children;
5405
5523
  if (props.legacy.renderStyle && props.textBlock.style) {
@@ -6024,7 +6142,7 @@ function validateSelection(editorEngine, editorElement) {
6024
6142
  const newDOMRange = DOMEditor.toDOMRange(editorEngine, editorEngine.snapshot.context.selection);
6025
6143
  (newDOMRange.startOffset !== existingDOMRange.startOffset || newDOMRange.endOffset !== existingDOMRange.endOffset) && (debug.selection("DOM range out of sync, validating selection"), domSelection?.removeAllRanges(), domSelection.addRange(newDOMRange));
6026
6144
  } catch {
6027
- debug.selection("Could not resolve selection, selecting top document"), applyDeselect(editorEngine), editorEngine.snapshot.context.value.length > 0 && applySelect(editorEngine, start(editorEngine, [])), editorEngine.onChange();
6145
+ debug.selection("Could not resolve selection, skipping DOM sync this tick");
6028
6146
  }
6029
6147
  }
6030
6148
  const PortableTextEditable = forwardRef(function(props, forwardedRef) {
@@ -6416,9 +6534,16 @@ const PortableTextEditable = forwardRef(function(props, forwardedRef) {
6416
6534
  console.warn("Could not find position for dragstart event");
6417
6535
  return;
6418
6536
  }
6537
+ const dragPosition = {
6538
+ ...position_4,
6539
+ selection: getDragSelection({
6540
+ snapshot: editorEngine.snapshot,
6541
+ eventSelection: position_4.selection
6542
+ })
6543
+ };
6419
6544
  return editorActor.send({
6420
6545
  type: "dragstart",
6421
- origin: position_4
6546
+ origin: dragPosition
6422
6547
  }), editorActor.send({
6423
6548
  type: "behavior event",
6424
6549
  behaviorEvent: {
@@ -6428,7 +6553,7 @@ const PortableTextEditable = forwardRef(function(props, forwardedRef) {
6428
6553
  clientY: event_8.clientY,
6429
6554
  dataTransfer: event_8.dataTransfer
6430
6555
  },
6431
- position: position_4
6556
+ position: dragPosition
6432
6557
  },
6433
6558
  editor: editorEngine
6434
6559
  }), !0;
@@ -9208,87 +9333,6 @@ class BlockIndexMap extends Map {
9208
9333
  }]));
9209
9334
  }
9210
9335
  }
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
9336
  function withRemoteChanges(editor, fn) {
9293
9337
  const prev = editor.isProcessingRemoteChanges;
9294
9338
  editor.isProcessingRemoteChanges = !0, fn(), editor.isProcessingRemoteChanges = prev;
@@ -10607,10 +10651,7 @@ ${safeStringify(event.operation, 2)}`);
10607
10651
  operation.type !== "set.selection" && (operation.type === "insert.text" || operation.type === "remove.text" || (transformBlockIndexMap(editor.blockIndexMap, operation, event.beforeValue, editor.snapshot.context.value, {
10608
10652
  schema: context.schema,
10609
10653
  containers: editor.snapshot.context.containers
10610
- }), operation.path.length <= 2 && buildListIndexMap({
10611
- schema: context.schema,
10612
- value: editor.snapshot.context.value
10613
- }, editor.listIndexMap)));
10654
+ }), editor.listIndexMapDirty = !0));
10614
10655
  });
10615
10656
  return () => {
10616
10657
  unsubscribeNormalizationLog?.(), unsubscribeIndexMaps();
@@ -10644,7 +10685,7 @@ function createEditorEngine(config) {
10644
10685
  }, 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
10686
  undos: [],
10646
10687
  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;
10688
+ }, 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
10689
  const editorEngine = plugins(withDOM(editor), {
10649
10690
  editorActor: config.editorActor
10650
10691
  });
@@ -11374,7 +11415,39 @@ function getCompoundClientRect(nodes) {
11374
11415
  }
11375
11416
  return new DOMRect(left, top, right - left, bottom - top);
11376
11417
  }
11418
+ function fitBlocksToDestination(snapshot, blocks) {
11419
+ if (blocks.length === 0)
11420
+ return [];
11421
+ const startBlock = getSelectionStartBlock(snapshot);
11422
+ if (!startBlock)
11423
+ return [...blocks];
11424
+ const resolvedAt = resolveContainerAt(snapshot.context.containers, snapshot.context.value, startBlock.path), subSchema = resolvedAt && "field" in resolvedAt && resolvedAt.of ? getSubSchema(snapshot.context.schema, resolvedAt.of) : getPathSubSchema(snapshot, startBlock.path), accepted = getRootAcceptedTypes(subSchema);
11425
+ if (accepted.size === 0)
11426
+ return [];
11427
+ const result = [];
11428
+ for (const block of blocks)
11429
+ fitOne(block, accepted, result);
11430
+ return result;
11431
+ }
11432
+ function fitOne(block, accepted, out) {
11433
+ if (accepted.has(block._type)) {
11434
+ out.push(block);
11435
+ return;
11436
+ }
11437
+ for (const value of Object.values(block))
11438
+ if (Array.isArray(value))
11439
+ for (const child of value)
11440
+ isBlockLike(child) && fitOne(child, accepted, out);
11441
+ }
11442
+ function isBlockLike(value) {
11443
+ return typeof value == "object" && value !== null && "_type" in value && typeof value._type == "string";
11444
+ }
11377
11445
  function isDropTargetingDragOrigin(dropSelection, dragOriginSelection, snapshot) {
11446
+ if (isCollapsedRange(dragOriginSelection)) {
11447
+ const originPath = dragOriginSelection.anchor.path;
11448
+ if (isAncestorPath(originPath, dropSelection.anchor.path) || isAncestorPath(originPath, dropSelection.focus.path))
11449
+ return !0;
11450
+ }
11378
11451
  if (!isOverlappingSelection(dropSelection)({
11379
11452
  ...snapshot,
11380
11453
  context: {
@@ -11413,25 +11486,18 @@ const coreDndBehaviors = [
11413
11486
  ...snapshot.context,
11414
11487
  selection: dragSelection
11415
11488
  }
11416
- }), draggedDomNodes = {
11417
- blockNodes: dom.getBlockNodes({
11418
- ...snapshot,
11419
- context: {
11420
- ...snapshot.context,
11421
- selection: dragSelection
11422
- }
11423
- }),
11424
- childNodes: dom.getChildNodes({
11425
- ...snapshot,
11426
- context: {
11427
- ...snapshot.context,
11428
- selection: dragSelection
11429
- }
11430
- })
11489
+ }), dragSnapshot = {
11490
+ ...snapshot,
11491
+ context: {
11492
+ ...snapshot.context,
11493
+ selection: dragSelection
11494
+ }
11431
11495
  };
11432
11496
  return {
11433
- dragSelection,
11434
- draggedDomNodes,
11497
+ draggedDomNodes: {
11498
+ blockNodes: dom.getBlockNodes(dragSnapshot),
11499
+ childNodes: dom.getChildNodes(dragSnapshot)
11500
+ },
11435
11501
  selectingEntireBlocks
11436
11502
  };
11437
11503
  },
@@ -11439,7 +11505,6 @@ const coreDndBehaviors = [
11439
11505
  dom,
11440
11506
  event
11441
11507
  }, {
11442
- dragSelection,
11443
11508
  draggedDomNodes,
11444
11509
  selectingEntireBlocks
11445
11510
  }) => {
@@ -11451,10 +11516,7 @@ const coreDndBehaviors = [
11451
11516
  const customGhost = dragGhost.querySelector("[data-pt-drag-ghost-element]");
11452
11517
  if (customGhost && dragGhost.replaceChildren(customGhost), dragGhost.setAttribute("data-dragged", ""), dragGhost.style.position = "absolute", dragGhost.style.left = "-99999px", dragGhost.style.boxSizing = "border-box", document.body.appendChild(dragGhost), customGhost) {
11453
11518
  const customGhostRect = customGhost.getBoundingClientRect(), x = event.originEvent.clientX - customGhostRect.left, y = event.originEvent.clientY - customGhostRect.top;
11454
- return dragGhost.style.width = `${customGhostRect.width}px`, dragGhost.style.height = `${customGhostRect.height}px`, [raise({
11455
- type: "select",
11456
- at: dragSelection
11457
- }), effect(() => {
11519
+ return dragGhost.style.width = `${customGhostRect.width}px`, dragGhost.style.height = `${customGhostRect.height}px`, [effect(() => {
11458
11520
  dom.setDragGhost({
11459
11521
  event,
11460
11522
  ghost: {
@@ -11466,10 +11528,7 @@ const coreDndBehaviors = [
11466
11528
  }), forward(event)];
11467
11529
  } else {
11468
11530
  const blocksDomRect = getCompoundClientRect(draggedDomNodes.blockNodes), x = event.originEvent.clientX - blocksDomRect.left, y = event.originEvent.clientY - blocksDomRect.top;
11469
- return dragGhost.style.width = `${blocksDomRect.width}px`, dragGhost.style.height = `${blocksDomRect.height}px`, [raise({
11470
- type: "select",
11471
- at: dragSelection
11472
- }), effect(() => {
11531
+ return dragGhost.style.width = `${blocksDomRect.width}px`, dragGhost.style.height = `${blocksDomRect.height}px`, [effect(() => {
11473
11532
  dom.setDragGhost({
11474
11533
  event,
11475
11534
  ghost: {
@@ -11486,10 +11545,7 @@ const coreDndBehaviors = [
11486
11545
  dragGhost.appendChild(child);
11487
11546
  dragGhost.style.position = "absolute", dragGhost.style.left = "-99999px", dragGhost.style.boxSizing = "border-box", document.body.appendChild(dragGhost);
11488
11547
  const childrenDomRect = getCompoundClientRect(draggedDomNodes.childNodes), x = event.originEvent.clientX - childrenDomRect.left, y = event.originEvent.clientY - childrenDomRect.top;
11489
- return dragGhost.style.width = `${childrenDomRect.width}px`, dragGhost.style.height = `${childrenDomRect.height}px`, [raise({
11490
- type: "select",
11491
- at: dragSelection
11492
- }), effect(() => {
11548
+ return dragGhost.style.width = `${childrenDomRect.width}px`, dragGhost.style.height = `${childrenDomRect.height}px`, [effect(() => {
11493
11549
  dom.setDragGhost({
11494
11550
  event,
11495
11551
  ghost: {
@@ -11578,48 +11634,52 @@ const coreDndBehaviors = [
11578
11634
  const dragOrigin = event.originEvent.dragOrigin, dragSelection = getDragSelection({
11579
11635
  eventSelection: dragOrigin.selection,
11580
11636
  snapshot
11581
- }), dropPosition = event.originEvent.position.selection, droppingOnDragOrigin = dragOrigin ? isDropTargetingDragOrigin(dropPosition, dragSelection, snapshot) : !1, draggingEntireBlocks = isSelectingEntireBlocks({
11637
+ }), dropPosition = event.originEvent.position.selection, droppingOnDragOrigin = dragOrigin ? isDropTargetingDragOrigin(dropPosition, dragSelection, snapshot) : !1, dragSnapshot = {
11582
11638
  ...snapshot,
11583
11639
  context: {
11584
11640
  ...snapshot.context,
11585
11641
  selection: dragSelection
11586
11642
  }
11587
- }), draggedBlocks = getFragment({
11643
+ }, draggingEntireBlocks = isSelectingEntireBlocks(dragSnapshot), draggedNodes = getFragment(dragSnapshot), fittedBlocks = fitBlocksToDestination({
11644
+ ...snapshot,
11588
11645
  context: {
11589
11646
  ...snapshot.context,
11590
- selection: dragSelection
11647
+ selection: dropPosition
11591
11648
  }
11592
- });
11649
+ }, event.data);
11593
11650
  return droppingOnDragOrigin ? !1 : {
11594
11651
  dropPosition,
11595
11652
  draggingEntireBlocks,
11596
- draggedBlocks,
11653
+ draggedNodes,
11597
11654
  dragOrigin,
11598
- originEvent: event.originEvent
11655
+ originEvent: event.originEvent,
11656
+ fittedBlocks
11599
11657
  };
11600
11658
  },
11601
- actions: [({
11602
- event
11603
- }, {
11659
+ actions: [(_, {
11604
11660
  draggingEntireBlocks,
11605
- draggedBlocks,
11661
+ draggedNodes,
11606
11662
  dragOrigin,
11607
11663
  dropPosition,
11608
- originEvent
11609
- }) => [raise({
11610
- type: "select",
11611
- at: dropPosition
11612
- }), ...draggingEntireBlocks ? draggedBlocks.map((block) => raise({
11613
- type: "delete.block",
11614
- at: block.path
11615
- })) : [raise({
11616
- type: "delete",
11617
- at: dragOrigin.selection
11618
- })], raise({
11619
- type: "insert.blocks",
11620
- blocks: event.data,
11621
- placement: draggingEntireBlocks ? originEvent.position.block === "start" ? "before" : originEvent.position.block === "end" ? "after" : "auto" : "auto"
11622
- })]]
11664
+ originEvent,
11665
+ fittedBlocks
11666
+ }) => {
11667
+ const deleteEvents = draggingEntireBlocks ? draggedNodes.map((entry) => raise({
11668
+ type: "unset",
11669
+ at: entry.path
11670
+ })) : [raise({
11671
+ type: "delete",
11672
+ at: dragOrigin.selection
11673
+ })];
11674
+ return [raise({
11675
+ type: "select",
11676
+ at: dropPosition
11677
+ }), ...deleteEvents, raise({
11678
+ type: "insert.blocks",
11679
+ blocks: fittedBlocks,
11680
+ placement: draggingEntireBlocks ? originEvent.position.block === "start" ? "before" : originEvent.position.block === "end" ? "after" : "auto" : "auto"
11681
+ })];
11682
+ }]
11623
11683
  })
11624
11684
  ], coreInsertBehaviors = [defineBehavior({
11625
11685
  on: "insert.text",
@@ -13268,13 +13328,15 @@ function removeLeadingChildrenOf(editor, blockPath, endChildPath) {
13268
13328
  removeNodeAt(editor, firstChild.path), firstChild = getFirstChild(editor.snapshot, blockPath);
13269
13329
  }
13270
13330
  function removeBlocksBetween(editor, startBlockPath, endBlockPath) {
13271
- let cursor = getSibling(editor.snapshot, startBlockPath, {
13272
- direction: "next"
13331
+ let cursor = getSibling(editor.snapshot, endBlockPath, {
13332
+ direction: "previous"
13273
13333
  });
13274
- for (; cursor && !pathEquals(cursor.path, endBlockPath); )
13275
- removeNodeAt(editor, cursor.path), cursor = getSibling(editor.snapshot, startBlockPath, {
13276
- direction: "next"
13334
+ for (; cursor && !pathEquals(cursor.path, startBlockPath); ) {
13335
+ const previous = getSibling(editor.snapshot, cursor.path, {
13336
+ direction: "previous"
13277
13337
  });
13338
+ removeNodeAt(editor, cursor.path), cursor = previous;
13339
+ }
13278
13340
  }
13279
13341
  function mergeBlock(editor, startBlockPath, endBlockPath, removeEmptyStartBlock) {
13280
13342
  if (pathEquals(startBlockPath, endBlockPath))
@@ -14833,35 +14895,7 @@ const abstractAnnotationBehaviors = [defineBehavior({
14833
14895
  ...event,
14834
14896
  type: "delete"
14835
14897
  })]]
14836
- })];
14837
- function fitBlocksToDestination(snapshot, blocks) {
14838
- if (blocks.length === 0)
14839
- return [];
14840
- const startBlock = getSelectionStartBlock(snapshot);
14841
- if (!startBlock)
14842
- return [...blocks];
14843
- const subSchema = getPathSubSchema(snapshot, startBlock.path), accepted = getRootAcceptedTypes(subSchema);
14844
- if (accepted.size === 0)
14845
- return [];
14846
- const result = [];
14847
- for (const block of blocks)
14848
- fitOne(block, accepted, result);
14849
- return result;
14850
- }
14851
- function fitOne(block, accepted, out) {
14852
- if (accepted.has(block._type)) {
14853
- out.push(block);
14854
- return;
14855
- }
14856
- for (const value of Object.values(block))
14857
- if (Array.isArray(value))
14858
- for (const child of value)
14859
- isBlockLike(child) && fitOne(child, accepted, out);
14860
- }
14861
- function isBlockLike(value) {
14862
- return typeof value == "object" && value !== null && "_type" in value && typeof value._type == "string";
14863
- }
14864
- const mimeTypePriority = ["application/x-portable-text", "application/json", "text/markdown", "text/html", "text/plain"];
14898
+ })], mimeTypePriority = ["application/x-portable-text", "application/json", "text/markdown", "text/html", "text/plain"];
14865
14899
  function getFirstAvailableData({
14866
14900
  dataTransfer,
14867
14901
  startAfter
@@ -16035,13 +16069,22 @@ const abstractInsertBehaviors = [
16035
16069
  event
16036
16070
  }) => {
16037
16071
  const converter = snapshot.context.converters.find((converter2) => converter2.mimeType === event.mimeType);
16038
- return converter ? converter.serialize({
16039
- snapshot,
16072
+ if (!converter)
16073
+ return !1;
16074
+ const snapshotForConverter = event.originEvent.type === "drag.dragstart" ? {
16075
+ ...snapshot,
16076
+ context: {
16077
+ ...snapshot.context,
16078
+ selection: event.originEvent.position.selection
16079
+ }
16080
+ } : snapshot;
16081
+ return converter.serialize({
16082
+ snapshot: snapshotForConverter,
16040
16083
  event: {
16041
16084
  type: "serialize",
16042
16085
  originEvent: event.originEvent.type
16043
16086
  }
16044
- }) : !1;
16087
+ });
16045
16088
  },
16046
16089
  actions: [({
16047
16090
  event
@@ -17368,7 +17411,7 @@ const editorMachine = setup({
17368
17411
  }
17369
17412
  }), TYPE_DEBOUNCE = 250, FLUSH_INTERVAL = (
17370
17413
  // @ts-expect-error - dot notation required for Vite to replace at build time
17371
- process.env.NODE_ENV === "test" ? 250 : 1e3
17414
+ process.env.NODE_ENV === "test" ? 500 : 1e3
17372
17415
  );
17373
17416
  function createMutationBatcher({
17374
17417
  editorActor,
@@ -17484,12 +17527,36 @@ function createRelay() {
17484
17527
  send: (event) => {
17485
17528
  status !== "stopped" && (mailbox.push(event), status === "started" && drainMailbox());
17486
17529
  },
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
- }),
17530
+ on: (type, listener, options) => {
17531
+ let stored, unsubscribed = !1;
17532
+ if (options?.batch) {
17533
+ let scheduled = !1;
17534
+ const pendingEvents = [];
17535
+ stored = (event) => {
17536
+ pendingEvents.push(event), !scheduled && (scheduled = !0, queueMicrotask(() => {
17537
+ if (scheduled = !1, unsubscribed || status === "stopped") {
17538
+ pendingEvents.length = 0;
17539
+ return;
17540
+ }
17541
+ const events = pendingEvents.slice();
17542
+ pendingEvents.length = 0;
17543
+ try {
17544
+ listener(events);
17545
+ } catch (error) {
17546
+ console.error(error);
17547
+ }
17548
+ }));
17549
+ };
17550
+ } else
17551
+ stored = listener;
17552
+ return listeners.set(type, [...listeners.get(type) ?? [], stored]), {
17553
+ unsubscribe: () => {
17554
+ unsubscribed = !0;
17555
+ const current = listeners.get(type) ?? [], index = current.indexOf(stored);
17556
+ index !== -1 && listeners.set(type, [...current.slice(0, index), ...current.slice(index + 1)]);
17557
+ }
17558
+ };
17559
+ },
17493
17560
  start: () => {
17494
17561
  status = "started", drainMailbox();
17495
17562
  },
@@ -18549,8 +18616,12 @@ function createInternalEditor(config) {
18549
18616
  }));
18550
18617
  }
18551
18618
  },
18552
- on: (event, listener) => relay.on(event, (event2) => {
18553
- switch (event2.type) {
18619
+ on: (type, listener, options) => options?.batch ? relay.on(type, (events) => {
18620
+ listener(events);
18621
+ }, {
18622
+ batch: !0
18623
+ }) : relay.on(type, (event) => {
18624
+ switch (event.type) {
18554
18625
  case "blurred":
18555
18626
  case "done loading":
18556
18627
  case "editable":
@@ -18564,19 +18635,16 @@ function createInternalEditor(config) {
18564
18635
  case "ready":
18565
18636
  case "selection":
18566
18637
  case "value changed":
18567
- listener(event2);
18638
+ listener(event);
18568
18639
  break;
18569
18640
  }
18570
18641
  }),
18571
18642
  subscribe(observer) {
18572
- const actorSubscription = editorActor.subscribe({
18643
+ return subscribeCoalesced(editorActor, {
18573
18644
  next: () => observer.next?.(editor.getSnapshot()),
18574
18645
  error: observer.error,
18575
18646
  complete: observer.complete
18576
18647
  });
18577
- return {
18578
- unsubscribe: () => actorSubscription.unsubscribe()
18579
- };
18580
18648
  }
18581
18649
  };
18582
18650
  return {