@input/pen-core 0.1.8 → 0.2.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/dist/index.cjs CHANGED
@@ -208,6 +208,7 @@ __export(index_exports, {
208
208
  shouldShowBlockInDefaultMenus: () => shouldShowBlockInDefaultMenus,
209
209
  singleController: () => singleController,
210
210
  slashMenuGroupOf: () => slashMenuGroupOf,
211
+ smoothStreamControllerFacet: () => smoothStreamControllerFacet,
211
212
  snapToNormalPosition: () => snapToNormalPosition,
212
213
  snapshotsControllerFacet: () => snapshotsControllerFacet,
213
214
  sortDeltaAttributes: () => sortDeltaAttributes,
@@ -5107,17 +5108,54 @@ function normalizeFieldEditorType(schema) {
5107
5108
  return "none";
5108
5109
  }
5109
5110
 
5111
+ // src/editor/documentPreorder.ts
5112
+ function documentPreorderBlockIds(editor) {
5113
+ return documentPreorderBlockIdsFromState(editor.documentState);
5114
+ }
5115
+ function documentPreorderBlockIdsFromState(state) {
5116
+ const ids = [];
5117
+ for (const block of state.blocks) {
5118
+ ids.push(block.id);
5119
+ }
5120
+ return ids;
5121
+ }
5122
+ function documentPreorderBlockIdsFromDoc(doc) {
5123
+ const ids = [];
5124
+ const seen = /* @__PURE__ */ new Set();
5125
+ const blocks = doc.blocks;
5126
+ const order = doc.blockOrder;
5127
+ const walk = (id) => {
5128
+ if (seen.has(id)) {
5129
+ return;
5130
+ }
5131
+ seen.add(id);
5132
+ ids.push(id);
5133
+ const blockMap = blocks.get(id);
5134
+ const children = blockMap?.get("children");
5135
+ if (!children) {
5136
+ return;
5137
+ }
5138
+ for (let i = 0; i < children.length; i++) {
5139
+ walk(children.get(i));
5140
+ }
5141
+ };
5142
+ for (let i = 0; i < order.length; i++) {
5143
+ walk(order.get(i));
5144
+ }
5145
+ return ids;
5146
+ }
5147
+
5110
5148
  // src/editor/range.ts
5111
5149
  var DocumentRangeImpl = class {
5112
5150
  start;
5113
5151
  end;
5114
5152
  _anchor;
5115
5153
  _focus;
5116
- _doc;
5154
+ _order;
5117
5155
  constructor(anchor, focus, doc) {
5118
5156
  this._anchor = anchor;
5119
5157
  this._focus = focus;
5120
- this._doc = doc;
5158
+ this._order = documentPreorderBlockIdsFromDoc(doc);
5121
5159
  const anchorIdx = this._indexOfBlock(anchor.blockId);
5122
5160
  const focusIdx = this._indexOfBlock(focus.blockId);
5123
5161
  if (anchorIdx < focusIdx || anchorIdx === focusIdx && (anchor.offset ?? 0) <= (focus.offset ?? 0)) {
@@ -5146,13 +5184,10 @@ var DocumentRangeImpl = class {
5146
5184
  get blockRange() {
5147
5185
  const startIdx = this._indexOfBlock(this.start.blockId);
5148
5186
  const endIdx = this._indexOfBlock(this.end.blockId);
5149
- const result = [];
5150
- for (let i = startIdx; i <= endIdx; i++) {
5151
- result.push(
5152
- this._doc.blockOrder.get(i)
5153
- );
5187
+ if (startIdx < 0 || endIdx < 0) {
5188
+ return [];
5154
5189
  }
5155
- return result;
5190
+ return this._order.slice(startIdx, endIdx + 1);
5156
5191
  }
5157
5192
  contains(point) {
5158
5193
  const idx = this._indexOfBlock(point.blockId);
@@ -5188,10 +5223,7 @@ var DocumentRangeImpl = class {
5188
5223
  };
5189
5224
  }
5190
5225
  _indexOfBlock(blockId) {
5191
- for (let i = 0; i < this._doc.blockOrder.length; i++) {
5192
- if (this._doc.blockOrder.get(i) === blockId) return i;
5193
- }
5194
- return -1;
5226
+ return this._order.indexOf(blockId);
5195
5227
  }
5196
5228
  };
5197
5229
 
@@ -5255,13 +5287,10 @@ function blockIdsFromOrder(order, anchorId, focusId) {
5255
5287
  );
5256
5288
  }
5257
5289
  function blockIdsBetween(doc, anchorId, focusId) {
5258
- const order = doc.blockOrder;
5259
- return sliceBlockIds(
5260
- indexOfBlock(order, anchorId),
5261
- indexOfBlock(order, focusId),
5290
+ return blockIdsFromOrder(
5291
+ documentPreorderBlockIdsFromDoc(doc),
5262
5292
  anchorId,
5263
- focusId,
5264
- (index) => order.get(index)
5293
+ focusId
5265
5294
  );
5266
5295
  }
5267
5296
  function sliceBlockIds(anchorIndex, focusIndex, anchorId, focusId, idAt) {
@@ -5282,14 +5311,6 @@ function sliceBlockIds(anchorIndex, focusIndex, anchorId, focusId, idAt) {
5282
5311
  }
5283
5312
  return ids;
5284
5313
  }
5285
- function indexOfBlock(order, blockId) {
5286
- for (let i = 0; i < order.length; i++) {
5287
- if (order.get(i) === blockId) {
5288
- return i;
5289
- }
5290
- }
5291
- return -1;
5292
- }
5293
5314
 
5294
5315
  // src/editor/anchorRepair.ts
5295
5316
  function sitsInMovedRange(offset, assoc, range) {
@@ -7977,7 +7998,7 @@ function readTextAnchor(editor) {
7977
7998
  return selection.anchor;
7978
7999
  }
7979
8000
  function documentOrderedTextPoints(editor, selection) {
7980
- const order = editor.documentState.blockOrder;
8001
+ const order = documentPreorderBlockIds(editor);
7981
8002
  const anchorIndex = order.indexOf(selection.anchor.blockId);
7982
8003
  const focusIndex = order.indexOf(selection.focus.blockId);
7983
8004
  if (anchorIndex < 0 || focusIndex < 0) {
@@ -7991,7 +8012,7 @@ function documentOrderedTextPoints(editor, selection) {
7991
8012
 
7992
8013
  // src/commands/commandSnapshots.ts
7993
8014
  function buildNormalPositionSnapshot(editor) {
7994
- const blockOrder = [...editor.documentState.blockOrder];
8015
+ const blockOrder = [...getVisibleBlockIds(editor)];
7995
8016
  const blocks = {};
7996
8017
  for (const blockId of blockOrder) {
7997
8018
  const block = editor.getBlock(blockId);
@@ -8012,7 +8033,7 @@ function buildNormalPositionSnapshot(editor) {
8012
8033
  return { blockOrder, blocks };
8013
8034
  }
8014
8035
  function buildTransitionSnapshot(editor) {
8015
- const blockOrder = [...editor.documentState.blockOrder];
8036
+ const blockOrder = [...getVisibleBlockIds(editor)];
8016
8037
  const blocks = {};
8017
8038
  for (const blockId of blockOrder) {
8018
8039
  const block = editor.getBlock(blockId);
@@ -8309,7 +8330,7 @@ function replaceSingleBlockRange(blockId, start, end, text, marks) {
8309
8330
  };
8310
8331
  }
8311
8332
  function replaceMultiBlockRange(editor, start, end, text, marks) {
8312
- const order = editor.documentState.blockOrder;
8333
+ const order = documentPreorderBlockIds(editor);
8313
8334
  const startIndex = order.indexOf(start.blockId);
8314
8335
  const endIndex = order.indexOf(end.blockId);
8315
8336
  if (startIndex < 0 || endIndex < 0 || startIndex >= endIndex) {
@@ -8348,7 +8369,7 @@ function replaceMultiBlockRange(editor, start, end, text, marks) {
8348
8369
  );
8349
8370
  }
8350
8371
  function replaceTextToTextRange(editor, start, end, text, marks, startIndex, endIndex, startLength) {
8351
- const order = editor.documentState.blockOrder;
8372
+ const order = documentPreorderBlockIds(editor);
8352
8373
  const ops = [];
8353
8374
  if (start.offset < startLength) {
8354
8375
  ops.push(
@@ -8410,7 +8431,7 @@ function replaceTextToTextRange(editor, start, end, text, marks, startIndex, end
8410
8431
  };
8411
8432
  }
8412
8433
  function replaceMixedBoundaryRange(editor, start, end, text, marks, startIndex, endIndex, startEditable, endEditable, startLength) {
8413
- const order = editor.documentState.blockOrder;
8434
+ const order = documentPreorderBlockIds(editor);
8414
8435
  const ops = [];
8415
8436
  if (startEditable) {
8416
8437
  if (start.offset < startLength) {
@@ -8805,6 +8826,10 @@ function handleGraphemeCaret(editor, param, direction) {
8805
8826
  if (fromCell !== void 0) {
8806
8827
  return finishNonVertical(editor, fromCell);
8807
8828
  }
8829
+ const collapsed = collapseTextRange(editor, param, direction);
8830
+ if (collapsed !== void 0) {
8831
+ return finishNonVertical(editor, collapsed);
8832
+ }
8808
8833
  const focus = readTextFocus(editor);
8809
8834
  if (!focus) {
8810
8835
  return false;
@@ -8823,6 +8848,18 @@ function handleGraphemeCaret(editor, param, direction) {
8823
8848
  selection: extendSelection(editor, param.extend, next)
8824
8849
  });
8825
8850
  }
8851
+ function collapseTextRange(editor, param, direction) {
8852
+ const selection = editor.selection;
8853
+ if (param.extend || !selection || selection.type !== "text" || isCollapsed(selection)) {
8854
+ return void 0;
8855
+ }
8856
+ const ordered = documentOrderedTextPoints(editor, selection);
8857
+ if (!ordered) {
8858
+ return void 0;
8859
+ }
8860
+ const edge = direction === 1 ? ordered.end : ordered.start;
8861
+ return { selection: collapsedAt(edge.blockId, edge.offset) };
8862
+ }
8826
8863
  function handleWordCaret(editor, param, direction) {
8827
8864
  const fromCellEdit = handleCellEditingCaret(
8828
8865
  editor,
@@ -9056,7 +9093,7 @@ function crossBlock(editor, blockId, direction) {
9056
9093
  };
9057
9094
  }
9058
9095
  function documentEdgePoint(editor, edge) {
9059
- const order = editor.documentState.blockOrder;
9096
+ const order = getVisibleBlockIds(editor);
9060
9097
  if (order.length === 0) {
9061
9098
  return null;
9062
9099
  }
@@ -9300,11 +9337,10 @@ var multiplayerControllerFacet = singleController(
9300
9337
  );
9301
9338
  var snapshotsControllerFacet = singleController("history.controller");
9302
9339
  var assetProviderFacet = singleController("pen.assetProvider");
9303
- var toolRuntimeFacet = singleController(
9304
- "tools.toolRuntime"
9305
- );
9340
+ var toolRuntimeFacet = singleController("tools.toolRuntime");
9306
9341
  var announcerFacet = singleController("pen.announcer");
9307
9342
  var streamingTargetFacet = singleController("deltaStream.target");
9343
+ var smoothStreamControllerFacet = singleController("ai.smoothStream");
9308
9344
 
9309
9345
  // src/commands/history.ts
9310
9346
  var historyUndo = defineCommand("history.undo");
@@ -10085,7 +10121,7 @@ function toggleMarkAcrossBlocks(editor, selection, param) {
10085
10121
  if (!range) {
10086
10122
  return false;
10087
10123
  }
10088
- const order = editor.documentState.blockOrder;
10124
+ const order = documentPreorderBlockIds(editor);
10089
10125
  const startIndex = order.indexOf(range.start.blockId);
10090
10126
  const endIndex = order.indexOf(range.end.blockId);
10091
10127
  if (startIndex < 0 || endIndex < 0) {
@@ -11096,6 +11132,7 @@ var FACET_BY_SLOT_KEY = {
11096
11132
  "pen.messages": messagesFacet,
11097
11133
  "pen.a11yLabel": a11yLabelFacet,
11098
11134
  "delta-stream:target": streamingTargetFacet,
11135
+ "smooth-stream:controller": smoothStreamControllerFacet,
11099
11136
  [import_pen_types7.ANNOUNCER_SLOT_KEY]: announcerFacet
11100
11137
  };
11101
11138
  function writeAssignedSlot(self, key, value) {
@@ -15256,6 +15293,7 @@ function mapOffsetThroughSplices(splices, offset, assoc) {
15256
15293
  shouldShowBlockInDefaultMenus,
15257
15294
  singleController,
15258
15295
  slashMenuGroupOf,
15296
+ smoothStreamControllerFacet,
15259
15297
  snapToNormalPosition,
15260
15298
  snapshotsControllerFacet,
15261
15299
  sortDeltaAttributes,
package/dist/index.d.cts CHANGED
@@ -304,7 +304,7 @@ declare class DocumentRangeImpl implements DocumentRange {
304
304
  };
305
305
  private readonly _anchor;
306
306
  private readonly _focus;
307
- private readonly _doc;
307
+ private readonly _order;
308
308
  constructor(anchor: {
309
309
  blockId: string;
310
310
  offset?: number;
@@ -456,9 +456,10 @@ declare function createTextSelection(input: {
456
456
  declare function isCollapsed(sel: ReadonlySelectionState): boolean;
457
457
  declare function isMultiBlock(sel: ReadonlySelectionState): boolean;
458
458
  /**
459
- * Document-order block ids covered by `sel`. Pass a plain `blockOrder`
460
- * snapshot (`editor.documentState.blockOrder`) from a renderer effect —
461
- * walking a live `Y.Array` through a deep-proxied document writes back.
459
+ * Document-order block ids covered by `sel`. A live `PenDocument` walks
460
+ * nested `children` as well as top-level `blockOrder`. Pass a plain id
461
+ * snapshot from a renderer effect — walking a live `Y.Array` through a
462
+ * deep-proxied document writes back.
462
463
  */
463
464
  declare function getSelectionBlockRange(doc: PenDocument | readonly string[], sel: ReadonlySelectionState): string[];
464
465
  declare function isBlockSelected(blockOrder: readonly string[], sel: ReadonlySelectionState, blockId: string): boolean;
@@ -1101,6 +1102,8 @@ declare const assetProviderFacet: _input_pen_types.Facet<unknown, unknown>;
1101
1102
  declare const toolRuntimeFacet: _input_pen_types.Facet<unknown, unknown>;
1102
1103
  declare const announcerFacet: _input_pen_types.Facet<unknown, unknown>;
1103
1104
  declare const streamingTargetFacet: _input_pen_types.Facet<unknown, unknown>;
1105
+ /** Facet that publishes the smooth-stream controller, or null when the extension is not installed. */
1106
+ declare const smoothStreamControllerFacet: _input_pen_types.Facet<unknown, unknown>;
1104
1107
 
1105
1108
  declare function affectedBlockIdsFromSummary(summary: Pick<ChangeSummary, "blockText" | "structural">, documentOrder?: readonly string[]): string[];
1106
1109
 
@@ -1113,4 +1116,4 @@ declare function affectedBlockIdsFromSummary(summary: Pick<ChangeSummary, "block
1113
1116
  */
1114
1117
  declare function mapOffsetThroughSplices(splices: readonly TextSplice[], offset: number, assoc: Assoc): number;
1115
1118
 
1116
- export { A11Y_MISSING_LABEL_CODE, APPLY_STORM_CODE, APPLY_STORM_QUEUE_LIMIT, type BeforeApplyHook, type BlockDirection, type BlockDirectionResolver, type BlockDirectionSetting, type CaretMotionParam, type CellCaretFocus, type CellCaretWrite, type ClipboardHandler, type CommandDispatchContext, type CommandHandlerTable, type CommandRegistry, type ContentMove, type ConvertBlockParam, type CreateCommandRegistryOptions, type CreateFacetRegistryOptions, type CreateHeadlessEditorOptions, type DecorationSource, type DefaultKeymapBinding, type DefaultKeymapContext, type DefinedBlockSchema, type DeleteGranularity, type DeleteParam, type DocumentMigration, DocumentRangeImpl, type EditorA11yLabelAttrs, EventEmitter, ExtensionManagerImpl, type FacetRegistry, type FacetSettleInput, HOOK_PRIORITIES, type InsertTextParam, type Keymap, type KeymapPlatform, type MigrationReport, type NormalPositionSnapshot, PIPELINE_PHASES, PSEUDO_LOCALE_CLOSE, PSEUDO_LOCALE_OPEN, type PendingBlock, type PendingBlockImportPolicyViolation, type PendingBlockProfilePolicyViolation, type ProfilePolicyViolation, type SchemaA11yAttrs, type SchemaA11yKind, SchemaEngineImpl, type SchemaRegistryConfig, SchemaRegistryImpl, type SelectBlockParam, SelectionAuthorityImpl as SelectionAuthority, type StructureBlockParam, type SuggestionMenuBoundary, type SuggestionMenuTarget, type SuggestionMenuTrigger, type ToggleMarkParam, type UrlContext, type UrlPolicy, type VerticalCaretDirection, type VerticalCaretMeasure, type VerticalCaretMeasureResult, type VerticalCaretPoint, type WordRange, a11yLabelFacet, affectedBlockIdsFromSummary, aiAutocompleteControllerFacet, aiControllerFacet, aiEgressExtension, aiEgressFacet, aiInlineCompletionFacet, aiInlineHistoryFacet, aiReviewControllerFacet, aiSuggestionsControllerFacet, announceEditorA11y, announcerFacet, applyDirectedBinding, applyMergeBlocks, applySplitBlock, ariaReadOnlyFacet, assetProviderFacet, beforeApplyFacet, blockDirectionFacet, blockLogicalText, blocksToOps, buildMergeBlocksRecipe, buildNormalPositionSnapshot, buildSplitBlockRecipe, buildTableChildren, builtinCommandHandlers, caretBlockEnd, caretBlockStart, caretDocEnd, caretDocStart, caretDown, caretLeft, caretLineEnd, caretLineStart, caretRight, caretUp, caretWordLeft, caretWordRight, clipboardFacet, collectEditorKeyBindings, collectToolExecutionOutput, commandHandler, commandsFacet, convertBlock, convertBlockOps, createAppHandle, createBlockHandle, createCommandRegistry, createDecorationSet, createDocumentSession, createEditor, createEmptySchema, createFacetRegistry, createHeadlessEditor, createImportResult, createMutationGroupMetadata, createPseudoLocaleCatalog, createTextSelection, decorationsFacet, deepEqual, defaultDirectionFacet, defaultKeymapBindings, defineBlock, defineCommand, defineExtension, defineFacet, delegatesToGridEditing, deleteAdjacentInlineAtom, deleteBackward, deleteBlock, deleteForward, deriveContentMoves, duplicateBlock, emptyDecorationSet, ensureInlineCompletionController, fieldEditorHostFacet, filterAIRequest, filterOpsForDocumentProfile, filterPendingBlocksForDocumentProfile, foldAndNormalize, getApplyOptionsGroupId, getBlockSelectionRoleFromSchema, getBlockSelectionRoleFromType, getCellCaretFocus, getCommandRegistry, getEditorSelectionRecord, getFlowCapabilityFromSchema, getFlowCapabilityFromType, getInlineCompletionController, getNumberedListItemValue, getOpOriginGroupId, getOpOriginType, getSelectionBlockRange, getVerticalCaretGoalX, getVerticalCaretMeasure, hasFieldEditorSurface, hasIndexedCellSelectionMetadata, historyRedo, historyUndo, hookPriorityToPrecedence, indent, inlineLogicalText, inputRulesEngineFacet, inputRulesFacet, insertLineBreak, insertText, interpolateMessage, isBlockSelected, isCollapsed, isContainerBlock, isContainerBlockType, isContinuousTextFlowCapability, isMultiBlock, isPseudoLocaleText, keyBindingPriorityToPrecedence, keymapFacet, localeFacet, mapOffsetThroughSplices, mergeDecorationSets, mergeSchemas, messagesFacet, moveBlockDown, moveBlockUp, multiplayerControllerFacet, nextGraphemeBoundary, nextWordBoundary, normalizePendingBlocksForImport, orderSlashMenuItemsByGroup, outdent, previousGraphemeBoundary, previousWordBoundary, priorityToPrecedence, prop, renderSelectionTargetBlockText, renderSelectionTargetText, repairAnchor, reportPendingBlockImportViolations, reportPendingBlockProfileViolations, resolveA11yBlockTypeLabel, resolveA11ySpec, resolveBlockDirection, resolveBlockFlowCapability, resolveCellSelectionCoord, resolveCellSelectionMatrix, resolveDefaultKeymap, resolveDirectedBinding, resolveDirectedCommand, resolveEditorA11yLabel, resolveEditorMessage, resolveEditorSchema, resolveFieldEditorBehavior, resolveFieldEditorInputMode, resolveFocusBlockDirection, resolveMessage, resolveSchema, resolveSchemaA11y, resolveSelectionTargetBlockIds, resolveSuggestionMenuTarget, runMigrations, searchControllerFacet, selectAdjacentInlineAtom, selectAll, selectBlock, selectionToRange, setCellCaretFocus, setVerticalCaretGoalX, setVerticalCaretMeasure, shouldAllowDirectBlockPaste, shouldAllowFlowInsertionInSlashMenu, shouldExposeBlockInTooling, shouldForceBlockScopedSelectAll, shouldRenderContainerChildren, shouldShowBlockInDefaultMenus, singleController, slashMenuGroupOf, snapToNormalPosition, snapshotsControllerFacet, sortDeltaAttributes, spliceDeleteOp, spliceInsertOp, splitBlock, streamThroughEgress, streamingTargetFacet, suggestion, supportsInlineInputRules, supportsInlineMarks, tableCellDown, tableCellNext, tableCellPrev, tableEscapeGrid, toPseudoLocaleText, toggleMark, toolRuntimeFacet, undoManagerFacet, undoMetadataControllerFacet, undoRestoreControllerFacet, urlPolicy, urlPolicyFacet, usesInlineTextSelection, wordRangeAt };
1119
+ export { A11Y_MISSING_LABEL_CODE, APPLY_STORM_CODE, APPLY_STORM_QUEUE_LIMIT, type BeforeApplyHook, type BlockDirection, type BlockDirectionResolver, type BlockDirectionSetting, type CaretMotionParam, type CellCaretFocus, type CellCaretWrite, type ClipboardHandler, type CommandDispatchContext, type CommandHandlerTable, type CommandRegistry, type ContentMove, type ConvertBlockParam, type CreateCommandRegistryOptions, type CreateFacetRegistryOptions, type CreateHeadlessEditorOptions, type DecorationSource, type DefaultKeymapBinding, type DefaultKeymapContext, type DefinedBlockSchema, type DeleteGranularity, type DeleteParam, type DocumentMigration, DocumentRangeImpl, type EditorA11yLabelAttrs, EventEmitter, ExtensionManagerImpl, type FacetRegistry, type FacetSettleInput, HOOK_PRIORITIES, type InsertTextParam, type Keymap, type KeymapPlatform, type MigrationReport, type NormalPositionSnapshot, PIPELINE_PHASES, PSEUDO_LOCALE_CLOSE, PSEUDO_LOCALE_OPEN, type PendingBlock, type PendingBlockImportPolicyViolation, type PendingBlockProfilePolicyViolation, type ProfilePolicyViolation, type SchemaA11yAttrs, type SchemaA11yKind, SchemaEngineImpl, type SchemaRegistryConfig, SchemaRegistryImpl, type SelectBlockParam, SelectionAuthorityImpl as SelectionAuthority, type StructureBlockParam, type SuggestionMenuBoundary, type SuggestionMenuTarget, type SuggestionMenuTrigger, type ToggleMarkParam, type UrlContext, type UrlPolicy, type VerticalCaretDirection, type VerticalCaretMeasure, type VerticalCaretMeasureResult, type VerticalCaretPoint, type WordRange, a11yLabelFacet, affectedBlockIdsFromSummary, aiAutocompleteControllerFacet, aiControllerFacet, aiEgressExtension, aiEgressFacet, aiInlineCompletionFacet, aiInlineHistoryFacet, aiReviewControllerFacet, aiSuggestionsControllerFacet, announceEditorA11y, announcerFacet, applyDirectedBinding, applyMergeBlocks, applySplitBlock, ariaReadOnlyFacet, assetProviderFacet, beforeApplyFacet, blockDirectionFacet, blockLogicalText, blocksToOps, buildMergeBlocksRecipe, buildNormalPositionSnapshot, buildSplitBlockRecipe, buildTableChildren, builtinCommandHandlers, caretBlockEnd, caretBlockStart, caretDocEnd, caretDocStart, caretDown, caretLeft, caretLineEnd, caretLineStart, caretRight, caretUp, caretWordLeft, caretWordRight, clipboardFacet, collectEditorKeyBindings, collectToolExecutionOutput, commandHandler, commandsFacet, convertBlock, convertBlockOps, createAppHandle, createBlockHandle, createCommandRegistry, createDecorationSet, createDocumentSession, createEditor, createEmptySchema, createFacetRegistry, createHeadlessEditor, createImportResult, createMutationGroupMetadata, createPseudoLocaleCatalog, createTextSelection, decorationsFacet, deepEqual, defaultDirectionFacet, defaultKeymapBindings, defineBlock, defineCommand, defineExtension, defineFacet, delegatesToGridEditing, deleteAdjacentInlineAtom, deleteBackward, deleteBlock, deleteForward, deriveContentMoves, duplicateBlock, emptyDecorationSet, ensureInlineCompletionController, fieldEditorHostFacet, filterAIRequest, filterOpsForDocumentProfile, filterPendingBlocksForDocumentProfile, foldAndNormalize, getApplyOptionsGroupId, getBlockSelectionRoleFromSchema, getBlockSelectionRoleFromType, getCellCaretFocus, getCommandRegistry, getEditorSelectionRecord, getFlowCapabilityFromSchema, getFlowCapabilityFromType, getInlineCompletionController, getNumberedListItemValue, getOpOriginGroupId, getOpOriginType, getSelectionBlockRange, getVerticalCaretGoalX, getVerticalCaretMeasure, hasFieldEditorSurface, hasIndexedCellSelectionMetadata, historyRedo, historyUndo, hookPriorityToPrecedence, indent, inlineLogicalText, inputRulesEngineFacet, inputRulesFacet, insertLineBreak, insertText, interpolateMessage, isBlockSelected, isCollapsed, isContainerBlock, isContainerBlockType, isContinuousTextFlowCapability, isMultiBlock, isPseudoLocaleText, keyBindingPriorityToPrecedence, keymapFacet, localeFacet, mapOffsetThroughSplices, mergeDecorationSets, mergeSchemas, messagesFacet, moveBlockDown, moveBlockUp, multiplayerControllerFacet, nextGraphemeBoundary, nextWordBoundary, normalizePendingBlocksForImport, orderSlashMenuItemsByGroup, outdent, previousGraphemeBoundary, previousWordBoundary, priorityToPrecedence, prop, renderSelectionTargetBlockText, renderSelectionTargetText, repairAnchor, reportPendingBlockImportViolations, reportPendingBlockProfileViolations, resolveA11yBlockTypeLabel, resolveA11ySpec, resolveBlockDirection, resolveBlockFlowCapability, resolveCellSelectionCoord, resolveCellSelectionMatrix, resolveDefaultKeymap, resolveDirectedBinding, resolveDirectedCommand, resolveEditorA11yLabel, resolveEditorMessage, resolveEditorSchema, resolveFieldEditorBehavior, resolveFieldEditorInputMode, resolveFocusBlockDirection, resolveMessage, resolveSchema, resolveSchemaA11y, resolveSelectionTargetBlockIds, resolveSuggestionMenuTarget, runMigrations, searchControllerFacet, selectAdjacentInlineAtom, selectAll, selectBlock, selectionToRange, setCellCaretFocus, setVerticalCaretGoalX, setVerticalCaretMeasure, shouldAllowDirectBlockPaste, shouldAllowFlowInsertionInSlashMenu, shouldExposeBlockInTooling, shouldForceBlockScopedSelectAll, shouldRenderContainerChildren, shouldShowBlockInDefaultMenus, singleController, slashMenuGroupOf, smoothStreamControllerFacet, snapToNormalPosition, snapshotsControllerFacet, sortDeltaAttributes, spliceDeleteOp, spliceInsertOp, splitBlock, streamThroughEgress, streamingTargetFacet, suggestion, supportsInlineInputRules, supportsInlineMarks, tableCellDown, tableCellNext, tableCellPrev, tableEscapeGrid, toPseudoLocaleText, toggleMark, toolRuntimeFacet, undoManagerFacet, undoMetadataControllerFacet, undoRestoreControllerFacet, urlPolicy, urlPolicyFacet, usesInlineTextSelection, wordRangeAt };
package/dist/index.d.ts CHANGED
@@ -304,7 +304,7 @@ declare class DocumentRangeImpl implements DocumentRange {
304
304
  };
305
305
  private readonly _anchor;
306
306
  private readonly _focus;
307
- private readonly _doc;
307
+ private readonly _order;
308
308
  constructor(anchor: {
309
309
  blockId: string;
310
310
  offset?: number;
@@ -456,9 +456,10 @@ declare function createTextSelection(input: {
456
456
  declare function isCollapsed(sel: ReadonlySelectionState): boolean;
457
457
  declare function isMultiBlock(sel: ReadonlySelectionState): boolean;
458
458
  /**
459
- * Document-order block ids covered by `sel`. Pass a plain `blockOrder`
460
- * snapshot (`editor.documentState.blockOrder`) from a renderer effect —
461
- * walking a live `Y.Array` through a deep-proxied document writes back.
459
+ * Document-order block ids covered by `sel`. A live `PenDocument` walks
460
+ * nested `children` as well as top-level `blockOrder`. Pass a plain id
461
+ * snapshot from a renderer effect — walking a live `Y.Array` through a
462
+ * deep-proxied document writes back.
462
463
  */
463
464
  declare function getSelectionBlockRange(doc: PenDocument | readonly string[], sel: ReadonlySelectionState): string[];
464
465
  declare function isBlockSelected(blockOrder: readonly string[], sel: ReadonlySelectionState, blockId: string): boolean;
@@ -1101,6 +1102,8 @@ declare const assetProviderFacet: _input_pen_types.Facet<unknown, unknown>;
1101
1102
  declare const toolRuntimeFacet: _input_pen_types.Facet<unknown, unknown>;
1102
1103
  declare const announcerFacet: _input_pen_types.Facet<unknown, unknown>;
1103
1104
  declare const streamingTargetFacet: _input_pen_types.Facet<unknown, unknown>;
1105
+ /** Facet that publishes the smooth-stream controller, or null when the extension is not installed. */
1106
+ declare const smoothStreamControllerFacet: _input_pen_types.Facet<unknown, unknown>;
1104
1107
 
1105
1108
  declare function affectedBlockIdsFromSummary(summary: Pick<ChangeSummary, "blockText" | "structural">, documentOrder?: readonly string[]): string[];
1106
1109
 
@@ -1113,4 +1116,4 @@ declare function affectedBlockIdsFromSummary(summary: Pick<ChangeSummary, "block
1113
1116
  */
1114
1117
  declare function mapOffsetThroughSplices(splices: readonly TextSplice[], offset: number, assoc: Assoc): number;
1115
1118
 
1116
- export { A11Y_MISSING_LABEL_CODE, APPLY_STORM_CODE, APPLY_STORM_QUEUE_LIMIT, type BeforeApplyHook, type BlockDirection, type BlockDirectionResolver, type BlockDirectionSetting, type CaretMotionParam, type CellCaretFocus, type CellCaretWrite, type ClipboardHandler, type CommandDispatchContext, type CommandHandlerTable, type CommandRegistry, type ContentMove, type ConvertBlockParam, type CreateCommandRegistryOptions, type CreateFacetRegistryOptions, type CreateHeadlessEditorOptions, type DecorationSource, type DefaultKeymapBinding, type DefaultKeymapContext, type DefinedBlockSchema, type DeleteGranularity, type DeleteParam, type DocumentMigration, DocumentRangeImpl, type EditorA11yLabelAttrs, EventEmitter, ExtensionManagerImpl, type FacetRegistry, type FacetSettleInput, HOOK_PRIORITIES, type InsertTextParam, type Keymap, type KeymapPlatform, type MigrationReport, type NormalPositionSnapshot, PIPELINE_PHASES, PSEUDO_LOCALE_CLOSE, PSEUDO_LOCALE_OPEN, type PendingBlock, type PendingBlockImportPolicyViolation, type PendingBlockProfilePolicyViolation, type ProfilePolicyViolation, type SchemaA11yAttrs, type SchemaA11yKind, SchemaEngineImpl, type SchemaRegistryConfig, SchemaRegistryImpl, type SelectBlockParam, SelectionAuthorityImpl as SelectionAuthority, type StructureBlockParam, type SuggestionMenuBoundary, type SuggestionMenuTarget, type SuggestionMenuTrigger, type ToggleMarkParam, type UrlContext, type UrlPolicy, type VerticalCaretDirection, type VerticalCaretMeasure, type VerticalCaretMeasureResult, type VerticalCaretPoint, type WordRange, a11yLabelFacet, affectedBlockIdsFromSummary, aiAutocompleteControllerFacet, aiControllerFacet, aiEgressExtension, aiEgressFacet, aiInlineCompletionFacet, aiInlineHistoryFacet, aiReviewControllerFacet, aiSuggestionsControllerFacet, announceEditorA11y, announcerFacet, applyDirectedBinding, applyMergeBlocks, applySplitBlock, ariaReadOnlyFacet, assetProviderFacet, beforeApplyFacet, blockDirectionFacet, blockLogicalText, blocksToOps, buildMergeBlocksRecipe, buildNormalPositionSnapshot, buildSplitBlockRecipe, buildTableChildren, builtinCommandHandlers, caretBlockEnd, caretBlockStart, caretDocEnd, caretDocStart, caretDown, caretLeft, caretLineEnd, caretLineStart, caretRight, caretUp, caretWordLeft, caretWordRight, clipboardFacet, collectEditorKeyBindings, collectToolExecutionOutput, commandHandler, commandsFacet, convertBlock, convertBlockOps, createAppHandle, createBlockHandle, createCommandRegistry, createDecorationSet, createDocumentSession, createEditor, createEmptySchema, createFacetRegistry, createHeadlessEditor, createImportResult, createMutationGroupMetadata, createPseudoLocaleCatalog, createTextSelection, decorationsFacet, deepEqual, defaultDirectionFacet, defaultKeymapBindings, defineBlock, defineCommand, defineExtension, defineFacet, delegatesToGridEditing, deleteAdjacentInlineAtom, deleteBackward, deleteBlock, deleteForward, deriveContentMoves, duplicateBlock, emptyDecorationSet, ensureInlineCompletionController, fieldEditorHostFacet, filterAIRequest, filterOpsForDocumentProfile, filterPendingBlocksForDocumentProfile, foldAndNormalize, getApplyOptionsGroupId, getBlockSelectionRoleFromSchema, getBlockSelectionRoleFromType, getCellCaretFocus, getCommandRegistry, getEditorSelectionRecord, getFlowCapabilityFromSchema, getFlowCapabilityFromType, getInlineCompletionController, getNumberedListItemValue, getOpOriginGroupId, getOpOriginType, getSelectionBlockRange, getVerticalCaretGoalX, getVerticalCaretMeasure, hasFieldEditorSurface, hasIndexedCellSelectionMetadata, historyRedo, historyUndo, hookPriorityToPrecedence, indent, inlineLogicalText, inputRulesEngineFacet, inputRulesFacet, insertLineBreak, insertText, interpolateMessage, isBlockSelected, isCollapsed, isContainerBlock, isContainerBlockType, isContinuousTextFlowCapability, isMultiBlock, isPseudoLocaleText, keyBindingPriorityToPrecedence, keymapFacet, localeFacet, mapOffsetThroughSplices, mergeDecorationSets, mergeSchemas, messagesFacet, moveBlockDown, moveBlockUp, multiplayerControllerFacet, nextGraphemeBoundary, nextWordBoundary, normalizePendingBlocksForImport, orderSlashMenuItemsByGroup, outdent, previousGraphemeBoundary, previousWordBoundary, priorityToPrecedence, prop, renderSelectionTargetBlockText, renderSelectionTargetText, repairAnchor, reportPendingBlockImportViolations, reportPendingBlockProfileViolations, resolveA11yBlockTypeLabel, resolveA11ySpec, resolveBlockDirection, resolveBlockFlowCapability, resolveCellSelectionCoord, resolveCellSelectionMatrix, resolveDefaultKeymap, resolveDirectedBinding, resolveDirectedCommand, resolveEditorA11yLabel, resolveEditorMessage, resolveEditorSchema, resolveFieldEditorBehavior, resolveFieldEditorInputMode, resolveFocusBlockDirection, resolveMessage, resolveSchema, resolveSchemaA11y, resolveSelectionTargetBlockIds, resolveSuggestionMenuTarget, runMigrations, searchControllerFacet, selectAdjacentInlineAtom, selectAll, selectBlock, selectionToRange, setCellCaretFocus, setVerticalCaretGoalX, setVerticalCaretMeasure, shouldAllowDirectBlockPaste, shouldAllowFlowInsertionInSlashMenu, shouldExposeBlockInTooling, shouldForceBlockScopedSelectAll, shouldRenderContainerChildren, shouldShowBlockInDefaultMenus, singleController, slashMenuGroupOf, snapToNormalPosition, snapshotsControllerFacet, sortDeltaAttributes, spliceDeleteOp, spliceInsertOp, splitBlock, streamThroughEgress, streamingTargetFacet, suggestion, supportsInlineInputRules, supportsInlineMarks, tableCellDown, tableCellNext, tableCellPrev, tableEscapeGrid, toPseudoLocaleText, toggleMark, toolRuntimeFacet, undoManagerFacet, undoMetadataControllerFacet, undoRestoreControllerFacet, urlPolicy, urlPolicyFacet, usesInlineTextSelection, wordRangeAt };
1119
+ export { A11Y_MISSING_LABEL_CODE, APPLY_STORM_CODE, APPLY_STORM_QUEUE_LIMIT, type BeforeApplyHook, type BlockDirection, type BlockDirectionResolver, type BlockDirectionSetting, type CaretMotionParam, type CellCaretFocus, type CellCaretWrite, type ClipboardHandler, type CommandDispatchContext, type CommandHandlerTable, type CommandRegistry, type ContentMove, type ConvertBlockParam, type CreateCommandRegistryOptions, type CreateFacetRegistryOptions, type CreateHeadlessEditorOptions, type DecorationSource, type DefaultKeymapBinding, type DefaultKeymapContext, type DefinedBlockSchema, type DeleteGranularity, type DeleteParam, type DocumentMigration, DocumentRangeImpl, type EditorA11yLabelAttrs, EventEmitter, ExtensionManagerImpl, type FacetRegistry, type FacetSettleInput, HOOK_PRIORITIES, type InsertTextParam, type Keymap, type KeymapPlatform, type MigrationReport, type NormalPositionSnapshot, PIPELINE_PHASES, PSEUDO_LOCALE_CLOSE, PSEUDO_LOCALE_OPEN, type PendingBlock, type PendingBlockImportPolicyViolation, type PendingBlockProfilePolicyViolation, type ProfilePolicyViolation, type SchemaA11yAttrs, type SchemaA11yKind, SchemaEngineImpl, type SchemaRegistryConfig, SchemaRegistryImpl, type SelectBlockParam, SelectionAuthorityImpl as SelectionAuthority, type StructureBlockParam, type SuggestionMenuBoundary, type SuggestionMenuTarget, type SuggestionMenuTrigger, type ToggleMarkParam, type UrlContext, type UrlPolicy, type VerticalCaretDirection, type VerticalCaretMeasure, type VerticalCaretMeasureResult, type VerticalCaretPoint, type WordRange, a11yLabelFacet, affectedBlockIdsFromSummary, aiAutocompleteControllerFacet, aiControllerFacet, aiEgressExtension, aiEgressFacet, aiInlineCompletionFacet, aiInlineHistoryFacet, aiReviewControllerFacet, aiSuggestionsControllerFacet, announceEditorA11y, announcerFacet, applyDirectedBinding, applyMergeBlocks, applySplitBlock, ariaReadOnlyFacet, assetProviderFacet, beforeApplyFacet, blockDirectionFacet, blockLogicalText, blocksToOps, buildMergeBlocksRecipe, buildNormalPositionSnapshot, buildSplitBlockRecipe, buildTableChildren, builtinCommandHandlers, caretBlockEnd, caretBlockStart, caretDocEnd, caretDocStart, caretDown, caretLeft, caretLineEnd, caretLineStart, caretRight, caretUp, caretWordLeft, caretWordRight, clipboardFacet, collectEditorKeyBindings, collectToolExecutionOutput, commandHandler, commandsFacet, convertBlock, convertBlockOps, createAppHandle, createBlockHandle, createCommandRegistry, createDecorationSet, createDocumentSession, createEditor, createEmptySchema, createFacetRegistry, createHeadlessEditor, createImportResult, createMutationGroupMetadata, createPseudoLocaleCatalog, createTextSelection, decorationsFacet, deepEqual, defaultDirectionFacet, defaultKeymapBindings, defineBlock, defineCommand, defineExtension, defineFacet, delegatesToGridEditing, deleteAdjacentInlineAtom, deleteBackward, deleteBlock, deleteForward, deriveContentMoves, duplicateBlock, emptyDecorationSet, ensureInlineCompletionController, fieldEditorHostFacet, filterAIRequest, filterOpsForDocumentProfile, filterPendingBlocksForDocumentProfile, foldAndNormalize, getApplyOptionsGroupId, getBlockSelectionRoleFromSchema, getBlockSelectionRoleFromType, getCellCaretFocus, getCommandRegistry, getEditorSelectionRecord, getFlowCapabilityFromSchema, getFlowCapabilityFromType, getInlineCompletionController, getNumberedListItemValue, getOpOriginGroupId, getOpOriginType, getSelectionBlockRange, getVerticalCaretGoalX, getVerticalCaretMeasure, hasFieldEditorSurface, hasIndexedCellSelectionMetadata, historyRedo, historyUndo, hookPriorityToPrecedence, indent, inlineLogicalText, inputRulesEngineFacet, inputRulesFacet, insertLineBreak, insertText, interpolateMessage, isBlockSelected, isCollapsed, isContainerBlock, isContainerBlockType, isContinuousTextFlowCapability, isMultiBlock, isPseudoLocaleText, keyBindingPriorityToPrecedence, keymapFacet, localeFacet, mapOffsetThroughSplices, mergeDecorationSets, mergeSchemas, messagesFacet, moveBlockDown, moveBlockUp, multiplayerControllerFacet, nextGraphemeBoundary, nextWordBoundary, normalizePendingBlocksForImport, orderSlashMenuItemsByGroup, outdent, previousGraphemeBoundary, previousWordBoundary, priorityToPrecedence, prop, renderSelectionTargetBlockText, renderSelectionTargetText, repairAnchor, reportPendingBlockImportViolations, reportPendingBlockProfileViolations, resolveA11yBlockTypeLabel, resolveA11ySpec, resolveBlockDirection, resolveBlockFlowCapability, resolveCellSelectionCoord, resolveCellSelectionMatrix, resolveDefaultKeymap, resolveDirectedBinding, resolveDirectedCommand, resolveEditorA11yLabel, resolveEditorMessage, resolveEditorSchema, resolveFieldEditorBehavior, resolveFieldEditorInputMode, resolveFocusBlockDirection, resolveMessage, resolveSchema, resolveSchemaA11y, resolveSelectionTargetBlockIds, resolveSuggestionMenuTarget, runMigrations, searchControllerFacet, selectAdjacentInlineAtom, selectAll, selectBlock, selectionToRange, setCellCaretFocus, setVerticalCaretGoalX, setVerticalCaretMeasure, shouldAllowDirectBlockPaste, shouldAllowFlowInsertionInSlashMenu, shouldExposeBlockInTooling, shouldForceBlockScopedSelectAll, shouldRenderContainerChildren, shouldShowBlockInDefaultMenus, singleController, slashMenuGroupOf, smoothStreamControllerFacet, snapToNormalPosition, snapshotsControllerFacet, sortDeltaAttributes, spliceDeleteOp, spliceInsertOp, splitBlock, streamThroughEgress, streamingTargetFacet, suggestion, supportsInlineInputRules, supportsInlineMarks, tableCellDown, tableCellNext, tableCellPrev, tableEscapeGrid, toPseudoLocaleText, toggleMark, toolRuntimeFacet, undoManagerFacet, undoMetadataControllerFacet, undoRestoreControllerFacet, urlPolicy, urlPolicyFacet, usesInlineTextSelection, wordRangeAt };
package/dist/index.mjs CHANGED
@@ -4873,17 +4873,54 @@ function normalizeFieldEditorType(schema) {
4873
4873
  return "none";
4874
4874
  }
4875
4875
 
4876
+ // src/editor/documentPreorder.ts
4877
+ function documentPreorderBlockIds(editor) {
4878
+ return documentPreorderBlockIdsFromState(editor.documentState);
4879
+ }
4880
+ function documentPreorderBlockIdsFromState(state) {
4881
+ const ids = [];
4882
+ for (const block of state.blocks) {
4883
+ ids.push(block.id);
4884
+ }
4885
+ return ids;
4886
+ }
4887
+ function documentPreorderBlockIdsFromDoc(doc) {
4888
+ const ids = [];
4889
+ const seen = /* @__PURE__ */ new Set();
4890
+ const blocks = doc.blocks;
4891
+ const order = doc.blockOrder;
4892
+ const walk = (id) => {
4893
+ if (seen.has(id)) {
4894
+ return;
4895
+ }
4896
+ seen.add(id);
4897
+ ids.push(id);
4898
+ const blockMap = blocks.get(id);
4899
+ const children = blockMap?.get("children");
4900
+ if (!children) {
4901
+ return;
4902
+ }
4903
+ for (let i = 0; i < children.length; i++) {
4904
+ walk(children.get(i));
4905
+ }
4906
+ };
4907
+ for (let i = 0; i < order.length; i++) {
4908
+ walk(order.get(i));
4909
+ }
4910
+ return ids;
4911
+ }
4912
+
4876
4913
  // src/editor/range.ts
4877
4914
  var DocumentRangeImpl = class {
4878
4915
  start;
4879
4916
  end;
4880
4917
  _anchor;
4881
4918
  _focus;
4882
- _doc;
4919
+ _order;
4883
4920
  constructor(anchor, focus, doc) {
4884
4921
  this._anchor = anchor;
4885
4922
  this._focus = focus;
4886
- this._doc = doc;
4923
+ this._order = documentPreorderBlockIdsFromDoc(doc);
4887
4924
  const anchorIdx = this._indexOfBlock(anchor.blockId);
4888
4925
  const focusIdx = this._indexOfBlock(focus.blockId);
4889
4926
  if (anchorIdx < focusIdx || anchorIdx === focusIdx && (anchor.offset ?? 0) <= (focus.offset ?? 0)) {
@@ -4912,13 +4949,10 @@ var DocumentRangeImpl = class {
4912
4949
  get blockRange() {
4913
4950
  const startIdx = this._indexOfBlock(this.start.blockId);
4914
4951
  const endIdx = this._indexOfBlock(this.end.blockId);
4915
- const result = [];
4916
- for (let i = startIdx; i <= endIdx; i++) {
4917
- result.push(
4918
- this._doc.blockOrder.get(i)
4919
- );
4952
+ if (startIdx < 0 || endIdx < 0) {
4953
+ return [];
4920
4954
  }
4921
- return result;
4955
+ return this._order.slice(startIdx, endIdx + 1);
4922
4956
  }
4923
4957
  contains(point) {
4924
4958
  const idx = this._indexOfBlock(point.blockId);
@@ -4954,10 +4988,7 @@ var DocumentRangeImpl = class {
4954
4988
  };
4955
4989
  }
4956
4990
  _indexOfBlock(blockId) {
4957
- for (let i = 0; i < this._doc.blockOrder.length; i++) {
4958
- if (this._doc.blockOrder.get(i) === blockId) return i;
4959
- }
4960
- return -1;
4991
+ return this._order.indexOf(blockId);
4961
4992
  }
4962
4993
  };
4963
4994
 
@@ -5021,13 +5052,10 @@ function blockIdsFromOrder(order, anchorId, focusId) {
5021
5052
  );
5022
5053
  }
5023
5054
  function blockIdsBetween(doc, anchorId, focusId) {
5024
- const order = doc.blockOrder;
5025
- return sliceBlockIds(
5026
- indexOfBlock(order, anchorId),
5027
- indexOfBlock(order, focusId),
5055
+ return blockIdsFromOrder(
5056
+ documentPreorderBlockIdsFromDoc(doc),
5028
5057
  anchorId,
5029
- focusId,
5030
- (index) => order.get(index)
5058
+ focusId
5031
5059
  );
5032
5060
  }
5033
5061
  function sliceBlockIds(anchorIndex, focusIndex, anchorId, focusId, idAt) {
@@ -5048,14 +5076,6 @@ function sliceBlockIds(anchorIndex, focusIndex, anchorId, focusId, idAt) {
5048
5076
  }
5049
5077
  return ids;
5050
5078
  }
5051
- function indexOfBlock(order, blockId) {
5052
- for (let i = 0; i < order.length; i++) {
5053
- if (order.get(i) === blockId) {
5054
- return i;
5055
- }
5056
- }
5057
- return -1;
5058
- }
5059
5079
 
5060
5080
  // src/editor/anchorRepair.ts
5061
5081
  function sitsInMovedRange(offset, assoc, range) {
@@ -7756,7 +7776,7 @@ function readTextAnchor(editor) {
7756
7776
  return selection.anchor;
7757
7777
  }
7758
7778
  function documentOrderedTextPoints(editor, selection) {
7759
- const order = editor.documentState.blockOrder;
7779
+ const order = documentPreorderBlockIds(editor);
7760
7780
  const anchorIndex = order.indexOf(selection.anchor.blockId);
7761
7781
  const focusIndex = order.indexOf(selection.focus.blockId);
7762
7782
  if (anchorIndex < 0 || focusIndex < 0) {
@@ -7770,7 +7790,7 @@ function documentOrderedTextPoints(editor, selection) {
7770
7790
 
7771
7791
  // src/commands/commandSnapshots.ts
7772
7792
  function buildNormalPositionSnapshot(editor) {
7773
- const blockOrder = [...editor.documentState.blockOrder];
7793
+ const blockOrder = [...getVisibleBlockIds(editor)];
7774
7794
  const blocks = {};
7775
7795
  for (const blockId of blockOrder) {
7776
7796
  const block = editor.getBlock(blockId);
@@ -7791,7 +7811,7 @@ function buildNormalPositionSnapshot(editor) {
7791
7811
  return { blockOrder, blocks };
7792
7812
  }
7793
7813
  function buildTransitionSnapshot(editor) {
7794
- const blockOrder = [...editor.documentState.blockOrder];
7814
+ const blockOrder = [...getVisibleBlockIds(editor)];
7795
7815
  const blocks = {};
7796
7816
  for (const blockId of blockOrder) {
7797
7817
  const block = editor.getBlock(blockId);
@@ -8088,7 +8108,7 @@ function replaceSingleBlockRange(blockId, start, end, text, marks) {
8088
8108
  };
8089
8109
  }
8090
8110
  function replaceMultiBlockRange(editor, start, end, text, marks) {
8091
- const order = editor.documentState.blockOrder;
8111
+ const order = documentPreorderBlockIds(editor);
8092
8112
  const startIndex = order.indexOf(start.blockId);
8093
8113
  const endIndex = order.indexOf(end.blockId);
8094
8114
  if (startIndex < 0 || endIndex < 0 || startIndex >= endIndex) {
@@ -8127,7 +8147,7 @@ function replaceMultiBlockRange(editor, start, end, text, marks) {
8127
8147
  );
8128
8148
  }
8129
8149
  function replaceTextToTextRange(editor, start, end, text, marks, startIndex, endIndex, startLength) {
8130
- const order = editor.documentState.blockOrder;
8150
+ const order = documentPreorderBlockIds(editor);
8131
8151
  const ops = [];
8132
8152
  if (start.offset < startLength) {
8133
8153
  ops.push(
@@ -8189,7 +8209,7 @@ function replaceTextToTextRange(editor, start, end, text, marks, startIndex, end
8189
8209
  };
8190
8210
  }
8191
8211
  function replaceMixedBoundaryRange(editor, start, end, text, marks, startIndex, endIndex, startEditable, endEditable, startLength) {
8192
- const order = editor.documentState.blockOrder;
8212
+ const order = documentPreorderBlockIds(editor);
8193
8213
  const ops = [];
8194
8214
  if (startEditable) {
8195
8215
  if (start.offset < startLength) {
@@ -8584,6 +8604,10 @@ function handleGraphemeCaret(editor, param, direction) {
8584
8604
  if (fromCell !== void 0) {
8585
8605
  return finishNonVertical(editor, fromCell);
8586
8606
  }
8607
+ const collapsed = collapseTextRange(editor, param, direction);
8608
+ if (collapsed !== void 0) {
8609
+ return finishNonVertical(editor, collapsed);
8610
+ }
8587
8611
  const focus = readTextFocus(editor);
8588
8612
  if (!focus) {
8589
8613
  return false;
@@ -8602,6 +8626,18 @@ function handleGraphemeCaret(editor, param, direction) {
8602
8626
  selection: extendSelection(editor, param.extend, next)
8603
8627
  });
8604
8628
  }
8629
+ function collapseTextRange(editor, param, direction) {
8630
+ const selection = editor.selection;
8631
+ if (param.extend || !selection || selection.type !== "text" || isCollapsed(selection)) {
8632
+ return void 0;
8633
+ }
8634
+ const ordered = documentOrderedTextPoints(editor, selection);
8635
+ if (!ordered) {
8636
+ return void 0;
8637
+ }
8638
+ const edge = direction === 1 ? ordered.end : ordered.start;
8639
+ return { selection: collapsedAt(edge.blockId, edge.offset) };
8640
+ }
8605
8641
  function handleWordCaret(editor, param, direction) {
8606
8642
  const fromCellEdit = handleCellEditingCaret(
8607
8643
  editor,
@@ -8835,7 +8871,7 @@ function crossBlock(editor, blockId, direction) {
8835
8871
  };
8836
8872
  }
8837
8873
  function documentEdgePoint(editor, edge) {
8838
- const order = editor.documentState.blockOrder;
8874
+ const order = getVisibleBlockIds(editor);
8839
8875
  if (order.length === 0) {
8840
8876
  return null;
8841
8877
  }
@@ -9079,11 +9115,10 @@ var multiplayerControllerFacet = singleController(
9079
9115
  );
9080
9116
  var snapshotsControllerFacet = singleController("history.controller");
9081
9117
  var assetProviderFacet = singleController("pen.assetProvider");
9082
- var toolRuntimeFacet = singleController(
9083
- "tools.toolRuntime"
9084
- );
9118
+ var toolRuntimeFacet = singleController("tools.toolRuntime");
9085
9119
  var announcerFacet = singleController("pen.announcer");
9086
9120
  var streamingTargetFacet = singleController("deltaStream.target");
9121
+ var smoothStreamControllerFacet = singleController("ai.smoothStream");
9087
9122
 
9088
9123
  // src/commands/history.ts
9089
9124
  var historyUndo = defineCommand("history.undo");
@@ -9864,7 +9899,7 @@ function toggleMarkAcrossBlocks(editor, selection, param) {
9864
9899
  if (!range) {
9865
9900
  return false;
9866
9901
  }
9867
- const order = editor.documentState.blockOrder;
9902
+ const order = documentPreorderBlockIds(editor);
9868
9903
  const startIndex = order.indexOf(range.start.blockId);
9869
9904
  const endIndex = order.indexOf(range.end.blockId);
9870
9905
  if (startIndex < 0 || endIndex < 0) {
@@ -10891,6 +10926,7 @@ var FACET_BY_SLOT_KEY = {
10891
10926
  "pen.messages": messagesFacet,
10892
10927
  "pen.a11yLabel": a11yLabelFacet,
10893
10928
  "delta-stream:target": streamingTargetFacet,
10929
+ "smooth-stream:controller": smoothStreamControllerFacet,
10894
10930
  [ANNOUNCER_SLOT_KEY]: announcerFacet
10895
10931
  };
10896
10932
  function writeAssignedSlot(self, key, value) {
@@ -15076,6 +15112,7 @@ export {
15076
15112
  shouldShowBlockInDefaultMenus,
15077
15113
  singleController,
15078
15114
  slashMenuGroupOf,
15115
+ smoothStreamControllerFacet,
15079
15116
  snapToNormalPosition,
15080
15117
  snapshotsControllerFacet,
15081
15118
  sortDeltaAttributes,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@input/pen-core",
3
- "version": "0.1.8",
3
+ "version": "0.2.0",
4
4
  "description": "Headless, extension-first editor engine for human-AI co-authoring",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/input-systems/pen#readme",
@@ -43,8 +43,8 @@
43
43
  },
44
44
  "sideEffects": false,
45
45
  "dependencies": {
46
- "@input/pen-yjs": "^0.1.8",
47
- "@input/pen-types": "^0.1.8"
46
+ "@input/pen-yjs": "^0.2.0",
47
+ "@input/pen-types": "^0.2.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "tsup": "^8.4.0",