noteloom 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noteloom.cjs","sources":["../src/store/operations.js","../src/store/EditorStore.js","../src/store/history.js","../src/registry/blockRegistry.js","../src/registry/inlineRegistry.js","../src/react/EditorProvider.jsx","../src/react/useBlock.js","../src/utils/idGen.js","../src/react/domRunSync.js","../src/blocks/shared/blockEmpty.js","../src/blocks/shared/contentless.js","../src/react/focusRun.js","../src/react/EditableBlockContent.jsx","../src/blocks/shared/navigationCommands.js","../src/react/selectionResolve.js","../src/blocks/shared/blockCommands.js","../src/blocks/shared/leafBlockFactory.js","../src/blocks/shared/ensureRootNonEmpty.js","../src/blocks/shared/mergeCommands.js","../src/blocks/shared/focusAfterMerge.js","../src/blocks/shared/convertBlockType.js","../src/blocks/paragraph/markdownShortcuts.js","../src/blocks/paragraph/ParagraphBlock.jsx","../src/inline/marks.js","../src/inline/runOps.js","../src/react/icons.jsx","../src/blocks/paragraph/index.js","../src/blocks/heading/HeadingBlock.jsx","../src/blocks/heading/index.js","../src/react/useBlockChildren.js","../src/react/BlockErrorBoundary.jsx","../src/react/BlockRenderer.jsx","../src/react/useOutsideClickAndEscape.js","../src/clipboard/serialize.js","../src/blocks/shared/blockActions.js","../src/react/BlockGutterRow.jsx","../src/react/BlockChildren.jsx","../src/blocks/listItem/listMarkers.js","../src/blocks/listItem/createListItemBlock.js","../src/blocks/listItem/indentCommands.js","../src/blocks/listItem/mergeCommands.js","../src/blocks/listItem/exitListItem.js","../src/blocks/listItem/ListItemBlock.jsx","../src/blocks/listItem/index.js","../src/blocks/table/tableColumns.js","../src/blocks/table/tableEditCommands.js","../src/react/Select.jsx","../src/blocks/table/tagColors.js","../src/blocks/table/TableHeaderRow.jsx","../src/blocks/table/TableBlock.jsx","../src/blocks/table/TableRowBlock.jsx","../src/blocks/table/tableNavigation.js","../src/blocks/table/TableCellBlock.jsx","../src/blocks/table/createTableBlock.js","../src/blocks/table/index.js","../src/blocks/layout/LayoutBlock.jsx","../src/blocks/layout/LayoutColumnBlock.jsx","../src/blocks/layout/createLayoutBlock.js","../src/blocks/layout/index.js","../src/blocks/divider/DividerBlock.jsx","../src/blocks/divider/index.js","../src/blocks/callout/createCalloutBlock.js","../src/blocks/callout/CalloutBlock.jsx","../src/blocks/callout/index.js","../src/blocks/blockquote/BlockquoteBlock.jsx","../src/blocks/blockquote/index.js","../src/blocks/code/CodeBlock.jsx","../src/blocks/code/index.js","../src/blocks/toggleHeading/mergeCommands.js","../src/blocks/toggleHeading/ToggleHeadingBlock.jsx","../src/blocks/toggleHeading/createToggleHeadingBlock.js","../src/blocks/toggleHeading/index.js","../src/react/Modal.jsx","../src/blocks/button/ButtonEditModal.jsx","../src/blocks/button/ButtonBlock.jsx","../src/blocks/button/createButtonBlock.js","../src/blocks/button/index.js","../src/blocks/embed/EmbedBlock.jsx","../src/blocks/embed/createEmbedBlock.js","../src/blocks/embed/index.js","../src/blocks/index.js","../src/inlineTypes/select/SelectInlineNode.jsx","../src/inlineTypes/shared/insertInlineRun.js","../src/inlineTypes/select/index.js","../src/inlineTypes/date/DateInlineNode.jsx","../src/inlineTypes/date/index.js","../src/inlineTypes/checkbox/CheckboxInlineNode.jsx","../src/inlineTypes/checkbox/index.js","../src/inlineTypes/tableSelect/TableSelectInlineNode.jsx","../src/inlineTypes/tableSelect/index.js","../src/inlineTypes/emoji/index.js","../src/inlineTypes/index.js","../src/react/useFieldTypes.js","../src/react/useHistory.js","../src/clipboard/mimeType.js","../src/clipboard/domWalk.js","../src/clipboard/deserialize.js","../src/inline/deleteCommands.js","../src/blocks/shared/blockRangeActions.js","../src/react/useClipboardHandlers.js","../src/inline/markCommands.js","../src/react/selectAllCommand.js","../src/blocks/shared/deleteSelectedBlock.js","../src/react/useEditorKeyboardShortcuts.js","../src/clipboard/copyBlockRange.js","../src/react/BlockRangeActionMenu.jsx","../src/react/useBlockRangeDrag.js","../src/react/EditorTrailingSpace.jsx","../src/commands/SlashMenu.jsx","../src/commands/useTriggerMenu.js","../src/commands/useSlashMenuTrigger.js","../src/inlineTypes/emoji/emojiList.js","../src/inlineTypes/shared/insertPlainText.js","../src/inlineTypes/emoji/emojiCommands.js","../src/commands/useEmojiMenuTrigger.js","../src/commands/useAtMenuTrigger.js","../src/commands/FloatingToolbar.jsx","../src/commands/useFloatingToolbarTrigger.js","../src/inlineTypes/customSelect/CustomSelectInlineNode.jsx","../src/inlineTypes/customSelect/createSelectFieldType.jsx","../src/inlineTypes/customSelect/registerStoredFieldTypes.js","../src/inlineTypes/customSelect/useRegisterFieldTypes.js","../src/inlineTypes/customSelect/FieldTypeEditorModal.jsx"],"sourcesContent":["export const OP = {\n INSERT_BLOCK: 'insertBlock',\n REMOVE_BLOCK: 'removeBlock',\n MOVE_BLOCK: 'moveBlock',\n UPDATE_BLOCK_PROPS: 'updateBlockProps',\n UPDATE_RUN: 'updateRun',\n SET_BLOCK_CONTENT_IDS: 'setBlockContentIds',\n REPLACE_RUN_SPAN: 'replaceRunSpan',\n SET_BLOCK_RUNS: 'setBlockRuns',\n ADD_FIELD_TYPE: 'addFieldType',\n UPDATE_FIELD_TYPE: 'updateFieldType',\n REMOVE_FIELD_TYPE: 'removeFieldType',\n};\n\nexport function insertBlock(block, parentId, index, subtree) {\n return { type: OP.INSERT_BLOCK, block, parentId, index, subtree };\n}\n\nexport function removeBlock(id) {\n return { type: OP.REMOVE_BLOCK, id };\n}\n\nexport function moveBlock(id, toParentId, toIndex) {\n return { type: OP.MOVE_BLOCK, id, toParentId, toIndex };\n}\n\nexport function updateBlockProps(id, patch) {\n return { type: OP.UPDATE_BLOCK_PROPS, id, patch };\n}\n\nexport function updateRun(id, patch) {\n return { type: OP.UPDATE_RUN, id, patch };\n}\n\n/** Directly reassigns a block's contentIds array (e.g. merging one block's runs into another). */\nexport function setBlockContentIds(blockId, contentIds) {\n return { type: OP.SET_BLOCK_CONTENT_IDS, blockId, contentIds };\n}\n\n/**\n * Replaces a contiguous span of existing run ids within a leaf block's\n * contentIds with a new set of run objects — e.g. splitting one run into\n * before/formatted-middle/after when toggling a mark on part of its text.\n * `oldRunIds` must be contiguous in the block's current contentIds.\n */\nexport function replaceRunSpan(blockId, oldRunIds, newRuns) {\n return { type: OP.REPLACE_RUN_SPAN, blockId, oldRunIds, newRuns };\n}\n\n/**\n * Wholesale replaces a leaf block's entire run list (and their order) —\n * the \"I don't know exactly what changed structurally, just resync\n * everything\" escape hatch used when reconciling arbitrary DOM mutations\n * (paste-into-contentEditable, IME composition boundaries) back into the\n * store. Prefer per-run `updateRun` when only text values changed — this\n * op is coarser-grained for undo (one step for the whole resync).\n */\nexport function setBlockRuns(blockId, runs) {\n return { type: OP.SET_BLOCK_RUNS, blockId, runs };\n}\n\n/**\n * Persists a user-created custom select field type (see\n * createSelectFieldType / registerStoredFieldTypes) — `fieldType` is\n * `{ id, label, placeholder, variant, options: [{value,label,color?}] }`.\n * Only ever used for STATIC, in-editor-authored types; code-registered\n * (developer-defined, possibly dynamic/DB-backed) field types never go\n * through the store at all.\n */\nexport function addFieldType(fieldType) {\n return { type: OP.ADD_FIELD_TYPE, fieldType };\n}\n\nexport function updateFieldType(id, patch) {\n return { type: OP.UPDATE_FIELD_TYPE, id, patch };\n}\n\nexport function removeFieldType(id) {\n return { type: OP.REMOVE_FIELD_TYPE, id };\n}\n","import {\n OP,\n insertBlock,\n removeBlock,\n moveBlock,\n updateBlockProps,\n updateRun,\n setBlockContentIds,\n replaceRunSpan,\n setBlockRuns,\n addFieldType,\n updateFieldType,\n removeFieldType,\n} from './operations.js';\n\n/** Sentinel subscribe/notify key for \"the fieldTypes collection changed\" — see useFieldTypes. */\nconst FIELD_TYPES_KEY = '$fieldTypes';\n\n/**\n * Flat, normalized document store with per-id pub-sub.\n *\n * Every write replaces only the object(s) whose data actually changed, so\n * `getBlock(id)`/`getRun(id)` return a referentially stable value across any\n * update that doesn't touch that exact id. That stability is what lets\n * `useSyncExternalStore` (in the React bindings) skip re-rendering anything\n * that wasn't part of a given operation.\n *\n * Whether a given child id in `contentIds` refers to another Block or to a\n * Run is never encoded on the store — it's discovered by membership (ids are\n * unique across both maps), which keeps the store decoupled from the block\n * type registry.\n */\nexport class EditorStore {\n constructor(doc) {\n this.blocks = new Map((doc?.blocks ?? []).map((b) => [b.id, b]));\n this.runs = new Map((doc?.runs ?? []).map((r) => [r.id, r]));\n this.rootId = doc?.rootId ?? null;\n this.fieldTypes = new Map((doc?.fieldTypes ?? []).map((f) => [f.id, f]));\n this._fieldTypesSnapshot = null; // invalidated (set to null) on every fieldTypes mutation — see getFieldTypes\n this._listeners = new Map(); // id -> Set<() => void>\n }\n\n getBlock(id) {\n return this.blocks.get(id);\n }\n\n getRun(id) {\n return this.runs.get(id);\n }\n\n /**\n * Persisted, user-created custom select field types (static only) —\n * insertion order. Returns the SAME array reference across calls unless\n * a fieldTypes op ran in between — required for useSyncExternalStore\n * (see useFieldTypes), same reference-stability contract as\n * getBlock/getRun.\n */\n getFieldTypes() {\n if (!this._fieldTypesSnapshot) this._fieldTypesSnapshot = [...this.fieldTypes.values()];\n return this._fieldTypesSnapshot;\n }\n\n getFieldType(id) {\n return this.fieldTypes.get(id);\n }\n\n getRootId() {\n return this.rootId;\n }\n\n subscribe(id, listener) {\n let set = this._listeners.get(id);\n if (!set) {\n set = new Set();\n this._listeners.set(id, set);\n }\n set.add(listener);\n return () => {\n set.delete(listener);\n if (set.size === 0) this._listeners.delete(id);\n };\n }\n\n _notify(touchedIds) {\n for (const id of touchedIds) {\n const set = this._listeners.get(id);\n if (!set) continue;\n // copy before iterating: a listener may unsubscribe during notification\n for (const listener of [...set]) listener();\n }\n }\n\n /** Recursively collects a block (or run) and everything reachable under it. */\n _captureSubtree(rootId) {\n const blocks = [];\n const runs = [];\n const walk = (id) => {\n if (this.runs.has(id)) {\n runs.push(this.runs.get(id));\n return;\n }\n const block = this.blocks.get(id);\n if (!block) return;\n blocks.push(block);\n for (const childId of block.contentIds) walk(childId);\n // A block type (e.g. list_item) may hold its own inline runs in\n // props.titleRunIds alongside nested child blocks in contentIds.\n // Walk that too, generically, so nothing gets orphaned on delete.\n for (const runId of block.props?.titleRunIds ?? []) walk(runId);\n };\n walk(rootId);\n return { blocks, runs };\n }\n\n _deleteSubtree(rootId) {\n const walk = (id) => {\n if (this.runs.has(id)) {\n this.runs.delete(id);\n return;\n }\n const block = this.blocks.get(id);\n if (!block) return;\n for (const childId of block.contentIds) walk(childId);\n for (const runId of block.props?.titleRunIds ?? []) walk(runId);\n this.blocks.delete(id);\n };\n walk(rootId);\n }\n\n /**\n * Applies one operation, mutating only the affected map entries, and\n * returns the inverse operation (computed from state captured *before* the\n * mutation, per-op — never reconstructed afterward).\n */\n applyOperation(op) {\n switch (op.type) {\n case OP.UPDATE_RUN: {\n const run = this.runs.get(op.id);\n const previousPatch = {};\n for (const key of Object.keys(op.patch)) previousPatch[key] = run[key];\n this.runs.set(op.id, { ...run, ...op.patch });\n this._notify([op.id]);\n return updateRun(op.id, previousPatch);\n }\n\n case OP.UPDATE_BLOCK_PROPS: {\n const block = this.blocks.get(op.id);\n const previousPatch = {};\n for (const key of Object.keys(op.patch)) previousPatch[key] = block.props[key];\n this.blocks.set(op.id, { ...block, props: { ...block.props, ...op.patch } });\n this._notify([op.id]);\n return updateBlockProps(op.id, previousPatch);\n }\n\n case OP.INSERT_BLOCK: {\n if (op.subtree) {\n for (const b of op.subtree.blocks) this.blocks.set(b.id, b);\n for (const r of op.subtree.runs) this.runs.set(r.id, r);\n } else {\n this.blocks.set(op.block.id, op.block);\n }\n const parent = this.blocks.get(op.parentId);\n const newContentIds = [...parent.contentIds];\n const index = op.index ?? newContentIds.length;\n newContentIds.splice(index, 0, op.block.id);\n this.blocks.set(op.parentId, { ...parent, contentIds: newContentIds });\n this._notify([op.block.id, op.parentId]);\n return removeBlock(op.block.id);\n }\n\n case OP.REMOVE_BLOCK: {\n const target = this.blocks.get(op.id);\n const parentId = target.parentId;\n const parent = this.blocks.get(parentId);\n const index = parent.contentIds.indexOf(op.id);\n const subtree = this._captureSubtree(op.id);\n this._deleteSubtree(op.id);\n const newContentIds = parent.contentIds.filter((cid) => cid !== op.id);\n this.blocks.set(parentId, { ...parent, contentIds: newContentIds });\n this._notify([parentId]);\n return { type: OP.INSERT_BLOCK, block: target, parentId, index, subtree };\n }\n\n case OP.MOVE_BLOCK: {\n const target = this.blocks.get(op.id);\n const fromParentId = target.parentId;\n const fromParent = this.blocks.get(fromParentId);\n const fromIndex = fromParent.contentIds.indexOf(op.id);\n\n const trimmedFromContentIds = fromParent.contentIds.filter((cid) => cid !== op.id);\n this.blocks.set(fromParentId, { ...fromParent, contentIds: trimmedFromContentIds });\n\n const toParent =\n op.toParentId === fromParentId\n ? this.blocks.get(fromParentId)\n : this.blocks.get(op.toParentId);\n const newToContentIds = [...toParent.contentIds];\n newToContentIds.splice(op.toIndex ?? newToContentIds.length, 0, op.id);\n this.blocks.set(op.toParentId, { ...toParent, contentIds: newToContentIds });\n\n this.blocks.set(op.id, { ...this.blocks.get(op.id), parentId: op.toParentId });\n\n const touched = new Set([op.id, fromParentId, op.toParentId]);\n this._notify(touched);\n return moveBlock(op.id, fromParentId, fromIndex);\n }\n\n case OP.SET_BLOCK_CONTENT_IDS: {\n const block = this.blocks.get(op.blockId);\n const previousContentIds = block.contentIds;\n this.blocks.set(op.blockId, { ...block, contentIds: op.contentIds });\n this._notify([op.blockId]);\n return setBlockContentIds(op.blockId, previousContentIds);\n }\n\n case OP.REPLACE_RUN_SPAN: {\n const block = this.blocks.get(op.blockId);\n // The run span lives in contentIds for a plain leaf block (paragraph,\n // heading, tableCell), or in props.titleRunIds for a listItem (whose\n // contentIds instead holds nested child list items).\n const inContentIds = block.contentIds.indexOf(op.oldRunIds[0]) !== -1;\n const sourceArray = inContentIds ? block.contentIds : block.props?.titleRunIds ?? [];\n const startIndex = sourceArray.indexOf(op.oldRunIds[0]);\n\n const removedRuns = op.oldRunIds.map((id) => this.runs.get(id));\n for (const id of op.oldRunIds) this.runs.delete(id);\n for (const r of op.newRuns) this.runs.set(r.id, r);\n\n const newArray = [...sourceArray];\n newArray.splice(startIndex, op.oldRunIds.length, ...op.newRuns.map((r) => r.id));\n\n if (inContentIds) {\n this.blocks.set(op.blockId, { ...block, contentIds: newArray });\n } else {\n this.blocks.set(op.blockId, { ...block, props: { ...block.props, titleRunIds: newArray } });\n }\n this._notify([op.blockId, ...op.oldRunIds, ...op.newRuns.map((r) => r.id)]);\n return replaceRunSpan(\n op.blockId,\n op.newRuns.map((r) => r.id),\n removedRuns,\n );\n }\n\n case OP.SET_BLOCK_RUNS: {\n const block = this.blocks.get(op.blockId);\n // Same dual-path convention as REPLACE_RUN_SPAN: a listItem's own\n // runs live in props.titleRunIds (contentIds holds nested child\n // items instead); every other run-bearing leaf uses contentIds.\n const usesTitleRunIds = block.props && 'titleRunIds' in block.props;\n const previousRunIds = usesTitleRunIds ? block.props.titleRunIds : block.contentIds;\n const previousRuns = previousRunIds.map((id) => this.runs.get(id)).filter(Boolean);\n\n for (const id of previousRunIds) this.runs.delete(id);\n for (const r of op.runs) this.runs.set(r.id, r);\n const newRunIds = op.runs.map((r) => r.id);\n\n if (usesTitleRunIds) {\n this.blocks.set(op.blockId, { ...block, props: { ...block.props, titleRunIds: newRunIds } });\n } else {\n this.blocks.set(op.blockId, { ...block, contentIds: newRunIds });\n }\n this._notify([op.blockId, ...previousRunIds, ...newRunIds]);\n return setBlockRuns(op.blockId, previousRuns);\n }\n\n case OP.ADD_FIELD_TYPE: {\n this.fieldTypes.set(op.fieldType.id, op.fieldType);\n this._fieldTypesSnapshot = null;\n this._notify([FIELD_TYPES_KEY]);\n return removeFieldType(op.fieldType.id);\n }\n\n case OP.UPDATE_FIELD_TYPE: {\n const existing = this.fieldTypes.get(op.id);\n const previousPatch = {};\n for (const key of Object.keys(op.patch)) previousPatch[key] = existing[key];\n this.fieldTypes.set(op.id, { ...existing, ...op.patch });\n this._fieldTypesSnapshot = null;\n this._notify([FIELD_TYPES_KEY]);\n return updateFieldType(op.id, previousPatch);\n }\n\n case OP.REMOVE_FIELD_TYPE: {\n const existing = this.fieldTypes.get(op.id);\n this.fieldTypes.delete(op.id);\n this._fieldTypesSnapshot = null;\n this._notify([FIELD_TYPES_KEY]);\n return addFieldType(existing);\n }\n\n default:\n throw new Error(`Unknown operation type: ${op.type}`);\n }\n }\n\n /** Applies a batch as one transaction: all mutations first, one notify pass, one combined inverse list. */\n applyOperations(ops) {\n return ops.map((op) => this.applyOperation(op));\n }\n\n toJSON() {\n return {\n blocks: [...this.blocks.values()],\n runs: [...this.runs.values()],\n rootId: this.rootId,\n fieldTypes: [...this.fieldTypes.values()],\n };\n }\n\n static fromJSON(doc) {\n return new EditorStore(doc);\n }\n}\n","const IDLE_MS = 500;\n\n/**\n * Wraps an EditorStore with operation-based undo/redo and an audit log.\n *\n * Exposes the exact same read/write surface as EditorStore (getBlock,\n * getRun, getRootId, subscribe, applyOperation, toJSON) so any component\n * written against a plain store works unchanged when given a History\n * instance instead — `applyOperation` here just also records the inverse\n * before delegating to the store.\n *\n * Undo/redo replay inverse/forward operations directly (no full-document\n * snapshot). Rapid edits to the same run coalesce into one undo step via a\n * short idle timeout and a word-boundary heuristic; structural operations\n * (insert/remove/move block) never coalesce, each is its own undo step.\n * Every batch carries {actorId, timestamp}, which is also what backs the\n * audit log (`getHistoryLog`) — a bounded undo/redo stack and an unbounded\n * audit log are deliberately kept separate, since undoing/redoing should\n * not erase \"who changed what, when\".\n */\nexport class History {\n constructor(store, { idleMs = IDLE_MS } = {}) {\n this.store = store;\n this.idleMs = idleMs;\n this.undoStack = [];\n this.redoStack = [];\n this.currentBatch = null;\n this.idleTimer = null;\n this.historyLog = [];\n this._listeners = new Set();\n this._undoRedoSnapshot = { canUndo: false, canRedo: false };\n }\n\n /**\n * Cached {canUndo, canRedo} snapshot — only a new object when either value\n * actually changed, so useSyncExternalStore's getSnapshot can call this\n * every render without ever seeing a \"changed\" reference for no reason.\n */\n getUndoRedoSnapshot() {\n const canUndo = this.canUndo();\n const canRedo = this.canRedo();\n if (this._undoRedoSnapshot.canUndo !== canUndo || this._undoRedoSnapshot.canRedo !== canRedo) {\n this._undoRedoSnapshot = { canUndo, canRedo };\n }\n return this._undoRedoSnapshot;\n }\n\n // --- read surface: delegate straight through ---\n getBlock(id) {\n return this.store.getBlock(id);\n }\n\n getRun(id) {\n return this.store.getRun(id);\n }\n\n getRootId() {\n return this.store.getRootId();\n }\n\n getFieldTypes() {\n return this.store.getFieldTypes();\n }\n\n getFieldType(id) {\n return this.store.getFieldType(id);\n }\n\n subscribe(id, listener) {\n return this.store.subscribe(id, listener);\n }\n\n toJSON() {\n return this.store.toJSON();\n }\n\n // --- write surface ---\n applyOperation(op, meta = {}) {\n return this.perform(op, meta);\n }\n\n applyOperations(ops, meta = {}) {\n return ops.map((op) => this.perform(op, meta));\n }\n\n /**\n * Applies several operations as one atomic undo step (e.g. merging a\n * block into its previous sibling is remove-empty-block + reassign-\n * contentIds + delete-shell — three ops that must undo together, not one\n * press per op). Flushes any in-progress typing batch first so the merge\n * doesn't get folded into unrelated coalescing.\n */\n performBatch(ops, meta = {}) {\n const actorId = meta.actorId ?? null;\n const timestamp = meta.timestamp ?? Date.now();\n this._commitCurrentBatch();\n\n const inverses = [];\n for (const op of ops) {\n inverses.unshift(this.store.applyOperation(op));\n this.historyLog.push({ opType: op.type, id: op.id ?? op.blockId ?? op.block?.id, actorId, timestamp });\n }\n\n this.redoStack = [];\n this.undoStack.push({\n ops: [...ops],\n inverses,\n batchKey: null,\n actorId,\n timestamp,\n lastTimestamp: timestamp,\n boundaryHit: true,\n });\n this._notify();\n }\n\n perform(op, meta = {}) {\n const actorId = meta.actorId ?? null;\n const timestamp = meta.timestamp ?? Date.now();\n const inverse = this.store.applyOperation(op);\n this._record(op, inverse, { actorId, timestamp });\n return inverse;\n }\n\n _batchKeyFor(op) {\n // Only same-run text edits coalesce; every structural op is its own step.\n return op.type === 'updateRun' ? `run:${op.id}` : null;\n }\n\n _isWordBoundary(op) {\n if (op.type !== 'updateRun') return false;\n const value = op.patch?.value;\n if (typeof value !== 'string' || value.length === 0) return false;\n return /\\s/.test(value[value.length - 1]);\n }\n\n _record(op, inverse, meta) {\n this.redoStack = [];\n const batchKey = this._batchKeyFor(op);\n const withinIdle = this.currentBatch && meta.timestamp - this.currentBatch.lastTimestamp <= this.idleMs;\n const sameBatch =\n this.currentBatch &&\n batchKey !== null &&\n this.currentBatch.batchKey === batchKey &&\n withinIdle &&\n !this.currentBatch.boundaryHit;\n\n if (sameBatch) {\n this.currentBatch.ops.push(op);\n this.currentBatch.inverses.unshift(inverse); // undo applies most-recent-first\n this.currentBatch.lastTimestamp = meta.timestamp;\n if (this._isWordBoundary(op)) this.currentBatch.boundaryHit = true;\n } else {\n this._commitCurrentBatch();\n this.currentBatch = {\n ops: [op],\n inverses: [inverse],\n batchKey,\n actorId: meta.actorId,\n timestamp: meta.timestamp,\n lastTimestamp: meta.timestamp,\n boundaryHit: this._isWordBoundary(op),\n };\n }\n\n this._resetIdleTimer();\n this.historyLog.push({\n opType: op.type,\n id: op.id ?? op.block?.id,\n actorId: meta.actorId,\n timestamp: meta.timestamp,\n });\n this._notify();\n }\n\n _resetIdleTimer() {\n if (this.idleTimer) clearTimeout(this.idleTimer);\n this.idleTimer = setTimeout(() => {\n this._commitCurrentBatch();\n this._notify();\n }, this.idleMs);\n }\n\n _commitCurrentBatch() {\n if (!this.currentBatch) return;\n this.undoStack.push(this.currentBatch);\n this.currentBatch = null;\n if (this.idleTimer) {\n clearTimeout(this.idleTimer);\n this.idleTimer = null;\n }\n }\n\n /** Force any in-progress coalescing batch to close (e.g. on blur). */\n flush() {\n this._commitCurrentBatch();\n this._notify();\n }\n\n undo() {\n this._commitCurrentBatch();\n const entry = this.undoStack.pop();\n if (!entry) return false;\n for (const inverse of entry.inverses) this.store.applyOperation(inverse);\n this.redoStack.push(entry);\n this._notify();\n return true;\n }\n\n redo() {\n const entry = this.redoStack.pop();\n if (!entry) return false;\n for (const op of entry.ops) this.store.applyOperation(op);\n this.undoStack.push(entry);\n this._notify();\n return true;\n }\n\n canUndo() {\n return this.undoStack.length > 0 || this.currentBatch !== null;\n }\n\n canRedo() {\n return this.redoStack.length > 0;\n }\n\n /** Unbounded (never popped by undo/redo) who/when/what audit trail. */\n getHistoryLog() {\n return [...this.historyLog];\n }\n\n subscribeToHistory(listener) {\n this._listeners.add(listener);\n return () => this._listeners.delete(listener);\n }\n\n _notify() {\n for (const listener of this._listeners) listener();\n }\n}\n","/**\n * Central registry of block types. Every consumer of a block's behavior\n * (the renderer, the slash-command menu, clipboard serialize/deserialize)\n * looks entries up here instead of switching on `block.type` itself — adding\n * a new block type is only ever \"call `register` once\".\n *\n * entry shape:\n * {\n * component, // React component, receives only { id }\n * isLeaf, // true if contentIds points at Runs, false if at child Blocks\n * defaultProps, // props for a freshly-inserted block of this type\n * toHTML(block, ctx), // ctx: { store, registry } -> html string\n * fromHTML(domNode, ctx), // -> constructed { block, runs } | null if this type doesn't claim the node\n * toPlainText(block, ctx), // -> plain text string\n * slashCommand: { label, icon, keywords, run(store, atBlockId) } | undefined,\n * slashCommands: [ { label, icon, keywords, run } ] | undefined // for a type offering more than one variant (e.g. listItem: bulleted/numbered/to-do)\n * }\n */\nexport class BlockRegistry {\n constructor() {\n this._types = new Map();\n }\n\n register(type, entry) {\n this._types.set(type, entry);\n }\n\n get(type) {\n return this._types.get(type);\n }\n\n isLeaf(type) {\n return Boolean(this._types.get(type)?.isLeaf);\n }\n\n listSlashCommands() {\n const commands = [];\n for (const entry of this._types.values()) {\n if (entry.slashCommand) commands.push(entry.slashCommand);\n if (entry.slashCommands) commands.push(...entry.slashCommands);\n }\n return commands;\n }\n\n listHtmlMatchers() {\n return [...this._types.values()].filter((entry) => entry.fromHTML);\n }\n}\n\nexport function createBlockRegistry() {\n return new BlockRegistry();\n}\n","/**\n * Registry of inline run types beyond plain text — e.g. a `select` chip, a\n * `date` chip, mixed directly into a paragraph's running text alongside\n * ordinary text runs. Parallel to BlockRegistry: `RunNode` (the per-run\n * renderer) looks entries up here instead of switching on `run.type`\n * itself, so adding a new inline type is only ever \"call `register` once\".\n *\n * entry shape:\n * {\n * component, // React component, receives only { id } (like BlockRenderer's contract)\n * isAtomic: true, // always true today: every registered inline type renders as a single\n * // contentEditable=false island (see RunNode) — the browser then handles\n * // arrow-key skip-over and single-backspace-delete for it natively.\n * toHTML(run, ctx), // ctx: { store, registry, inlineRegistry } -> html string\n * fromHTML(domNode, ctx), // -> constructed Run | null if this type doesn't claim the node\n * toPlainText(run, ctx), // -> plain text string\n * slashCommand: { label, icon, keywords, run(store, {blockId, runId}) } | undefined,\n * slashCommands: [ { label, icon, keywords, run } ] | undefined // for a type offering several commands\n * // at once (e.g. emoji: one entry per emoji, all sharing an \"emoji\" keyword)\n * // — mirrors BlockRegistry's own singular/plural split.\n * atCommand / atCommands, // same shape as slashCommand/slashCommands, listed under useAtMenuTrigger's\n * // \"@\" trigger instead of (or in addition to) \"/\" — e.g. createSelectFieldType's\n * // `triggers` option decides which of these two lists a given field type joins.\n * // A command object itself doesn't care which character triggered it (`run`\n * // only consumes {blockId, runId, sliceStart, sliceEnd}), so the very same\n * // object can be — and typically is — assigned to both slashCommand and atCommand.\n * }\n *\n * A plain `type: 'text'` run is handled directly by RunNode and never goes\n * through this registry — there's nothing to register for it.\n */\nexport class InlineRegistry {\n constructor() {\n this._types = new Map();\n }\n\n register(type, entry) {\n this._types.set(type, entry);\n }\n\n /** Drops a registered type — e.g. deleting a user-created custom field type. */\n unregister(type) {\n this._types.delete(type);\n }\n\n get(type) {\n return this._types.get(type);\n }\n\n listHtmlMatchers() {\n return [...this._types.values()].filter((entry) => entry.fromHTML);\n }\n\n listSlashCommands() {\n const commands = [];\n for (const entry of this._types.values()) {\n if (entry.slashCommand) commands.push(entry.slashCommand);\n if (entry.slashCommands) commands.push(...entry.slashCommands);\n }\n return commands;\n }\n\n /** Same shape as listSlashCommands, sourced from atCommand/atCommands instead — see useAtMenuTrigger. */\n listAtCommands() {\n const commands = [];\n for (const entry of this._types.values()) {\n if (entry.atCommand) commands.push(entry.atCommand);\n if (entry.atCommands) commands.push(...entry.atCommands);\n }\n return commands;\n }\n}\n\nexport function createInlineRegistry() {\n return new InlineRegistry();\n}\n","import { createContext, useCallback, useContext, useMemo, useRef, useState } from 'react';\n\nconst EditorContext = createContext(null);\n\nexport function EditorProvider({ store, registry, inlineRegistry = null, history = null, children }) {\n // `store` may be a plain EditorStore or a History instance (same read/write\n // surface) — components call useEditorStore() and get whichever was given,\n // undo/redo-aware or not, without caring which.\n //\n // isWholeDocumentSelected is ephemeral UI interaction state, not document\n // data — deliberately plain useState here, not part of the store. It's\n // the \"select everything\" flag a second Ctrl+A press sets (see\n // useEditorKeyboardShortcuts + useWholeDocumentSelection): every block\n // lives in its own separate contentEditable region, and browsers don't\n // reliably support a native Selection/Range spanning multiple independent\n // contentEditable islands constructed via script — so cross-block \"select\n // all\" is its own custom selection model instead of a native one, the\n // same way Notion's whole-block selection isn't native browser text\n // selection either. This package ships no default styling, so rendering\n // the corresponding highlight is left to the host app (see this hook's\n // own doc comment).\n const [isWholeDocumentSelected, setIsWholeDocumentSelected] = useState(false);\n\n // A contiguous run of top-level block ids selected by dragging from the\n // gutter margin (see useBlockRangeDrag/BlockGutterRow) — Notion's \"drag\n // in the margin to select several blocks\" gesture. `[]` means nothing is\n // range-selected. Kept in DOCUMENT order (matches root.contentIds), not\n // drag order, so Move up/down and Delete don't need to re-sort it.\n // Ephemeral UI state, same rationale as isWholeDocumentSelected above —\n // this is a *different* selection mechanism from that one (an arbitrary\n // contiguous slice vs. literally everything), so they're independent,\n // non-overlapping bits of state.\n const [selectedBlockRange, setSelectedBlockRange] = useState([]);\n\n // Preview-mode toggle — also ephemeral UI state, not document data (a\n // reload always starts back in edit mode). While true, BlockChildren\n // skips rendering the per-block gutter entirely and omits any block\n // whose own props.hidden is true, instead of rendering it dimmed the way\n // edit mode does (see BlockGutterRow's Hide/Show menu item) — the whole\n // point of \"hidden\" is that it disappears from the preview a reader\n // eventually sees, while staying editable (just visually dimmed) for\n // whoever's still writing it.\n const [isPreviewMode, setIsPreviewMode] = useState(false);\n\n // Ephemeral \"which custom field type is the create/edit modal open for\"\n // state — null (closed), the string 'new' (create flow), or an existing\n // fieldTypes id (edit flow). See useFieldTypeEditor + FieldTypeEditorModal\n // (inlineTypes/customSelect): kept here, not in that module, so this core\n // file never has to import anything from a concrete inline type — the\n // modal itself is host-mounted (same pattern as EditorTrailingSpace),\n // reading this shared open/closed target via the hook below.\n const [fieldTypeEditorTarget, setFieldTypeEditorTarget] = useState(null);\n const openCreateFieldType = useCallback(() => setFieldTypeEditorTarget('new'), []);\n const openEditFieldType = useCallback((id) => setFieldTypeEditorTarget(id), []);\n const closeFieldTypeEditor = useCallback(() => setFieldTypeEditorTarget(null), []);\n\n // A single non-editable/contentless block (image, divider, etc.) that's\n // \"selected\" pending a second Backspace/Delete to actually remove it —\n // matching Notion/TipTap's convention for atomic nodes: the first press\n // adjacent to one just highlights it, the second one deletes it.\n //\n // Deliberately NOT React state: this can be set on every single\n // Backspace/Delete press throughout ordinary typing near a non-editable\n // block, and putting it in the same memoized context value as\n // store/registry/etc. would re-render every block in the whole document\n // on every such press (unlike isWholeDocumentSelected above, which only\n // ever changes on a deliberate, rare \"select everything\" action). A\n // plain ref plus a stable setter that imperatively toggles a DOM class\n // avoids that entirely — the same imperative-DOM-update discipline\n // EditableBlockContent already uses for its own host nodes.\n const selectedBlockIdRef = useRef(null);\n\n const getSelectedBlockId = useCallback(() => selectedBlockIdRef.current, []);\n\n const setSelectedBlockId = useCallback((id) => {\n const prevId = selectedBlockIdRef.current;\n if (prevId === id) return;\n if (prevId) document.querySelector(`[data-block-id=\"${prevId}\"]`)?.classList.remove('be-block-selected');\n selectedBlockIdRef.current = id;\n if (id) document.querySelector(`[data-block-id=\"${id}\"]`)?.classList.add('be-block-selected');\n }, []);\n\n const value = useMemo(\n () => ({\n store,\n registry,\n inlineRegistry,\n history,\n isWholeDocumentSelected,\n setIsWholeDocumentSelected,\n selectedBlockRange,\n setSelectedBlockRange,\n getSelectedBlockId,\n setSelectedBlockId,\n isPreviewMode,\n setIsPreviewMode,\n fieldTypeEditorTarget,\n openCreateFieldType,\n openEditFieldType,\n closeFieldTypeEditor,\n }),\n [\n store,\n registry,\n inlineRegistry,\n history,\n isWholeDocumentSelected,\n selectedBlockRange,\n getSelectedBlockId,\n setSelectedBlockId,\n isPreviewMode,\n fieldTypeEditorTarget,\n openCreateFieldType,\n openEditFieldType,\n closeFieldTypeEditor,\n ],\n );\n return <EditorContext.Provider value={value}>{children}</EditorContext.Provider>;\n}\n\nexport function useEditorContext() {\n const ctx = useContext(EditorContext);\n if (!ctx) {\n throw new Error('Editor hooks must be used within an <EditorProvider>');\n }\n return ctx;\n}\n\nexport function useEditorStore() {\n return useEditorContext().store;\n}\n\nexport function useBlockRegistry() {\n return useEditorContext().registry;\n}\n\nexport function useInlineRegistry() {\n return useEditorContext().inlineRegistry;\n}\n\n/**\n * `[isWholeDocumentSelected, setIsWholeDocumentSelected]` — the custom\n * \"select all\" state (see EditorProvider's doc comment for why this isn't\n * a native Selection). A host app renders the highlight itself, typically\n * by conditionally adding a class to its surface element and styling\n * `.that-class > [data-block-id]` — every top-level block is a direct DOM\n * child of whatever rendered `<BlockChildren parentId={rootId} />`, so a\n * plain CSS child-combinator is enough; no wrapper markup is needed.\n */\nexport function useWholeDocumentSelection() {\n const { isWholeDocumentSelected, setIsWholeDocumentSelected } = useEditorContext();\n return [isWholeDocumentSelected, setIsWholeDocumentSelected];\n}\n\n/**\n * `[selectedBlockRange, setSelectedBlockRange]` — the drag-selected\n * contiguous run of top-level block ids (see EditorProvider's doc comment).\n * `setSelectedBlockRange([])` clears it. A host app renders the highlight\n * itself (see be-block-row-range-selected in the example app's CSS) and\n * mounts `<BlockRangeActionMenu />` once anywhere under the provider to get\n * the Copy/Cut/Delete/Move/Hide action menu that appears once a drag\n * finishes — see useBlockRangeDrag for the drag mechanics themselves.\n */\nexport function useBlockRangeSelection() {\n const { selectedBlockRange, setSelectedBlockRange } = useEditorContext();\n return [selectedBlockRange, setSelectedBlockRange];\n}\n\n/**\n * `{ getSelectedBlockId, setSelectedBlockId }` — the single-block\n * \"selected, pending a second Backspace/Delete to remove it\" state (see\n * EditorProvider's doc comment on selectedBlockIdRef for why this is a\n * ref-backed pair of stable functions rather than React state: reading it\n * inside an event handler via `getSelectedBlockId()` always returns the\n * current value without subscribing to it, so setting it doesn't\n * re-render every block in the document). `setSelectedBlockId` also\n * imperatively toggles the `be-block-selected` CSS class on the relevant\n * block's own `[data-block-id]` element; a host app can restyle that\n * class however it likes (a highlighted border, same as Notion/TipTap).\n */\nexport function useSelectedBlock() {\n const { getSelectedBlockId, setSelectedBlockId } = useEditorContext();\n return { getSelectedBlockId, setSelectedBlockId };\n}\n\n/**\n * `[isPreviewMode, setIsPreviewMode]` — toggles the whole editor between\n * edit mode (every block renders normally, hidden ones dimmed via\n * BlockGutterRow's own styling) and preview mode (BlockChildren renders\n * without the per-block gutter at all, and skips any block whose\n * `props.hidden` is true entirely — see BlockChildren's doc comment). A\n * host app wires its own toggle button/keyboard shortcut to this, same as\n * useWholeDocumentSelection.\n */\nexport function usePreviewMode() {\n const { isPreviewMode, setIsPreviewMode } = useEditorContext();\n return [isPreviewMode, setIsPreviewMode];\n}\n\n/**\n * `{ target, openCreate, openEdit, close }` — shared open/closed state for\n * the custom field type create/edit modal (see\n * inlineTypes/customSelect/FieldTypeEditorModal.jsx). `target` is `null`\n * when closed, `'new'` while creating, or an existing fieldTypes id while\n * editing one. A host app renders `<FieldTypeEditorModal />` once anywhere\n * under the provider (it reads this hook itself) and wires its own \"+ New\n * field type\" button to `openCreate()`; a field type's own chips call\n * `openEdit(id)` from their \"Manage options…\" popover entry (see\n * createSelectFieldType's `onManage`).\n */\nexport function useFieldTypeEditor() {\n const { fieldTypeEditorTarget, openCreateFieldType, openEditFieldType, closeFieldTypeEditor } = useEditorContext();\n return {\n target: fieldTypeEditorTarget,\n openCreate: openCreateFieldType,\n openEdit: openEditFieldType,\n close: closeFieldTypeEditor,\n };\n}\n","import { useCallback, useSyncExternalStore } from 'react';\nimport { useEditorStore } from './EditorProvider.jsx';\n\n/**\n * Subscribes to exactly one block by id. `store.getBlock(id)` is guaranteed\n * by EditorStore's mutation discipline to return the same reference across\n * renders unless that exact block changed, which is what makes this safe\n * with useSyncExternalStore (no infinite-loop / \"getSnapshot should be\n * cached\" warning). Never derive a new object from the snapshot here — do\n * that in the calling component with useMemo instead.\n */\nexport function useBlock(id) {\n const store = useEditorStore();\n const subscribe = useCallback((onStoreChange) => store.subscribe(id, onStoreChange), [store, id]);\n const getSnapshot = useCallback(() => store.getBlock(id), [store, id]);\n return useSyncExternalStore(subscribe, getSnapshot);\n}\n\n/** Same contract as useBlock, for inline Run leaves. */\nexport function useRun(id) {\n const store = useEditorStore();\n const subscribe = useCallback((onStoreChange) => store.subscribe(id, onStoreChange), [store, id]);\n const getSnapshot = useCallback(() => store.getRun(id), [store, id]);\n return useSyncExternalStore(subscribe, getSnapshot);\n}\n","export function genId() {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n return `id-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n}\n","import { genId } from '../utils/idGen.js';\n\n/**\n * A completely empty `<span></span>` (no text node at all) is not a valid\n * caret anchor in many browsers' contentEditable implementation: clicking\n * into it places the caret at the *container* level instead, and typing\n * then inserts a brand-new text node as a *sibling* of the empty span\n * rather than inside it. That stray node is never one React created, so it\n * becomes invisible to React's reconciliation from that point on — every\n * subsequent keystroke reads a DOM that's drifted further from what React\n * thinks it rendered, which is what produced runaway duplicated/shrinking\n * text. The fix (the same one Slate/Lexical use) is to never render a\n * truly empty text node: an empty run gets this zero-width-space\n * placeholder instead, giving the browser a real anchor, and it's stripped\n * back out whenever DOM text is read back into a run's logical value.\n */\nexport const EMPTY_RUN_PLACEHOLDER = '​';\n\nconst ZERO_WIDTH_SPACE_RE = /​/g;\n\n/** Strips the placeholder out of a string, however many times it appears. */\nexport function stripEmptyRunPlaceholder(text) {\n return (text ?? '').replace(ZERO_WIDTH_SPACE_RE, '');\n}\n\nfunction readRunText(node) {\n return stripEmptyRunPlaceholder(node.textContent);\n}\n\n/**\n * Reconciles a contentEditable container's *actual current* child nodes\n * back against the run list it was last rendered with. This is what makes\n * one shared contentEditable region per block work: React renders each run\n * as a child (a plain `<span data-run-id>` for text, an atomic\n * `contentEditable={false}` island for a non-text inline type), the browser\n * mutates that DOM natively as the user types/deletes/pastes, and this\n * function reads the result back into run objects on the container's\n * `input` event.\n *\n * Fast path (`onlyValueChanges: true`): every child still has the same\n * data-run-id, in the same order, and only text values differ — the\n * common case for ordinary typing, since the browser's native text edit\n * stays inside the existing span whose data-run-id attribute survives\n * untouched. Callers should apply per-run `updateRun` ops in this case, to\n * preserve History's per-run undo coalescing.\n *\n * Slow path (`onlyValueChanges: false`): node(s) appeared/disappeared/\n * reordered — e.g. paste, IME composition boundaries, or an atomic inline\n * chip being deleted as a whole unit. Callers should apply one\n * `setBlockRuns` op (see operations.js) as a single coarser undo step.\n *\n * Atomic (non-text) runs are matched by id only and never have their value\n * re-derived from DOM text content — they render their own UI, not plain\n * text, so `textContent` isn't a meaningful \"value\" for them.\n */\nexport function reconcileDomToRuns(containerEl, currentRuns) {\n const byId = new Map(currentRuns.map((run) => [run.id, run]));\n const seen = new Set();\n const nextRuns = [];\n let sameIdentityAndOrder = true;\n\n for (const node of containerEl.childNodes) {\n const runId = node.nodeType === 1 ? node.dataset?.runId : undefined;\n\n if (runId && byId.has(runId)) {\n seen.add(runId);\n const existing = byId.get(runId);\n\n if (existing.type !== 'text') {\n nextRuns.push(existing); // atomic: identity-only, never re-derive from DOM\n continue;\n }\n\n const newValue = readRunText(node);\n nextRuns.push(newValue === existing.value ? existing : { ...existing, value: newValue });\n continue;\n }\n\n // No existing run matches this DOM node at all: a structural change\n // (new text node from typing at a boundary, paste, IME, etc.).\n sameIdentityAndOrder = false;\n const text = readRunText(node);\n if (text) nextRuns.push({ id: genId(), type: 'text', value: text, marks: {} });\n }\n\n if (currentRuns.some((run) => !seen.has(run.id))) sameIdentityAndOrder = false; // a run's node vanished\n if (nextRuns.length !== currentRuns.length) sameIdentityAndOrder = false;\n if (sameIdentityAndOrder) {\n for (let i = 0; i < nextRuns.length; i += 1) {\n if (nextRuns[i].id !== currentRuns[i].id) {\n sameIdentityAndOrder = false;\n break;\n }\n }\n }\n\n const changed = !sameIdentityAndOrder || nextRuns.some((run, i) => run !== currentRuns[i]);\n\n return { runs: nextRuns, changed, onlyValueChanges: sameIdentityAndOrder };\n}\n","/**\n * True when `run` contributes no real content: absent, or a text run whose\n * value is ''. An atomic (non-text) run — a date/select/checkbox/custom-field\n * chip — is never blank even without a \"value\", since there's a real chip\n * sitting there for the user to see/interact with.\n */\nexport function isRunBlank(run) {\n if (!run) return true;\n if (run.type !== 'text') return false;\n return (run.value ?? '') === '';\n}\n\n/**\n * True when every run in `runIds` is blank — used to decide whether to show\n * a placeholder hint (e.g. \"Type '/' for commands\") for a block that has\n * nothing in it yet. Same semantics as isCurrentBlockEmpty in\n * react/selectAllCommand.js (which needs a live caret to find the block\n * first); this version just takes run ids directly, since callers here\n * already have the block in hand from useBlock.\n */\nexport function isRunsEmpty(store, runIds) {\n if (!runIds || runIds.length === 0) return true;\n return runIds.every((id) => isRunBlank(store.getRun(id)));\n}\n","/** True for a block with nothing to merge/focus into (e.g. a divider): no run-bearing contentIds and no titleRunIds. */\nexport function isContentlessBlock(store, block) {\n if (!block) return false;\n const hasRuns = block.contentIds.length > 0;\n const hasTitleRuns = (block.props?.titleRunIds?.length ?? 0) > 0;\n return !hasRuns && !hasTitleRuns;\n}\n","function focusRunAt(runId, atStart) {\n requestAnimationFrame(() => {\n const el = document.querySelector(`[data-run-id=\"${runId}\"]`);\n if (!el) return;\n el.focus();\n const range = document.createRange();\n range.selectNodeContents(el);\n range.collapse(atStart);\n const selection = window.getSelection();\n selection?.removeAllRanges();\n selection?.addRange(range);\n });\n}\n\n/** Best-effort: move DOM focus + caret to the end of the given run's editable element. */\nexport function focusRunEnd(runId) {\n focusRunAt(runId, false);\n}\n\n/** Best-effort: move DOM focus + caret to the start of the given run's editable element. */\nexport function focusRunStart(runId) {\n focusRunAt(runId, true);\n}\n\n/** Best-effort: move DOM focus + caret to a specific character offset within the given (text) run. */\nexport function focusRunAtOffset(runId, offset) {\n requestAnimationFrame(() => {\n const el = document.querySelector(`[data-run-id=\"${runId}\"]`);\n if (!el) return;\n el.focus();\n const textNode = el.firstChild;\n const range = document.createRange();\n if (textNode && textNode.nodeType === 3) {\n const clamped = Math.max(0, Math.min(offset, textNode.length));\n range.setStart(textNode, clamped);\n range.setEnd(textNode, clamped);\n } else {\n range.selectNodeContents(el);\n range.collapse(offset <= 0);\n }\n const selection = window.getSelection();\n selection?.removeAllRanges();\n selection?.addRange(range);\n });\n}\n","import { useCallback, useEffect, useLayoutEffect, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useEditorStore, useInlineRegistry, useSelectedBlock } from './EditorProvider.jsx';\nimport { useRun } from './useBlock.js';\nimport { updateRun, setBlockRuns, removeBlock } from '../store/operations.js';\nimport { reconcileDomToRuns, EMPTY_RUN_PLACEHOLDER, stripEmptyRunPlaceholder } from './domRunSync.js';\nimport { isRunBlank, isRunsEmpty } from '../blocks/shared/blockEmpty.js';\nimport { isContentlessBlock } from '../blocks/shared/contentless.js';\nimport { genId } from '../utils/idGen.js';\nimport { focusRunEnd, focusRunStart } from './focusRun.js';\n\n/**\n * Keeps the block wrapper's data-empty attribute (see the be-*[data-empty]\n * placeholder CSS) in sync on every keystroke — not just on structural\n * changes. Ordinary typing goes through the \"onlyValueChanges\" fast path in\n * handleInput below, which applies a plain updateRun op that only notifies\n * that *run's* own subscribers (see EditorStore's UPDATE_RUN case) — the\n * block itself never re-renders, by design, so it can't recompute this\n * itself from a React render the way its *initial* data-empty value is set.\n * Written directly onto containerRef.current.parentElement — always the block's\n * own wrapper element (the div/h-tag every ParagraphBlock/HeadingBlock/\n * ListItemBlock renders EditableBlockContent directly inside of) — gated on\n * data-placeholder so this is a no-op for block types (table cells) that\n * don't opt into the placeholder hint at all.\n */\nfunction syncEmptyAttr(container, runs) {\n const wrapper = container?.parentElement;\n if (!wrapper || !wrapper.hasAttribute('data-placeholder')) return;\n const isEmpty = runs.length === 0 || runs.every(isRunBlank);\n if (isEmpty) wrapper.setAttribute('data-empty', '');\n else wrapper.removeAttribute('data-empty');\n}\n\nfunction marksToStyle(marks = {}) {\n return {\n fontWeight: marks.bold ? 'bold' : undefined,\n fontStyle: marks.italic ? 'italic' : undefined,\n textDecoration: [marks.underline && 'underline', marks.strike && 'line-through'].filter(Boolean).join(' ') || undefined,\n verticalAlign: marks.subscript ? 'sub' : marks.superscript ? 'super' : undefined,\n fontSize: marks.subscript || marks.superscript ? 'smaller' : undefined,\n color: marks.color || undefined,\n backgroundColor: marks.highlight || undefined,\n };\n}\n\n/**\n * Syncs one text run's value/marks onto a `host` DOM element that\n * `EditableBlockContent` created and owns imperatively (see hostsRef/\n * getOrCreateHost below) — this component renders no DOM of its own\n * (`return null`); it only ever writes into `host` via a layout effect,\n * the same \"only touch the DOM if it actually differs\" discipline the old\n * EditableRun used.\n *\n * Subscribes to its own run via useRun (not a prop pre-resolved by the\n * parent) so an *external* value change — undo/redo, a future\n * collaborator's edit — still triggers a re-render and gets synced to the\n * DOM. Local typing bypasses this entirely: the browser mutates the text\n * node directly, `EditableBlockContent`'s input handler writes the same\n * value back into the store, and this sync then sees the DOM (once the\n * placeholder is stripped) already matches and does nothing.\n *\n * Critical: the comparison below is against the *stripped* DOM text, not\n * the raw text. `host.textContent = ...` always destroys and recreates the\n * underlying Text node, which resets/collapses the browser's active\n * Selection — comparing raw text (including the placeholder) meant every\n * empty-to-non-empty transition triggered a \"cleanup\" write that looked\n * harmless but silently reset the caret to the start of the run right\n * after the very first keystroke. Comparing stripped text means ordinary\n * typing — where the DOM already holds the right characters plus a leftover\n * placeholder byte — is a true no-op, so the caret is never touched.\n */\nfunction TextRunSpan({ id, host, onValueSynced }) {\n const run = useRun(id);\n\n useLayoutEffect(() => {\n if (!host || !run) return;\n const value = run.value ?? '';\n const currentLogicalText = stripEmptyRunPlaceholder(host.textContent);\n const needsRewrite = currentLogicalText !== value || (value === '' && host.textContent === '');\n if (needsRewrite) {\n host.textContent = value === '' ? EMPTY_RUN_PLACEHOLDER : value;\n }\n\n const style = marksToStyle(run.marks);\n host.style.fontWeight = style.fontWeight ?? '';\n host.style.fontStyle = style.fontStyle ?? '';\n host.style.textDecoration = style.textDecoration ?? '';\n host.style.verticalAlign = style.verticalAlign ?? '';\n host.style.fontSize = style.fontSize ?? '';\n host.style.color = style.color ?? '';\n host.style.backgroundColor = style.backgroundColor ?? '';\n\n // Covers value changes this component didn't cause itself — undo/redo,\n // a future collaborator's edit — which only notify this *run's* own\n // subscribers (see EditorStore's UPDATE_RUN case), never the block's.\n // Ordinary typing is already covered by handleInput's own call to\n // syncEmptyAttr; this makes every other path to a run's value changing\n // keep the placeholder hint in sync too.\n onValueSynced?.();\n }, [host, run, onValueSynced]);\n\n return null;\n}\n\n/**\n * When the collapsed caret sits right at the boundary between a text run\n * and an atomic (contentEditable={false}) inline chip, native Backspace/\n * Delete would have the *browser* rip that chip's DOM node out on its own —\n * before React ever finds out. React's fiber tree still expects that node\n * to be there, so the next commit's `removeChild` throws\n * (\"NotFoundError: ... not a child of this node\"). The fix is to never let\n * the browser touch an atomic node's DOM directly: detect the adjacency\n * here, `preventDefault`, and delete the run purely through the store so\n * React's own reconciliation is the only thing that ever removes that DOM\n * node.\n *\n * Deliberately does NOT use `previousElementSibling`/`nextElementSibling` to\n * decide whether the neighbor is atomic — holding Backspace/Delete down\n * fires keydowns faster than React necessarily commits the previous\n * removal's DOM update, so a chip that's already gone from the *logical*\n * run list can still be physically sitting in the DOM for one more event.\n * Trusting that lingering DOM node re-triggered a second delete of an\n * already-deleted run and reproduced the same crash intermittently. `runIds`\n * (the block's current prop, always in sync with the store) and `getRun`\n * are the source of truth for \"what's adjacent and is it atomic\"; the DOM\n * is only used to find which run the caret currently sits in.\n */\nfunction findAdjacentAtomicRunId(containerEl, runIds, getRun, backward) {\n const selection = window.getSelection?.();\n if (!selection || !selection.isCollapsed || selection.rangeCount === 0) return null;\n const { anchorNode, anchorOffset } = selection;\n if (!anchorNode || !containerEl.contains(anchorNode)) return null;\n\n const neighborAtomicId = (caretRunId) => {\n const idx = runIds.indexOf(caretRunId);\n if (idx === -1) return null; // caret's run already isn't in the current logical model\n const neighborId = backward ? runIds[idx - 1] : runIds[idx + 1];\n if (!neighborId) return null;\n const neighborRun = getRun(neighborId);\n return neighborRun && neighborRun.type !== 'text' ? neighborId : null;\n };\n\n // Some browsers select an atomic island as a whole unit, anchoring the\n // caret on the container itself with a child-index offset rather than\n // inside an adjacent text node.\n if (anchorNode === containerEl) {\n const idx = backward ? anchorOffset - 1 : anchorOffset;\n const child = containerEl.childNodes[idx];\n const runId = child?.nodeType === 1 ? child.dataset?.runId : undefined;\n if (!runId || runIds.indexOf(runId) === -1) return null;\n const run = getRun(runId);\n return run && run.type !== 'text' ? runId : null;\n }\n\n const el = anchorNode.nodeType === 1 ? anchorNode : anchorNode.parentElement;\n const runEl = el?.closest?.('[data-run-id]');\n if (!runEl || !containerEl.contains(runEl)) return null;\n\n const atBoundary = backward ? anchorOffset === 0 : anchorOffset === (anchorNode.textContent ?? '').length;\n if (!atBoundary) return null;\n\n return neighborAtomicId(runEl.getAttribute('data-run-id'));\n}\n\n/**\n * Real browsers frequently turn arrow-key navigation past an atomic\n * `contentEditable={false}` island into a *non-collapsed* \"select this one\n * node as a unit\" selection (the same way an `<img>` gets selected as a\n * whole), rather than leaving a collapsed caret beside it — this is common\n * on ArrowLeft/ArrowRight approach and on click. `findAdjacentAtomicRunId`\n * only handles the collapsed-caret case; without this check, Backspace/\n * Delete on a whole-node selection falls through to native deletion and\n * reproduces the exact same removeChild crash it was meant to prevent.\n *\n * Same rapid-repeat-keydown caution as findAdjacentAtomicRunId: confirm the\n * selected node's run id is still in `runIds` before trusting it.\n */\nfunction findWhollySelectedAtomicRunId(containerEl, runIds, getRun) {\n const selection = window.getSelection?.();\n if (!selection || selection.isCollapsed || selection.rangeCount === 0) return null;\n const range = selection.getRangeAt(0);\n if (range.startContainer !== range.endContainer) return null;\n if (!containerEl.contains(range.startContainer)) return null;\n if (range.endOffset !== range.startOffset + 1) return null;\n\n const child = range.startContainer.childNodes[range.startOffset];\n const runId = child?.nodeType === 1 ? child.dataset?.runId : undefined;\n if (!runId || runIds.indexOf(runId) === -1) return null;\n const run = getRun(runId);\n return run && run.type !== 'text' ? runId : null;\n}\n\n/**\n * Resolves a Range/StaticRange boundary point to \"which child of\n * containerEl does it fall in, and at what character offset\" — the common\n * currency computeRunsAfterRangeDeletion needs for both boundaries,\n * regardless of whether the point addresses a run's text node directly or\n * the container itself (the same child-index addressing style seen in\n * findAdjacentAtomicRunId/findWhollySelectedAtomicRunId for whole-node\n * selections). Returns null if the point isn't inside any known run.\n */\nfunction resolveRangeBoundary(containerEl, node, offset) {\n if (node === containerEl) return { childIndex: offset, charOffset: null };\n const el = node.nodeType === 1 ? node : node.parentElement;\n const runEl = el?.closest?.('[data-run-id]');\n if (!runEl || !containerEl.contains(runEl)) return null;\n const childIndex = Array.prototype.indexOf.call(containerEl.childNodes, runEl);\n const charOffset = node === runEl ? (offset === 0 ? 0 : (runEl.textContent ?? '').length) : offset;\n return { childIndex, charOffset };\n}\n\n/**\n * Typing a replacement character (or composing, or a word/line/cut\n * deletion) over a selection that spans or fully covers an atomic chip\n * goes through `beforeinput`, not a Backspace/Delete keydown — so it's a\n * completely different native-DOM-mutation path than the one\n * findAdjacentAtomicRunId/findWhollySelectedAtomicRunId guard, and hits the\n * exact same removeChild crash if left to native handling. This computes\n * the resulting run list ourselves for any range that touches at least one\n * atomic run, so the caller can preventDefault and apply it through the\n * store instead. Returns null when the range doesn't touch any atomic run\n * at all, so ordinary text edits are completely unaffected — no change in\n * behavior, no new failure mode, for the common case.\n */\nfunction computeRunsAfterRangeDeletion(containerEl, runIds, getRun, range) {\n const start = resolveRangeBoundary(containerEl, range.startContainer, range.startOffset);\n const end = resolveRangeBoundary(containerEl, range.endContainer, range.endOffset);\n if (!start || !end) return null;\n\n const children = Array.from(containerEl.childNodes).filter(\n (n) => n.nodeType === 1 && n.dataset?.runId && runIds.indexOf(n.dataset.runId) !== -1,\n );\n\n let touchesAtomic = false;\n const nextRuns = [];\n let insertionIndex = null;\n\n children.forEach((child, i) => {\n const runId = child.dataset.runId;\n const run = getRun(runId);\n if (!run) return;\n\n const beforeStart = i < start.childIndex;\n const afterEnd = end.charOffset === null ? i >= end.childIndex : i > end.childIndex;\n\n if (beforeStart || afterEnd) {\n nextRuns.push(run);\n return;\n }\n\n const isStartChild = start.charOffset !== null && i === start.childIndex;\n const isEndChild = end.charOffset !== null && i === end.childIndex;\n\n if (run.type !== 'text') {\n touchesAtomic = true;\n if (insertionIndex === null) insertionIndex = nextRuns.length;\n return; // atomic run fully consumed by the range: dropped\n }\n\n const value = run.value ?? '';\n if (isStartChild && isEndChild) {\n const survivor = value.slice(0, start.charOffset) + value.slice(end.charOffset);\n if (survivor) nextRuns.push({ ...run, value: survivor });\n insertionIndex = nextRuns.length;\n } else if (isStartChild) {\n const prefix = value.slice(0, start.charOffset);\n if (prefix) nextRuns.push({ ...run, value: prefix });\n if (insertionIndex === null) insertionIndex = nextRuns.length;\n } else if (isEndChild) {\n const suffix = value.slice(end.charOffset);\n if (suffix) nextRuns.push({ id: genId(), type: 'text', value: suffix, marks: run.marks });\n }\n // else: fully inside the range, dropped entirely\n });\n\n if (!touchesAtomic) return null;\n return { nextRuns, insertionIndex: insertionIndex ?? nextRuns.length };\n}\n\n/** Caret is collapsed and sits at the very first text position of the container's first child. */\nfunction isCaretAtContainerStart(containerEl) {\n const selection = window.getSelection?.();\n if (!selection || !selection.isCollapsed) return false;\n const firstChild = containerEl.firstChild;\n if (!firstChild) return true;\n\n if (selection.anchorNode === containerEl) return selection.anchorOffset === 0;\n\n let probe = firstChild;\n while (probe && probe.firstChild) probe = probe.firstChild;\n if (selection.anchorNode !== probe && selection.anchorNode !== firstChild) return false;\n\n // A first run that's still just the placeholder has no real content yet,\n // so any caret position within it (offset 0 or 1) counts as \"at start\".\n const maxStartOffset = probe.nodeType === 3 && probe.textContent === EMPTY_RUN_PLACEHOLDER ? 1 : 0;\n return selection.anchorOffset <= maxStartOffset;\n}\n\n/** Symmetric to isCaretAtContainerStart: caret is collapsed at the very last text position of the container's last child. */\nfunction isCaretAtContainerEnd(containerEl) {\n const selection = window.getSelection?.();\n if (!selection || !selection.isCollapsed) return false;\n const lastChild = containerEl.lastChild;\n if (!lastChild) return true;\n\n if (selection.anchorNode === containerEl) return selection.anchorOffset >= containerEl.childNodes.length;\n\n let probe = lastChild;\n while (probe && probe.lastChild) probe = probe.lastChild;\n if (selection.anchorNode !== probe && selection.anchorNode !== lastChild) return false;\n\n const textLength = probe.nodeType === 3 ? (probe.textContent ?? '').length : 0;\n return selection.anchorOffset >= textLength;\n}\n\n/**\n * Resolves the sibling of `blockId` in `direction` ('backward' | 'forward')\n * only if it's a non-editable/contentless block (image/video/audio/file\n * embed, divider, ...) — a real leaf/container with actual content returns\n * null here, since Backspace/Delete into *that* is ordinary merge/no-op\n * territory (handled by onBackspaceAtStart), not this select-then-delete\n * flow.\n */\nfunction findAdjacentContentlessSiblingId(store, blockId, direction) {\n const block = store.getBlock(blockId);\n const parent = store.getBlock(block?.parentId);\n if (!parent) return null;\n const index = parent.contentIds.indexOf(blockId);\n const adjacentIndex = direction === 'backward' ? index - 1 : index + 1;\n if (adjacentIndex < 0 || adjacentIndex >= parent.contentIds.length) return null;\n const adjacentId = parent.contentIds[adjacentIndex];\n return isContentlessBlock(store, store.getBlock(adjacentId)) ? adjacentId : null;\n}\n\n/**\n * Dispatches one run's id to the right renderer: TextRunSpan for text, the\n * inline registry's component otherwise. Also passes `blockId` (the\n * containing leaf block — a paragraph, or a table cell) down to atomic\n * components — runs themselves have no parent back-reference in the store,\n * so this is the only place that can hand it to them. Most inline types\n * ignore it (select/date/custom field types are self-contained); it exists for types\n * like a table's select column that need to resolve their own containing\n * cell/row/table to read shared, column-level state.\n */\nfunction RunNode({ id, blockId, host, inlineRegistry, onValueSynced }) {\n const run = useRun(id);\n if (!run) return null;\n if (run.type === 'text') return <TextRunSpan id={id} host={host} onValueSynced={onValueSynced} />;\n\n const entry = inlineRegistry?.get(run.type);\n if (!entry) {\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.warn(`[block-editor] No inline type registered for \"${run.type}\" (run: ${id})`);\n }\n return null;\n }\n const Component = entry.component;\n return <Component id={id} blockId={blockId} />;\n}\n\n/**\n * Creates (once) or reuses the persistent DOM element that hosts one run's\n * content — `data-run-id`, and for atomic (non-text) runs `contentEditable=\n * \"false\"`, live on this element, not on anything React renders into it.\n * The host is looked up directly from the store (not the `useRun` hook)\n * because this only needs to run once per id, at creation time — a run's\n * type never changes after creation (a semantic change always creates a\n * new run with a new id elsewhere in this codebase), so there's nothing to\n * keep reactive here.\n */\nfunction getOrCreateHost(hostsMap, store, id) {\n let host = hostsMap.get(id);\n if (!host) {\n host = document.createElement('span');\n host.dataset.runId = id;\n const run = store.getRun(id);\n if (run && run.type !== 'text') host.setAttribute('contenteditable', 'false');\n hostsMap.set(id, host);\n }\n return host;\n}\n\n/**\n * Renders every run of a leaf block (paragraph/heading/tableCell's own\n * contentIds, or a listItem's props.titleRunIds) inside ONE shared\n * contentEditable region — replacing the old one-contentEditable-per-run\n * model. This is what lets the browser's native selection/typing/cursor\n * movement work across formatting boundaries and atomic inline elements\n * (a select/date chip), instead of each run being its own disconnected\n * editable island.\n *\n * Every run — text or atomic — gets a persistent \"host\" DOM element that\n * *this component creates, positions, and removes imperatively* (see\n * hostsRef/getOrCreateHost and the layout effect below); React only ever\n * renders each run's *content* into its host via `createPortal`. React's\n * own fiber tree therefore never owns the operation of inserting or\n * removing a run's DOM node relative to its siblings — that's the same\n * technique Lexical uses for its \"decorator\" nodes. It's what closes the\n * \"NotFoundError: removeChild ... not a child of this node\" crash for\n * good: that error was always React's commit phase trying to remove a\n * host node the *browser* had already ripped out natively (via Backspace/\n * Delete, typing over a selection, word-delete, autocorrect, IME, drag —\n * there is no finite list of native paths that can do this). Since React\n * no longer has a fiber responsible for that removal at all, no native\n * mutation of a run's DOM node can ever race against — or be duplicated\n * by — a React-driven one.\n *\n * `runIds` must come from the caller's own `useBlock` subscription\n * (block.contentIds for paragraph/heading/tableCell, or\n * block.props.titleRunIds for a listItem) — that's what keeps this\n * component reactive to *structural* changes (e.g. a mark-toggle split),\n * while each individual run's *value* reactivity is owned by RunNode/\n * TextRunSpan subscribing to that one run id themselves.\n */\nexport function EditableBlockContent({\n blockId,\n runIds,\n onEnter,\n onBackspaceAtStart,\n onDeleteAtEnd,\n onArrowUp,\n onArrowDown,\n onTab,\n onShiftTab,\n onAutoformat,\n}) {\n const store = useEditorStore();\n const inlineRegistry = useInlineRegistry();\n const { getSelectedBlockId, setSelectedBlockId } = useSelectedBlock();\n const containerRef = useRef(null);\n // IME composition (CJK/Korean/etc.) produces a sequence of transient,\n // uncommitted `input` events while the user is still choosing characters.\n // Reconciling — and possibly rewriting DOM text — mid-composition would\n // fight the browser/OS IME UI and can cut a composition session short.\n // Defer reconciliation until compositionend commits the final text.\n const isComposingRef = useRef(false);\n const hostsRef = useRef(new Map()); // runId -> persistent host DOM element (see getOrCreateHost)\n\n // Keeps containerRef's *actual* DOM children (the hosts) in the same\n // membership/order as runIds — the only place any run's DOM node is ever\n // inserted or removed. Runs on every runIds change (structural edits:\n // insert/remove/reorder/split); ordinary text edits don't change runIds\n // at all, so this doesn't run on every keystroke.\n useLayoutEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const liveIds = new Set(runIds);\n for (const [id, host] of hostsRef.current) {\n if (!liveIds.has(id)) {\n host.remove();\n hostsRef.current.delete(id);\n }\n }\n\n let previous = null;\n for (const id of runIds) {\n const host = hostsRef.current.get(id);\n if (!host) continue; // created synchronously during render, in the map already\n const expectedNext = previous ? previous.nextSibling : container.firstChild;\n if (expectedNext !== host) container.insertBefore(host, expectedNext);\n previous = host;\n }\n }, [runIds]);\n\n const handleInput = useCallback(() => {\n if (isComposingRef.current) return;\n const container = containerRef.current;\n if (!container) return;\n const currentRuns = runIds.map((id) => store.getRun(id)).filter(Boolean);\n const { runs: nextRuns, changed, onlyValueChanges } = reconcileDomToRuns(container, currentRuns);\n if (!changed) return;\n\n if (onlyValueChanges) {\n nextRuns.forEach((run, i) => {\n if (run !== currentRuns[i]) store.applyOperation(updateRun(run.id, { value: run.value }));\n });\n // A markdown shortcut (e.g. \"1. \" -> ordered list) always types into a\n // single existing run, never a structural DOM change, so it only ever\n // applies on this branch. On a match, blockId's block was just\n // replaced by a different type — the container/wrapper this callback\n // is running inside of is about to unmount, so there's nothing left\n // here to sync.\n if (onAutoformat?.(nextRuns)) return;\n } else {\n // Same \"never zero runs\" guard as removeRun — belt-and-suspenders,\n // since reconcileDomToRuns normally never drops a matched run.\n store.applyOperation(\n setBlockRuns(blockId, nextRuns.length ? nextRuns : [{ id: genId(), type: 'text', value: '', marks: {} }]),\n );\n }\n syncEmptyAttr(container, nextRuns);\n }, [store, blockId, runIds, onAutoformat]);\n\n const syncEmptyFromStore = useCallback(() => {\n syncEmptyAttr(\n containerRef.current,\n runIds.map((id) => store.getRun(id)).filter(Boolean),\n );\n }, [store, runIds]);\n\n const handleCompositionStart = useCallback(() => {\n isComposingRef.current = true;\n }, []);\n\n const handleCompositionEnd = useCallback(() => {\n isComposingRef.current = false;\n handleInput(); // reconcile now that the composed text has been committed\n }, [handleInput]);\n\n const removeRun = useCallback(\n (runId) => {\n const currentRuns = runIds.map((id) => store.getRun(id)).filter(Boolean);\n const nextRuns = currentRuns.filter((run) => run.id !== runId);\n // Never leave the block with zero runs: an empty contentEditable\n // region (no children at all) isn't a valid caret anchor in most\n // browsers, so the very next keystroke lands on the *container*\n // instead of any run, producing a stray untracked text node that\n // reconcileDomToRuns can't ever match back to an existing run —\n // every keystroke after that mints a brand new run+host instead of\n // updating one in place (the \"characters double\" bug).\n store.applyOperation(\n setBlockRuns(blockId, nextRuns.length ? nextRuns : [{ id: genId(), type: 'text', value: '', marks: {} }]),\n );\n },\n [store, blockId, runIds],\n );\n\n /**\n * Notion/TipTap's convention for a non-editable neighbor (image/video/\n * audio/file embed, divider): the first Backspace/Delete that reaches it\n * only selects/highlights it (see the be-block-selected class toggled by\n * setSelectedBlockId); a second press while it's already selected is\n * what actually removes it. Neither press ever touches or refocuses\n * *this* block — the caret never moves, since only the neighbor is\n * selected or removed, not anything in the block the user is actually\n * typing in.\n */\n const selectOrDeleteContentlessNeighbor = useCallback(\n (neighborId) => {\n if (getSelectedBlockId() === neighborId) {\n store.applyOperation(removeBlock(neighborId));\n setSelectedBlockId(null);\n } else {\n setSelectedBlockId(neighborId);\n }\n },\n [store, getSelectedBlockId, setSelectedBlockId],\n );\n\n /**\n * Catches every native content-editable mutation that can rip an atomic\n * run's DOM node out directly — not just Backspace/Delete, but typing a\n * replacement character over a selection that spans a chip, Ctrl/Cmd+\n * Backspace word/line delete, and cut — all of which fire `beforeinput`\n * with the exact range about to be affected (`getTargetRanges()`, falling\n * back to the live selection where unsupported). When that range touches\n * an atomic run, this computes the resulting content itself and applies\n * it through the store, so the browser never gets to mutate that node.\n * Ordinary text-only edits are untouched: computeRunsAfterRangeDeletion\n * returns null for them and this handler is a no-op, leaving the existing\n * fast-path onInput reconciliation to handle typing exactly as before.\n */\n const handleBeforeInput = useCallback(\n (event) => {\n if (isComposingRef.current) return;\n const inputType = event.inputType ?? '';\n const isDelete = inputType.startsWith('delete');\n const isReplaceTyped = inputType === 'insertText' || inputType === 'insertReplacementText';\n if (!isDelete && !isReplaceTyped) return;\n\n const container = containerRef.current;\n if (!container) return;\n\n const targetRanges = event.getTargetRanges?.();\n const selection = window.getSelection?.();\n const range = targetRanges?.[0] ?? (selection?.rangeCount ? selection.getRangeAt(0) : null);\n if (!range) return;\n if (!container.contains(range.startContainer) || !container.contains(range.endContainer)) return;\n\n const result = computeRunsAfterRangeDeletion(container, runIds, (id) => store.getRun(id), range);\n if (!result) return; // no atomic run in range: let native/existing handling proceed unchanged\n\n event.preventDefault();\n let { nextRuns, insertionIndex } = result;\n\n let focusRunId = null;\n let focusAtStart = false;\n\n if (isReplaceTyped && event.data) {\n const typedRun = { id: genId(), type: 'text', value: event.data, marks: {} };\n nextRuns = [...nextRuns.slice(0, insertionIndex), typedRun, ...nextRuns.slice(insertionIndex)];\n focusRunId = typedRun.id;\n focusAtStart = false;\n } else if (insertionIndex > 0) {\n focusRunId = nextRuns[insertionIndex - 1]?.id;\n focusAtStart = false;\n } else if (nextRuns.length > 0) {\n focusRunId = nextRuns[0].id;\n focusAtStart = true;\n }\n\n const finalRuns = nextRuns.length ? nextRuns : [{ id: genId(), type: 'text', value: '', marks: {} }];\n store.applyOperation(setBlockRuns(blockId, finalRuns));\n\n const landingRunId = focusRunId ?? finalRuns[0].id;\n if (focusAtStart) focusRunStart(landingRunId);\n else focusRunEnd(landingRunId);\n },\n [store, blockId, runIds],\n );\n\n // React's `onBeforeInput` JSX prop does NOT correspond to the native\n // `beforeinput` event — it's a legacy pre-InputEvent-spec polyfill\n // synthesized from keypress/textInput/composition events, so it never\n // fires for Backspace/Delete/word-delete and carries no `inputType` or\n // `getTargetRanges()`. Attaching a real native listener directly (same\n // pattern useEditorKeyboardShortcuts uses for its own native handling)\n // is the only way to actually observe and cancel these before the\n // browser mutates an atomic run's DOM node itself.\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return undefined;\n container.addEventListener('beforeinput', handleBeforeInput);\n return () => container.removeEventListener('beforeinput', handleBeforeInput);\n }, [handleBeforeInput]);\n\n const handleKeyDown = useCallback(\n (event) => {\n // While composing, Enter/Backspace/arrows are the IME's own candidate-\n // selection UI (confirming a suggestion, moving between candidates) —\n // must not also trigger this block's own Enter/merge/navigation.\n if (isComposingRef.current) return;\n\n if (event.key === 'Enter' && onEnter) {\n event.preventDefault();\n onEnter(event);\n return;\n }\n if (event.key === 'Backspace') {\n const container = containerRef.current;\n const wholeId = container && findWhollySelectedAtomicRunId(container, runIds, store.getRun.bind(store));\n if (wholeId) {\n event.preventDefault();\n removeRun(wholeId);\n return;\n }\n const atomicId = container && findAdjacentAtomicRunId(container, runIds, store.getRun.bind(store), true);\n if (atomicId) {\n event.preventDefault();\n removeRun(atomicId);\n return;\n }\n if (container && isCaretAtContainerStart(container)) {\n // Only offer the select-then-delete flow for a non-editable\n // neighbor when THIS block still has real content of its own —\n // an empty current block (e.g. a trailing blank paragraph right\n // after an image) must disappear on its own first, exactly like\n // Backspace on any other empty block, before the neighbor is\n // offered at all. Otherwise the very first Backspace on an empty\n // paragraph would highlight the image instead of removing the\n // paragraph, which is backwards. onBackspaceAtStart (the normal\n // merge/delete path) handles the empty case, and itself lands on\n // selecting the neighbor via focusAfterMerge once there's\n // nothing left of the current block to focus back into.\n const isCurrentEmpty = isRunsEmpty(store, runIds);\n if (!isCurrentEmpty) {\n const neighborId = findAdjacentContentlessSiblingId(store, blockId, 'backward');\n if (neighborId) {\n event.preventDefault();\n selectOrDeleteContentlessNeighbor(neighborId);\n return;\n }\n }\n // Always claim this keypress once we know it's Backspace-at-\n // absolute-start being handled here (native backspace has nothing\n // to do at this exact position anyway, so this is a no-op for the\n // browser) — this is what lets the global handler in\n // useEditorKeyboardShortcuts distinguish \"a neighbor was *just*\n // selected as part of *this* keypress\" (defaultPrevented is now\n // true, so it must NOT also delete that neighbor on this same\n // press) from \"a neighbor was already selected from a *previous*\n // keypress\" (a fresh event, defaultPrevented starts false again,\n // so the global handler correctly deletes it then).\n event.preventDefault();\n if (onBackspaceAtStart) onBackspaceAtStart(event);\n }\n return;\n }\n if (event.key === 'Delete') {\n const container = containerRef.current;\n const wholeId = container && findWhollySelectedAtomicRunId(container, runIds, store.getRun.bind(store));\n if (wholeId) {\n event.preventDefault();\n removeRun(wholeId);\n return;\n }\n const atomicId = container && findAdjacentAtomicRunId(container, runIds, store.getRun.bind(store), false);\n if (atomicId) {\n event.preventDefault();\n removeRun(atomicId);\n return;\n }\n if (container && isCaretAtContainerEnd(container)) {\n const neighborId = findAdjacentContentlessSiblingId(store, blockId, 'forward');\n if (neighborId) {\n event.preventDefault();\n selectOrDeleteContentlessNeighbor(neighborId);\n return;\n }\n if (onDeleteAtEnd) onDeleteAtEnd(event);\n }\n return;\n }\n if (event.key === 'ArrowUp' && onArrowUp) {\n event.preventDefault();\n onArrowUp(event);\n return;\n }\n if (event.key === 'ArrowDown' && onArrowDown) {\n event.preventDefault();\n onArrowDown(event);\n return;\n }\n if (event.key === 'Tab') {\n if (event.shiftKey && onShiftTab) {\n event.preventDefault();\n onShiftTab(event);\n } else if (!event.shiftKey && onTab) {\n event.preventDefault();\n onTab(event);\n }\n }\n },\n [\n onEnter,\n onBackspaceAtStart,\n onDeleteAtEnd,\n onArrowUp,\n onArrowDown,\n onTab,\n onShiftTab,\n removeRun,\n selectOrDeleteContentlessNeighbor,\n runIds,\n blockId,\n store,\n ],\n );\n\n return (\n <span\n ref={containerRef}\n className=\"be-editable\"\n contentEditable\n suppressContentEditableWarning\n onInput={handleInput}\n onCompositionStart={handleCompositionStart}\n onCompositionEnd={handleCompositionEnd}\n onKeyDown={handleKeyDown}\n >\n {runIds.map((id) => {\n const host = getOrCreateHost(hostsRef.current, store, id);\n return createPortal(\n <RunNode\n key={id}\n id={id}\n blockId={blockId}\n host={host}\n inlineRegistry={inlineRegistry}\n onValueSynced={syncEmptyFromStore}\n />,\n host,\n );\n })}\n </span>\n );\n}\n","import { focusRunEnd } from '../../react/focusRun.js';\n\nfunction adjacentSiblingId(store, blockId, direction) {\n const block = store.getBlock(blockId);\n const parent = block && store.getBlock(block.parentId);\n if (!parent) return null;\n const index = parent.contentIds.indexOf(blockId);\n const adjacentIndex = direction === 'up' ? index - 1 : index + 1;\n if (adjacentIndex < 0 || adjacentIndex >= parent.contentIds.length) return null;\n return parent.contentIds[adjacentIndex];\n}\n\n/**\n * Resolves which run id should receive focus when moving from `blockId` in\n * `direction` ('up' | 'down') — pure logic, no DOM, so it's directly\n * testable. When the adjacent sibling is a container with actual content\n * (a table with rows, a layout with columns holding blocks), this *enters*\n * it — landing in its first cell/child when moving down, or its last when\n * moving up — via resolveBlockFirstRun/resolveBlockLastRun. Only a sibling\n * with truly nothing focusable at all (a divider, or an empty table with\n * zero rows) gets skipped over entirely, continuing the search to the next\n * sibling after it.\n */\nexport function resolveAdjacentFocusTarget(store, blockId, direction) {\n let currentId = blockId;\n while (true) {\n const adjacentId = adjacentSiblingId(store, currentId, direction);\n if (!adjacentId) return null;\n const runId = direction === 'up' ? resolveBlockLastRun(store, adjacentId) : resolveBlockFirstRun(store, adjacentId);\n if (runId) return runId;\n currentId = adjacentId; // truly empty (no rows/children at all): keep walking past it\n }\n}\n\n/** Moves focus to the nearest focusable sibling block's text in `direction` (see resolveAdjacentFocusTarget). */\nexport function focusAdjacentBlock(store, blockId, direction) {\n const targetRunId = resolveAdjacentFocusTarget(store, blockId, direction);\n if (targetRunId) focusRunEnd(targetRunId);\n}\n\n/**\n * Resolves the first directly-focusable run inside `blockId`, descending\n * into containers as needed — a leaf's own contentIds/titleRunIds are\n * already run ids, but a table's contentIds are row *block* ids (recurse\n * into the first row, then its first cell, then that cell's runs), and\n * likewise for a layout's columns. Used to focus into a block right after\n * it's created (Enter, a slash command), so the caret always lands\n * somewhere typeable instead of staying on the block that triggered it.\n */\nexport function resolveBlockFirstRun(store, blockId) {\n const block = store.getBlock(blockId);\n if (!block) return null;\n const runIds = block.props?.titleRunIds ?? block.contentIds;\n if (!runIds || runIds.length === 0) return null;\n const firstId = runIds[0];\n if (store.getRun(firstId)) return firstId; // a leaf's ids are runs directly\n return resolveBlockFirstRun(store, firstId); // a container's ids are child blocks: recurse\n}\n\n/** Moves focus to the first typeable position inside `blockId` (see resolveBlockFirstRun). */\nexport function focusBlockStart(store, blockId) {\n const runId = resolveBlockFirstRun(store, blockId);\n if (runId) focusRunEnd(runId);\n}\n\n/** Symmetric to resolveBlockFirstRun: the last directly-focusable run inside `blockId`, descending into containers' last child. */\nexport function resolveBlockLastRun(store, blockId) {\n const block = store.getBlock(blockId);\n if (!block) return null;\n const runIds = block.props?.titleRunIds ?? block.contentIds;\n if (!runIds || runIds.length === 0) return null;\n const lastId = runIds[runIds.length - 1];\n if (store.getRun(lastId)) return lastId;\n return resolveBlockLastRun(store, lastId);\n}\n\n/** Moves focus to the last typeable position inside `blockId` (see resolveBlockLastRun). */\nexport function focusBlockEnd(store, blockId) {\n const runId = resolveBlockLastRun(store, blockId);\n if (runId) focusRunEnd(runId);\n}\n","import { stripEmptyRunPlaceholder } from './domRunSync.js';\n\n/**\n * v1 scope: resolves the native selection only when it's a non-collapsed\n * range entirely within one run's single text node — matches the same\n * single-run limitation as toggleMarkOnRunRange and the clipboard range\n * resolution. Returns null for collapsed selections or ranges spanning\n * multiple runs/blocks.\n */\nexport function resolveRunSelection() {\n const selection = window.getSelection?.();\n if (!selection || selection.rangeCount === 0) return null;\n const range = selection.getRangeAt(0);\n if (range.collapsed || range.startContainer !== range.endContainer) return null;\n\n const container = range.startContainer;\n const el = container.nodeType === 1 ? container : container.parentElement;\n const runEl = el?.closest?.('[data-run-id]');\n if (!runEl) return null;\n const blockEl = runEl.closest('[data-block-id]');\n if (!blockEl) return null;\n\n const rawText = container.textContent ?? '';\n return {\n runId: runEl.getAttribute('data-run-id'),\n blockId: blockEl.getAttribute('data-block-id'),\n startOffset: stripEmptyRunPlaceholder(rawText.slice(0, range.startOffset)).length,\n endOffset: stripEmptyRunPlaceholder(rawText.slice(0, range.endOffset)).length,\n };\n}\n\n/**\n * Native selection gestures that don't drill into a specific run's text\n * node — Ctrl+A \"select all\" within one contentEditable region is the main\n * one — anchor directly on the shared contentEditable container instead,\n * addressing by child-index rather than character offset. Without this,\n * detecting \"the whole current block is already selected\" (the trigger for\n * promoting a second Ctrl+A to a whole-document selection) silently fails\n * for exactly the selection shape native select-all actually produces.\n */\nfunction resolveContainerLevelSelection(node, offset) {\n if (node?.nodeType !== 1 || node.getAttribute?.('contenteditable') !== 'true') return null;\n const children = node.childNodes;\n if (children.length === 0) return null;\n\n const atEnd = offset >= children.length;\n const child = children[atEnd ? children.length - 1 : Math.max(0, offset)];\n const runId = child?.nodeType === 1 ? child.dataset?.runId : undefined;\n if (!runId) return null;\n const blockEl = child.closest('[data-block-id]');\n if (!blockEl) return null;\n\n return {\n runId,\n blockId: blockEl.getAttribute('data-block-id'),\n // Raw DOM length, not the logical (placeholder-stripped) length: a run\n // that started empty and was later typed into keeps a leftover\n // zero-width-space byte in its actual text node forever (see\n // TextRunSpan in EditableBlockContent.jsx — never rewritten, to avoid\n // resetting the caret on every keystroke), even though run.value itself\n // is clean. Using the raw length here would put native select-all's\n // offset one character ahead of run.value.length for exactly those\n // blocks, which is exactly what silently broke \"is the whole block\n // selected\" detection for any block typed into after being created\n // empty (slash-menu-created blocks, Enter-split blocks, etc.).\n offset: atEnd ? stripEmptyRunPlaceholder(child.textContent ?? '').length : 0,\n };\n}\n\nfunction resolveRunAndOffset(node, offset) {\n const containerLevel = resolveContainerLevelSelection(node, offset);\n if (containerLevel) return containerLevel;\n\n let el = node?.nodeType === 1 ? node : node?.parentElement;\n const runEl = el?.closest?.('[data-run-id]');\n if (!runEl) return null;\n const blockEl = runEl.closest('[data-block-id]');\n if (!blockEl) return null;\n\n // `offset` is a raw DOM char index when node is the run's own text node;\n // when the selection anchors on the run element itself (e.g. an empty/\n // atomic island), it's a child-node index instead — convert to a char\n // count. Either way, strip any leftover placeholder byte so the result\n // lines up with run.value.length (see the matching comment in\n // resolveContainerLevelSelection above — same underlying cause).\n let charOffset = stripEmptyRunPlaceholder((node.textContent ?? '').slice(0, offset)).length;\n if (node === runEl) {\n charOffset = 0;\n for (let i = 0; i < offset && i < runEl.childNodes.length; i += 1) {\n charOffset += stripEmptyRunPlaceholder(runEl.childNodes[i].textContent ?? '').length;\n }\n }\n\n return {\n runId: runEl.getAttribute('data-run-id'),\n blockId: blockEl.getAttribute('data-block-id'),\n offset: charOffset,\n };\n}\n\n/**\n * Resolves a *collapsed* caret to the run+char-offset it sits at — used by\n * Enter-to-split so the new block gets exactly the text after the caret,\n * instead of always starting blank. Returns null for a non-collapsed\n * selection or a caret that isn't inside any run at all.\n */\nexport function resolveCollapsedCaret() {\n const selection = window.getSelection?.();\n if (!selection || selection.rangeCount === 0 || !selection.isCollapsed) return null;\n return resolveRunAndOffset(selection.anchorNode, selection.anchorOffset);\n}\n\n/**\n * Resolves a non-collapsed selection that may span *multiple runs within\n * the same block* (e.g. selecting text that crosses a bold boundary) —\n * generalizes resolveRunSelection's single-run limitation. Returns null if\n * the selection spans multiple blocks (use resolveCrossBlockSelection for\n * that) or if either end isn't inside a run at all.\n */\nexport function resolveMultiRunSelection() {\n const selection = window.getSelection?.();\n if (!selection || selection.rangeCount === 0 || selection.isCollapsed) return null;\n\n const anchor = resolveRunAndOffset(selection.anchorNode, selection.anchorOffset);\n const focus = resolveRunAndOffset(selection.focusNode, selection.focusOffset);\n if (!anchor || !focus) return null;\n if (anchor.blockId !== focus.blockId) return null; // cross-block: use resolveCrossBlockSelection\n\n return {\n blockId: anchor.blockId,\n startRunId: anchor.runId,\n startOffset: anchor.offset,\n endRunId: focus.runId,\n endOffset: focus.offset,\n };\n}\n\n/**\n * Resolves a non-collapsed selection spanning *multiple sibling blocks*\n * under a shared parent (e.g. from the middle of one paragraph through the\n * middle of another a few blocks down) — for toggleMarkOverBlockRange.\n * Needs `store` (unlike the other resolvers here) to walk the parent's\n * contentIds and slice out the sibling range. Returns null when the\n * selection is actually within one block (use resolveMultiRunSelection\n * instead), or when the two blocks aren't siblings under the same parent\n * (nested at different depths — not supported in v1).\n */\nexport function resolveCrossBlockSelection(store) {\n const selection = window.getSelection?.();\n if (!selection || selection.rangeCount === 0 || selection.isCollapsed) return null;\n\n const anchor = resolveRunAndOffset(selection.anchorNode, selection.anchorOffset);\n const focus = resolveRunAndOffset(selection.focusNode, selection.focusOffset);\n if (!anchor || !focus) return null;\n if (anchor.blockId === focus.blockId) return null; // same block: use resolveMultiRunSelection\n\n const startBlock = store.getBlock(anchor.blockId);\n const parent = startBlock && store.getBlock(startBlock.parentId);\n if (!parent) return null;\n\n const ids = parent.contentIds;\n const i1 = ids.indexOf(anchor.blockId);\n const i2 = ids.indexOf(focus.blockId);\n if (i1 === -1 || i2 === -1) return null; // not siblings under the same parent\n\n const [from, to] = i1 <= i2 ? [i1, i2] : [i2, i1];\n\n return {\n blockIds: ids.slice(from, to + 1),\n startBlockId: anchor.blockId,\n startRunId: anchor.runId,\n startOffset: anchor.offset,\n endBlockId: focus.blockId,\n endRunId: focus.runId,\n endOffset: focus.offset,\n };\n}\n","import { insertBlock, updateRun, setBlockRuns, removeBlock } from '../../store/operations.js';\nimport { focusBlockStart } from './navigationCommands.js';\nimport { resolveCollapsedCaret } from '../../react/selectionResolve.js';\nimport { genId } from '../../utils/idGen.js';\n\n/**\n * Inserts a new block immediately after `currentBlockId`, as a sibling under\n * the same parent. `factory(parentId)` must return `{ block, runs, subtreeBlocks }`\n * — `runs` may be empty for non-leaf types, and `subtreeBlocks` (default [])\n * holds any additional descendant blocks for multi-level inserts (e.g. a\n * table's rows/cells alongside its own root block). Shared by every block\n * type's slash command so \"where do I insert relative to the current block\"\n * is written once.\n */\nexport function insertSiblingAfter(store, currentBlockId, factory) {\n const current = store.getBlock(currentBlockId);\n const parentId = current.parentId;\n const parent = store.getBlock(parentId);\n const index = parent.contentIds.indexOf(currentBlockId) + 1;\n const { block, runs = [], subtreeBlocks = [] } = factory(parentId);\n store.applyOperation(insertBlock(block, parentId, index, { blocks: [block, ...subtreeBlocks], runs }));\n return block.id;\n}\n\n/**\n * Same as insertSiblingAfter, but also moves focus into the new block —\n * every editor does this (Enter, or picking a block from the slash menu,\n * always lands the caret in the thing you just created, never leaves it on\n * the block you triggered it from). Descends into containers (table,\n * layout) to find the first actually-typeable position.\n */\nexport function insertSiblingAfterAndFocus(store, currentBlockId, factory) {\n const newBlockId = insertSiblingAfter(store, currentBlockId, factory);\n focusBlockStart(store, newBlockId);\n return newBlockId;\n}\n\n/**\n * Inserts a new block as the *first child* of `parentBlockId` and focuses\n * it. Used when a container block (a list item with nested items beneath\n * it) needs the new block to appear visually right after the parent's own\n * content but before its existing children — since children render\n * *inside* the parent's own DOM subtree, a \"sibling in the grandparent's\n * array\" would only ever land after that whole subtree, not between the\n * parent's title and its first child.\n */\nexport function insertFirstChildAndFocus(store, parentBlockId, factory) {\n const { block, runs = [], subtreeBlocks = [] } = factory(parentBlockId);\n store.applyOperation(insertBlock(block, parentBlockId, 0, { blocks: [block, ...subtreeBlocks], runs }));\n focusBlockStart(store, block.id);\n return block.id;\n}\n\nfunction applyOps(store, ops) {\n if (typeof store.performBatch === 'function') {\n store.performBatch(ops);\n } else {\n for (const op of ops) store.applyOperation(op);\n }\n}\n\n/**\n * Pure: splits an ordered list of Run objects at `caretRunId`/`caretOffset`\n * into \"everything before the caret\" and \"everything at/after it\",\n * splitting the caret's own run in two when it's a text run with content on\n * both sides. Identity is preserved wherever possible (a run that doesn't\n * actually get cut keeps its id) so only a genuine mid-run split spends a\n * new id. Neither side is ever left with zero runs — a block needs at least\n * one run to render/anchor a caret in, so an empty side gets a fresh blank\n * text run.\n */\nexport function splitRunsAtCaret(runs, caretRunId, caretOffset) {\n const idx = runs.findIndex((r) => r.id === caretRunId);\n if (idx === -1) return null;\n\n const caretRun = runs[idx];\n const before = runs.slice(0, idx);\n const after = runs.slice(idx + 1);\n\n if (caretRun.type === 'text') {\n const value = caretRun.value ?? '';\n const leftValue = value.slice(0, caretOffset);\n const rightValue = value.slice(caretOffset);\n if (leftValue && rightValue) {\n before.push({ ...caretRun, value: leftValue });\n after.unshift({ ...caretRun, id: genId(), value: rightValue });\n } else if (rightValue) {\n after.unshift(caretRun); // caret at the run's start: whole run moves right, unchanged\n } else {\n before.push(caretRun); // caret at the run's end (or run already empty): stays left, unchanged\n }\n } else if (caretOffset > 0) {\n before.push(caretRun); // atomic run: never split inside it, only before/after\n } else {\n after.unshift(caretRun);\n }\n\n const leftRuns = before.length ? before : [{ id: genId(), type: 'text', value: '', marks: {} }];\n const rightRuns = after.length ? after : [{ id: genId(), type: 'text', value: '', marks: {} }];\n return { leftRuns, rightRuns };\n}\n\n/**\n * Enter-to-split: every real editor splits the block's content at the\n * caret (text before stays, text after moves into the new sibling) rather\n * than always creating a blank sibling and leaving all the text behind.\n * Falls back to the old \"just append an empty sibling\" behavior when there\n * is no resolvable live caret in this exact block (no DOM selection at all,\n * as in most non-interactive tests, or a caret that landed somewhere else).\n *\n * `currentRunIds` must be the block's own run ids (contentIds for a plain\n * leaf, props.titleRunIds for a listItem) — same convention as\n * EditableBlockContent's `runIds` prop. `factory(parentId, initialRuns?)`\n * must accept the optional pre-built run list (see createTextLeafBlock/\n * createListItemBlock).\n */\nexport function insertSiblingSplitAtCaretAndFocus(store, blockId, currentRunIds, factory) {\n const current = store.getBlock(blockId);\n const parent = store.getBlock(current.parentId);\n const index = parent.contentIds.indexOf(blockId) + 1;\n return splitAndInsertAtCaret(store, blockId, currentRunIds, factory, {\n insertParentId: parent.id,\n insertIndex: index,\n fallback: () => insertSiblingAfterAndFocus(store, blockId, factory),\n });\n}\n\n/**\n * Same idea as insertSiblingSplitAtCaretAndFocus, but for the \"this item has\n * nested children\" case (see insertFirstChildAndFocus): the new block's\n * content is the split-off right-hand runs, and it lands as the first child\n * of `blockId` itself (whose own title runs get truncated to the left half)\n * rather than as its sibling.\n */\nexport function insertFirstChildSplitAtCaretAndFocus(store, blockId, currentRunIds, factory) {\n return splitAndInsertAtCaret(store, blockId, currentRunIds, factory, {\n insertParentId: blockId,\n insertIndex: 0,\n fallback: () => insertFirstChildAndFocus(store, blockId, factory),\n });\n}\n\nfunction splitAndInsertAtCaret(store, blockId, currentRunIds, factory, { insertParentId, insertIndex, fallback }) {\n const caret = resolveCollapsedCaret();\n if (!caret || caret.blockId !== blockId) return fallback();\n\n const currentRuns = currentRunIds.map((id) => store.getRun(id)).filter(Boolean);\n const split = splitRunsAtCaret(currentRuns, caret.runId, caret.offset);\n if (!split) return fallback();\n\n const { leftRuns, rightRuns } = split;\n const { block, runs = rightRuns, subtreeBlocks = [] } = factory(insertParentId, rightRuns);\n\n // Enter at the very start of a block's content leaves nothing before the\n // caret, so leftRuns comes back empty — but the block staying behind\n // must never end up with zero runs: an empty contentEditable region isn't\n // a valid caret anchor in most browsers, so the next time someone types\n // into it, every keystroke mints a brand-new run instead of updating one\n // in place (the same \"characters double\" bug this exact guard fixes for\n // removeRun/handleInput in EditableBlockContent).\n const survivingLeftRuns = leftRuns.length ? leftRuns : [{ id: genId(), type: 'text', value: '', marks: {} }];\n\n applyOps(store, [\n setBlockRuns(blockId, survivingLeftRuns),\n insertBlock(block, insertParentId, insertIndex, { blocks: [block, ...subtreeBlocks], runs }),\n ]);\n focusBlockStart(store, block.id);\n return block.id;\n}\n\nfunction getOwnRunIds(block) {\n return block?.props?.titleRunIds ?? block?.contentIds ?? [];\n}\n\n// A listItem's own text lives in props.titleRunIds while contentIds holds\n// its nested child *blocks* — so for it (and any other block shaped that\n// way), contentIds having entries means it has children, not extra runs.\nfunction hasNestedChildren(block) {\n return Boolean(block?.props?.titleRunIds) && (block.contentIds?.length ?? 0) > 0;\n}\n\n/**\n * Converts an empty block in place to a different type, instead of leaving\n * the old empty block behind with a new sibling after it — e.g. picking\n * \"Heading\" from the slash menu on a still-empty paragraph turns that same\n * paragraph into the heading, rather than inserting a heading after an\n * orphaned blank paragraph. Removes the old block and inserts the new one\n * at the same index as one atomic step, so undo/redo treats it as a single\n * operation.\n */\nfunction replaceBlockInPlace(store, blockId, factory) {\n const current = store.getBlock(blockId);\n const parentId = current.parentId;\n const parent = store.getBlock(parentId);\n const index = parent.contentIds.indexOf(blockId);\n const { block, runs = [], subtreeBlocks = [] } = factory(parentId);\n\n applyOps(store, [\n removeBlock(blockId),\n insertBlock(block, parentId, index, { blocks: [block, ...subtreeBlocks], runs }),\n ]);\n focusBlockStart(store, block.id);\n return block.id;\n}\n\n/**\n * Slash-command entry point for block-level commands: removes the\n * \"/query\" span from the triggering run (merging whatever was before and\n * after it — a block command doesn't need to preserve a split point the\n * way an inline command does, since it's creating an entirely separate\n * sibling block, not splicing into this one).\n *\n * If trimming the query leaves the block completely empty — it was the\n * block's only run and the block has no nested children — the block is\n * converted in place (replaceBlockInPlace) rather than inserted after,\n * which would otherwise leave a pointless empty block sitting above the\n * one the user actually meant to create. Otherwise, behaves as before:\n * trims the query and inserts+focuses the new block after the current one.\n */\nexport function trimSlashQueryAndInsertAfter(store, { blockId, runId, sliceStart, sliceEnd }, factory) {\n const run = store.getRun(runId);\n const value = run?.value ?? '';\n const newValue = value.slice(0, sliceStart) + value.slice(sliceEnd);\n\n const block = store.getBlock(blockId);\n const ownRunIds = getOwnRunIds(block);\n const isOnlyRun = ownRunIds.length === 1 && ownRunIds[0] === runId;\n const wouldBeEmpty = isOnlyRun && newValue === '' && !hasNestedChildren(block);\n\n if (wouldBeEmpty) {\n return replaceBlockInPlace(store, blockId, factory);\n }\n\n store.applyOperation(updateRun(runId, { value: newValue }));\n return insertSiblingAfterAndFocus(store, blockId, factory);\n}\n","import { genId } from '../../utils/idGen.js';\n\n/**\n * Builds a factory(parentId, initialRuns?) -> {block, runs} for a text leaf\n * block. Most callers (slash commands) omit `initialRuns` and get a single\n * blank run; Enter-to-split passes the runs that landed after the caret so\n * the new block starts with that text instead of empty.\n */\nexport function createTextLeafBlock(type, props = {}) {\n return function factory(parentId, initialRuns) {\n const blockId = genId();\n const runs = initialRuns?.length ? initialRuns : [{ id: genId(), type: 'text', value: '', marks: {} }];\n return {\n block: { id: blockId, type, parentId, contentIds: runs.map((r) => r.id), props },\n runs,\n };\n };\n}\n","import { insertBlock } from '../../store/operations.js';\nimport { createTextLeafBlock } from './leafBlockFactory.js';\n\n/**\n * Call after any operation that might have deleted the *last* block under\n * the document root. Every real editor keeps at least one empty paragraph\n * rather than allowing a genuinely blank document — a page with zero\n * children isn't just a UX dead end (nothing to click into), it also\n * breaks caret placement entirely, since there's no contentEditable region\n * left anywhere for the browser to anchor a click or keystroke in.\n *\n * No-op (returns null) if the root already has content. `store` may be a\n * plain EditorStore or a History wrapper — either way this issues its own\n * `applyOperation` call, so call it *after* whatever batch removed the\n * block, not folded into that same batch (the fallback should only ever\n * fire if the removal actually emptied the root, which isn't knowable\n * until after it's applied).\n */\nexport function ensureRootNonEmpty(store) {\n const rootId = store.getRootId();\n const root = store.getBlock(rootId);\n if (!root || root.contentIds.length > 0) return null;\n\n const { block, runs } = createTextLeafBlock('paragraph')(rootId);\n store.applyOperation(insertBlock(block, rootId, 0, { blocks: [block], runs }));\n return block.id;\n}\n","import { removeBlock, setBlockContentIds, insertBlock } from '../../store/operations.js';\nimport { isContentlessBlock } from './contentless.js';\nimport { createTextLeafBlock } from './leafBlockFactory.js';\nimport { ensureRootNonEmpty } from './ensureRootNonEmpty.js';\n\n// Container types that should vanish entirely once their one-and-only\n// content block is emptied out, rather than leaving an empty box behind —\n// e.g. an empty callout with nothing typed into it. Deliberately does NOT\n// include layoutColumn: removing one column would break an N-column\n// layout's symmetry, which isn't the same situation as a callout with\n// nothing left to say.\nconst UNWRAP_WHEN_SOLE_CHILD_EMPTIED = new Set(['callout']);\n\n// Block types whose contentIds are always run ids (never child blocks) and\n// whose only real difference is presentational (heading level, or a quote's\n// left border, vs plain paragraph) — merging across these keeps the\n// surviving (previous) block's own type/props untouched, so merging a\n// paragraph up into a heading stays a heading, backspacing into a quote\n// keeps it a quote, and vice versa. Deliberately does NOT include\n// tableCell/listItem: those have distinct structural roles (a cell belongs\n// to a row; a list item carries indentation/marker state) where \"just\n// concatenate the text and keep whichever type was already there\" isn't\n// the right semantics.\nexport const MERGEABLE_TEXT_TYPES = new Set(['paragraph', 'heading', 'blockquote']);\n\nexport function canMergeTypes(prevType, blockType) {\n return prevType === blockType || (MERGEABLE_TEXT_TYPES.has(prevType) && MERGEABLE_TEXT_TYPES.has(blockType));\n}\n\n/**\n * Backspace-at-start-of-block behavior:\n * 1. If the previous sibling is contentless (e.g. a divider), delete *it*\n * first and stay put — matches the familiar \"backspace clears the\n * nearest obstacle\" convention (Notion et al.), and means a second\n * backspace then merges into whatever's before the divider.\n * 2. Else if this block is empty, delete it.\n * 3. Else merge its inline content onto the end of the previous sibling —\n * same type, or both are in MERGEABLE_TEXT_TYPES (paragraph/heading, in\n * either direction) — and delete the now-empty shell. Any other type\n * pairing (a table, a list item, ...) is left alone; merging into those\n * doesn't have well-defined semantics in v1.\n *\n * 4. Special case when there's *nothing before this block at all* (it's\n * first in its container, so there's no \"merge into\" target): a block\n * with real content still does nothing (matches every other editor —\n * Backspace at the absolute start of the first line is a no-op when\n * there's something to preserve). But an *empty* leading block should\n * still go away — removed outright if something follows it, or, if\n * it's the only block left, replaced with a blank paragraph (same\n * \"never leave nothing to click into\" fallback as\n * exitListItemToParagraph / ensureRootNonEmpty). Without this, an empty\n * heading/paragraph that happens to be first (very often *the only\n * block left* after deleting everything else) could never be removed\n * at all.\n *\n * All of this is one atomic undo step: if `store` is a History instance\n * (has performBatch), the ops are grouped; a plain EditorStore just applies\n * them in sequence (no undo tracking to group).\n *\n * Returns the id of the block that should receive focus afterward, or null\n * if there was nothing to do.\n */\nexport function mergeWithPreviousOrDelete(store, blockId) {\n const block = store.getBlock(blockId);\n if (!block) return null;\n\n const parent = store.getBlock(block.parentId);\n const index = parent.contentIds.indexOf(blockId);\n const isEmpty = block.contentIds.length === 0 || (block.contentIds.length === 1 && isBlankRun(store, block.contentIds[0]));\n\n if (index <= 0) {\n if (!isEmpty) return null; // real content, nothing before it: no-op, as every other editor does\n\n if (parent.contentIds.length > 1) {\n applyOps(store, [removeBlock(blockId)]);\n return store.getBlock(parent.id).contentIds[0]; // whatever's now first\n }\n\n // The sole (now-empty) child of a container that should disappear once\n // there's nothing left in it (e.g. a callout) — remove the CONTAINER\n // itself, not just this child, instead of leaving an empty box behind.\n if (UNWRAP_WHEN_SOLE_CHILD_EMPTIED.has(parent.type)) {\n return unwrapEmptyContainer(store, parent);\n }\n\n if (block.type === 'paragraph') return null; // already the fallback shape; nothing to do\n\n const { block: fallbackBlock, runs } = createTextLeafBlock('paragraph')(parent.id);\n applyOps(store, [\n insertBlock(fallbackBlock, parent.id, index, { blocks: [fallbackBlock], runs }),\n removeBlock(blockId),\n ]);\n return fallbackBlock.id;\n }\n\n const prevId = parent.contentIds[index - 1];\n const prev = store.getBlock(prevId);\n\n // An empty CURRENT block always goes first, even when the previous\n // sibling is a non-editable block (divider/embed) — Backspace on a\n // trailing empty paragraph should make the empty paragraph disappear\n // (ordinary empty-block behavior) before anything about the\n // non-editable neighbor is offered at all. Checking isContentlessBlock\n // first here would instead delete the neighbor immediately, one\n // Backspace too early. (In the normal keyboard path this is actually\n // decided one layer up, in EditableBlockContent, which only offers the\n // neighbor select-then-delete flow once the current block has real\n // content left — this ordering just keeps the pure function's own\n // behavior consistent for direct callers.)\n if (isEmpty) {\n applyOps(store, [removeBlock(blockId)]);\n return prevId;\n }\n\n if (isContentlessBlock(store, prev)) {\n applyOps(store, [removeBlock(prevId)]);\n return blockId; // stay put; the obstacle is gone, no DOM remount needed\n }\n\n if (!prev || !canMergeTypes(prev.type, block.type)) return null;\n\n const mergedContentIds = [...prev.contentIds, ...block.contentIds];\n applyOps(store, [\n setBlockContentIds(prevId, mergedContentIds),\n setBlockContentIds(blockId, []), // detach moved runs before deleting the shell\n removeBlock(blockId),\n ]);\n return prevId;\n}\n\nfunction isBlankRun(store, runId) {\n const run = store.getRun(runId);\n return !run || (run.value ?? '') === '';\n}\n\n/**\n * Removes `container` itself (e.g. a callout whose only child was just\n * emptied out), focusing whatever now sits where it used to — its previous\n * sibling, or else its next sibling, or else (the container was the only\n * thing under the document root) whatever ensureRootNonEmpty falls back\n * to, so there's always still somewhere to land the caret.\n */\nfunction unwrapEmptyContainer(store, container) {\n const grandParent = store.getBlock(container.parentId);\n if (!grandParent) return null;\n const idx = grandParent.contentIds.indexOf(container.id);\n const prevId = idx > 0 ? grandParent.contentIds[idx - 1] : null;\n const nextId = idx !== -1 && idx < grandParent.contentIds.length - 1 ? grandParent.contentIds[idx + 1] : null;\n\n applyOps(store, [removeBlock(container.id)]);\n const fallbackId = ensureRootNonEmpty(store);\n return prevId ?? nextId ?? fallbackId;\n}\n\nfunction applyOps(store, ops) {\n if (typeof store.performBatch === 'function') {\n store.performBatch(ops);\n } else {\n for (const op of ops) store.applyOperation(op);\n }\n}\n","import { isContentlessBlock } from './contentless.js';\nimport { focusRunEnd } from '../../react/focusRun.js';\n\n/**\n * Resolves what to do with focus after a merge/delete operation returns\n * `focusBlockId` — normally focus the end of its last run, but if that\n * target has no runs at all to focus (e.g. the current block's own empty\n * content was just deleted, landing \"focus\" on a divider/embed sibling),\n * there's nothing to put a caret in. Select/highlight it instead, via the\n * exact same select-then-delete flow as backspacing straight into a\n * non-editable neighbor (see EditableBlockContent's\n * selectOrDeleteContentlessNeighbor) — this is what makes that flow\n * reachable at all for \"empty paragraph right after an image\": the empty\n * paragraph is deleted first (ordinary empty-block Backspace), *then* the\n * image becomes selected, rather than the image jumping straight to\n * selected before the empty paragraph itself ever goes away.\n */\nexport function focusAfterMerge(store, focusBlockId, currentBlockId, setSelectedBlockId) {\n if (!focusBlockId || focusBlockId === currentBlockId) return;\n const focusBlock = store.getBlock(focusBlockId);\n if (isContentlessBlock(store, focusBlock)) {\n setSelectedBlockId(focusBlockId);\n // The current block (whose empty content just got deleted) is gone\n // from the DOM entirely, so — unlike EditableBlockContent's own\n // select-then-delete flow, which deliberately never steals focus away\n // from a block that's still there — nothing else has focus here.\n // Move it onto the now-selected non-editable block directly (divider/\n // embed both set tabIndex={-1} for exactly this) so the surface's own\n // keydown listener keeps capturing the next Backspace/Delete.\n requestAnimationFrame(() => {\n document.querySelector(`[data-block-id=\"${focusBlockId}\"]`)?.focus();\n });\n return;\n }\n const lastRunId =\n focusBlock?.contentIds?.[focusBlock.contentIds.length - 1] ??\n focusBlock?.props?.titleRunIds?.[focusBlock.props.titleRunIds.length - 1];\n if (lastRunId) focusRunEnd(lastRunId);\n}\n","import { genId } from '../../utils/idGen.js';\nimport { insertBlock, removeBlock, setBlockContentIds, updateBlockProps } from '../../store/operations.js';\n\n/**\n * Builds the ops that replace `blockId` in place with a new block of a\n * different type at the same position, carrying over `runIds` (reusing the\n * existing Run objects — never recreated) rather than creating new ones, so\n * any marks/text already typed survive the conversion. `props` may include\n * `titleRunIds` (for a listItem-shaped target) — `runIds` is threaded into\n * whichever of contentIds/props.titleRunIds the target type actually uses\n * (and whichever the *source* type used, when detaching).\n *\n * The new block is inserted EMPTY first, and `runIds` is only handed to it\n * via a separate setBlockContentIds/updateBlockProps op afterward — never\n * embedded directly in the insert's own subtree. This matters for undo:\n * REMOVE_BLOCK (insertBlock's inverse) recursively deletes every run still\n * reachable from the block being removed, so if the new block's *initial*\n * insert already listed `runIds` as its contentIds, undoing that insert\n * later (as part of a bigger undo replay) would delete those runs out from\n * under the old block they're being given back to. Transferring ownership\n * via its own dedicated op keeps every step's inverse a simple \"restore the\n * previous list\" with no recursive deletion, so runIds safely survive a\n * full undo/redo round-trip regardless of step order.\n *\n * Returns `{ ops, newBlockId }` rather than applying anything itself — the\n * caller folds `ops` into its own batch (e.g. alongside an `updateRun` that\n * strips a matched markdown-shortcut prefix from the first run), so the\n * whole thing is one atomic undo step.\n */\nexport function convertBlockType(store, blockId, type, props, runIds) {\n const block = store.getBlock(blockId);\n const parent = store.getBlock(block.parentId);\n const index = parent.contentIds.indexOf(blockId);\n const targetUsesTitleRunIds = 'titleRunIds' in props;\n const sourceUsesTitleRunIds = 'titleRunIds' in (block.props ?? {});\n\n const newBlock = { id: genId(), type, parentId: block.parentId, contentIds: [], props };\n\n const transferOp = targetUsesTitleRunIds\n ? updateBlockProps(newBlock.id, { titleRunIds: runIds })\n : setBlockContentIds(newBlock.id, runIds);\n\n const detachOp = sourceUsesTitleRunIds\n ? updateBlockProps(blockId, { titleRunIds: [] })\n : setBlockContentIds(blockId, []);\n\n return {\n newBlockId: newBlock.id,\n ops: [\n insertBlock(newBlock, block.parentId, index, { blocks: [newBlock], runs: [] }),\n transferOp,\n detachOp,\n removeBlock(blockId),\n ],\n };\n}\n","import { updateRun } from '../../store/operations.js';\nimport { convertBlockType } from '../shared/convertBlockType.js';\nimport { focusRunStart } from '../../react/focusRun.js';\n\nfunction applyOps(store, ops) {\n if (typeof store.performBatch === 'function') store.performBatch(ops);\n else for (const op of ops) store.applyOperation(op);\n}\n\n// Notion/TipTap-style markdown shortcuts: a recognized prefix, typed at the\n// very start of an otherwise-plain paragraph, converts the block once the\n// pattern is complete — most need a trailing trigger space (\"# \", \"- \",\n// \"1. \", \"> \", \"[] \"), matching every other editor's convention that the\n// space itself commits the conversion (so \"#\" alone, mid-typing, doesn't\n// convert early); \"```\" has no trailing space since there's nothing after\n// the third backtick to wait for.\n//\n// The trigger character class is `[  ]`, not a literal \" \" — browsers\n// commonly insert a *non-breaking* space (U+00A0) instead of an ordinary\n// one for a trailing space in a contentEditable region (so it doesn't get\n// collapsed away by normal HTML whitespace rules), and every one of these\n// shortcuts' trigger is exactly that: the last character in the region at\n// the moment it's typed. Matching only a literal \" \" meant none of these\n// ever fired against real typed input, only against text set up directly\n// in a test — jsdom doesn't reproduce this browser quirk, which is why it\n// wasn't caught there.\nconst RULES = [\n { re: /^(#{1,3})[  ]$/, type: 'heading', props: (m) => ({ level: m[1].length }) },\n { re: /^[-*][  ]$/, type: 'listItem', props: () => ({ ordered: false, titleRunIds: [] }) },\n { re: /^\\d+\\.[  ]$/, type: 'listItem', props: () => ({ ordered: true, titleRunIds: [] }) },\n { re: /^\\[\\][  ]$/, type: 'listItem', props: () => ({ ordered: false, checked: false, titleRunIds: [] }) },\n { re: /^>[  ]$/, type: 'blockquote', props: () => ({}) },\n { re: /^```$/, type: 'code', props: () => ({ language: 'plaintext' }) },\n];\n\n/**\n * Checks the block's current run list against every rule above and, on a\n * match, converts it: strips the matched prefix from the first run's text\n * and swaps the block for the matching type via convertBlockType, carrying\n * over the (now-stripped) run so any text/marks typed after the prefix\n * survive — all as one atomic undo step. Only fires when the block's\n * ENTIRE content is a single plain text run (no marks/atomic runs mixed in\n * yet); typing the same characters mid-sentence, or spanning multiple\n * runs, never triggers it, matching how Notion/TipTap scope this to a\n * fresh, still-plain line.\n *\n * `runs` is the block's just-committed run list (see EditableBlockContent's\n * handleInput, onlyValueChanges path — a markdown shortcut is always typed\n * into a single existing run, never a structural DOM change). Returns\n * `true` if a conversion happened (the caller should treat blockId as gone\n * — a new block now occupies its place).\n */\nexport function applyMarkdownShortcut(store, blockId, runs) {\n if (runs.length !== 1 || runs[0].type !== 'text') return false;\n const value = runs[0].value ?? '';\n\n for (const rule of RULES) {\n const match = rule.re.exec(value);\n if (!match) continue;\n\n const strippedValue = value.slice(match[0].length);\n const { ops } = convertBlockType(store, blockId, rule.type, rule.props(match), [runs[0].id]);\n applyOps(store, [updateRun(runs[0].id, { value: strippedValue }), ...ops]);\n focusRunStart(runs[0].id);\n return true;\n }\n return false;\n}\n","import { useCallback } from 'react';\nimport { EditableBlockContent } from '../../react/EditableBlockContent.jsx';\nimport { useBlock } from '../../react/useBlock.js';\nimport { useEditorStore, useSelectedBlock } from '../../react/EditorProvider.jsx';\nimport { insertSiblingSplitAtCaretAndFocus, insertSiblingAfterAndFocus } from '../shared/blockCommands.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\nimport { mergeWithPreviousOrDelete } from '../shared/mergeCommands.js';\nimport { isRunsEmpty } from '../shared/blockEmpty.js';\nimport { focusAfterMerge } from '../shared/focusAfterMerge.js';\nimport { focusRunEnd } from '../../react/focusRun.js';\nimport { focusAdjacentBlock } from '../shared/navigationCommands.js';\nimport { applyMarkdownShortcut } from './markdownShortcuts.js';\n\n// Container types a nested paragraph can \"exit\" out of on an empty last\n// line — pressing Enter on a blank final paragraph inside one of these\n// creates the new paragraph as a SIBLING OF THE CONTAINER ITSELF (back out\n// at the outer level), instead of yet another paragraph nested inside it.\n// This is how you get out of a callout/toggle heading's body to keep\n// writing in the main document — there's no other affordance for it, so\n// without this an empty trailing line is a dead end.\nconst EXITABLE_PARENT_TYPES = new Set(['callout', 'toggleHeading']);\n\nexport function ParagraphBlock({ id }) {\n const store = useEditorStore();\n const block = useBlock(id);\n const { setSelectedBlockId } = useSelectedBlock();\n\n const handleEnter = useCallback(() => {\n const parent = store.getBlock(block?.parentId);\n const isEmpty = isRunsEmpty(store, block?.contentIds ?? []);\n const isLastChild = Boolean(parent) && parent.contentIds[parent.contentIds.length - 1] === id;\n\n if (isEmpty && isLastChild && EXITABLE_PARENT_TYPES.has(parent?.type)) {\n insertSiblingAfterAndFocus(store, parent.id, createTextLeafBlock('paragraph'));\n return;\n }\n\n insertSiblingSplitAtCaretAndFocus(store, id, block?.contentIds ?? [], createTextLeafBlock('paragraph'));\n }, [store, id, block]);\n\n const handleBackspaceAtStart = useCallback(() => {\n const parent = store.getBlock(block?.parentId);\n const isEmpty = isRunsEmpty(store, block?.contentIds ?? []);\n const isSoleChild = parent?.contentIds?.length === 1 && parent.contentIds[0] === id;\n\n if (isEmpty && isSoleChild && parent?.type === 'toggleHeading') {\n // Pop back out to the toggle heading's own title instead of deleting\n // anything here — mirrors how a nested list item's empty Backspace\n // pops out one level at a time. Backspacing *again* from the title\n // (now that focus is there) is what actually removes an entirely\n // blank toggle heading, via mergeToggleHeadingOrNoop — this is the\n // first of those two steps, not a dead end.\n const titleRunIds = parent.props?.titleRunIds ?? [];\n const lastTitleRunId = titleRunIds[titleRunIds.length - 1];\n if (lastTitleRunId) focusRunEnd(lastTitleRunId);\n return;\n }\n\n const focusBlockId = mergeWithPreviousOrDelete(store, id);\n focusAfterMerge(store, focusBlockId, id, setSelectedBlockId);\n }, [store, id, block, setSelectedBlockId]);\n\n const handleArrowUp = useCallback(() => focusAdjacentBlock(store, id, 'up'), [store, id]);\n const handleArrowDown = useCallback(() => focusAdjacentBlock(store, id, 'down'), [store, id]);\n\n const handleAutoformat = useCallback((runs) => applyMarkdownShortcut(store, id, runs), [store, id]);\n\n if (!block) return null;\n const isEmpty = isRunsEmpty(store, block.contentIds);\n\n return (\n <div\n className=\"be-paragraph\"\n data-block-id={id}\n data-empty={isEmpty ? '' : undefined}\n data-placeholder=\"Type '/' for commands\"\n >\n <EditableBlockContent\n blockId={id}\n runIds={block.contentIds}\n onEnter={handleEnter}\n onBackspaceAtStart={handleBackspaceAtStart}\n onArrowUp={handleArrowUp}\n onArrowDown={handleArrowDown}\n onAutoformat={handleAutoformat}\n />\n </div>\n );\n}\n","/**\n * Serialization for a single inline Run. Shared by every leaf block type\n * (paragraph, heading, list item title, table cell) so formatting logic is\n * written exactly once instead of once per block type.\n *\n * `ctx.inlineRegistry` is optional — callers that don't mix in any\n * non-text inline types (or are serializing a run known to be plain text)\n * can omit it; a non-text run with no registry available just falls back\n * to its raw `value` rather than throwing.\n */\n\nexport function escapeHTML(str) {\n return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n\nexport function escapeAttr(str) {\n return escapeHTML(str).replace(/\"/g, '&quot;');\n}\n\nexport function runToHTML(run, ctx) {\n if (!run) return '';\n\n if (run.type !== 'text') {\n const entry = ctx?.inlineRegistry?.get(run.type);\n return entry ? entry.toHTML(run, ctx) : escapeHTML(run.value ?? '');\n }\n\n const marks = run.marks ?? {};\n let html = escapeHTML(run.value ?? '');\n if (marks.code) html = `<code>${html}</code>`;\n if (marks.bold) html = `<strong>${html}</strong>`;\n if (marks.italic) html = `<em>${html}</em>`;\n if (marks.underline) html = `<u>${html}</u>`;\n if (marks.strike) html = `<s>${html}</s>`;\n if (marks.subscript) html = `<sub>${html}</sub>`;\n if (marks.superscript) html = `<sup>${html}</sup>`;\n if (marks.color) html = `<span style=\"color:${escapeAttr(marks.color)}\">${html}</span>`;\n if (marks.highlight) html = `<span style=\"background-color:${escapeAttr(marks.highlight)}\">${html}</span>`;\n if (marks.link?.href) html = `<a href=\"${escapeAttr(marks.link.href)}\">${html}</a>`;\n return html;\n}\n\nexport function runToPlainText(run, ctx) {\n if (!run) return '';\n if (run.type !== 'text') {\n const entry = ctx?.inlineRegistry?.get(run.type);\n return entry ? entry.toPlainText(run, ctx) : (run.value ?? '');\n }\n return run.value ?? '';\n}\n","import { genId } from '../utils/idGen.js';\n\nconst TAG_TO_MARK = {\n STRONG: 'bold',\n B: 'bold',\n EM: 'italic',\n I: 'italic',\n U: 'underline',\n S: 'strike',\n STRIKE: 'strike',\n DEL: 'strike',\n CODE: 'code',\n SUB: 'subscript',\n SUP: 'superscript',\n};\n\n/**\n * Walks a DOM node's inline children (text + <strong>/<em>/<a>/etc., plus\n * any registered non-text inline type like a select chip) and produces an\n * array of Run objects carrying the accumulated marks. Reused by every leaf\n * block type's fromHTML matcher so paste-formatting logic is written once,\n * not duplicated per block type.\n *\n * `ctx.inlineRegistry` is optional — omit it if the caller never mixes in\n * non-text inline types (matched elements just fall through to their own\n * text content instead).\n */\nexport function domInlineToRuns(node, ctx, activeMarks = {}) {\n const runs = [];\n\n const walk = (n, marks) => {\n if (n.nodeType === 3 /* TEXT_NODE */) {\n const value = n.textContent;\n if (value) runs.push({ id: genId(), type: 'text', value, marks: { ...marks } });\n return;\n }\n if (n.nodeType !== 1 /* ELEMENT_NODE */) return;\n\n if (ctx?.inlineRegistry) {\n for (const entry of ctx.inlineRegistry.listHtmlMatchers()) {\n const run = entry.fromHTML(n, ctx);\n if (run) {\n runs.push(run);\n return; // atomic: don't also walk its children as plain text\n }\n }\n }\n\n let nextMarks = marks;\n const markName = TAG_TO_MARK[n.tagName];\n if (markName) nextMarks = { ...nextMarks, [markName]: true };\n if (n.tagName === 'A' && n.getAttribute('href')) {\n nextMarks = { ...nextMarks, link: { href: n.getAttribute('href') } };\n }\n // Color/highlight round-trip via inline style (see marks.js's runToHTML)\n // rather than a fixed tag — style.color/backgroundColor are only ever\n // set by us in that exact shape, so reading them back is unambiguous\n // for our own copy/paste; arbitrary third-party HTML with these styles\n // picks up the same treatment, which is a reasonable default.\n if (n.style?.color) nextMarks = { ...nextMarks, color: n.style.color };\n if (n.style?.backgroundColor) nextMarks = { ...nextMarks, highlight: n.style.backgroundColor };\n\n for (const child of n.childNodes) walk(child, nextMarks);\n };\n\n walk(node, activeMarks);\n return runs.length ? runs : [{ id: genId(), type: 'text', value: '', marks: {} }];\n}\n","/**\n * One shared icon family for every interactive control across the editor —\n * outline style (24x24 viewBox, 2px stroke, no fill, round caps/joins,\n * matching the common Feather/Lucide convention) so every icon inherits its\n * color from surrounding text via stroke=\"currentColor\" and scales via the\n * `size` prop, instead of the previously ad-hoc mix of unicode characters\n * (▸ ▾ × 📎 +) and single-letter text labels (B/I/U/S) each block used to\n * render on its own.\n */\nfunction Icon({ children, size = 16, strokeWidth = 2, ...rest }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n {...rest}\n >\n {children}\n </svg>\n );\n}\n\nexport function ChevronRightIcon(props) {\n return (\n <Icon {...props}>\n <polyline points=\"9 18 15 12 9 6\" />\n </Icon>\n );\n}\n\nexport function ChevronDownIcon(props) {\n return (\n <Icon {...props}>\n <polyline points=\"6 9 12 15 18 9\" />\n </Icon>\n );\n}\n\nexport function XIcon(props) {\n return (\n <Icon {...props}>\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </Icon>\n );\n}\n\nexport function PaperclipIcon(props) {\n return (\n <Icon {...props}>\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </Icon>\n );\n}\n\nexport function PlusIcon(props) {\n return (\n <Icon {...props}>\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </Icon>\n );\n}\n\nexport function BoldIcon(props) {\n return (\n <Icon {...props}>\n <path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\" />\n <path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\" />\n </Icon>\n );\n}\n\nexport function ItalicIcon(props) {\n return (\n <Icon {...props}>\n <line x1=\"19\" y1=\"4\" x2=\"10\" y2=\"4\" />\n <line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\" />\n <line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\" />\n </Icon>\n );\n}\n\nexport function UnderlineIcon(props) {\n return (\n <Icon {...props}>\n <path d=\"M6 3v7a6 6 0 0 0 12 0V3\" />\n <line x1=\"4\" y1=\"21\" x2=\"20\" y2=\"21\" />\n </Icon>\n );\n}\n\nexport function StrikethroughIcon(props) {\n return (\n <Icon {...props}>\n <path d=\"M16 4H9a3 3 0 0 0-2.83 4\" />\n <path d=\"M14 12a4 4 0 0 1 0 8H6\" />\n <line x1=\"4\" y1=\"12\" x2=\"20\" y2=\"12\" />\n </Icon>\n );\n}\n\nexport function AlignLeftIcon(props) {\n return (\n <Icon {...props}>\n <line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\" />\n <line x1=\"17\" y1=\"10\" x2=\"3\" y2=\"10\" />\n <line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\" />\n <line x1=\"17\" y1=\"18\" x2=\"3\" y2=\"18\" />\n </Icon>\n );\n}\n\nexport function AlignCenterIcon(props) {\n return (\n <Icon {...props}>\n <line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\" />\n <line x1=\"18\" y1=\"10\" x2=\"6\" y2=\"10\" />\n <line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\" />\n <line x1=\"18\" y1=\"18\" x2=\"6\" y2=\"18\" />\n </Icon>\n );\n}\n\nexport function AlignRightIcon(props) {\n return (\n <Icon {...props}>\n <line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\" />\n <line x1=\"21\" y1=\"10\" x2=\"7\" y2=\"10\" />\n <line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\" />\n <line x1=\"21\" y1=\"18\" x2=\"7\" y2=\"18\" />\n </Icon>\n );\n}\n\n// A 2x3 grid of solid dots (drag-handle convention) — unlike every other\n// icon here, these are filled, not stroked outlines: a 1px-radius circle\n// with only a stroke renders as a barely-visible ring at this size, so each\n// dot overrides the shared Icon wrapper's fill=\"none\"/stroke defaults\n// directly rather than inheriting them.\nexport function GripVerticalIcon(props) {\n return (\n <Icon {...props}>\n {[5, 12, 19].flatMap((cy) =>\n [9, 15].map((cx) => <circle key={`${cx}-${cy}`} cx={cx} cy={cy} r=\"1.3\" fill=\"currentColor\" stroke=\"none\" />),\n )}\n </Icon>\n );\n}\n\nexport function TrashIcon(props) {\n return (\n <Icon {...props}>\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n <line x1=\"10\" y1=\"11\" x2=\"10\" y2=\"17\" />\n <line x1=\"14\" y1=\"11\" x2=\"14\" y2=\"17\" />\n </Icon>\n );\n}\n\nexport function CopyIcon(props) {\n return (\n <Icon {...props}>\n <rect x=\"9\" y=\"9\" width=\"12\" height=\"12\" rx=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </Icon>\n );\n}\n\nexport function ArrowUpIcon(props) {\n return (\n <Icon {...props}>\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"5\" />\n <polyline points=\"5 12 12 5 19 12\" />\n </Icon>\n );\n}\n\nexport function ArrowDownIcon(props) {\n return (\n <Icon {...props}>\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <polyline points=\"19 12 12 19 5 12\" />\n </Icon>\n );\n}\n\nexport function ScissorsIcon(props) {\n return (\n <Icon {...props}>\n <circle cx=\"6\" cy=\"6\" r=\"3\" />\n <circle cx=\"6\" cy=\"18\" r=\"3\" />\n <line x1=\"20\" y1=\"4\" x2=\"8.12\" y2=\"15.88\" />\n <line x1=\"14.47\" y1=\"14.48\" x2=\"20\" y2=\"20\" />\n <line x1=\"8.12\" y1=\"8.12\" x2=\"12\" y2=\"12\" />\n </Icon>\n );\n}\n\n// --- Slash-menu command icons ---------------------------------------------\n// One icon per command so the \"/\" menu reads like Notion/TipTap's own\n// (glyph + label, not label-only) — see SlashMenu.jsx and each block/\n// inline type's own `slashCommand(s)` definition for where these attach.\n\nexport function TextIcon(props) {\n return (\n <Icon {...props}>\n <line x1=\"17\" y1=\"6\" x2=\"3\" y2=\"6\" />\n <line x1=\"21\" y1=\"12\" x2=\"3\" y2=\"12\" />\n <line x1=\"15\" y1=\"18\" x2=\"3\" y2=\"18\" />\n </Icon>\n );\n}\n\n/** Parameterized by `level` (1-3) — a single \"H\" + digit, filled text rather than the shared stroke-only glyphs above. */\nexport function HeadingIcon({ level = 1, size = 16, ...rest }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\" {...rest}>\n <text x=\"2\" y=\"18\" fontSize=\"14\" fontWeight=\"700\" fill=\"currentColor\" fontFamily=\"inherit\">\n H{level}\n </text>\n </svg>\n );\n}\n\n// Fixed-level wrappers around HeadingIcon — plain-.js command definitions\n// (e.g. blocks/heading/index.js) can't write JSX to pass `level` themselves,\n// so each level gets its own importable component instead.\nexport function Heading1Icon(props) {\n return <HeadingIcon level={1} {...props} />;\n}\nexport function Heading2Icon(props) {\n return <HeadingIcon level={2} {...props} />;\n}\nexport function Heading3Icon(props) {\n return <HeadingIcon level={3} {...props} />;\n}\n\nexport function QuoteIcon(props) {\n return (\n <Icon {...props}>\n <path d=\"M7 7a3 3 0 0 0-3 3v3a2 2 0 0 0 2 2h2a1 1 0 0 0 1-1v-4a1 1 0 0 0-1-1H6a3 3 0 0 1 3-3z\" />\n <path d=\"M17 7a3 3 0 0 0-3 3v3a2 2 0 0 0 2 2h2a1 1 0 0 0 1-1v-4a1 1 0 0 0-1-1h-2a3 3 0 0 1 3-3z\" />\n </Icon>\n );\n}\n\nexport function CodeIcon(props) {\n return (\n <Icon {...props}>\n <polyline points=\"9 8 4 12 9 16\" />\n <polyline points=\"15 8 20 12 15 16\" />\n </Icon>\n );\n}\n\nexport function DividerIcon(props) {\n return (\n <Icon {...props}>\n <line x1=\"4\" y1=\"12\" x2=\"20\" y2=\"12\" />\n </Icon>\n );\n}\n\nexport function CalloutIcon(props) {\n return (\n <Icon {...props}>\n <path d=\"M4 5h16a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H9l-4 4v-4H4a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1z\" />\n <line x1=\"7\" y1=\"9\" x2=\"17\" y2=\"9\" />\n <line x1=\"7\" y1=\"12.5\" x2=\"13\" y2=\"12.5\" />\n </Icon>\n );\n}\n\nexport function ButtonIcon(props) {\n return (\n <Icon {...props}>\n <rect x=\"3\" y=\"8\" width=\"18\" height=\"8\" rx=\"3\" />\n <line x1=\"8\" y1=\"12\" x2=\"16\" y2=\"12\" />\n </Icon>\n );\n}\n\nexport function TableIcon(props) {\n return (\n <Icon {...props}>\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"1\" />\n <line x1=\"3\" y1=\"10\" x2=\"21\" y2=\"10\" />\n <line x1=\"3\" y1=\"16\" x2=\"21\" y2=\"16\" />\n <line x1=\"9\" y1=\"4\" x2=\"9\" y2=\"20\" />\n <line x1=\"15\" y1=\"4\" x2=\"15\" y2=\"20\" />\n </Icon>\n );\n}\n\nexport function ColumnsIcon(props) {\n return (\n <Icon {...props}>\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"1\" />\n <line x1=\"9\" y1=\"4\" x2=\"9\" y2=\"20\" />\n <line x1=\"15\" y1=\"4\" x2=\"15\" y2=\"20\" />\n </Icon>\n );\n}\n\nexport function BulletedListIcon(props) {\n return (\n <Icon {...props}>\n <circle cx=\"4.5\" cy=\"6\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"4.5\" cy=\"12\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"4.5\" cy=\"18\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\" />\n <line x1=\"9\" y1=\"6\" x2=\"21\" y2=\"6\" />\n <line x1=\"9\" y1=\"12\" x2=\"21\" y2=\"12\" />\n <line x1=\"9\" y1=\"18\" x2=\"21\" y2=\"18\" />\n </Icon>\n );\n}\n\nexport function NumberedListIcon(props) {\n return (\n <Icon {...props}>\n <line x1=\"10\" y1=\"6\" x2=\"21\" y2=\"6\" />\n <line x1=\"10\" y1=\"12\" x2=\"21\" y2=\"12\" />\n <line x1=\"10\" y1=\"18\" x2=\"21\" y2=\"18\" />\n <text x=\"2\" y=\"8.5\" fontSize=\"7\" fontWeight=\"700\" fill=\"currentColor\" stroke=\"none\">\n 1\n </text>\n <text x=\"2\" y=\"14.5\" fontSize=\"7\" fontWeight=\"700\" fill=\"currentColor\" stroke=\"none\">\n 2\n </text>\n <text x=\"2\" y=\"20.5\" fontSize=\"7\" fontWeight=\"700\" fill=\"currentColor\" stroke=\"none\">\n 3\n </text>\n </Icon>\n );\n}\n\nexport function CheckboxIcon(props) {\n return (\n <Icon {...props}>\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"3\" />\n <polyline points=\"8 12 11 15 16 9\" />\n </Icon>\n );\n}\n\nexport function MentionIcon(props) {\n return (\n <Icon {...props}>\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M16 12v1.5a2.5 2.5 0 0 0 5 0V12a9 9 0 1 0-4.5 7.79\" />\n </Icon>\n );\n}\n\nexport function DateIcon(props) {\n return (\n <Icon {...props}>\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"16\" rx=\"2\" />\n <line x1=\"3\" y1=\"10\" x2=\"21\" y2=\"10\" />\n <line x1=\"8\" y1=\"3\" x2=\"8\" y2=\"7\" />\n <line x1=\"16\" y1=\"3\" x2=\"16\" y2=\"7\" />\n </Icon>\n );\n}\n\nexport function SelectIcon(props) {\n return (\n <Icon {...props}>\n <path d=\"M12 3h7a2 2 0 0 1 2 2v7a2 2 0 0 1-.59 1.41l-8 8a2 2 0 0 1-2.82 0l-7-7a2 2 0 0 1 0-2.82l8-8A2 2 0 0 1 12 3z\" />\n <circle cx=\"15.5\" cy=\"8.5\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\" />\n </Icon>\n );\n}\n\nexport function ImageIcon(props) {\n return (\n <Icon {...props}>\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"2\" />\n <circle cx=\"9\" cy=\"10\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\" />\n <path d=\"M4 17l5-5 4 4 4-5 4 6\" />\n </Icon>\n );\n}\n\nexport function VideoIcon(props) {\n return (\n <Icon {...props}>\n <rect x=\"3\" y=\"5\" width=\"14\" height=\"14\" rx=\"2\" />\n <path d=\"M17 10l4-2.5v9L17 14\" />\n </Icon>\n );\n}\n\nexport function EyeIcon(props) {\n return (\n <Icon {...props}>\n <path d=\"M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </Icon>\n );\n}\n\nexport function EyeOffIcon(props) {\n return (\n <Icon {...props}>\n <path d=\"M17.94 17.94A10.94 10.94 0 0 1 12 19c-6.5 0-10-7-10-7a18.5 18.5 0 0 1 5.06-5.94M9.9 4.24A10.94 10.94 0 0 1 12 4c6.5 0 10 7 10 7a18.5 18.5 0 0 1-2.16 3.19\" />\n <path d=\"M14.12 14.12a3 3 0 1 1-4.24-4.24\" />\n <line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\" />\n </Icon>\n );\n}\n\nexport function AudioIcon(props) {\n return (\n <Icon {...props}>\n <line x1=\"4\" y1=\"10\" x2=\"4\" y2=\"14\" />\n <line x1=\"8\" y1=\"7\" x2=\"8\" y2=\"17\" />\n <line x1=\"12\" y1=\"4\" x2=\"12\" y2=\"20\" />\n <line x1=\"16\" y1=\"7\" x2=\"16\" y2=\"17\" />\n <line x1=\"20\" y1=\"10\" x2=\"20\" y2=\"14\" />\n </Icon>\n );\n}\n","import { ParagraphBlock } from './ParagraphBlock.jsx';\nimport { runToHTML, runToPlainText } from '../../inline/marks.js';\nimport { domInlineToRuns } from '../../inline/runOps.js';\nimport { genId } from '../../utils/idGen.js';\nimport { trimSlashQueryAndInsertAfter } from '../shared/blockCommands.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\nimport { TextIcon } from '../../react/icons.jsx';\n\nfunction toHTML(block, ctx) {\n const runs = block.contentIds.map((runId) => ctx.store.getRun(runId));\n return `<p>${runs.map((r) => runToHTML(r, ctx)).join('')}</p>`;\n}\n\nfunction toPlainText(block, ctx) {\n return block.contentIds.map((runId) => runToPlainText(ctx.store.getRun(runId), ctx)).join('');\n}\n\nfunction fromHTML(node, ctx) {\n if (node.tagName !== 'P') return null;\n const runs = domInlineToRuns(node, ctx);\n const block = { id: genId(), type: 'paragraph', parentId: null, contentIds: runs.map((r) => r.id), props: {} };\n return { block, runs };\n}\n\nexport const paragraphBlockType = {\n component: ParagraphBlock,\n isLeaf: true,\n defaultProps: {},\n toHTML,\n toPlainText,\n fromHTML,\n slashCommand: {\n label: 'Text',\n icon: TextIcon,\n keywords: ['paragraph', 'text', 'p'],\n run: (store, ctx) => trimSlashQueryAndInsertAfter(store, ctx, createTextLeafBlock('paragraph')),\n },\n};\n","import { useCallback } from 'react';\nimport { EditableBlockContent } from '../../react/EditableBlockContent.jsx';\nimport { useBlock } from '../../react/useBlock.js';\nimport { useEditorStore, useSelectedBlock } from '../../react/EditorProvider.jsx';\nimport { insertSiblingSplitAtCaretAndFocus } from '../shared/blockCommands.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\nimport { mergeWithPreviousOrDelete } from '../shared/mergeCommands.js';\nimport { isRunsEmpty } from '../shared/blockEmpty.js';\nimport { focusAfterMerge } from '../shared/focusAfterMerge.js';\nimport { focusAdjacentBlock } from '../shared/navigationCommands.js';\n\nexport function HeadingBlock({ id }) {\n const store = useEditorStore();\n const block = useBlock(id);\n const { setSelectedBlockId } = useSelectedBlock();\n\n const handleEnter = useCallback(() => {\n insertSiblingSplitAtCaretAndFocus(store, id, block?.contentIds ?? [], createTextLeafBlock('paragraph'));\n }, [store, id, block]);\n\n const handleBackspaceAtStart = useCallback(() => {\n const focusBlockId = mergeWithPreviousOrDelete(store, id);\n focusAfterMerge(store, focusBlockId, id, setSelectedBlockId);\n }, [store, id, setSelectedBlockId]);\n\n const handleArrowUp = useCallback(() => focusAdjacentBlock(store, id, 'up'), [store, id]);\n const handleArrowDown = useCallback(() => focusAdjacentBlock(store, id, 'down'), [store, id]);\n\n if (!block) return null;\n const level = block.props?.level ?? 3;\n const Tag = `h${level}`;\n const isEmpty = isRunsEmpty(store, block.contentIds);\n\n return (\n <Tag\n className=\"be-heading\"\n data-block-id={id}\n data-empty={isEmpty ? '' : undefined}\n data-placeholder={`Heading ${level}`}\n >\n <EditableBlockContent\n blockId={id}\n runIds={block.contentIds}\n onEnter={handleEnter}\n onBackspaceAtStart={handleBackspaceAtStart}\n onArrowUp={handleArrowUp}\n onArrowDown={handleArrowDown}\n />\n </Tag>\n );\n}\n","import { HeadingBlock } from './HeadingBlock.jsx';\nimport { runToHTML, runToPlainText } from '../../inline/marks.js';\nimport { domInlineToRuns } from '../../inline/runOps.js';\nimport { genId } from '../../utils/idGen.js';\nimport { trimSlashQueryAndInsertAfter } from '../shared/blockCommands.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\nimport { Heading1Icon, Heading2Icon, Heading3Icon } from '../../react/icons.jsx';\n\nconst HEADING_ICONS = { 1: Heading1Icon, 2: Heading2Icon, 3: Heading3Icon };\n\nconst TAG_TO_LEVEL = { H1: 1, H2: 2, H3: 3 };\n\nfunction toHTML(block, ctx) {\n const level = block.props?.level ?? 3;\n const runs = block.contentIds.map((runId) => ctx.store.getRun(runId));\n return `<h${level}>${runs.map((r) => runToHTML(r, ctx)).join('')}</h${level}>`;\n}\n\nfunction toPlainText(block, ctx) {\n return block.contentIds.map((runId) => runToPlainText(ctx.store.getRun(runId), ctx)).join('');\n}\n\nfunction fromHTML(node, ctx) {\n const level = TAG_TO_LEVEL[node.tagName];\n if (!level) return null;\n const runs = domInlineToRuns(node, ctx);\n const block = {\n id: genId(),\n type: 'heading',\n parentId: null,\n contentIds: runs.map((r) => r.id),\n props: { level },\n };\n return { block, runs };\n}\n\nexport const headingBlockType = {\n component: HeadingBlock,\n isLeaf: true,\n defaultProps: { level: 3 },\n toHTML,\n toPlainText,\n fromHTML,\n slashCommands: [\n {\n label: 'Heading 1',\n icon: HEADING_ICONS[1],\n keywords: ['heading', 'h1', 'title'],\n run: (store, ctx) => trimSlashQueryAndInsertAfter(store, ctx, createTextLeafBlock('heading', { level: 1 })),\n },\n {\n label: 'Heading 2',\n icon: HEADING_ICONS[2],\n keywords: ['heading', 'h2', 'subtitle'],\n run: (store, ctx) => trimSlashQueryAndInsertAfter(store, ctx, createTextLeafBlock('heading', { level: 2 })),\n },\n {\n label: 'Heading 3',\n icon: HEADING_ICONS[3],\n keywords: ['heading', 'h3', 'title'],\n run: (store, ctx) => trimSlashQueryAndInsertAfter(store, ctx, createTextLeafBlock('heading', { level: 3 })),\n },\n ],\n};\n","import { useCallback, useSyncExternalStore } from 'react';\nimport { useEditorStore } from './EditorProvider.jsx';\n\n// Stable empty-array reference so a not-yet-existing/childless block never\n// trips the useSyncExternalStore \"snapshot changed\" check by returning a\n// fresh [] every call.\nconst EMPTY_CONTENT_IDS = [];\n\n/**\n * Subscribes only to a block's `contentIds` array reference. EditorStore\n * only replaces that reference when membership/order actually changes\n * (insert/remove/move), never on a leaf edit inside one of the children —\n * so this hook (and the list-rendering component that calls it) does not\n * re-render on every keystroke inside a child, only on structural changes.\n */\nexport function useBlockChildren(parentId) {\n const store = useEditorStore();\n const subscribe = useCallback((onStoreChange) => store.subscribe(parentId, onStoreChange), [store, parentId]);\n const getSnapshot = useCallback(() => {\n const block = store.getBlock(parentId);\n return block ? block.contentIds : EMPTY_CONTENT_IDS;\n }, [store, parentId]);\n return useSyncExternalStore(subscribe, getSnapshot);\n}\n","import { Component, Fragment } from 'react';\n\n/**\n * Wraps a single block's rendered output so that a crash in one block (e.g.\n * a contentEditable/DOM desync throwing during React's commit phase) can't\n * take the whole document down with it — without this, an uncaught error\n * from any single block unmounts the entire root, blanking the page for a\n * problem that only ever affected one paragraph.\n *\n * Recovery is a full remount, not a permanent fallback message: the DOM\n * subtree that threw may be in a state React no longer trusts, so the only\n * sound way back is to throw it away and rebuild fresh from the current\n * store state, which is unaffected (the store is a separate source of\n * truth from the DOM). Bumping `nonce` and keying a Fragment on it forces\n * exactly that remount with zero extra DOM nodes. Recovery happens on the\n * next microtask so React finishes unwinding the failed commit first.\n */\nexport class BlockErrorBoundary extends Component {\n state = { hasError: false, nonce: 0 };\n\n static getDerivedStateFromError() {\n return { hasError: true };\n }\n\n componentDidCatch(error, info) {\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.error('[block-editor] a block failed to render; recovering by remounting it:', error, info);\n }\n this.props.onError?.(error, info);\n queueMicrotask(() => this.setState((s) => ({ hasError: false, nonce: s.nonce + 1 })));\n }\n\n render() {\n if (this.state.hasError) return null; // one brief frame while recovery is queued\n return <Fragment key={this.state.nonce}>{this.props.children}</Fragment>;\n }\n}\n","import { memo } from 'react';\nimport { useBlock } from './useBlock.js';\nimport { useBlockRegistry } from './EditorProvider.jsx';\nimport { BlockErrorBoundary } from './BlockErrorBoundary.jsx';\n\n/**\n * Recursive entry point: given a block id, looks up its type in the\n * registry and renders that type's component. Every block component (leaf\n * or container) receives only `id` — never the whole document — and is\n * memoized here so unrelated blocks skip re-rendering when a sibling's\n * data changes elsewhere in the tree.\n */\nexport const BlockRenderer = memo(function BlockRenderer({ id }) {\n const block = useBlock(id);\n const registry = useBlockRegistry();\n\n if (!block) return null; // about to be removed this frame; render nothing\n\n const entry = registry.get(block.type);\n if (!entry) {\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.warn(`[block-editor] No block type registered for \"${block.type}\" (id: ${id})`);\n }\n return null;\n }\n\n const Component = entry.component;\n return (\n <BlockErrorBoundary>\n <Component id={id} />\n </BlockErrorBoundary>\n );\n});\n","import { useEffect } from 'react';\n\n/**\n * Closes whatever `isOpen` gates when the user clicks outside every ref in\n * `refs`, or presses Escape — the same ~15-line pattern this codebase\n * previously copy-pasted independently in FloatingToolbar, TableHeaderRow's\n * column menu, and Modal. Extracted here so a new consumer (Select) doesn't\n * need a fourth copy; the existing three call sites are left as-is (their\n * own small variations — e.g. Modal's backdrop-click check — aren't worth\n * disturbing for this).\n *\n * `refs` accepts either a single ref or an array of refs — a consumer whose\n * popover is portaled somewhere else in the DOM (e.g. Select's popover,\n * portaled to document.body so it isn't nested inside a contentEditable\n * region) needs a second ref for that portaled element, since it's no\n * longer a DOM descendant of the trigger's own root.\n */\nexport function useOutsideClickAndEscape(refs, isOpen, onClose) {\n useEffect(() => {\n if (!isOpen) return undefined;\n const refList = Array.isArray(refs) ? refs : [refs];\n const handlePointerDown = (event) => {\n const inside = refList.some((ref) => ref.current && ref.current.contains(event.target));\n if (!inside) onClose();\n };\n const handleKeyDown = (event) => {\n if (event.key === 'Escape') onClose();\n };\n document.addEventListener('mousedown', handlePointerDown);\n document.addEventListener('keydown', handleKeyDown);\n return () => {\n document.removeEventListener('mousedown', handlePointerDown);\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [isOpen, onClose, refs]);\n}\n","/**\n * Serializes an ordered list of top-level (sibling) block ids into the three\n * clipboard payloads. All per-type formatting is delegated to the registry\n * (toHTML/toPlainText) — this module only owns cross-block concerns: joining\n * blocks together and grouping consecutive `listItem` blocks into one\n * wrapping <ul>/<ol> (a single list item's toHTML only knows about itself,\n * not its siblings).\n */\nimport { genId } from '../utils/idGen.js';\n\nexport function serializeBlockRange(store, registry, blockIds, inlineRegistry) {\n const ctx = { store, registry, inlineRegistry };\n return {\n html: serializeHTML(store, registry, blockIds, ctx),\n text: blockIds\n .map((id) => {\n const block = store.getBlock(id);\n return registry.get(block.type).toPlainText(block, ctx);\n })\n .join('\\n'),\n json: JSON.stringify({ version: 1, blocks: blockIds.map((id) => captureSubtree(store, id)) }),\n };\n}\n\nfunction serializeHTML(store, registry, blockIds, ctx) {\n let html = '';\n let i = 0;\n while (i < blockIds.length) {\n const block = store.getBlock(blockIds[i]);\n if (block.type === 'listItem') {\n const ordered = Boolean(block.props.ordered);\n let itemsHTML = '';\n let j = i;\n while (j < blockIds.length) {\n const candidate = store.getBlock(blockIds[j]);\n if (candidate.type !== 'listItem' || Boolean(candidate.props.ordered) !== ordered) break;\n itemsHTML += registry.get('listItem').toHTML(candidate, ctx);\n j += 1;\n }\n const tag = ordered ? 'ol' : 'ul';\n html += `<${tag}>${itemsHTML}</${tag}>`;\n i = j;\n } else if (block.type === 'blockquote') {\n // Same grouping idea as listItem above: each blockquote block's own\n // toHTML only emits its own line (a <p>), since the model keeps\n // multi-line quotes as separate sibling blocks rather than one\n // container — consecutive quote siblings share one wrapping\n // <blockquote> on the way out, matching how they'd come back in via\n // domWalk's consumeBlockquote.\n let linesHTML = '';\n let j = i;\n while (j < blockIds.length) {\n const candidate = store.getBlock(blockIds[j]);\n if (candidate.type !== 'blockquote') break;\n linesHTML += registry.get('blockquote').toHTML(candidate, ctx);\n j += 1;\n }\n html += `<blockquote>${linesHTML}</blockquote>`;\n i = j;\n } else {\n html += registry.get(block.type).toHTML(block, ctx);\n i += 1;\n }\n }\n return html;\n}\n\n/**\n * Read-only capture of a block subtree (block + descendants + their runs)\n * — used for the app-specific clipboard JSON, and reused as-is by\n * `duplicateBlock` (see blocks/shared/blockActions.js) since \"clone this\n * subtree with fresh ids\" is exactly the same operation either way.\n */\nexport function captureSubtree(store, rootId) {\n const blocks = [];\n const runs = [];\n const walk = (id) => {\n const run = store.getRun(id);\n if (run) {\n runs.push(run);\n return;\n }\n const block = store.getBlock(id);\n if (!block) return;\n blocks.push(block);\n for (const childId of block.contentIds) walk(childId);\n for (const runId of block.props?.titleRunIds ?? []) walk(runId);\n };\n walk(rootId);\n return { rootId, blocks, runs };\n}\n\n/**\n * Regenerates ids for a captured subtree so pasting the same clipboard\n * contents twice never collides with ids already in the document (or with\n * the ids still referenced by the copy source, if it's the same doc).\n */\nexport function remapSubtreeIds({ rootId, blocks, runs }) {\n const idMap = new Map();\n for (const b of blocks) idMap.set(b.id, genId());\n for (const r of runs) idMap.set(r.id, genId());\n const remap = (id) => idMap.get(id) ?? id;\n\n const newBlocks = blocks.map((b) => ({\n ...b,\n id: remap(b.id),\n parentId: b.parentId ? remap(b.parentId) : b.parentId,\n contentIds: b.contentIds.map(remap),\n props: {\n ...b.props,\n ...(b.props?.titleRunIds ? { titleRunIds: b.props.titleRunIds.map(remap) } : {}),\n },\n }));\n const newRuns = runs.map((r) => ({ ...r, id: remap(r.id) }));\n const newRootId = remap(rootId);\n\n return {\n block: newBlocks.find((b) => b.id === newRootId),\n runs: newRuns,\n subtreeBlocks: newBlocks.filter((b) => b.id !== newRootId),\n };\n}\n","import { insertBlock, removeBlock, moveBlock } from '../../store/operations.js';\nimport { captureSubtree, remapSubtreeIds } from '../../clipboard/serialize.js';\nimport { focusBlockStart } from './navigationCommands.js';\nimport { ensureRootNonEmpty } from './ensureRootNonEmpty.js';\n\n/**\n * Clones `blockId`'s entire subtree (itself + every descendant + their\n * runs, all with fresh ids — see remapSubtreeIds) and inserts the copy\n * right after the original, then focuses the copy's own first typeable\n * position. Reuses the exact same subtree-capture/id-remap machinery the\n * same-editor clipboard JSON path already relies on (see serialize.js) —\n * \"duplicate\" is exactly \"copy, then paste right after itself.\"\n */\nexport function duplicateBlock(store, blockId) {\n const original = store.getBlock(blockId);\n if (!original) return null;\n const parent = store.getBlock(original.parentId);\n const index = parent.contentIds.indexOf(blockId);\n\n const subtree = captureSubtree(store, blockId);\n const { block, runs, subtreeBlocks } = remapSubtreeIds(subtree);\n\n store.applyOperation(insertBlock(block, parent.id, index + 1, { blocks: [block, ...subtreeBlocks], runs }));\n focusBlockStart(store, block.id);\n return block.id;\n}\n\n/**\n * Swaps `blockId` with its previous sibling under the same parent — a\n * no-op (returns false) if it's already first. `moveBlock`'s own `toIndex`\n * is interpreted against the array *after* the block has already been\n * removed from it (see EditorStore's MOVE_BLOCK case) — `index - 1` lands\n * it exactly one slot earlier in that already-shifted array, which is\n * what makes this a plain adjacent swap rather than needing any special\n * \"moving backward\" arithmetic.\n */\nexport function moveBlockUp(store, blockId) {\n const block = store.getBlock(blockId);\n const parent = block && store.getBlock(block.parentId);\n if (!parent) return false;\n const index = parent.contentIds.indexOf(blockId);\n if (index <= 0) return false;\n store.applyOperation(moveBlock(blockId, parent.id, index - 1));\n return true;\n}\n\n/** Symmetric to moveBlockUp: swaps with the next sibling, a no-op if already last. */\nexport function moveBlockDown(store, blockId) {\n const block = store.getBlock(blockId);\n const parent = block && store.getBlock(block.parentId);\n if (!parent) return false;\n const index = parent.contentIds.indexOf(blockId);\n if (index === -1 || index >= parent.contentIds.length - 1) return false;\n store.applyOperation(moveBlock(blockId, parent.id, index + 1));\n return true;\n}\n\n/**\n * Removes `blockId` (its whole subtree) and moves focus to whatever's now\n * in its old spot — the previous sibling, or else the next one, or else\n * (it was the only top-level block) whatever ensureRootNonEmpty falls back\n * to, so there's always still somewhere to land the caret. Same\n * prev-or-next-or-fallback convention as unwrapEmptyContainer/\n * removeTableAndFocusSibling elsewhere in this codebase.\n */\nexport function deleteBlockAndFocusSibling(store, blockId) {\n const block = store.getBlock(blockId);\n if (!block) return null;\n const parent = store.getBlock(block.parentId);\n const index = parent.contentIds.indexOf(blockId);\n const prevId = index > 0 ? parent.contentIds[index - 1] : null;\n const nextId = index !== -1 && index < parent.contentIds.length - 1 ? parent.contentIds[index + 1] : null;\n\n store.applyOperation(removeBlock(blockId));\n const fallbackId = ensureRootNonEmpty(store);\n const targetId = prevId ?? nextId ?? fallbackId;\n if (targetId) focusBlockStart(store, targetId);\n return targetId ?? null;\n}\n","import { useCallback, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useEditorStore, useBlockRangeSelection } from './EditorProvider.jsx';\nimport { useBlock } from './useBlock.js';\nimport { useOutsideClickAndEscape } from './useOutsideClickAndEscape.js';\nimport { BlockRenderer } from './BlockRenderer.jsx';\nimport { insertSiblingAfterAndFocus } from '../blocks/shared/blockCommands.js';\nimport { createTextLeafBlock } from '../blocks/shared/leafBlockFactory.js';\nimport { duplicateBlock, moveBlockUp, moveBlockDown, deleteBlockAndFocusSibling } from '../blocks/shared/blockActions.js';\nimport { updateBlockProps } from '../store/operations.js';\nimport { PlusIcon, GripVerticalIcon, CopyIcon, ArrowUpIcon, ArrowDownIcon, TrashIcon, EyeIcon, EyeOffIcon } from './icons.jsx';\n\n/**\n * Wraps ONE top-level block with a hover-revealed left gutter — a \"+\" to\n * insert a new paragraph right after it, and a grip-handle trigger opening\n * a small menu (Duplicate / Move Up / Move Down / Hide-Show / Delete), the\n * same per-block affordance Notion/TipTap/editor.js all show. Only used for\n * TOP-LEVEL blocks (see BlockChildren's `isTopLevel` prop) — nested\n * content (list item children, table cells, layout columns) doesn't get\n * its own gutter, matching every one of those editors' own convention of\n * only offering this at the outermost level. Never rendered at all in\n * preview mode (see BlockChildren) — a preview isn't something you edit.\n *\n * Deliberately does not implement drag-and-drop reordering itself (a much\n * larger feature on its own) — the grip icon here is just the\n * conventional trigger for the menu; Move Up/Down cover reordering\n * instead. The menu is portaled to document.body (position:fixed off the\n * trigger's own rect), same convention as Select/SlashMenu/the table\n * header menu elsewhere in this codebase.\n *\n * \"Hide\"/\"Show\" toggles a generic `props.hidden` flag — works on any block\n * type since props is a free-form per-block object, no schema change\n * needed anywhere. In edit mode a hidden block still renders with full\n * functionality, just dimmed (see the be-block-row-hidden CSS) as a visual\n * reminder it won't appear once switched to preview mode, where\n * BlockChildren skips it entirely instead.\n *\n * `be-block-row-range-selected` (see useBlockRangeSelection) highlights\n * this row when it's part of a drag-selected block range — the actual\n * drag-start detection lives in useBlockRangeDrag, mounted once at the\n * surface level rather than here, since it needs to catch presses in the\n * blank page margin on either side of the content column too, not just\n * this row's own narrow gutter.\n */\nexport function BlockGutterRow({ id }) {\n const store = useEditorStore();\n const block = useBlock(id);\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n const [rect, setRect] = useState(null);\n const triggerRef = useRef(null);\n const menuRef = useRef(null);\n const outsideRefs = useMemo(() => [triggerRef, menuRef], []);\n const [selectedBlockRange] = useBlockRangeSelection();\n const isRangeSelected = selectedBlockRange.includes(id);\n\n const closeMenu = useCallback(() => setIsMenuOpen(false), []);\n useOutsideClickAndEscape(outsideRefs, isMenuOpen, closeMenu);\n\n const openMenu = useCallback(() => {\n setRect(triggerRef.current?.getBoundingClientRect() ?? null);\n setIsMenuOpen(true);\n }, []);\n\n const handleAdd = useCallback(() => {\n insertSiblingAfterAndFocus(store, id, createTextLeafBlock('paragraph'));\n }, [store, id]);\n\n const handleDuplicate = useCallback(() => {\n duplicateBlock(store, id);\n closeMenu();\n }, [store, id, closeMenu]);\n\n const handleMoveUp = useCallback(() => {\n moveBlockUp(store, id);\n closeMenu();\n }, [store, id, closeMenu]);\n\n const handleMoveDown = useCallback(() => {\n moveBlockDown(store, id);\n closeMenu();\n }, [store, id, closeMenu]);\n\n const handleDelete = useCallback(() => {\n deleteBlockAndFocusSibling(store, id);\n closeMenu();\n }, [store, id, closeMenu]);\n\n const isHidden = Boolean(block?.props?.hidden);\n const handleToggleHidden = useCallback(() => {\n store.applyOperation(updateBlockProps(id, { hidden: !isHidden }));\n closeMenu();\n }, [store, id, isHidden, closeMenu]);\n\n if (!block) return null;\n\n return (\n <div\n className={`be-block-row${isHidden ? ' be-block-row-hidden' : ''}${isRangeSelected ? ' be-block-row-range-selected' : ''}`}\n data-block-row-id={id}\n >\n <div className={`be-block-gutter${isMenuOpen ? ' be-block-gutter-active' : ''}`} contentEditable={false}>\n <button type=\"button\" className=\"be-block-gutter-btn\" onClick={handleAdd} aria-label=\"Add block below\">\n <PlusIcon size={16} />\n </button>\n <button\n ref={triggerRef}\n type=\"button\"\n className=\"be-block-gutter-btn\"\n aria-label=\"More options\"\n aria-haspopup=\"menu\"\n aria-expanded={isMenuOpen}\n onClick={() => (isMenuOpen ? closeMenu() : openMenu())}\n >\n <GripVerticalIcon size={16} />\n </button>\n </div>\n <div className=\"be-block-row-content\">\n <BlockRenderer id={id} />\n </div>\n {isMenuOpen &&\n rect &&\n createPortal(\n <div\n ref={menuRef}\n role=\"menu\"\n aria-label=\"Block options\"\n className=\"be-block-gutter-menu\"\n style={{ position: 'fixed', top: rect.bottom + 4, left: rect.left }}\n >\n <button type=\"button\" role=\"menuitem\" className=\"be-block-gutter-menu-item\" onClick={handleDuplicate}>\n <CopyIcon size={15} /> Duplicate\n </button>\n <button type=\"button\" role=\"menuitem\" className=\"be-block-gutter-menu-item\" onClick={handleMoveUp}>\n <ArrowUpIcon size={15} /> Move up\n </button>\n <button type=\"button\" role=\"menuitem\" className=\"be-block-gutter-menu-item\" onClick={handleMoveDown}>\n <ArrowDownIcon size={15} /> Move down\n </button>\n <button type=\"button\" role=\"menuitem\" className=\"be-block-gutter-menu-item\" onClick={handleToggleHidden}>\n {isHidden ? <EyeIcon size={15} /> : <EyeOffIcon size={15} />}\n {isHidden ? 'Show in preview' : 'Hide in preview'}\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"be-block-gutter-menu-item be-block-gutter-menu-item-danger\"\n onClick={handleDelete}\n >\n <TrashIcon size={15} /> Delete\n </button>\n </div>,\n document.body,\n )}\n </div>\n );\n}\n","import { useBlockChildren } from './useBlockChildren.js';\nimport { useEditorStore, usePreviewMode } from './EditorProvider.jsx';\nimport { BlockRenderer } from './BlockRenderer.jsx';\nimport { BlockGutterRow } from './BlockGutterRow.jsx';\n\n/**\n * Renders the child blocks of any container block. This is the single piece\n * of tree-walking logic shared by every container type (page, list item,\n * table row, table cell-as-container, layout column) — none of them need\n * their own child-rendering loop.\n *\n * `isTopLevel` opts into wrapping each child with the per-block hover\n * gutter (+/duplicate/move/delete/hide — see BlockGutterRow) — pass it only\n * for the ONE call site rendering the document's actual top-level blocks\n * (the page root), never for a nested container's own children: Notion/\n * TipTap/editor.js all restrict this affordance to the outermost level\n * only, and showing it for a table cell's or list item's own content would\n * be visually cramped and semantically confusing (e.g. \"delete\" there\n * could read as deleting the cell/item itself or just its content).\n *\n * In preview mode (see usePreviewMode), the gutter never renders at all —\n * a preview isn't something you edit — and any block whose own\n * `props.hidden` is true is skipped entirely, at every level (not just\n * top-level), rather than rendered dimmed the way edit mode shows it: the\n * whole point of \"hidden\" is that it disappears from what a reader\n * eventually sees.\n */\nexport function BlockChildren({ parentId, isTopLevel = false }) {\n const contentIds = useBlockChildren(parentId);\n const store = useEditorStore();\n const [isPreviewMode] = usePreviewMode();\n\n const visibleIds = isPreviewMode ? contentIds.filter((childId) => !store.getBlock(childId)?.props?.hidden) : contentIds;\n\n if (isTopLevel && !isPreviewMode) {\n return visibleIds.map((childId) => <BlockGutterRow key={childId} id={childId} />);\n }\n return visibleIds.map((childId) => <BlockRenderer key={childId} id={childId} />);\n}\n","const ALPHA_START = 'a'.charCodeAt(0);\nconst ROMAN_TABLE = [\n [1000, 'm'],\n [900, 'cm'],\n [500, 'd'],\n [400, 'cd'],\n [100, 'c'],\n [90, 'xc'],\n [50, 'l'],\n [40, 'xl'],\n [10, 'x'],\n [9, 'ix'],\n [5, 'v'],\n [4, 'iv'],\n [1, 'i'],\n];\n\n/** 1 -> \"a\", 26 -> \"z\", 27 -> \"aa\", ... (spreadsheet-column style, no zero digit). */\nfunction toAlpha(n) {\n let out = '';\n while (n > 0) {\n n -= 1;\n out = String.fromCharCode(ALPHA_START + (n % 26)) + out;\n n = Math.floor(n / 26);\n }\n return out;\n}\n\nfunction toRoman(n) {\n let out = '';\n let rest = n;\n for (const [value, symbol] of ROMAN_TABLE) {\n while (rest >= value) {\n out += symbol;\n rest -= value;\n }\n }\n return out;\n}\n\n/**\n * A \"plain\" list item is one whose marker is a bullet/number (not a to-do\n * checkbox, not a toggle disclosure triangle) — only these participate in\n * numbering/bullet-style cycling at all.\n */\nfunction isPlainMarkerItem(block) {\n return block?.type === 'listItem' && block.props?.checked === undefined && block.props?.collapsed === undefined;\n}\n\n/**\n * How many listItem ancestors this block is nested under — 0 for a\n * top-level item, 1 for its first nested level, and so on. Cycles every 3\n * levels for marker style (matching Notion/Word's numbered-list convention:\n * 1,2,3 -> a,b,c -> i,ii,iii -> 1,2,3 again as you keep nesting), applied\n * uniformly regardless of whether ancestors at those levels happen to be\n * ordered, bulleted, or a mix.\n */\nexport function listItemDepth(store, block) {\n let depth = 0;\n let current = block;\n while (current) {\n const parent = store.getBlock(current.parentId);\n if (!parent || parent.type !== 'listItem') break;\n depth += 1;\n current = parent;\n }\n return depth;\n}\n\n/**\n * This item's 1-based position within its *contiguous run* of ordered\n * sibling list items — counting backward from this item only while\n * immediately-preceding siblings are also plain ordered list items, so\n * numbering restarts at 1 after any interruption (a bullet item, a toggle,\n * a to-do, or a completely different block type), the same way Notion\n * restarts a numbered list after a break rather than continuing a global\n * counter across the whole document.\n */\nexport function orderedItemIndex(store, block, siblingIds) {\n const pos = siblingIds.indexOf(block.id);\n let count = 1;\n for (let i = pos - 1; i >= 0; i -= 1) {\n const sibling = store.getBlock(siblingIds[i]);\n if (!isPlainMarkerItem(sibling) || !sibling.props.ordered) break;\n count += 1;\n }\n return count;\n}\n\n/** e.g. depth 0 -> \"1.\", depth 1 -> \"a.\", depth 2 -> \"i.\", depth 3 -> \"1.\" again. */\nexport function orderedMarkerText(depth, index) {\n const style = ((depth % 3) + 3) % 3;\n if (style === 0) return `${index}.`;\n if (style === 1) return `${toAlpha(index)}.`;\n return `${toRoman(index)}.`;\n}\n\nconst BULLET_GLYPHS = ['•', '◦', '▪'];\n\n/** e.g. depth 0 -> \"•\" (disc), depth 1 -> \"◦\" (circle), depth 2 -> \"▪\" (square), depth 3 -> \"•\" again. */\nexport function bulletMarkerText(depth) {\n const style = ((depth % 3) + 3) % 3;\n return BULLET_GLYPHS[style];\n}\n","import { genId } from '../../utils/idGen.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\n\n/**\n * factory(parentId, initialRuns?) -> {block, runs, subtreeBlocks} for a\n * list item. `checked` left undefined (default) renders a bullet/number\n * marker; passing a boolean turns it into a to-do item with a checkbox\n * marker. `collapsed` left undefined (default) is the same plain bullet/\n * number/todo marker; passing a boolean turns it into a \"toggle\" item\n * instead — a disclosure triangle marker whose nested children (contentIds)\n * render only while `collapsed` is false. `checked` and `collapsed` are\n * mutually exclusive markers in the UI (whichever is set decides which\n * marker renders; see ListItemBlock) — passing both is not a supported\n * combination, matches Notion's own \"one marker style per item\".\n * `initialRuns`, when given (Enter-to-split), seeds the title with the runs\n * that landed after the caret instead of a single blank run.\n *\n * A toggle is seeded with one empty paragraph child right away (same\n * convention as callout/toggleHeading) — without this, a toggle created\n * with no children at all has nothing to expand: its own disclosure\n * marker has nothing to reveal, and there was no other way to get content\n * into it (this was a real dead end for exactly this reason before the\n * seeding was added).\n */\nexport function createListItemBlock({ ordered = false, checked, collapsed } = {}) {\n return function factory(parentId, initialRuns) {\n const blockId = genId();\n const runs = initialRuns?.length ? initialRuns : [{ id: genId(), type: 'text', value: '', marks: {} }];\n const props = { ordered, titleRunIds: runs.map((r) => r.id) };\n if (checked !== undefined) props.checked = checked;\n\n let contentIds = [];\n let subtreeBlocks = [];\n let allRuns = runs;\n if (collapsed !== undefined) {\n props.collapsed = collapsed;\n const { block: childBlock, runs: childRuns } = createTextLeafBlock('paragraph')(blockId);\n contentIds = [childBlock.id];\n subtreeBlocks = [childBlock];\n allRuns = [...runs, ...childRuns];\n }\n\n return {\n block: { id: blockId, type: 'listItem', parentId, contentIds, props },\n runs: allRuns,\n subtreeBlocks,\n };\n };\n}\n","import { moveBlock } from '../../store/operations.js';\nimport { focusAdjacentBlock, focusBlockStart } from '../shared/navigationCommands.js';\n\n/**\n * Tab: makes this list item a child (nested one level deeper) of its\n * previous sibling — but only when that previous sibling is itself a\n * listItem. Nesting under a non-container block (a paragraph, heading,\n * etc.) would silently make this item invisible: only container block\n * types render `<BlockChildren>` for their contentIds, so a listItem\n * reparented under, say, a paragraph would still exist in the store but\n * never be rendered anywhere — this is what \"the whole list disappeared\"\n * turned out to be. When there's no previous sibling to nest under (this\n * is the first item, or no valid listItem precedes it), Tab moves focus to\n * the next block instead of doing nothing silently.\n *\n * moveBlock reparents the item — a different contentIds array now owns it,\n * so React remounts its subtree under the new parent and any DOM focus it\n * had is destroyed. Must explicitly refocus afterward, same as every other\n * reparenting path (outdent-on-Backspace, outdent-on-Enter) already does.\n */\nexport function indentListItem(store, blockId) {\n const block = store.getBlock(blockId);\n const parent = store.getBlock(block.parentId);\n const index = parent.contentIds.indexOf(blockId);\n const prevId = index > 0 ? parent.contentIds[index - 1] : null;\n const prev = prevId ? store.getBlock(prevId) : null;\n\n if (!prev || prev.type !== 'listItem') {\n focusAdjacentBlock(store, blockId, 'down');\n return;\n }\n\n store.applyOperation(moveBlock(blockId, prevId, prev.contentIds.length));\n focusBlockStart(store, blockId);\n}\n\n/**\n * Shift+Tab: promotes this list item to be a sibling of its current parent\n * list item, placed right after it. No-op if the parent isn't itself a\n * list item (i.e. this item is already at the top level). Also reparents\n * (see indentListItem's note above) — refocuses afterward for the same\n * reason.\n */\nexport function outdentListItem(store, blockId) {\n const block = store.getBlock(blockId);\n const currentParent = store.getBlock(block.parentId);\n if (!currentParent || currentParent.type !== 'listItem') return;\n const grandParentId = currentParent.parentId;\n const grandParent = store.getBlock(grandParentId);\n const parentIndex = grandParent.contentIds.indexOf(currentParent.id);\n store.applyOperation(moveBlock(blockId, grandParentId, parentIndex + 1));\n focusBlockStart(store, blockId);\n}\n","import { removeBlock, updateBlockProps, insertBlock } from '../../store/operations.js';\nimport { outdentListItem } from './indentCommands.js';\nimport { isContentlessBlock } from '../shared/contentless.js';\nimport { isRunsEmpty } from '../shared/blockEmpty.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\n\nfunction applyOps(store, ops) {\n if (typeof store.performBatch === 'function') store.performBatch(ops);\n else for (const op of ops) store.applyOperation(op);\n}\n\nexport function isBlankTitle(store, titleRunIds) {\n return titleRunIds.length === 0 || (titleRunIds.length === 1 && (store.getRun(titleRunIds[0])?.value ?? '') === '');\n}\n\n/**\n * True when a list item's own nested content is empty — either no children\n * at all, or just its single seeded blank paragraph, still untouched. A\n * toggle item (collapsed !== undefined) is *always* seeded with one blank\n * paragraph child by createListItemBlock, so checking for literally zero\n * children (as the rest of this file used to) can never be true for a\n * toggle in practice — making an entirely empty toggle permanently\n * undeletable via Backspace. This treats \"just the untouched seeded\n * paragraph\" the same as \"no children\", matching the same fix already\n * applied to toggle heading (see toggleHeading/mergeCommands.js's\n * isBodyEmpty).\n */\nfunction isBodyEmpty(store, block) {\n const childIds = block.contentIds ?? [];\n if (childIds.length === 0) return true;\n if (childIds.length > 1) return false;\n const onlyChild = store.getBlock(childIds[0]);\n return Boolean(onlyChild) && onlyChild.type === 'paragraph' && isRunsEmpty(store, onlyChild.contentIds);\n}\n\n/**\n * Backspace-at-start-of-title behavior for a list item, distinct from\n * mergeWithPreviousOrDelete (paragraph/heading) because a list item's own\n * text lives in props.titleRunIds, not contentIds (contentIds holds nested\n * child items instead).\n *\n * - Previous sibling at this level is contentless (e.g. a divider): delete\n * *it* first and stay put, same convention as mergeWithPreviousOrDelete.\n * - Previous sibling at this level + this item is empty: just delete it.\n * - Previous sibling at this level + this item has text, no nested\n * children of its own: merge its title onto the previous sibling's title\n * (only when the previous sibling is also a listItem) and delete the\n * shell. If it has nested children, merging is skipped (v1 scope — see\n * navigationCommands' similar container-boundary caveat).\n * - No previous sibling, but nested under another list item: outdent\n * instead (matches common list-editor Backspace behavior).\n * - No previous sibling and already top-level: no-op (nothing sensible to\n * merge into without cross-container merging, which is out of scope).\n *\n * Returns `{ focusBlockId, needsRefocus }` or null if nothing happened.\n * `needsRefocus` distinguishes two cases that both return the item's own\n * id: after an outdent the item is reparented (a different contentIds\n * array owns it, so React remounts it and focus is lost — needsRefocus:\n * true); after deleting a preceding divider the item never moved (same\n * parent, same position, no remount — needsRefocus: false, the browser\n * keeps the caret where it already was).\n */\nexport function mergeListItemOrOutdent(store, blockId) {\n const block = store.getBlock(blockId);\n if (!block) return null;\n const parent = store.getBlock(block.parentId);\n const index = parent.contentIds.indexOf(blockId);\n const titleRunIds = block.props.titleRunIds ?? [];\n const titleEmpty = isBlankTitle(store, titleRunIds);\n // Entirely empty means BOTH the title and the nested body are empty (see\n // isBodyEmpty) — an empty title with real nested content underneath\n // (very common for a toggle, whose whole point is holding content under\n // a collapsed/expanded line) must not vanish along with its subtree just\n // because its own title happens to be blank right now.\n const empty = titleEmpty && isBodyEmpty(store, block);\n\n if (index > 0) {\n const prevId = parent.contentIds[index - 1];\n const prev = store.getBlock(prevId);\n\n // An empty CURRENT item goes first, even next to a non-editable\n // previous sibling (divider) — see the matching comment in\n // shared/mergeCommands.js for why this ordering matters.\n if (empty) {\n applyOps(store, [removeBlock(blockId)]);\n return { focusBlockId: prevId, needsRefocus: true };\n }\n\n if (isContentlessBlock(store, prev)) {\n applyOps(store, [removeBlock(prevId)]);\n return { focusBlockId: blockId, needsRefocus: false };\n }\n\n if (prev?.type === 'listItem' && block.contentIds.length === 0) {\n const mergedTitleRunIds = [...(prev.props.titleRunIds ?? []), ...titleRunIds];\n applyOps(store, [\n updateBlockProps(prevId, { titleRunIds: mergedTitleRunIds }),\n updateBlockProps(blockId, { titleRunIds: [] }), // detach before delete\n removeBlock(blockId),\n ]);\n return { focusBlockId: prevId, needsRefocus: true };\n }\n\n return null; // has nested children or previous sibling isn't a listItem: v1 skips this merge\n }\n\n if (parent.type === 'listItem') {\n outdentListItem(store, blockId);\n return { focusBlockId: blockId, needsRefocus: true }; // reparented: remounted, needs explicit refocus\n }\n\n // Top-level first item with nothing before it: real content stays put,\n // matching every other editor's \"Backspace at the absolute start is a\n // no-op when there's something to preserve\". But an entirely empty item\n // should still be removable — same \"never a permanent dead end\" fallback\n // as mergeToggleHeadingOrNoop/mergeWithPreviousOrDelete: without this, a\n // toggle (always seeded with one blank child) could never satisfy the old\n // \"contentIds.length === 0\" check, making it permanently undeletable\n // whenever it happens to be first/only in its container.\n if (!empty) return null;\n\n if (parent.contentIds.length > 1) {\n applyOps(store, [removeBlock(blockId)]);\n return { focusBlockId: store.getBlock(parent.id).contentIds[0], needsRefocus: true };\n }\n\n const { block: fallbackBlock, runs } = createTextLeafBlock('paragraph')(parent.id);\n applyOps(store, [\n insertBlock(fallbackBlock, parent.id, index, { blocks: [fallbackBlock], runs }),\n removeBlock(blockId),\n ]);\n return { focusBlockId: fallbackBlock.id, needsRefocus: true };\n}\n","import { insertBlock, removeBlock, updateBlockProps } from '../../store/operations.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\nimport { focusBlockStart } from '../shared/navigationCommands.js';\n\nfunction applyOps(store, ops) {\n if (typeof store.performBatch === 'function') store.performBatch(ops);\n else for (const op of ops) store.applyOperation(op);\n}\n\n/**\n * Enter on an empty, top-level (not nested under another list item),\n * childless list item exits the list entirely: it's replaced in place by\n * an empty paragraph, and focus moves there. Matches every other list\n * editor's \"Enter on the last empty bullet leaves the list\" convention —\n * the nested case (mergeCommands.js's outdent-on-empty) only pops one\n * level; this is the top-level equivalent that leaves the list altogether.\n */\nexport function exitListItemToParagraph(store, blockId) {\n const block = store.getBlock(blockId);\n const parentId = block.parentId;\n const parent = store.getBlock(parentId);\n const index = parent.contentIds.indexOf(blockId);\n const { block: paragraphBlock, runs } = createTextLeafBlock('paragraph')(parentId);\n\n applyOps(store, [\n insertBlock(paragraphBlock, parentId, index, { blocks: [paragraphBlock], runs }),\n updateBlockProps(blockId, { titleRunIds: [] }), // detach its own (empty) run before deleting\n removeBlock(blockId),\n ]);\n\n focusBlockStart(store, paragraphBlock.id);\n return paragraphBlock.id;\n}\n","import { useCallback } from 'react';\nimport { useBlock } from '../../react/useBlock.js';\nimport { useBlockChildren } from '../../react/useBlockChildren.js';\nimport { EditableBlockContent } from '../../react/EditableBlockContent.jsx';\nimport { BlockChildren } from '../../react/BlockChildren.jsx';\nimport { useEditorStore, useSelectedBlock } from '../../react/EditorProvider.jsx';\nimport { listItemDepth, orderedItemIndex, orderedMarkerText, bulletMarkerText } from './listMarkers.js';\nimport { ChevronRightIcon, ChevronDownIcon } from '../../react/icons.jsx';\nimport { insertSiblingSplitAtCaretAndFocus, insertFirstChildSplitAtCaretAndFocus } from '../shared/blockCommands.js';\nimport { createListItemBlock } from './createListItemBlock.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\nimport { indentListItem, outdentListItem } from './indentCommands.js';\nimport { mergeListItemOrOutdent, isBlankTitle } from './mergeCommands.js';\nimport { exitListItemToParagraph } from './exitListItem.js';\nimport { isRunsEmpty } from '../shared/blockEmpty.js';\nimport { focusAfterMerge } from '../shared/focusAfterMerge.js';\nimport { updateBlockProps, insertBlock } from '../../store/operations.js';\nimport { focusAdjacentBlock } from '../shared/navigationCommands.js';\nimport { focusRunEnd } from '../../react/focusRun.js';\n\nfunction applyOps(store, ops) {\n if (typeof store.performBatch === 'function') store.performBatch(ops);\n else for (const op of ops) store.applyOperation(op);\n}\n\n/**\n * Indentation/nesting is modeled the same way as every other container\n * block (parentId + contentIds referencing child block ids) — a list item's\n * own text lives in props.titleRunIds (run ids) rather than contentIds,\n * since a list item needs both an inline title *and* nested child blocks at\n * once, unlike a pure leaf (paragraph/heading) or pure container (page).\n *\n * When `props.checked` is not undefined, this doubles as a to-do item: the\n * marker becomes a checkbox instead of a bullet/number.\n */\nexport function ListItemBlock({ id }) {\n const store = useEditorStore();\n const block = useBlock(id);\n const { setSelectedBlockId } = useSelectedBlock();\n // Subscribed purely so this item re-renders when a SIBLING is inserted,\n // removed, or reordered at this level — needed to keep its own marker\n // (numbered position, or depth-based bullet/number style) correct, since\n // BlockRenderer's memo would otherwise skip re-rendering this item on a\n // sibling-only structural change (its own block data didn't change).\n // Cheap and scoped to exactly this list level, unlike the parent\n // (BlockChildren) re-rendering, which is unaffected either way.\n const siblingIds = useBlockChildren(block?.parentId);\n\n const handleEnter = useCallback(() => {\n // Enter on an empty item that's nested under another list item pops it\n // out one level instead of creating yet another empty nested item —\n // this is how the caret \"comes out\" of a list, matching every other\n // list-editor's convention (Notion, Workflowy, Word, etc.).\n const titleRunIds = block?.props?.titleRunIds ?? [];\n const parent = store.getBlock(block?.parentId);\n const empty = isBlankTitle(store, titleRunIds);\n\n if (empty && parent?.type === 'listItem') {\n outdentListItem(store, id); // refocuses itself (reparenting remounts the DOM)\n return;\n }\n\n // Enter on an empty, top-level, childless item exits the list\n // altogether (becomes a paragraph) — matches the same convention every\n // other list editor uses for \"Enter on the last empty bullet\".\n const hasNestedChildren = (block?.contentIds?.length ?? 0) > 0;\n if (empty && parent?.type !== 'listItem' && !hasNestedChildren) {\n exitListItemToParagraph(store, id);\n return;\n }\n\n const isTodo = block?.props?.checked !== undefined;\n const isToggle = block?.props?.collapsed !== undefined;\n const factory = createListItemBlock({\n ordered: block?.props?.ordered,\n checked: isTodo ? false : undefined,\n collapsed: isToggle ? false : undefined,\n });\n\n // If this item already has nested children, the new item belongs at\n // the SAME indent level as those children, positioned before them —\n // not as this item's own sibling, which would render below the entire\n // nested list instead of right after the line the caret is on. This\n // does NOT apply to a toggle: its contentIds are the collapsible body,\n // not \"the next line of a continued list\" — Enter on a toggle's own\n // title always creates a new sibling toggle at the same level,\n // matching Notion (Tab is the only way to nest something under it).\n if (hasNestedChildren && !isToggle) {\n insertFirstChildSplitAtCaretAndFocus(store, id, titleRunIds, factory);\n } else {\n insertSiblingSplitAtCaretAndFocus(store, id, titleRunIds, factory);\n }\n }, [store, id, block]);\n\n const handleTab = useCallback(() => indentListItem(store, id), [store, id]);\n const handleShiftTab = useCallback(() => outdentListItem(store, id), [store, id]);\n\n const handleBackspaceAtStart = useCallback(() => {\n const result = mergeListItemOrOutdent(store, id);\n if (!result || !result.needsRefocus) return; // no-op, or stayed in place with no remount\n focusAfterMerge(store, result.focusBlockId, id, setSelectedBlockId);\n }, [store, id, setSelectedBlockId]);\n\n const handleArrowUp = useCallback(() => focusAdjacentBlock(store, id, 'up'), [store, id]);\n const handleArrowDown = useCallback(() => focusAdjacentBlock(store, id, 'down'), [store, id]);\n\n const toggleChecked = useCallback(() => {\n store.applyOperation(updateBlockProps(id, { checked: !block?.props?.checked }));\n }, [store, id, block?.props?.checked]);\n\n const toggleCollapsed = useCallback(() => {\n const hasChildren = (block?.contentIds?.length ?? 0) > 0;\n if (!hasChildren) {\n // A childless toggle has nothing to expand/collapse yet — this was\n // previously a disabled dead end (no way to ever get content into a\n // toggle that didn't happen to be seeded with a child already, e.g.\n // one created before the seeding in createListItemBlock existed, or\n // one whose only child was removed by some other action). Clicking\n // now bootstraps the first (empty) child and expands, the same\n // seeded shape callout/toggleHeading start with.\n const { block: childBlock, runs } = createTextLeafBlock('paragraph')(id);\n applyOps(store, [\n insertBlock(childBlock, id, 0, { blocks: [childBlock], runs }),\n updateBlockProps(id, { collapsed: false }),\n ]);\n focusRunEnd(childBlock.contentIds[0]);\n return;\n }\n store.applyOperation(updateBlockProps(id, { collapsed: !block?.props?.collapsed }));\n }, [store, id, block?.contentIds, block?.props?.collapsed]);\n\n if (!block) return null;\n const { ordered, checked, collapsed, titleRunIds = [] } = block.props;\n const isTodo = checked !== undefined;\n const isToggle = !isTodo && collapsed !== undefined;\n const hasNestedChildren = block.contentIds.length > 0;\n // Best-effort accessible name for the checkbox: a native checkbox with no\n // name reads to a screen reader as just \"checkbox, checked/not checked\",\n // with no indication of *which* to-do it's for. Atomic (non-text) runs\n // contribute nothing here — this is a plain-text summary, not a full\n // serialization.\n const titleText = titleRunIds\n .map((runId) => store.getRun(runId))\n .filter((run) => run?.type === 'text')\n .map((run) => run.value)\n .join('')\n .trim();\n\n return (\n <div className=\"be-list-item\" data-block-id={id}>\n <div className=\"be-list-item-row\">\n {isTodo ? (\n <input\n type=\"checkbox\"\n className=\"be-list-checkbox\"\n checked={Boolean(checked)}\n onChange={toggleChecked}\n aria-label={titleText || 'To-do item'}\n />\n ) : isToggle ? (\n // A real button (not decorative, unlike the plain bullet/number\n // marker below): it's the only way to reveal/hide this item's\n // children, so assistive tech needs to know it's interactive and\n // what state it's in.\n <button\n type=\"button\"\n className=\"be-list-toggle-marker\"\n onClick={toggleCollapsed}\n aria-expanded={!collapsed}\n aria-label={!hasNestedChildren ? 'Add content to toggle' : collapsed ? 'Expand toggle' : 'Collapse toggle'}\n >\n {collapsed ? <ChevronRightIcon /> : <ChevronDownIcon />}\n </button>\n ) : (\n // Decorative: list structure/position is conveyed by the DOM\n // order itself, not by this glyph, so it's hidden from assistive\n // tech. The glyph itself cycles with nesting depth (1,2,3 ->\n // a,b,c -> i,ii,iii for numbered; disc -> circle -> square for\n // bulleted, repeating every 3 levels), matching Notion/Word's\n // convention — see listMarkers.js.\n <span className=\"be-list-marker\" aria-hidden=\"true\">\n {ordered\n ? orderedMarkerText(listItemDepth(store, block), orderedItemIndex(store, block, siblingIds))\n : bulletMarkerText(listItemDepth(store, block))}\n </span>\n )}\n <div\n className=\"be-list-item-title\"\n data-empty={isRunsEmpty(store, titleRunIds) ? '' : undefined}\n data-placeholder={isTodo ? 'To-do' : isToggle ? 'Toggle' : 'List item'}\n style={checked ? { textDecoration: 'line-through', opacity: 0.6 } : undefined}\n >\n <EditableBlockContent\n blockId={id}\n runIds={titleRunIds}\n onEnter={handleEnter}\n onTab={handleTab}\n onShiftTab={handleShiftTab}\n onBackspaceAtStart={handleBackspaceAtStart}\n onArrowUp={handleArrowUp}\n onArrowDown={handleArrowDown}\n />\n </div>\n </div>\n {/*\n A toggle's children stay in the store (contentIds unchanged) while\n collapsed — only the DOM for them is skipped. Copy/cut/paste,\n select-all, and serialization all walk contentIds directly and have\n no notion of \"collapsed\" at all, so a collapsed toggle's hidden\n content still copies/serializes/undoes correctly for free; this is\n the only place collapsed state has any effect.\n */}\n {(!isToggle || !collapsed) && (\n <div className=\"be-list-item-children\">\n <BlockChildren parentId={id} />\n </div>\n )}\n </div>\n );\n}\n","import { ListItemBlock } from './ListItemBlock.jsx';\nimport { runToHTML, runToPlainText } from '../../inline/marks.js';\nimport { domInlineToRuns } from '../../inline/runOps.js';\nimport { genId } from '../../utils/idGen.js';\nimport { trimSlashQueryAndInsertAfter } from '../shared/blockCommands.js';\nimport { createListItemBlock } from './createListItemBlock.js';\nimport { BulletedListIcon, NumberedListIcon, CheckboxIcon, ChevronRightIcon } from '../../react/icons.jsx';\n\n/**\n * Emits just `<li>...</li>` (with nested `<ul>/<ol>` for indented children).\n * Grouping consecutive sibling list items into one wrapping `<ul>/<ol>` is\n * the container serializer's job (see clipboard/serialize.js), not this\n * block type's — a single item doesn't know about its siblings.\n */\nfunction toHTML(block, ctx) {\n const { titleRunIds = [], ordered } = block.props;\n const titleHTML = titleRunIds.map((runId) => runToHTML(ctx.store.getRun(runId), ctx)).join('');\n const childrenHTML = block.contentIds\n .map((childId) => ctx.registry.get(ctx.store.getBlock(childId).type).toHTML(ctx.store.getBlock(childId), ctx))\n .join('');\n const nested = childrenHTML ? `<${ordered ? 'ol' : 'ul'}>${childrenHTML}</${ordered ? 'ol' : 'ul'}>` : '';\n return `<li>${titleHTML}${nested}</li>`;\n}\n\nfunction toPlainText(block, ctx) {\n const { titleRunIds = [] } = block.props;\n return titleRunIds.map((runId) => runToPlainText(ctx.store.getRun(runId), ctx)).join('');\n}\n\n/** Builds one list item block (+ its nested list items) from a single <li>. */\nfunction fromLiNode(liNode, ctx) {\n const inlineNodes = [];\n const nestedListNodes = [];\n for (const child of liNode.childNodes) {\n if (child.nodeType === 1 && (child.tagName === 'UL' || child.tagName === 'OL')) {\n nestedListNodes.push(child);\n } else {\n inlineNodes.push(child);\n }\n }\n\n const wrapper = liNode.ownerDocument.createElement('span');\n for (const n of inlineNodes) wrapper.appendChild(n.cloneNode(true));\n const titleRuns = domInlineToRuns(wrapper, ctx);\n\n const blockId = genId();\n const childRuns = [...titleRuns];\n const childBlocks = [];\n const contentIds = [];\n\n for (const listNode of nestedListNodes) {\n const ordered = listNode.tagName === 'OL';\n for (const li of listNode.children) {\n if (li.tagName !== 'LI') continue;\n const nested = fromLiNode(li, ctx);\n nested.block.parentId = blockId;\n nested.block.props.ordered = ordered;\n childBlocks.push(nested.block, ...nested.childBlocks);\n childRuns.push(...nested.runs);\n contentIds.push(nested.block.id);\n }\n }\n\n const block = {\n id: blockId,\n type: 'listItem',\n parentId: null,\n contentIds,\n props: { ordered: false, titleRunIds: titleRuns.map((r) => r.id) },\n };\n\n return { block, runs: childRuns, childBlocks };\n}\n\nfunction fromHTML(node, ctx) {\n if (node.tagName !== 'LI') return null;\n const { block, runs, childBlocks } = fromLiNode(node, ctx);\n return { block, runs, subtreeBlocks: childBlocks };\n}\n\nexport const listItemBlockType = {\n component: ListItemBlock,\n isLeaf: false,\n defaultProps: { ordered: false, titleRunIds: [] },\n toHTML,\n toPlainText,\n fromHTML,\n slashCommands: [\n {\n label: 'Bulleted list',\n icon: BulletedListIcon,\n keywords: ['list', 'bullet', 'ul'],\n run: (store, ctx) => trimSlashQueryAndInsertAfter(store, ctx, createListItemBlock({ ordered: false })),\n },\n {\n label: 'Numbered list',\n icon: NumberedListIcon,\n keywords: ['list', 'number', 'ordered', 'ol'],\n run: (store, ctx) => trimSlashQueryAndInsertAfter(store, ctx, createListItemBlock({ ordered: true })),\n },\n {\n label: 'To-do list',\n icon: CheckboxIcon,\n keywords: ['todo', 'checkbox', 'task', 'checklist'],\n run: (store, ctx) =>\n trimSlashQueryAndInsertAfter(store, ctx, createListItemBlock({ ordered: false, checked: false })),\n },\n {\n label: 'Toggle list',\n icon: ChevronRightIcon,\n keywords: ['toggle', 'collapse', 'expand', 'dropdown', 'accordion'],\n run: (store, ctx) =>\n trimSlashQueryAndInsertAfter(store, ctx, createListItemBlock({ ordered: false, collapsed: false })),\n },\n ],\n};\n","import { genId } from '../../utils/idGen.js';\n\nexport const COLUMN_TYPES = ['text', 'date', 'checkbox', 'select'];\nexport const DEFAULT_COLUMN_TYPE = 'text';\nexport const DEFAULT_COLUMN_WIDTH = 160;\nexport const MIN_COLUMN_WIDTH = 80;\n\nexport function defaultColumnLabel(index) {\n return `Column ${index + 1}`;\n}\n\nexport function createDefaultColumns(count) {\n return Array.from({ length: count }, (_, i) => ({\n id: genId(),\n label: defaultColumnLabel(i),\n type: DEFAULT_COLUMN_TYPE,\n width: DEFAULT_COLUMN_WIDTH,\n }));\n}\n\n/**\n * Returns a table's column metadata (`{ id, label, type, width }` per\n * column), falling back to generated (all-text, default-width) defaults\n * when it's missing or the wrong length — a table pasted in from external\n * HTML, loaded from a document saved before this feature existed, or\n * hand-built by a host app never had a chance to set `props.columns` at\n * all, and it's cheap insurance against a stale array (e.g. a column\n * added/removed through a code path that didn't know to keep it in sync)\n * ever crashing the header row instead of just re-deriving something\n * sensible. Also fills in `type: 'text'`/`width: DEFAULT_COLUMN_WIDTH` for\n * any column entry that predates those fields.\n */\nexport function resolveColumns(table, colCount) {\n const columns = table.props?.columns;\n if (!Array.isArray(columns) || columns.length !== colCount) return createDefaultColumns(colCount);\n return columns.map((c) => {\n const type = c.type ?? DEFAULT_COLUMN_TYPE;\n const width = c.width ?? DEFAULT_COLUMN_WIDTH;\n return type === c.type && width === c.width ? c : { ...c, type, width };\n });\n}\n\n/**\n * A blank run of the given column type — the shape reused table-wide,\n * whether creating a fresh cell or converting an existing one. A \"select\"\n * column's runs are `tableSelect` runs with no options of their own — the\n * shared, column-level `options` array (see resolveColumns) is the single\n * source of truth every cell's dropdown reads from, so a brand new blank\n * cell in an already-typed select column immediately gets the same\n * choices as every other cell in that column, with nothing to seed here.\n */\nexport function blankRunForType(type) {\n switch (type) {\n case 'date':\n return { id: genId(), type: 'date', value: '', marks: {}, data: { isoDate: '' } };\n case 'checkbox':\n return { id: genId(), type: 'checkbox', value: '', marks: {}, data: { checked: false, label: '' } };\n case 'select':\n return { id: genId(), type: 'tableSelect', value: '', marks: {}, data: { selectedValue: '', selectedLabel: '' } };\n default:\n return { id: genId(), type: 'text', value: '', marks: {} };\n }\n}\n\n/** A fresh empty cell block + its one run, matching `column`'s type — the single \"create a table cell\" primitive every row/column insert path shares. */\nexport function createCellForColumn(parentId, column) {\n const run = blankRunForType(column?.type);\n return { block: { id: genId(), type: 'tableCell', parentId, contentIds: [run.id], props: {} }, run };\n}\n\n/**\n * Converts one existing run to `newType`, attempting to preserve its data\n * rather than silently discarding it (the bug this whole feature set was\n * partly motivated by fixing, compared to the legacy notevo table's\n * \"change type wipes the cell\" behavior). Converting *from* a non-text\n * atomic type reads its plain-text value via the old type's own\n * `toPlainText` (through the inline registry) rather than needing a\n * hand-written conversion for every type pair — e.g. a date becomes its\n * formatted string, which then seeds the new checkbox's label, etc.\n * `inlineRegistry` may be omitted only when `run.type` is already `'text'`\n * (no lookup needed for that case).\n *\n * Does NOT handle `newType === 'select'` — converting a whole column *to*\n * select needs to look at every cell together (to build one shared,\n * deduplicated option list), which a single-run function can't do; see\n * setColumnType's own dedicated handling for that case instead.\n */\nexport function convertRunToType(run, newType, inlineRegistry) {\n if (run.type === newType) return run;\n\n let text;\n if (run.type === 'text') {\n text = run.value ?? '';\n } else {\n const entry = inlineRegistry?.get(run.type);\n text = entry?.toPlainText ? entry.toPlainText(run) : '';\n }\n\n if (newType === 'date') {\n const parsed = text ? new Date(text) : null;\n const isoDate = parsed && !Number.isNaN(parsed.getTime()) ? parsed.toISOString().slice(0, 10) : '';\n return { id: genId(), type: 'date', value: '', marks: {}, data: { isoDate } };\n }\n if (newType === 'checkbox') {\n return { id: genId(), type: 'checkbox', value: '', marks: {}, data: { checked: false, label: text } };\n }\n return { id: genId(), type: 'text', value: text, marks: {} };\n}\n","import { removeBlock, insertBlock, updateBlockProps, setBlockRuns, updateRun } from '../../store/operations.js';\nimport { genId } from '../../utils/idGen.js';\nimport { focusBlockStart } from '../shared/navigationCommands.js';\nimport { ensureRootNonEmpty } from '../shared/ensureRootNonEmpty.js';\nimport { resolveColumns, createCellForColumn, convertRunToType, DEFAULT_COLUMN_TYPE, DEFAULT_COLUMN_WIDTH, MIN_COLUMN_WIDTH } from './tableColumns.js';\n\nfunction applyOps(store, ops) {\n if (typeof store.performBatch === 'function') store.performBatch(ops);\n else for (const op of ops) store.applyOperation(op);\n}\n\n/** Removes the whole table (used when deleting its last row/column) and focuses whatever's now at its old position. */\nfunction removeTableAndFocusSibling(store, table) {\n const parent = store.getBlock(table.parentId);\n const tableIndex = parent.contentIds.indexOf(table.id);\n applyOps(store, [removeBlock(table.id)]);\n\n // The table may have been the only block in the whole document — never\n // leave the document with zero blocks (see ensureRootNonEmpty).\n const fallbackParagraphId = ensureRootNonEmpty(store);\n if (fallbackParagraphId) {\n focusBlockStart(store, fallbackParagraphId);\n return null;\n }\n\n const parentAfter = store.getBlock(table.parentId);\n const siblingId = parentAfter.contentIds[tableIndex] ?? parentAfter.contentIds[tableIndex - 1];\n if (siblingId) focusBlockStart(store, siblingId);\n return null;\n}\n\n/**\n * Inserts a new empty row right after `rowId`, with the same column count,\n * and focuses its first cell. Each new cell matches its own column's\n * configured type (see tableColumns.js) — a date/select/checkbox column\n * keeps getting date/select/checkbox cells for every row added after it\n * was typed, not a plain blank text cell.\n */\nexport function insertRowAfter(store, rowId) {\n const row = store.getBlock(rowId);\n const table = store.getBlock(row.parentId);\n const rowIndex = table.contentIds.indexOf(rowId);\n const columns = resolveColumns(table, row.contentIds.length);\n\n const newRowId = genId();\n const cellBlocks = [];\n const runs = [];\n const contentIds = [];\n for (const column of columns) {\n const cell = createCellForColumn(newRowId, column);\n cellBlocks.push(cell.block);\n runs.push(cell.run);\n contentIds.push(cell.block.id);\n }\n const newRow = { id: newRowId, type: 'tableRow', parentId: table.id, contentIds, props: {} };\n\n store.applyOperation(insertBlock(newRow, table.id, rowIndex + 1, { blocks: [newRow, ...cellBlocks], runs }));\n focusBlockStart(store, newRowId);\n return newRowId;\n}\n\n/**\n * Removes a row. If it's the table's only row, removes the whole table\n * instead (nothing left to show otherwise) and focuses the block now at\n * the table's old position. Otherwise focuses the row that ends up in the\n * same slot (the next row, or the new-last row if the deleted one was last).\n */\nexport function deleteRow(store, rowId) {\n const row = store.getBlock(rowId);\n const table = store.getBlock(row.parentId);\n\n if (table.contentIds.length <= 1) {\n return removeTableAndFocusSibling(store, table);\n }\n\n const rowIndex = table.contentIds.indexOf(rowId);\n applyOps(store, [removeBlock(rowId)]);\n\n const updatedTable = store.getBlock(table.id);\n const targetRowIndex = Math.min(rowIndex, updatedTable.contentIds.length - 1);\n const targetRowId = updatedTable.contentIds[targetRowIndex];\n if (targetRowId) focusBlockStart(store, targetRowId);\n return targetRowId ?? null;\n}\n\n/** Inserts a new (always plain-text) column at `colIndex + 1` in every row of the table, and focuses the first new cell. One atomic undo step, including the new column's metadata. */\nexport function insertColumnAfter(store, tableId, colIndex) {\n const table = store.getBlock(tableId);\n const currentColumns = resolveColumns(table, table.contentIds[0] ? store.getBlock(table.contentIds[0]).contentIds.length : 0);\n const newColumn = { id: genId(), label: 'New Column', type: DEFAULT_COLUMN_TYPE, width: DEFAULT_COLUMN_WIDTH };\n const ops = [];\n let firstNewCellId = null;\n\n for (const rowId of table.contentIds) {\n const cell = createCellForColumn(rowId, newColumn);\n if (firstNewCellId === null) firstNewCellId = cell.block.id;\n ops.push(insertBlock(cell.block, rowId, colIndex + 1, { blocks: [cell.block], runs: [cell.run] }));\n }\n\n const nextColumns = [...currentColumns];\n nextColumns.splice(colIndex + 1, 0, newColumn);\n ops.push(updateBlockProps(tableId, { columns: nextColumns }));\n\n applyOps(store, ops);\n if (firstNewCellId) focusBlockStart(store, firstNewCellId);\n return firstNewCellId;\n}\n\n/**\n * Removes the cell at `colIndex` from every row. If it's the table's only\n * column, removes the whole table instead (same convention as deleteRow).\n * Otherwise focuses the cell now in the same column slot of the first row.\n * One atomic undo step, including the removed column's metadata.\n */\nexport function deleteColumn(store, tableId, colIndex) {\n const table = store.getBlock(tableId);\n const firstRow = store.getBlock(table.contentIds[0]);\n\n if (!firstRow || firstRow.contentIds.length <= 1) {\n return removeTableAndFocusSibling(store, table);\n }\n\n const currentColumns = resolveColumns(table, firstRow.contentIds.length);\n const ops = table.contentIds.map((rowId) => {\n const row = store.getBlock(rowId);\n return removeBlock(row.contentIds[colIndex]);\n });\n const nextColumns = currentColumns.filter((_, i) => i !== colIndex);\n ops.push(updateBlockProps(tableId, { columns: nextColumns }));\n applyOps(store, ops);\n\n const updatedFirstRow = store.getBlock(table.contentIds[0]);\n const targetColIndex = Math.min(colIndex, updatedFirstRow.contentIds.length - 1);\n const targetCellId = updatedFirstRow.contentIds[targetColIndex];\n if (targetCellId) focusBlockStart(store, targetCellId);\n return targetCellId ?? null;\n}\n\n/** Sets the column at `colIndex`'s pixel width (clamped to MIN_COLUMN_WIDTH) — one atomic undo step. */\nexport function setColumnWidth(store, tableId, colIndex, width) {\n const table = store.getBlock(tableId);\n const firstRow = store.getBlock(table.contentIds[0]);\n const currentColumns = resolveColumns(table, firstRow ? firstRow.contentIds.length : 0);\n if (!currentColumns[colIndex]) return;\n const nextColumns = [...currentColumns];\n nextColumns[colIndex] = { ...currentColumns[colIndex], width: Math.max(MIN_COLUMN_WIDTH, Math.round(width)) };\n store.applyOperation(updateBlockProps(tableId, { columns: nextColumns }));\n}\n\n/** Renames the column at `colIndex` — one atomic undo step. */\nexport function renameColumn(store, tableId, colIndex, label) {\n const table = store.getBlock(tableId);\n const firstRow = store.getBlock(table.contentIds[0]);\n const currentColumns = resolveColumns(table, firstRow ? firstRow.contentIds.length : 0);\n const nextColumns = [...currentColumns];\n if (!nextColumns[colIndex]) return;\n nextColumns[colIndex] = { ...nextColumns[colIndex], label };\n store.applyOperation(updateBlockProps(tableId, { columns: nextColumns }));\n}\n\nfunction cellRunsForColumn(store, table, colIndex) {\n return table.contentIds.map((rowId) => {\n const row = store.getBlock(rowId);\n const cellId = row.contentIds[colIndex];\n const cell = store.getBlock(cellId);\n return { cellId, run: store.getRun(cell.contentIds[0]) };\n });\n}\n\nfunction runPlainText(run, inlineRegistry) {\n if (!run) return '';\n if (run.type === 'text') return run.value ?? '';\n const entry = inlineRegistry?.get(run.type);\n return entry?.toPlainText ? entry.toPlainText(run) : '';\n}\n\n/**\n * Changing a column *to* select needs every cell's current value at once\n * (to build one shared, deduplicated option list — Notion's own \"text ->\n * select\" convention: one tag per distinct existing string, not one per\n * cell), which is why it's split out from the generic per-run\n * convertRunToType. Each cell is assigned whichever option matches its own\n * former text (blank cells stay unselected).\n */\nfunction buildSelectColumnConversion(store, table, colIndex, inlineRegistry) {\n const cellRuns = cellRunsForColumn(store, table, colIndex);\n const options = [];\n const optionByLabel = new Map();\n\n for (const { run } of cellRuns) {\n const text = runPlainText(run, inlineRegistry).trim();\n if (!text || optionByLabel.has(text)) continue;\n const option = { value: genId(), label: text };\n optionByLabel.set(text, option);\n options.push(option);\n }\n\n const newRuns = cellRuns.map(({ cellId, run }) => {\n const text = runPlainText(run, inlineRegistry).trim();\n const option = optionByLabel.get(text);\n return { cellId, run: { id: genId(), type: 'tableSelect', value: '', marks: {}, data: { selectedValue: option?.value ?? '', selectedLabel: option?.label ?? '' } } };\n });\n\n return { options, newRuns };\n}\n\n/**\n * Changes the column at `colIndex` to `newType`, converting every existing\n * cell's run in that column instead of discarding their data (unlike the\n * legacy notevo table this was modeled after, which silently wiped a\n * column's values on any type change). `inlineRegistry` is needed to read\n * a non-text run's plain-text value when converting *away* from an atomic\n * type (date/checkbox/select) — pass the one from `useInlineRegistry()`.\n * One atomic undo step for the whole column, metadata and every cell\n * together.\n */\nexport function setColumnType(store, tableId, colIndex, newType, inlineRegistry) {\n const table = store.getBlock(tableId);\n const firstRow = store.getBlock(table.contentIds[0]);\n const currentColumns = resolveColumns(table, firstRow ? firstRow.contentIds.length : 0);\n const column = currentColumns[colIndex];\n if (!column || column.type === newType) return;\n\n const nextColumns = [...currentColumns];\n\n if (newType === 'select') {\n const { options, newRuns } = buildSelectColumnConversion(store, table, colIndex, inlineRegistry);\n nextColumns[colIndex] = { ...column, type: newType, options };\n const ops = [updateBlockProps(tableId, { columns: nextColumns })];\n for (const { cellId, run } of newRuns) ops.push(setBlockRuns(cellId, [run]));\n applyOps(store, ops);\n return;\n }\n\n nextColumns[colIndex] = { ...column, type: newType };\n const ops = [updateBlockProps(tableId, { columns: nextColumns })];\n for (const { cellId, run: oldRun } of cellRunsForColumn(store, table, colIndex)) {\n if (!oldRun) continue;\n const newRun = convertRunToType(oldRun, newType, inlineRegistry);\n ops.push(setBlockRuns(cellId, [newRun]));\n }\n applyOps(store, ops);\n}\n\n/**\n * Replaces a \"select\" column's shared option list — the header menu's\n * add/rename/remove-option UI, acting on the whole column at once (unlike\n * the general inline `select` type's per-cell add/remove buttons). Any\n * cell whose `selectedValue` no longer matches a surviving option (i.e.\n * that option was removed) is cleared back to unselected rather than left\n * pointing at a dangling id; a cell whose option was only *renamed* keeps\n * its selection and just picks up the new label. One atomic undo step.\n */\nexport function setColumnOptions(store, tableId, colIndex, options) {\n const table = store.getBlock(tableId);\n const firstRow = store.getBlock(table.contentIds[0]);\n const currentColumns = resolveColumns(table, firstRow ? firstRow.contentIds.length : 0);\n const column = currentColumns[colIndex];\n if (!column) return;\n\n const nextColumns = [...currentColumns];\n nextColumns[colIndex] = { ...column, options };\n const ops = [updateBlockProps(tableId, { columns: nextColumns })];\n\n const optionById = new Map(options.map((o) => [o.value, o]));\n for (const { run } of cellRunsForColumn(store, table, colIndex)) {\n if (!run || run.type !== 'tableSelect') continue;\n const selectedValue = run.data?.selectedValue ?? '';\n const match = optionById.get(selectedValue);\n const nextSelectedValue = match ? selectedValue : '';\n const nextSelectedLabel = match ? match.label : '';\n if (nextSelectedValue !== selectedValue || nextSelectedLabel !== (run.data?.selectedLabel ?? '')) {\n ops.push(updateRun(run.id, { data: { selectedValue: nextSelectedValue, selectedLabel: nextSelectedLabel } }));\n }\n }\n\n applyOps(store, ops);\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ChevronDownIcon } from './icons.jsx';\nimport { useOutsideClickAndEscape } from './useOutsideClickAndEscape.js';\n\nfunction matchesQuery(option, query) {\n if (!query) return true;\n return option.label.toLowerCase().includes(query.toLowerCase());\n}\n\n/**\n * A lightweight, dependency-free \"searchable select\" (Ant Design Select-\n * style combobox) used everywhere this editor previously used a native\n * `<select>`: a trigger button showing the current value, opening a\n * fixed-position popover with a search input and a filtered, keyboard-\n * navigable option list on click. A native `<select>`'s own dropdown can't\n * be styled or searched, which is the whole reason this exists — visually\n * and behaviorally consistent across every dropdown in the editor instead\n * of each one looking like the browser's own chrome.\n *\n * `options` is `[{ value, label }]`; `onChange(value, option)` fires on\n * pick (both are passed since several call sites want the option's label\n * too, e.g. to store alongside its id). Deliberately does NOT support\n * creating new options inline — that's each call site's own concern (e.g.\n * a table's \"select\" column options are managed via TableHeaderRow's own\n * add/rename/remove UI) — this component only ever picks one of the\n * options it's given.\n *\n * The popover (search input + option list) is rendered via a portal to\n * `document.body` — same as SlashMenu/FloatingToolbar, which are also\n * mounted as siblings of the contentEditable tree, never nested inside it.\n * Several call sites mount this *trigger* deep inside an atomic\n * contentEditable=false inline chip (select/table-select/custom field type), which\n * itself lives inside a contentEditable=true paragraph. A real, focusable\n * `<input>` — unlike a native `<select>`'s own OS-level dropdown, which\n * never actually hands page focus to anything — left nested that deep\n * fights the surrounding contentEditable region for focus in ways real\n * browsers resolve inconsistently (and jsdom doesn't reproduce at all):\n * the very first character typed could land back in the paragraph instead\n * of the search box, since a real native `<input>` there is a genuinely new\n * DOM subtree fighting for focus a native `<select>` never had to. Portaling\n * the popover out to `document.body` sidesteps the whole problem — it's a\n * true DOM sibling of the editor surface, not a descendant, so it can never\n * lose that tug-of-war.\n *\n * `variant=\"tag\"` renders the selected value (and each option in the list)\n * as a small colored pill instead of plain text in a bordered/chevroned\n * box — Notion's own Select-property look. Pass `color: { bg, text }` on\n * each option for this (see blocks/table/tagColors.js); the trigger itself\n * loses its border/background/chevron chrome entirely in this mode — just\n * the pill (or the placeholder, if nothing's chosen yet) is clickable.\n *\n * `options` may also be a function `(query) => Option[] | Promise<Option[]>`\n * instead of a plain array — this is how custom field types (see\n * createSelectFieldType) support DB/API-backed option sources (react-\n * select's `loadOptions`, essentially) alongside plain static lists,\n * through the exact same component and contract. When `options` is a\n * function it's called fresh on every query change (debounced ~250ms so\n * fast typing doesn't fire one request per keystroke) — deliberately no\n * caching layer here, so the host's own resolver is always the source of\n * truth for a given query; any caching is that function's own concern.\n * Static array callers are entirely unaffected: filtering there stays\n * synchronous and instant, exactly as before.\n *\n * Since a dynamic resolver's currently-loaded page may not contain the\n * option matching the CURRENT value (it was picked under a different\n * query, or came from elsewhere), pass `selectedLabel` to control what the\n * trigger displays for the current value directly, instead of relying on\n * an `options.find(...)` lookup that only works for static arrays.\n */\nexport function Select({\n value,\n options,\n onChange,\n placeholder = 'Select…',\n ariaLabel,\n className = '',\n variant = 'default',\n selectedLabel,\n selectedColor,\n onManageOptions,\n manageOptionsLabel = 'Manage options…',\n}) {\n const [isOpen, setIsOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [activeIndex, setActiveIndex] = useState(0);\n const [rect, setRect] = useState(null);\n const [asyncOptions, setAsyncOptions] = useState([]);\n const [isLoading, setIsLoading] = useState(false);\n const [loadError, setLoadError] = useState(false);\n const rootRef = useRef(null);\n const buttonRef = useRef(null);\n const popoverRef = useRef(null);\n const inputRef = useRef(null);\n const activeOptionRef = useRef(null);\n const outsideRefs = useMemo(() => [rootRef, popoverRef], []);\n const isTag = variant === 'tag';\n const isDynamic = typeof options === 'function';\n\n const staticSelected = !isDynamic ? options.find((o) => o.value === value) : undefined;\n const selected = value\n ? (staticSelected ?? (selectedLabel ? { value, label: selectedLabel, color: selectedColor } : undefined))\n : undefined;\n\n const filtered = useMemo(\n () => (isDynamic ? asyncOptions : options.filter((o) => matchesQuery(o, query))),\n [isDynamic, asyncOptions, options, query],\n );\n\n // Dynamic resolvers already do their own query-based filtering (a DB\n // search, typically) — refetch on every query change while the popover\n // is open, debounced so a fast typist doesn't fire one call per keystroke.\n useEffect(() => {\n if (!isDynamic || !isOpen) return undefined;\n let cancelled = false;\n setIsLoading(true);\n setLoadError(false);\n const timer = setTimeout(() => {\n Promise.resolve(options(query))\n .then((result) => {\n if (cancelled) return;\n setAsyncOptions(result ?? []);\n setIsLoading(false);\n })\n .catch(() => {\n if (cancelled) return;\n setAsyncOptions([]);\n setIsLoading(false);\n setLoadError(true);\n });\n }, 250);\n return () => {\n cancelled = true;\n clearTimeout(timer);\n };\n }, [isDynamic, isOpen, options, query]);\n\n const close = useCallback(() => setIsOpen(false), []);\n\n useOutsideClickAndEscape(outsideRefs, isOpen, close);\n\n const open = useCallback(() => {\n setRect(buttonRef.current?.getBoundingClientRect() ?? null);\n setQuery('');\n setActiveIndex(0);\n setIsOpen(true);\n }, []);\n\n useEffect(() => {\n if (isOpen) inputRef.current?.focus();\n }, [isOpen]);\n\n // Keeps the keyboard-active option (Arrow Up/Down) visible as it moves\n // past the edge of the scrollable list — without this, arrowing down\n // past the bottom of a long option list leaves the \"active\" highlight\n // scrolled out of view with nothing on screen showing which one it is.\n useEffect(() => {\n activeOptionRef.current?.scrollIntoView?.({ block: 'nearest' });\n }, [activeIndex]);\n\n const selectOption = useCallback(\n (option) => {\n onChange(option.value, option);\n close();\n buttonRef.current?.focus();\n },\n [onChange, close],\n );\n\n const handleSearchKeyDown = useCallback(\n (event) => {\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n setActiveIndex((i) => Math.min(i + 1, Math.max(filtered.length - 1, 0)));\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n setActiveIndex((i) => Math.max(i - 1, 0));\n } else if (event.key === 'Enter') {\n event.preventDefault();\n if (filtered[activeIndex]) selectOption(filtered[activeIndex]);\n } else if (event.key === 'Escape') {\n event.preventDefault();\n close();\n buttonRef.current?.focus();\n }\n },\n [filtered, activeIndex, selectOption, close],\n );\n\n return (\n <span className={`be-select ${className}`.trim()} ref={rootRef}>\n <button\n type=\"button\"\n ref={buttonRef}\n className={`be-select-trigger${isTag ? ' be-select-trigger-tag' : ''}`}\n aria-haspopup=\"listbox\"\n aria-expanded={isOpen}\n aria-label={ariaLabel}\n onClick={() => (isOpen ? close() : open())}\n >\n {isTag ? (\n selected ? (\n <span className=\"be-select-tag\" style={{ background: selected.color?.bg, color: selected.color?.text }}>\n {selected.label}\n </span>\n ) : (\n <span className=\"be-select-value be-select-value-placeholder\">{placeholder}</span>\n )\n ) : (\n <>\n <span className=\"be-select-value\">{selected ? selected.label : placeholder}</span>\n <ChevronDownIcon size={14} className=\"be-select-chevron\" />\n </>\n )}\n </button>\n {isOpen &&\n rect &&\n createPortal(\n <div\n ref={popoverRef}\n className=\"be-select-popover\"\n style={{ position: 'fixed', top: rect.bottom + 4, left: rect.left, minWidth: rect.width }}\n >\n <input\n ref={inputRef}\n type=\"text\"\n className=\"be-select-search\"\n value={query}\n onChange={(event) => {\n setQuery(event.target.value);\n setActiveIndex(0);\n }}\n onKeyDown={handleSearchKeyDown}\n placeholder=\"Search…\"\n aria-label={ariaLabel ? `Search ${ariaLabel}` : 'Search options'}\n />\n <div className=\"be-select-options\" role=\"listbox\">\n {isDynamic && isLoading && <div className=\"be-select-empty\">Loading…</div>}\n {isDynamic && !isLoading && loadError && <div className=\"be-select-empty be-select-error\">Couldn't load options</div>}\n {!isLoading && !loadError && filtered.length === 0 && <div className=\"be-select-empty\">No results</div>}\n {!isLoading &&\n !loadError &&\n filtered.map((option, i) => (\n <div\n key={option.value}\n ref={i === activeIndex ? activeOptionRef : undefined}\n role=\"option\"\n aria-selected={option.value === value}\n className={`be-select-option${i === activeIndex ? ' be-select-option-active' : ''}${\n option.value === value ? ' be-select-option-selected' : ''\n }`}\n onMouseDown={(event) => {\n event.preventDefault(); // keep focus in the search input until a real selection commits\n selectOption(option);\n }}\n onMouseEnter={() => setActiveIndex(i)}\n >\n {isTag ? (\n <span className=\"be-select-tag\" style={{ background: option.color?.bg, color: option.color?.text }}>\n {option.label}\n </span>\n ) : (\n option.label\n )}\n </div>\n ))}\n </div>\n {onManageOptions && (\n <button\n type=\"button\"\n className=\"be-select-manage-options\"\n onMouseDown={(event) => {\n event.preventDefault();\n close();\n onManageOptions();\n }}\n >\n {manageOptionsLabel}\n </button>\n )}\n </div>,\n document.body,\n )}\n </span>\n );\n}\n","/**\n * Notion-style tag color palette for a table's \"select\" column — assigned\n * once, at option-creation time (see TableHeaderRow's SelectOptionsManager),\n * and stored on the option itself (`{ value, label, color }`) so it stays\n * stable across reorders/removals, the same way Notion's own Select\n * property keeps whatever color a tag was first given.\n */\nexport const TAG_COLORS = [\n { bg: '#e9e9e7', text: '#32302c' }, // gray (default)\n { bg: '#eee0da', text: '#64473a' }, // brown\n { bg: '#fadec9', text: '#8a4b23' }, // orange\n { bg: '#fdecc8', text: '#8a6116' }, // yellow\n { bg: '#dbeddb', text: '#256029' }, // green\n { bg: '#d3e5ef', text: '#1a5f8a' }, // blue\n { bg: '#e8deee', text: '#5b3a8a' }, // purple\n { bg: '#f5e0e9', text: '#8a3a5f' }, // pink\n { bg: '#ffe2dd', text: '#a13a2f' }, // red\n];\n\n/** Cycles through TAG_COLORS by index — deterministic, no randomness. */\nexport function pickTagColor(index) {\n return TAG_COLORS[((index % TAG_COLORS.length) + TAG_COLORS.length) % TAG_COLORS.length];\n}\n","import { useCallback, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useEditorStore, useInlineRegistry } from '../../react/EditorProvider.jsx';\nimport { useOutsideClickAndEscape } from '../../react/useOutsideClickAndEscape.js';\nimport { insertColumnAfter, deleteColumn, renameColumn, setColumnType, setColumnOptions, setColumnWidth } from './tableEditCommands.js';\nimport { COLUMN_TYPES, MIN_COLUMN_WIDTH } from './tableColumns.js';\nimport { genId } from '../../utils/idGen.js';\nimport { XIcon } from '../../react/icons.jsx';\nimport { Select } from '../../react/Select.jsx';\nimport { pickTagColor } from './tagColors.js';\n\nconst TYPE_LABELS = { text: 'Text', date: 'Date', checkbox: 'Checkbox', select: 'Select' };\nconst TYPE_OPTIONS = COLUMN_TYPES.map((type) => ({ value: type, label: TYPE_LABELS[type] }));\n\n/**\n * Manages a \"select\" column's shared option list (add/rename/remove) —\n * configured once here, for the whole column, rather than per cell. This\n * is the piece that makes a select column behave like Notion's Select\n * property instead of the general-purpose inline `select` type's\n * independent-per-chip options: every cell reads the *same* list (see\n * TableSelectInlineNode), so it only needs managing in one place.\n */\nfunction SelectOptionsManager({ tableId, colIndex, options }) {\n const store = useEditorStore();\n const [draft, setDraft] = useState('');\n\n const handleRename = useCallback(\n (optionValue, label) => {\n setColumnOptions(store, tableId, colIndex, options.map((o) => (o.value === optionValue ? { ...o, label } : o)));\n },\n [store, tableId, colIndex, options],\n );\n const handleRemove = useCallback(\n (optionValue) => setColumnOptions(store, tableId, colIndex, options.filter((o) => o.value !== optionValue)),\n [store, tableId, colIndex, options],\n );\n const handleAdd = useCallback(() => {\n const label = draft.trim();\n setDraft('');\n if (!label) return;\n // Color is assigned once, here, at creation time — not derived from\n // position at render time — so it stays the same tag color even after\n // other options are reordered/removed, matching Notion's own Select\n // property (a tag's color is fixed once you pick/create it).\n setColumnOptions(store, tableId, colIndex, [...options, { value: genId(), label, color: pickTagColor(options.length) }]);\n }, [store, tableId, colIndex, options, draft]);\n\n return (\n <div className=\"be-table-header-menu-options\">\n <div className=\"be-table-header-menu-options-label\">Options</div>\n {options.map((option, i) => (\n <div key={option.value} className=\"be-table-header-menu-option-row\">\n <span\n className=\"be-table-header-menu-option-swatch\"\n style={{ background: (option.color ?? pickTagColor(i)).bg }}\n aria-hidden=\"true\"\n />\n <input\n className=\"be-table-header-menu-option-input\"\n value={option.label}\n onChange={(event) => handleRename(option.value, event.target.value)}\n aria-label={`Rename option ${option.label}`}\n />\n <button\n type=\"button\"\n className=\"be-table-header-menu-option-remove\"\n onClick={() => handleRemove(option.value)}\n aria-label={`Remove option ${option.label}`}\n >\n <XIcon size={14} />\n </button>\n </div>\n ))}\n <div className=\"be-table-header-menu-option-row\">\n <input\n className=\"be-table-header-menu-option-input\"\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n placeholder=\"New option…\"\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n handleAdd();\n }\n }}\n />\n <button type=\"button\" className=\"be-table-header-menu-option-add\" onClick={handleAdd} aria-label=\"Add option\">\n +\n </button>\n </div>\n </div>\n );\n}\n\n/**\n * One header cell: an editable label, a small self-built menu (change\n * type, manage select options, insert column left/right, delete column),\n * and a drag handle on its right edge to resize the column.\n *\n * The menu is portaled to `document.body` (`position: fixed`, computed\n * from the trigger button's own bounding rect) — same convention as\n * Select/SlashMenu elsewhere in this codebase — instead of a plain\n * absolutely-positioned child of this `<th>`. A table can genuinely\n * overflow its wrapper (see `.be-table-wrapper`'s `overflow-x: auto`), and\n * a plain in-flow popup gets visually clipped by that; portaling escapes\n * it entirely, the same reason Select's own popover is portaled.\n *\n * Changing type runs every existing cell in the column through\n * setColumnType's data-preserving conversion (see tableColumns.js) rather\n * than discarding values — the actual gap this feature was built to close\n * versus the legacy notevo table it's modeled after.\n */\nfunction ColumnHeaderCell({ tableId, column, colIndex, colCount }) {\n const store = useEditorStore();\n const inlineRegistry = useInlineRegistry();\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n const [rect, setRect] = useState(null);\n const [dragWidth, setDragWidth] = useState(null);\n const triggerRef = useRef(null);\n const menuRef = useRef(null);\n const thRef = useRef(null);\n const outsideRefs = useMemo(() => [triggerRef, menuRef], []);\n\n const closeMenu = useCallback(() => setIsMenuOpen(false), []);\n useOutsideClickAndEscape(outsideRefs, isMenuOpen, closeMenu);\n\n const openMenu = useCallback(() => {\n setRect(triggerRef.current?.getBoundingClientRect() ?? null);\n setIsMenuOpen(true);\n }, []);\n\n const handleLabelChange = useCallback(\n (event) => renameColumn(store, tableId, colIndex, event.target.value),\n [store, tableId, colIndex],\n );\n const handleInsertLeft = useCallback(() => {\n insertColumnAfter(store, tableId, colIndex - 1);\n closeMenu();\n }, [store, tableId, colIndex, closeMenu]);\n const handleInsertRight = useCallback(() => {\n insertColumnAfter(store, tableId, colIndex);\n closeMenu();\n }, [store, tableId, colIndex, closeMenu]);\n const handleDelete = useCallback(() => {\n deleteColumn(store, tableId, colIndex);\n closeMenu();\n }, [store, tableId, colIndex, closeMenu]);\n const handleTypeChange = useCallback(\n (type) => setColumnType(store, tableId, colIndex, type, inlineRegistry),\n [store, tableId, colIndex, inlineRegistry],\n );\n\n // Live-updates the <colgroup>'s own <col> element directly during drag\n // (see TableBlock.jsx's data-col-index) rather than dispatching a store\n // write on every mousemove — the store only gets ONE write, on mouseup,\n // matching EmbedBlock's own resize-handle convention.\n const handleResizeStart = useCallback(\n (event) => {\n event.preventDefault();\n const table = thRef.current?.closest('table');\n const col = table?.querySelector(`col[data-col-index=\"${colIndex}\"]`);\n if (!col) return;\n const startWidth = thRef.current.getBoundingClientRect().width;\n const startX = event.clientX;\n\n const computeWidth = (moveEvent) => Math.max(MIN_COLUMN_WIDTH, Math.round(startWidth + (moveEvent.clientX - startX)));\n\n const handleMouseMove = (moveEvent) => {\n const width = computeWidth(moveEvent);\n col.style.width = `${width}px`;\n setDragWidth(width);\n };\n const handleMouseUp = (upEvent) => {\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n setColumnWidth(store, tableId, colIndex, computeWidth(upEvent));\n setDragWidth(null);\n };\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n },\n [store, tableId, colIndex],\n );\n\n return (\n <th ref={thRef} className=\"be-table-header-cell\" contentEditable={false}>\n <input\n className=\"be-table-header-label\"\n value={column.label}\n onChange={handleLabelChange}\n aria-label={`Column ${colIndex + 1} name`}\n />\n <button\n ref={triggerRef}\n type=\"button\"\n className=\"be-table-header-menu-trigger\"\n aria-label={`Column ${colIndex + 1} options`}\n aria-haspopup=\"menu\"\n aria-expanded={isMenuOpen}\n onClick={() => (isMenuOpen ? closeMenu() : openMenu())}\n >\n &#8942;\n </button>\n <div\n className=\"be-table-col-resize-handle\"\n onMouseDown={handleResizeStart}\n role=\"slider\"\n aria-label={`Resize column ${colIndex + 1}`}\n aria-valuemin={MIN_COLUMN_WIDTH}\n aria-valuenow={dragWidth ?? column.width}\n />\n {isMenuOpen &&\n rect &&\n createPortal(\n <div\n ref={menuRef}\n role=\"menu\"\n className=\"be-table-header-menu\"\n style={{ position: 'fixed', top: rect.bottom + 4, left: rect.right, transform: 'translateX(-100%)' }}\n >\n <div className=\"be-table-header-menu-type\">\n <span id={`be-table-col-type-${column.id}`}>Type</span>\n <Select\n value={column.type}\n options={TYPE_OPTIONS}\n onChange={handleTypeChange}\n ariaLabel=\"Column type\"\n className=\"be-table-header-type-select\"\n />\n </div>\n {column.type === 'select' && (\n <SelectOptionsManager tableId={tableId} colIndex={colIndex} options={column.options ?? []} />\n )}\n <button type=\"button\" role=\"menuitem\" className=\"be-table-header-menu-item\" onClick={handleInsertLeft}>\n Insert column left\n </button>\n <button type=\"button\" role=\"menuitem\" className=\"be-table-header-menu-item\" onClick={handleInsertRight}>\n Insert column right\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"be-table-header-menu-item be-table-header-menu-item-danger\"\n onClick={handleDelete}\n disabled={colCount <= 1}\n >\n Delete column\n </button>\n </div>,\n document.body,\n )}\n </th>\n );\n}\n\n/**\n * Renders as a real `<thead>` above the table's `<tbody>` (see TableBlock),\n * one `<th>` per column driven by the table's own `props.columns` metadata\n * (see tableColumns.js) — not a \"block\" of its own, since column labels\n * are table-level metadata, not content that needs runs/selection/undo\n * machinery of its own. A trailing spacer `<th>` keeps header columns\n * aligned with TableRowBlock's extra row-actions column.\n */\nexport function TableHeaderRow({ tableId, columns }) {\n return (\n <thead>\n <tr className=\"be-table-header-row\">\n {columns.map((column, i) => (\n <ColumnHeaderCell key={column.id} tableId={tableId} column={column} colIndex={i} colCount={columns.length} />\n ))}\n <th className=\"be-table-header-spacer\" aria-hidden=\"true\" />\n </tr>\n </thead>\n );\n}\n","import { useCallback } from 'react';\nimport { BlockChildren } from '../../react/BlockChildren.jsx';\nimport { useBlock } from '../../react/useBlock.js';\nimport { useEditorStore } from '../../react/EditorProvider.jsx';\nimport { insertRowAfter } from './tableEditCommands.js';\nimport { resolveColumns } from './tableColumns.js';\nimport { TableHeaderRow } from './TableHeaderRow.jsx';\nimport { PlusIcon } from '../../react/icons.jsx';\n\nexport function TableBlock({ id }) {\n const store = useEditorStore();\n const block = useBlock(id);\n\n const handleAddRow = useCallback(() => {\n const lastRowId = block?.contentIds?.[block.contentIds.length - 1];\n if (lastRowId) insertRowAfter(store, lastRowId);\n }, [store, block]);\n\n if (!block) return null;\n\n const firstRow = store.getBlock(block.contentIds[0]);\n const columns = resolveColumns(block, firstRow?.contentIds?.length ?? 0);\n\n return (\n <div className=\"be-table-wrapper\" data-block-id={id}>\n <table className=\"be-table\">\n {/*\n A <colgroup> is what makes column resizing work at all: with\n table-layout: fixed (see CSS), every <col>'s own width applies\n uniformly to that column across the header row AND every body\n row's cell at that index — one <col> per column is the single\n source of truth for its rendered width, so TableCellBlock/\n TableRowBlock never need their own column-width prop-threading.\n data-col-index is how the header's own resize-drag handler finds\n and live-updates the right <col> imperatively while dragging (see\n ColumnHeaderCell), without touching React state on every\n mousemove.\n */}\n <colgroup>\n {columns.map((column, i) => (\n <col key={column.id} data-col-index={i} style={{ width: column.width }} />\n ))}\n <col className=\"be-table-header-spacer-col\" />\n </colgroup>\n <TableHeaderRow tableId={id} columns={columns} />\n <tbody>\n <BlockChildren parentId={id} />\n </tbody>\n </table>\n <button type=\"button\" className=\"be-table-add-row\" contentEditable={false} onClick={handleAddRow}>\n <PlusIcon size={14} /> Add row\n </button>\n </div>\n );\n}\n","import { useCallback } from 'react';\nimport { BlockChildren } from '../../react/BlockChildren.jsx';\nimport { useEditorStore } from '../../react/EditorProvider.jsx';\nimport { deleteRow } from './tableEditCommands.js';\nimport { XIcon } from '../../react/icons.jsx';\n\n// Reuses the exact same container/tree-walking mechanism as every other\n// non-leaf block (page, layout column, list item children) — the only\n// difference is the wrapping <tr> tag.\nexport function TableRowBlock({ id }) {\n const store = useEditorStore();\n const handleDeleteRow = useCallback(() => deleteRow(store, id), [store, id]);\n\n return (\n <tr className=\"be-table-row\" data-block-id={id}>\n <BlockChildren parentId={id} />\n <td className=\"be-table-row-actions\" contentEditable={false}>\n <button type=\"button\" className=\"be-table-delete-row\" onClick={handleDeleteRow} aria-label=\"Delete row\" title=\"Delete row\">\n <XIcon size={14} />\n </button>\n </td>\n </tr>\n );\n}\n","import { focusRunEnd } from '../../react/focusRun.js';\nimport { resolveAdjacentFocusTarget } from '../shared/navigationCommands.js';\nimport { insertSiblingAfterAndFocus } from '../shared/blockCommands.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\n\nfunction locateCell(store, cellId) {\n const cell = store.getBlock(cellId);\n const row = store.getBlock(cell.parentId);\n const table = store.getBlock(row.parentId);\n return { table, row, rowIndex: table.contentIds.indexOf(row.id), colIndex: row.contentIds.indexOf(cellId) };\n}\n\n/**\n * Resolves the target cell id when moving from `cellId` in `direction`\n * ('left' | 'right' | 'up' | 'down'). Pure, no side effects — returns null\n * at any of the table's edges (first/last cell of a row, top/bottom of a\n * column), leaving what to do about that boundary to the caller\n * (moveToAdjacentCell).\n *\n * 'up'/'down' stay in the same column and return null at the table's\n * top/bottom edge — moving out of the table into a sibling block above/below\n * it is a follow-up (same cross-container caveat as navigationCommands.js).\n */\nexport function resolveAdjacentCellTarget(store, cellId, direction) {\n const { table, row, rowIndex, colIndex } = locateCell(store, cellId);\n\n if (direction === 'left' || direction === 'right') {\n const delta = direction === 'right' ? 1 : -1;\n const nextColIndex = colIndex + delta;\n if (nextColIndex >= 0 && nextColIndex < row.contentIds.length) {\n return row.contentIds[nextColIndex];\n }\n\n const nextRowIndex = rowIndex + delta;\n if (nextRowIndex < 0 || nextRowIndex >= table.contentIds.length) return null; // at the table's very first/last cell\n\n const targetRow = store.getBlock(table.contentIds[nextRowIndex]);\n const targetColIndex = direction === 'right' ? 0 : targetRow.contentIds.length - 1;\n return targetRow.contentIds[targetColIndex];\n }\n\n const delta = direction === 'down' ? 1 : -1;\n const targetRowIndex = rowIndex + delta;\n if (targetRowIndex < 0 || targetRowIndex >= table.contentIds.length) return null;\n const targetRow = store.getBlock(table.contentIds[targetRowIndex]);\n return targetRow.contentIds[colIndex] ?? targetRow.contentIds[targetRow.contentIds.length - 1] ?? null;\n}\n\n/**\n * Tab past the table's very last cell exits it entirely — focuses whatever\n * block already follows the table (entering it the same way arrow-key\n * navigation between top-level blocks does), or, if the table is the last\n * block in its container, creates a fresh blank paragraph after it and\n * focuses that. Either way Tab always lands somewhere, never a silent\n * no-op that leaves the user stuck at the end of a document that happens\n * to end in a table.\n */\nfunction exitTableForward(store, tableId) {\n const targetRunId = resolveAdjacentFocusTarget(store, tableId, 'down');\n if (targetRunId) {\n focusRunEnd(targetRunId);\n return;\n }\n insertSiblingAfterAndFocus(store, tableId, createTextLeafBlock('paragraph'));\n}\n\n/** Moves DOM focus to the adjacent cell resolved by resolveAdjacentCellTarget, or exits the table on Tab past its last cell (see exitTableForward). */\nexport function moveToAdjacentCell(store, cellId, direction) {\n const targetCellId = resolveAdjacentCellTarget(store, cellId, direction);\n if (targetCellId) {\n const targetCell = store.getBlock(targetCellId);\n const runId = targetCell?.contentIds?.[0];\n if (runId) focusRunEnd(runId);\n return;\n }\n\n if (direction === 'right') {\n const { table } = locateCell(store, cellId);\n exitTableForward(store, table.id);\n }\n // 'left' at the very first cell, and 'up'/'down' at the table's\n // top/bottom edge, remain a no-op (see resolveAdjacentCellTarget's doc\n // comment on that scope).\n}\n","import { useCallback } from 'react';\nimport { EditableBlockContent } from '../../react/EditableBlockContent.jsx';\nimport { useBlock } from '../../react/useBlock.js';\nimport { useEditorStore } from '../../react/EditorProvider.jsx';\nimport { moveToAdjacentCell } from './tableNavigation.js';\n\n// Deliberately near-identical to ParagraphBlock: a cell is a leaf block\n// whose contentIds are run ids, exactly like a paragraph — it gets\n// formatting/selection/serialization for free from the same run machinery.\n//\n// No Backspace-at-start handling: a cell merging into an adjacent cell has\n// no sensible meaning (no \"merge cells\" in v1), so native no-op is already\n// correct default behavior — not an omission.\nexport function TableCellBlock({ id }) {\n const store = useEditorStore();\n const block = useBlock(id);\n\n const handleTab = useCallback(() => moveToAdjacentCell(store, id, 'right'), [store, id]);\n const handleShiftTab = useCallback(() => moveToAdjacentCell(store, id, 'left'), [store, id]);\n const handleArrowUp = useCallback(() => moveToAdjacentCell(store, id, 'up'), [store, id]);\n const handleArrowDown = useCallback(() => moveToAdjacentCell(store, id, 'down'), [store, id]);\n // Enter moves down a row (spreadsheet-familiar), matching Tab's row-wrap convention.\n const handleEnter = useCallback(() => moveToAdjacentCell(store, id, 'down'), [store, id]);\n\n if (!block) return null;\n\n return (\n <td className=\"be-table-cell\" data-block-id={id}>\n <EditableBlockContent\n blockId={id}\n runIds={block.contentIds}\n onTab={handleTab}\n onShiftTab={handleShiftTab}\n onArrowUp={handleArrowUp}\n onArrowDown={handleArrowDown}\n onEnter={handleEnter}\n />\n </td>\n );\n}\n","import { genId } from '../../utils/idGen.js';\nimport { createDefaultColumns, createCellForColumn } from './tableColumns.js';\n\nfunction createRow(parentId, columns) {\n const rowId = genId();\n const cellBlocks = [];\n const runs = [];\n const contentIds = [];\n for (const column of columns) {\n const cell = createCellForColumn(rowId, column);\n cellBlocks.push(cell.block);\n runs.push(cell.run);\n contentIds.push(cell.block.id);\n }\n return { block: { id: rowId, type: 'tableRow', parentId, contentIds, props: {} }, blocks: cellBlocks, runs };\n}\n\n/** factory(parentId) -> {block, runs, subtreeBlocks} for a fresh rows x cols table. */\nexport function createTableBlock({ rows = 2, cols = 2 } = {}) {\n return function factory(parentId) {\n const tableId = genId();\n const columns = createDefaultColumns(cols);\n const subtreeBlocks = [];\n const allRuns = [];\n const rowIds = [];\n\n for (let r = 0; r < rows; r += 1) {\n const row = createRow(tableId, columns);\n subtreeBlocks.push(row.block, ...row.blocks);\n allRuns.push(...row.runs);\n rowIds.push(row.block.id);\n }\n\n const block = { id: tableId, type: 'table', parentId, contentIds: rowIds, props: { columns } };\n return { block, runs: allRuns, subtreeBlocks };\n };\n}\n","import { TableBlock } from './TableBlock.jsx';\nimport { TableRowBlock } from './TableRowBlock.jsx';\nimport { TableCellBlock } from './TableCellBlock.jsx';\nimport { runToHTML, runToPlainText, escapeHTML } from '../../inline/marks.js';\nimport { domInlineToRuns } from '../../inline/runOps.js';\nimport { genId } from '../../utils/idGen.js';\nimport { trimSlashQueryAndInsertAfter } from '../shared/blockCommands.js';\nimport { createTableBlock } from './createTableBlock.js';\nimport { resolveColumns } from './tableColumns.js';\nimport { TableIcon } from '../../react/icons.jsx';\n\n// --- tableCell: near-identical to paragraph's toHTML/fromHTML/toPlainText ---\n\nfunction cellToHTML(block, ctx) {\n const runs = block.contentIds.map((runId) => ctx.store.getRun(runId));\n return `<td>${runs.map((r) => runToHTML(r, ctx)).join('')}</td>`;\n}\n\nfunction cellToPlainText(block, ctx) {\n return block.contentIds.map((runId) => runToPlainText(ctx.store.getRun(runId), ctx)).join('');\n}\n\nfunction cellFromHTML(node, ctx) {\n if (node.tagName !== 'TD' && node.tagName !== 'TH') return null;\n const runs = domInlineToRuns(node, ctx);\n const block = { id: genId(), type: 'tableCell', parentId: null, contentIds: runs.map((r) => r.id), props: {} };\n return { block, runs };\n}\n\n// --- tableRow: pure container, recurses into cells via the registry ---\n\nfunction rowToHTML(block, ctx) {\n const cellsHTML = block.contentIds\n .map((cellId) => {\n const cellBlock = ctx.store.getBlock(cellId);\n return ctx.registry.get(cellBlock.type).toHTML(cellBlock, ctx);\n })\n .join('');\n return `<tr>${cellsHTML}</tr>`;\n}\n\nfunction rowToPlainText(block, ctx) {\n return block.contentIds\n .map((cellId) => {\n const cellBlock = ctx.store.getBlock(cellId);\n return ctx.registry.get(cellBlock.type).toPlainText(cellBlock, ctx);\n })\n .join('\\t');\n}\n\nfunction rowFromHTML(node, ctx) {\n if (node.tagName !== 'TR') return null;\n const cellNodes = [...node.children].filter((c) => c.tagName === 'TD' || c.tagName === 'TH');\n const rowId = genId();\n const cellBlocks = [];\n const runs = [];\n const contentIds = [];\n for (const cellNode of cellNodes) {\n const result = ctx.registry.get('tableCell').fromHTML(cellNode, ctx);\n if (!result) continue;\n result.block.parentId = rowId;\n cellBlocks.push(result.block);\n runs.push(...result.runs);\n contentIds.push(result.block.id);\n }\n const block = { id: rowId, type: 'tableRow', parentId: null, contentIds, props: {} };\n return { block, runs, subtreeBlocks: cellBlocks };\n}\n\n// --- table: container of rows ---\n\nfunction tableToHTML(block, ctx) {\n const firstRow = block.contentIds[0] && ctx.store.getBlock(block.contentIds[0]);\n const columns = resolveColumns(block, firstRow?.contentIds?.length ?? 0);\n const theadHTML = columns.length\n ? `<thead><tr>${columns.map((c) => `<th>${escapeHTML(c.label ?? '')}</th>`).join('')}</tr></thead>`\n : '';\n\n const rowsHTML = block.contentIds\n .map((rowId) => {\n const rowBlock = ctx.store.getBlock(rowId);\n return ctx.registry.get(rowBlock.type).toHTML(rowBlock, ctx);\n })\n .join('');\n return `<table>${theadHTML}<tbody>${rowsHTML}</tbody></table>`;\n}\n\nfunction tableToPlainText(block, ctx) {\n return block.contentIds\n .map((rowId) => {\n const rowBlock = ctx.store.getBlock(rowId);\n return ctx.registry.get(rowBlock.type).toPlainText(rowBlock, ctx);\n })\n .join('\\n');\n}\n\nfunction tableFromHTML(node, ctx) {\n if (node.tagName !== 'TABLE') return null;\n\n // A <thead> row holds column labels, not data — it must never be parsed\n // as a body row too (querySelectorAll('tr') would otherwise match it as\n // well as every <tbody> row, double-counting it). Its own labels are read\n // separately, into props.columns; external HTML with no <thead> at all\n // (pasted from another app) just gets none, and TableBlock/tableToHTML's\n // resolveColumns fallback generates sensible defaults for it.\n const theadRow = node.querySelector('thead tr');\n const bodyRowNodes = node.querySelector('tbody')\n ? [...node.querySelectorAll('tbody tr')]\n : [...node.querySelectorAll('tr')].filter((tr) => tr !== theadRow);\n\n const tableId = genId();\n const subtreeBlocks = [];\n const runs = [];\n const rowIds = [];\n for (const rowNode of bodyRowNodes) {\n const result = ctx.registry.get('tableRow').fromHTML(rowNode, ctx);\n if (!result) continue;\n result.block.parentId = tableId;\n for (const cellBlock of result.subtreeBlocks) cellBlock.parentId = result.block.id;\n subtreeBlocks.push(result.block, ...result.subtreeBlocks);\n runs.push(...result.runs);\n rowIds.push(result.block.id);\n }\n\n const props = {};\n if (theadRow) {\n const headerCells = [...theadRow.children].filter((c) => c.tagName === 'TH' || c.tagName === 'TD');\n props.columns = headerCells.map((cell) => ({ id: genId(), label: cell.textContent ?? '' }));\n }\n\n const block = { id: tableId, type: 'table', parentId: null, contentIds: rowIds, props };\n return { block, runs, subtreeBlocks };\n}\n\nexport const tableCellBlockType = {\n component: TableCellBlock,\n isLeaf: true,\n defaultProps: {},\n toHTML: cellToHTML,\n toPlainText: cellToPlainText,\n fromHTML: cellFromHTML,\n};\n\nexport const tableRowBlockType = {\n component: TableRowBlock,\n isLeaf: false,\n defaultProps: {},\n toHTML: rowToHTML,\n toPlainText: rowToPlainText,\n fromHTML: rowFromHTML,\n};\n\nexport const tableBlockType = {\n component: TableBlock,\n isLeaf: false,\n defaultProps: {},\n toHTML: tableToHTML,\n toPlainText: tableToPlainText,\n fromHTML: tableFromHTML,\n slashCommand: {\n label: 'Table',\n icon: TableIcon,\n keywords: ['table', 'grid'],\n run: (store, ctx) => trimSlashQueryAndInsertAfter(store, ctx, createTableBlock({ rows: 2, cols: 2 })),\n },\n};\n","import { BlockChildren } from '../../react/BlockChildren.jsx';\n\nexport function LayoutBlock({ id }) {\n return (\n <div className=\"be-layout\" data-block-id={id} style={{ display: 'flex', gap: '1em' }}>\n <BlockChildren parentId={id} />\n </div>\n );\n}\n","import { BlockChildren } from '../../react/BlockChildren.jsx';\n\n// Identical container mechanism to Page — a column just holds arbitrary\n// child blocks via contentIds, same as the document root does.\nexport function LayoutColumnBlock({ id }) {\n return (\n <div className=\"be-layout-column\" data-block-id={id}>\n <BlockChildren parentId={id} />\n </div>\n );\n}\n","import { genId } from '../../utils/idGen.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\n\n/** factory(parentId) -> {block, runs, subtreeBlocks} for a fresh N-column layout. */\nexport function createLayoutBlock({ columns = 2 } = {}) {\n return function factory(parentId) {\n const layoutId = genId();\n const subtreeBlocks = [];\n const allRuns = [];\n const columnIds = [];\n\n for (let c = 0; c < columns; c += 1) {\n const columnId = genId();\n // seed each column with one empty paragraph so there's somewhere to type\n const { block: paragraphBlock, runs } = createTextLeafBlock('paragraph')(columnId);\n const columnBlock = { id: columnId, type: 'layoutColumn', parentId: layoutId, contentIds: [paragraphBlock.id], props: {} };\n subtreeBlocks.push(columnBlock, paragraphBlock);\n allRuns.push(...runs);\n columnIds.push(columnId);\n }\n\n const block = { id: layoutId, type: 'layout', parentId, contentIds: columnIds, props: {} };\n return { block, runs: allRuns, subtreeBlocks };\n };\n}\n","import { LayoutBlock } from './LayoutBlock.jsx';\nimport { LayoutColumnBlock } from './LayoutColumnBlock.jsx';\nimport { trimSlashQueryAndInsertAfter } from '../shared/blockCommands.js';\nimport { createLayoutBlock } from './createLayoutBlock.js';\nimport { ColumnsIcon } from '../../react/icons.jsx';\n\nfunction containerToHTML(tagOpen, tagClose) {\n return (block, ctx) =>\n `${tagOpen}${block.contentIds\n .map((childId) => {\n const child = ctx.store.getBlock(childId);\n return ctx.registry.get(child.type).toHTML(child, ctx);\n })\n .join('')}${tagClose}`;\n}\n\nfunction containerToPlainText(block, ctx) {\n return block.contentIds\n .map((childId) => {\n const child = ctx.store.getBlock(childId);\n return ctx.registry.get(child.type).toPlainText(child, ctx);\n })\n .join('\\n');\n}\n\nexport const layoutColumnBlockType = {\n component: LayoutColumnBlock,\n isLeaf: false,\n defaultProps: {},\n toHTML: containerToHTML('<div>', '</div>'),\n toPlainText: containerToPlainText,\n // no fromHTML: a bare column has no distinct HTML representation of its\n // own outside a parent `layout`'s markup; layout.fromHTML would construct\n // both together if/when generic multi-column HTML import is added.\n};\n\nexport const layoutBlockType = {\n component: LayoutBlock,\n isLeaf: false,\n defaultProps: {},\n toHTML: containerToHTML('<div style=\"display:flex;gap:1em\">', '</div>'),\n toPlainText: containerToPlainText,\n slashCommands: [2, 3, 4, 5].map((columns) => ({\n label: `${columns} columns`,\n icon: ColumnsIcon,\n keywords: ['layout', 'columns', 'column', String(columns)],\n run: (store, ctx) => trimSlashQueryAndInsertAfter(store, ctx, createLayoutBlock({ columns })),\n })),\n};\n","// tabIndex={-1}: not in the normal Tab order, but focusable via .focus() —\n// needed so setSelectedBlockId (EditorProvider) can actually move DOM focus\n// here when it selects this block, keeping the surface's own keydown\n// listener capturing the next Backspace/Delete even after whatever\n// previously had focus (e.g. an adjacent empty paragraph) has just been\n// removed from the DOM entirely.\nexport function DividerBlock({ id }) {\n return <hr className=\"be-divider\" data-block-id={id} contentEditable={false} tabIndex={-1} />;\n}\n","import { DividerBlock } from './DividerBlock.jsx';\nimport { genId } from '../../utils/idGen.js';\nimport { insertSiblingAfter, insertSiblingAfterAndFocus } from '../shared/blockCommands.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\nimport { updateRun } from '../../store/operations.js';\nimport { DividerIcon } from '../../react/icons.jsx';\n\nfunction createDividerBlock() {\n return function factory(parentId) {\n return { block: { id: genId(), type: 'divider', parentId, contentIds: [], props: {} }, runs: [] };\n };\n}\n\nfunction toHTML() {\n return '<hr />';\n}\n\nfunction toPlainText() {\n return '---';\n}\n\nfunction fromHTML(node) {\n if (node.tagName !== 'HR') return null;\n return { block: { id: genId(), type: 'divider', parentId: null, contentIds: [], props: {} }, runs: [] };\n}\n\nexport const dividerBlockType = {\n component: DividerBlock,\n isLeaf: true,\n defaultProps: {},\n toHTML,\n toPlainText,\n fromHTML,\n slashCommand: {\n label: 'Divider',\n icon: DividerIcon,\n keywords: ['divider', 'hr', 'separator', 'line'],\n run: (store, { blockId, runId, sliceStart, sliceEnd }) => {\n const run = store.getRun(runId);\n const value = run?.value ?? '';\n store.applyOperation(updateRun(runId, { value: value.slice(0, sliceStart) + value.slice(sliceEnd) }));\n\n // seed a paragraph right after so there's always somewhere to type\n // past the divider — it has no run of its own to focus into.\n const dividerId = insertSiblingAfter(store, blockId, createDividerBlock());\n insertSiblingAfterAndFocus(store, dividerId, createTextLeafBlock('paragraph'));\n return dividerId;\n },\n },\n};\n","import { genId } from '../../utils/idGen.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\n\nexport const DEFAULT_CALLOUT_ICON = '💡';\n\n/**\n * factory(parentId) -> {block, runs, subtreeBlocks} for a fresh callout —\n * a plain container (same contentIds-holds-child-block-ids shape as\n * layoutColumn/page) plus an `icon` prop, seeded with one empty paragraph\n * so there's somewhere to type immediately (same convention as\n * createLayoutBlock's columns).\n */\nexport function createCalloutBlock({ icon = DEFAULT_CALLOUT_ICON } = {}) {\n return function factory(parentId) {\n const calloutId = genId();\n const { block: paragraphBlock, runs } = createTextLeafBlock('paragraph')(calloutId);\n const block = { id: calloutId, type: 'callout', parentId, contentIds: [paragraphBlock.id], props: { icon } };\n return { block, runs, subtreeBlocks: [paragraphBlock] };\n };\n}\n","import { useCallback, useState } from 'react';\nimport { BlockChildren } from '../../react/BlockChildren.jsx';\nimport { useBlock } from '../../react/useBlock.js';\nimport { useEditorStore } from '../../react/EditorProvider.jsx';\nimport { updateBlockProps } from '../../store/operations.js';\nimport { DEFAULT_CALLOUT_ICON } from './createCalloutBlock.js';\n\n/**\n * A plain container (contentIds hold child block ids, exactly like\n * layoutColumn/page) wrapped in a colored box with an editable icon — same\n * mechanism Notion/TipTap use for \"callout\": no bespoke text/run handling\n * of its own, so every child block (paragraph, list, another callout, ...)\n * gets full selection/copy/paste/format/undo support for free from the\n * shared container machinery, the same way layout columns already do.\n *\n * The icon is a plain text input rather than a dedicated emoji picker for\n * now (item 7 in the requested list) — swap this for that picker once it\n * exists; typing/pasting any emoji directly already works today.\n */\nexport function CalloutBlock({ id }) {\n const store = useEditorStore();\n const block = useBlock(id);\n const [editingIcon, setEditingIcon] = useState(false);\n\n const icon = block?.props?.icon ?? DEFAULT_CALLOUT_ICON;\n\n const commitIcon = useCallback(\n (event) => {\n const next = event.target.value.trim();\n if (next) store.applyOperation(updateBlockProps(id, { icon: next }));\n setEditingIcon(false);\n },\n [store, id],\n );\n\n const handleIconKeyDown = useCallback((event) => {\n if (event.key === 'Enter') event.currentTarget.blur();\n if (event.key === 'Escape') setEditingIcon(false);\n }, []);\n\n if (!block) return null;\n\n return (\n <div className=\"be-callout\" data-block-id={id}>\n {editingIcon ? (\n <input\n type=\"text\"\n className=\"be-callout-icon-input\"\n defaultValue={icon}\n autoFocus\n onBlur={commitIcon}\n onKeyDown={handleIconKeyDown}\n aria-label=\"Callout icon (paste or type an emoji)\"\n />\n ) : (\n <button\n type=\"button\"\n className=\"be-callout-icon\"\n onClick={() => setEditingIcon(true)}\n aria-label=\"Change callout icon\"\n title=\"Change icon\"\n >\n {icon}\n </button>\n )}\n <div className=\"be-callout-content\">\n <BlockChildren parentId={id} />\n </div>\n </div>\n );\n}\n","import { CalloutBlock } from './CalloutBlock.jsx';\nimport { trimSlashQueryAndInsertAfter } from '../shared/blockCommands.js';\nimport { createCalloutBlock, DEFAULT_CALLOUT_ICON } from './createCalloutBlock.js';\nimport { CalloutIcon } from '../../react/icons.jsx';\n\nfunction childrenToHTML(block, ctx) {\n return block.contentIds\n .map((childId) => {\n const child = ctx.store.getBlock(childId);\n return ctx.registry.get(child.type).toHTML(child, ctx);\n })\n .join('');\n}\n\nfunction toHTML(block, ctx) {\n const icon = block.props?.icon ?? DEFAULT_CALLOUT_ICON;\n return `<div class=\"callout\" data-icon=\"${icon}\"><div class=\"callout-icon\">${icon}</div><div class=\"callout-content\">${childrenToHTML(block, ctx)}</div></div>`;\n}\n\nfunction toPlainText(block, ctx) {\n const icon = block.props?.icon ?? DEFAULT_CALLOUT_ICON;\n const inner = block.contentIds\n .map((childId) => {\n const child = ctx.store.getBlock(childId);\n return ctx.registry.get(child.type).toPlainText(child, ctx);\n })\n .join('\\n');\n return `${icon} ${inner}`;\n}\n\nexport const calloutBlockType = {\n component: CalloutBlock,\n isLeaf: false,\n defaultProps: { icon: DEFAULT_CALLOUT_ICON },\n toHTML,\n toPlainText,\n // No fromHTML: same precedent as layoutColumn — there's no standard\n // external HTML shape for a \"callout\" box, so plain-HTML paste doesn't\n // need to reconstruct one. Same-editor copy/paste is already lossless\n // via the generic block-subtree JSON clipboard path\n // (captureSubtree in clipboard/serialize.js), which walks\n // contentIds generically and needs no per-type awareness at all.\n slashCommand: {\n label: 'Callout',\n icon: CalloutIcon,\n keywords: ['callout', 'aside', 'note', 'info', 'tip', 'warning'],\n run: (store, ctx) => trimSlashQueryAndInsertAfter(store, ctx, createCalloutBlock()),\n },\n};\n","import { useCallback } from 'react';\nimport { EditableBlockContent } from '../../react/EditableBlockContent.jsx';\nimport { useBlock } from '../../react/useBlock.js';\nimport { useEditorStore, useSelectedBlock } from '../../react/EditorProvider.jsx';\nimport { insertSiblingSplitAtCaretAndFocus } from '../shared/blockCommands.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\nimport { mergeWithPreviousOrDelete } from '../shared/mergeCommands.js';\nimport { isRunsEmpty } from '../shared/blockEmpty.js';\nimport { focusAfterMerge } from '../shared/focusAfterMerge.js';\nimport { focusAdjacentBlock } from '../shared/navigationCommands.js';\n\n/**\n * A leaf block, exactly like ParagraphBlock/HeadingBlock (contentIds are\n * its own run ids, not child blocks) — the only difference is presentation\n * (a <blockquote> tag with a left border). Enter exits the quote into a\n * plain paragraph sibling, matching heading's own convention (and Notion/\n * TipTap's actual quote behavior) — a quote is a single formatted block,\n * not a container you keep typing new lines into via Enter.\n */\nexport function BlockquoteBlock({ id }) {\n const store = useEditorStore();\n const block = useBlock(id);\n const { setSelectedBlockId } = useSelectedBlock();\n\n const handleEnter = useCallback(() => {\n insertSiblingSplitAtCaretAndFocus(store, id, block?.contentIds ?? [], createTextLeafBlock('paragraph'));\n }, [store, id, block]);\n\n const handleBackspaceAtStart = useCallback(() => {\n const focusBlockId = mergeWithPreviousOrDelete(store, id);\n focusAfterMerge(store, focusBlockId, id, setSelectedBlockId);\n }, [store, id, setSelectedBlockId]);\n\n const handleArrowUp = useCallback(() => focusAdjacentBlock(store, id, 'up'), [store, id]);\n const handleArrowDown = useCallback(() => focusAdjacentBlock(store, id, 'down'), [store, id]);\n\n if (!block) return null;\n const isEmpty = isRunsEmpty(store, block.contentIds);\n\n return (\n <blockquote\n className=\"be-blockquote\"\n data-block-id={id}\n data-empty={isEmpty ? '' : undefined}\n data-placeholder=\"Empty quote\"\n >\n <EditableBlockContent\n blockId={id}\n runIds={block.contentIds}\n onEnter={handleEnter}\n onBackspaceAtStart={handleBackspaceAtStart}\n onArrowUp={handleArrowUp}\n onArrowDown={handleArrowDown}\n />\n </blockquote>\n );\n}\n","import { BlockquoteBlock } from './BlockquoteBlock.jsx';\nimport { runToHTML, runToPlainText } from '../../inline/marks.js';\nimport { domInlineToRuns } from '../../inline/runOps.js';\nimport { genId } from '../../utils/idGen.js';\nimport { trimSlashQueryAndInsertAfter } from '../shared/blockCommands.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\nimport { QuoteIcon } from '../../react/icons.jsx';\n\nfunction toHTML(block, ctx) {\n const runs = block.contentIds.map((runId) => ctx.store.getRun(runId));\n return `<p>${runs.map((r) => runToHTML(r, ctx)).join('')}</p>`;\n}\n\nfunction toPlainText(block, ctx) {\n return block.contentIds.map((runId) => runToPlainText(ctx.store.getRun(runId), ctx)).join('');\n}\n\nfunction fromHTML(node, ctx) {\n if (node.tagName !== 'BLOCKQUOTE') return null;\n const runs = domInlineToRuns(node, ctx);\n const block = { id: genId(), type: 'blockquote', parentId: null, contentIds: runs.map((r) => r.id), props: {} };\n return { block, runs };\n}\n\nexport const blockquoteBlockType = {\n component: BlockquoteBlock,\n isLeaf: true,\n defaultProps: {},\n toHTML,\n toPlainText,\n fromHTML,\n slashCommand: {\n label: 'Quote',\n icon: QuoteIcon,\n keywords: ['quote', 'blockquote', 'citation'],\n run: (store, ctx) => trimSlashQueryAndInsertAfter(store, ctx, createTextLeafBlock('blockquote')),\n },\n};\n","import { useCallback } from 'react';\nimport { EditableBlockContent } from '../../react/EditableBlockContent.jsx';\nimport { Select } from '../../react/Select.jsx';\nimport { useBlock } from '../../react/useBlock.js';\nimport { useEditorStore } from '../../react/EditorProvider.jsx';\nimport { mergeWithPreviousOrDelete } from '../shared/mergeCommands.js';\nimport { isRunsEmpty } from '../shared/blockEmpty.js';\nimport { focusRunEnd, focusRunAtOffset } from '../../react/focusRun.js';\nimport { resolveCollapsedCaret } from '../../react/selectionResolve.js';\nimport { updateRun, updateBlockProps } from '../../store/operations.js';\nimport { focusAdjacentBlock } from '../shared/navigationCommands.js';\n\nexport const LANGUAGES = ['plaintext', 'javascript', 'python', 'html', 'css', 'json', 'bash', 'sql'];\nconst LANGUAGE_OPTIONS = LANGUAGES.map((lang) => ({ value: lang, label: lang }));\n\n/**\n * Inserts literal text at the live caret within `blockId`'s own run,\n * splicing directly into that run's value — used for Enter (a real \"\\n\",\n * not a block split: a code block is multi-line *within one block*, like a\n * <textarea>, matching Notion/TipTap) and Tab (two literal spaces, since\n * Tab inside code should never trigger indent-list/next-cell navigation).\n * Deliberately simple (single-run splice, no split-into-marks handling)\n * because code content is plain text — no rich inline formatting is\n * offered for it in this UI.\n */\nfunction insertLiteralTextAtCaret(store, blockId, text) {\n const caret = resolveCollapsedCaret();\n if (!caret || caret.blockId !== blockId) return;\n const run = store.getRun(caret.runId);\n if (!run || run.type !== 'text') return;\n const value = run.value ?? '';\n const newValue = value.slice(0, caret.offset) + text + value.slice(caret.offset);\n store.applyOperation(updateRun(run.id, { value: newValue }));\n focusRunAtOffset(run.id, caret.offset + text.length);\n}\n\n/**\n * A leaf block (own runs, same mechanism as paragraph/heading) rendered\n * inside a <pre><code> so embedded \"\\n\" characters actually break lines\n * (white-space: pre-wrap, see the CSS) — the only block type where Enter\n * doesn't split into a new sibling. Backspace-at-start still goes through\n * the ordinary shared mergeWithPreviousOrDelete: code is deliberately NOT\n * in MERGEABLE_TEXT_TYPES (concatenating code text into a plain paragraph,\n * or vice versa, has no sensible meaning — same exclusion as table/\n * listItem), so a *non-empty* code block simply won't merge into its\n * previous sibling; an *empty* one is still removed outright, landing\n * focus on whatever came before it.\n *\n * No syntax highlighting (tokenizing/coloring code) is performed — that\n * needs a highlighter library, which the zero-runtime-dependency\n * constraint on this package rules out. `props.language` is kept as plain\n * metadata (round-trips through copy/paste and serialization) for a host\n * app to feed into its own highlighter if it has one.\n */\nexport function CodeBlock({ id }) {\n const store = useEditorStore();\n const block = useBlock(id);\n\n const handleEnter = useCallback(() => insertLiteralTextAtCaret(store, id, '\\n'), [store, id]);\n const handleTab = useCallback(() => insertLiteralTextAtCaret(store, id, ' '), [store, id]);\n\n const handleBackspaceAtStart = useCallback(() => {\n const focusBlockId = mergeWithPreviousOrDelete(store, id);\n if (!focusBlockId || focusBlockId === id) return;\n const focusBlock = store.getBlock(focusBlockId);\n const lastRunId = focusBlock?.contentIds?.[focusBlock.contentIds.length - 1];\n if (lastRunId) focusRunEnd(lastRunId);\n }, [store, id]);\n\n const handleArrowUp = useCallback(() => focusAdjacentBlock(store, id, 'up'), [store, id]);\n const handleArrowDown = useCallback(() => focusAdjacentBlock(store, id, 'down'), [store, id]);\n\n const handleLanguageChange = useCallback(\n (language) => store.applyOperation(updateBlockProps(id, { language })),\n [store, id],\n );\n\n if (!block) return null;\n const language = block.props?.language ?? 'plaintext';\n const isEmpty = isRunsEmpty(store, block.contentIds);\n\n return (\n <div className=\"be-code-block\" data-block-id={id}>\n <div className=\"be-code-block-header\" contentEditable={false}>\n <Select\n className=\"be-code-block-language\"\n value={language}\n options={LANGUAGE_OPTIONS}\n onChange={handleLanguageChange}\n ariaLabel=\"Code language\"\n />\n </div>\n <pre className=\"be-code-block-pre\">\n <code data-empty={isEmpty ? '' : undefined} data-placeholder=\"Empty code block\">\n <EditableBlockContent\n blockId={id}\n runIds={block.contentIds}\n onEnter={handleEnter}\n onTab={handleTab}\n onBackspaceAtStart={handleBackspaceAtStart}\n onArrowUp={handleArrowUp}\n onArrowDown={handleArrowDown}\n />\n </code>\n </pre>\n </div>\n );\n}\n","import { CodeBlock } from './CodeBlock.jsx';\nimport { runToHTML, runToPlainText, escapeHTML } from '../../inline/marks.js';\nimport { genId } from '../../utils/idGen.js';\nimport { trimSlashQueryAndInsertAfter } from '../shared/blockCommands.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\nimport { CodeIcon } from '../../react/icons.jsx';\n\nfunction toHTML(block, ctx) {\n const runs = block.contentIds.map((runId) => ctx.store.getRun(runId));\n const language = block.props?.language;\n const langAttr = language && language !== 'plaintext' ? ` data-language=\"${escapeHTML(language)}\"` : '';\n return `<pre><code${langAttr}>${runs.map((r) => runToHTML(r, ctx)).join('')}</code></pre>`;\n}\n\nfunction toPlainText(block, ctx) {\n return block.contentIds.map((runId) => runToPlainText(ctx.store.getRun(runId), ctx)).join('');\n}\n\nfunction fromHTML(node, ctx) {\n if (node.tagName !== 'PRE') return null;\n const codeEl = node.querySelector('code') ?? node;\n const language = codeEl.getAttribute?.('data-language');\n const runId = genId();\n const block = {\n id: genId(),\n type: 'code',\n parentId: null,\n contentIds: [runId],\n props: language ? { language } : {},\n };\n return { block, runs: [{ id: runId, type: 'text', value: codeEl.textContent ?? '', marks: {} }] };\n}\n\nexport const codeBlockType = {\n component: CodeBlock,\n isLeaf: true,\n defaultProps: { language: 'plaintext' },\n toHTML,\n toPlainText,\n fromHTML,\n slashCommand: {\n label: 'Code',\n icon: CodeIcon,\n keywords: ['code', 'codeblock', 'snippet', 'pre'],\n run: (store, ctx) => trimSlashQueryAndInsertAfter(store, ctx, createTextLeafBlock('code')),\n },\n};\n","import { removeBlock, insertBlock } from '../../store/operations.js';\nimport { isContentlessBlock } from '../shared/contentless.js';\nimport { isRunsEmpty } from '../shared/blockEmpty.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\n\nexport function isBlankTitle(store, titleRunIds) {\n return titleRunIds.length === 0 || (titleRunIds.length === 1 && (store.getRun(titleRunIds[0])?.value ?? '') === '');\n}\n\n/**\n * True when this toggle heading's body has no real content at all — either\n * no children (shouldn't normally happen; createToggleHeadingBlock always\n * seeds one) or just its single seeded blank paragraph, still untouched.\n * Anything more (a second child, or the sole child holding real text/other\n * content) counts as \"has content\".\n */\nfunction isBodyEmpty(store, block) {\n const childIds = block.contentIds ?? [];\n if (childIds.length === 0) return true;\n if (childIds.length > 1) return false;\n const onlyChild = store.getBlock(childIds[0]);\n return Boolean(onlyChild) && onlyChild.type === 'paragraph' && isRunsEmpty(store, onlyChild.contentIds);\n}\n\nfunction applyOps(store, ops) {\n if (typeof store.performBatch === 'function') store.performBatch(ops);\n else for (const op of ops) store.applyOperation(op);\n}\n\n/**\n * Backspace-at-start for a toggle heading's own title. A toggle heading is\n * only ever removable when it's *entirely* blank — title empty AND its\n * body is empty too (see isBodyEmpty) — since createToggleHeadingBlock\n * always seeds one blank paragraph child, checking for literally zero\n * children (the previous version of this check) could never be true in\n * practice, making an empty toggle heading permanently undeletable via\n * Backspace. isBodyEmpty treats \"just the untouched seeded paragraph\" the\n * same as \"no children\" to fix that.\n *\n * No merge-into-previous-sibling behavior at all (unlike plain paragraph/\n * heading, which concatenate text into whatever's before them): a toggle\n * heading isn't in MERGEABLE_TEXT_TYPES, since \"concatenate this section's\n * title into a plain paragraph\" has no well-defined meaning once it may be\n * carrying nested children — matches the same non-mergeable precedent as\n * table/listItem/callout.\n */\nexport function mergeToggleHeadingOrNoop(store, blockId) {\n const block = store.getBlock(blockId);\n if (!block) return null;\n const parent = store.getBlock(block.parentId);\n const index = parent.contentIds.indexOf(blockId);\n const titleRunIds = block.props.titleRunIds ?? [];\n const empty = isBlankTitle(store, titleRunIds) && isBodyEmpty(store, block);\n\n if (index <= 0) {\n if (!empty) return null; // real content somewhere, nothing before it: no-op, as every other editor does\n\n if (parent.contentIds.length > 1) {\n applyOps(store, [removeBlock(blockId)]);\n return { focusBlockId: store.getBlock(parent.id).contentIds[0], needsRefocus: true };\n }\n\n // sole block in its container: replace with a blank paragraph so\n // there's still somewhere to type, same \"never leave nothing to click\n // into\" fallback as mergeWithPreviousOrDelete/ensureRootNonEmpty.\n const { block: fallbackBlock, runs } = createTextLeafBlock('paragraph')(parent.id);\n applyOps(store, [\n insertBlock(fallbackBlock, parent.id, index, { blocks: [fallbackBlock], runs }),\n removeBlock(blockId),\n ]);\n return { focusBlockId: fallbackBlock.id, needsRefocus: true };\n }\n\n const prevId = parent.contentIds[index - 1];\n const prev = store.getBlock(prevId);\n\n // An entirely-empty CURRENT toggle heading goes first, even next to a\n // non-editable previous sibling — see the matching comment in\n // shared/mergeCommands.js for why this ordering matters.\n if (empty) {\n applyOps(store, [removeBlock(blockId)]);\n return { focusBlockId: prevId, needsRefocus: true };\n }\n\n if (isContentlessBlock(store, prev)) {\n applyOps(store, [removeBlock(prevId)]);\n return { focusBlockId: blockId, needsRefocus: false };\n }\n\n return null;\n}\n","import { useCallback } from 'react';\nimport { useBlock } from '../../react/useBlock.js';\nimport { EditableBlockContent } from '../../react/EditableBlockContent.jsx';\nimport { BlockChildren } from '../../react/BlockChildren.jsx';\nimport { useEditorStore, useSelectedBlock } from '../../react/EditorProvider.jsx';\nimport { insertSiblingSplitAtCaretAndFocus, insertFirstChildSplitAtCaretAndFocus } from '../shared/blockCommands.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\nimport { mergeToggleHeadingOrNoop } from './mergeCommands.js';\nimport { isRunsEmpty } from '../shared/blockEmpty.js';\nimport { focusAfterMerge } from '../shared/focusAfterMerge.js';\nimport { updateBlockProps, insertBlock } from '../../store/operations.js';\nimport { focusAdjacentBlock } from '../shared/navigationCommands.js';\nimport { focusRunEnd } from '../../react/focusRun.js';\nimport { ChevronRightIcon, ChevronDownIcon } from '../../react/icons.jsx';\n\nfunction applyOps(store, ops) {\n if (typeof store.performBatch === 'function') store.performBatch(ops);\n else for (const op of ops) store.applyOperation(op);\n}\n\n/**\n * A heading whose section can be collapsed — same title+children split as\n * ListItemBlock (own text in props.titleRunIds, nested content in\n * contentIds), so collapsing is a purely local re-render (this component\n * conditionally skips <BlockChildren>) rather than needing any sibling-\n * range computation. Deliberately a distinct block type from `heading`\n * (not a retrofit) to avoid touching that type's existing leaf shape\n * (contentIds = its own runs) — heading is used throughout the merge/\n * split/serialize code as a plain leaf, and changing that shape would\n * ripple into all of it.\n */\nexport function ToggleHeadingBlock({ id }) {\n const store = useEditorStore();\n const block = useBlock(id);\n const { setSelectedBlockId } = useSelectedBlock();\n\n const handleEnter = useCallback(() => {\n const titleRunIds = block?.props?.titleRunIds ?? [];\n const hasNestedChildren = (block?.contentIds?.length ?? 0) > 0;\n const factory = createTextLeafBlock('paragraph');\n if (hasNestedChildren) {\n insertFirstChildSplitAtCaretAndFocus(store, id, titleRunIds, factory);\n } else {\n insertSiblingSplitAtCaretAndFocus(store, id, titleRunIds, factory);\n }\n }, [store, id, block]);\n\n const handleBackspaceAtStart = useCallback(() => {\n const result = mergeToggleHeadingOrNoop(store, id);\n if (!result || !result.needsRefocus) return;\n focusAfterMerge(store, result.focusBlockId, id, setSelectedBlockId);\n }, [store, id, setSelectedBlockId]);\n\n const handleArrowUp = useCallback(() => focusAdjacentBlock(store, id, 'up'), [store, id]);\n const handleArrowDown = useCallback(() => focusAdjacentBlock(store, id, 'down'), [store, id]);\n\n const toggleCollapsed = useCallback(() => {\n const hasChildren = (block?.contentIds?.length ?? 0) > 0;\n if (!hasChildren) {\n // A childless toggle heading has nothing to expand/collapse yet —\n // this was previously a disabled dead end. Clicking now bootstraps\n // the first (empty) child and expands, same fix as the toggle list\n // item's own marker.\n const { block: childBlock, runs } = createTextLeafBlock('paragraph')(id);\n applyOps(store, [\n insertBlock(childBlock, id, 0, { blocks: [childBlock], runs }),\n updateBlockProps(id, { collapsed: false }),\n ]);\n focusRunEnd(childBlock.contentIds[0]);\n return;\n }\n store.applyOperation(updateBlockProps(id, { collapsed: !block?.props?.collapsed }));\n }, [store, id, block?.contentIds, block?.props?.collapsed]);\n\n if (!block) return null;\n const { level = 2, collapsed, titleRunIds = [] } = block.props;\n const hasNestedChildren = block.contentIds.length > 0;\n const Tag = `h${level}`;\n\n return (\n <div className=\"be-toggle-heading\" data-block-id={id}>\n <div className=\"be-toggle-heading-row\">\n <button\n type=\"button\"\n className=\"be-toggle-heading-marker\"\n onClick={toggleCollapsed}\n aria-expanded={!collapsed}\n aria-label={!hasNestedChildren ? 'Add content to section' : collapsed ? 'Expand section' : 'Collapse section'}\n >\n {collapsed ? <ChevronRightIcon /> : <ChevronDownIcon />}\n </button>\n <Tag\n className=\"be-heading be-toggle-heading-title\"\n data-empty={isRunsEmpty(store, titleRunIds) ? '' : undefined}\n data-placeholder={`Toggle heading ${level}`}\n >\n <EditableBlockContent\n blockId={id}\n runIds={titleRunIds}\n onEnter={handleEnter}\n onBackspaceAtStart={handleBackspaceAtStart}\n onArrowUp={handleArrowUp}\n onArrowDown={handleArrowDown}\n />\n </Tag>\n </div>\n {!collapsed && (\n <div className=\"be-toggle-heading-children\">\n <BlockChildren parentId={id} />\n </div>\n )}\n </div>\n );\n}\n","import { genId } from '../../utils/idGen.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\n\n/**\n * factory(parentId, initialRuns?) -> {block, runs, subtreeBlocks} for a\n * toggle heading — its own text lives in props.titleRunIds (same\n * title+children split as listItem), while contentIds holds the section's\n * nested content, rendered only while props.collapsed is false. Seeded\n * with one empty paragraph child (same convention as callout/layout's\n * columns) so there's always at least one place to type into right away —\n * critical here specifically, since Enter on the title only ever inserts a\n * *first child* when the toggle heading already has children (see\n * ToggleHeadingBlock's handleEnter); without a seeded child, there'd be no\n * way to get content under a brand-new toggle heading at all.\n */\nexport function createToggleHeadingBlock({ level = 2, collapsed = false } = {}) {\n return function factory(parentId, initialRuns) {\n const blockId = genId();\n const runs = initialRuns?.length ? initialRuns : [{ id: genId(), type: 'text', value: '', marks: {} }];\n const { block: childBlock, runs: childRuns } = createTextLeafBlock('paragraph')(blockId);\n return {\n block: {\n id: blockId,\n type: 'toggleHeading',\n parentId,\n contentIds: [childBlock.id],\n props: { level, collapsed, titleRunIds: runs.map((r) => r.id) },\n },\n runs: [...runs, ...childRuns],\n subtreeBlocks: [childBlock],\n };\n };\n}\n","import { ToggleHeadingBlock } from './ToggleHeadingBlock.jsx';\nimport { runToHTML, runToPlainText } from '../../inline/marks.js';\nimport { domInlineToRuns } from '../../inline/runOps.js';\nimport { genId } from '../../utils/idGen.js';\nimport { trimSlashQueryAndInsertAfter } from '../shared/blockCommands.js';\nimport { createToggleHeadingBlock } from './createToggleHeadingBlock.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\nimport { ChevronRightIcon } from '../../react/icons.jsx';\n\n/**\n * <details>/<summary> is a genuine semantic match for a toggle heading —\n * `open` reflects the expanded state natively, so this round-trips through\n * any HTML consumer that understands plain HTML5 disclosure widgets, not\n * just this editor.\n */\nfunction toHTML(block, ctx) {\n const { titleRunIds = [], level = 2, collapsed } = block.props;\n const titleHTML = titleRunIds.map((runId) => runToHTML(ctx.store.getRun(runId), ctx)).join('');\n const childrenHTML = block.contentIds\n .map((childId) => {\n const child = ctx.store.getBlock(childId);\n return ctx.registry.get(child.type).toHTML(child, ctx);\n })\n .join('');\n return `<details${collapsed ? '' : ' open'}><summary><h${level}>${titleHTML}</h${level}></summary>${childrenHTML}</details>`;\n}\n\nfunction toPlainText(block, ctx) {\n const { titleRunIds = [] } = block.props;\n const title = titleRunIds.map((runId) => runToPlainText(ctx.store.getRun(runId), ctx)).join('');\n const children = block.contentIds\n .map((childId) => {\n const child = ctx.store.getBlock(childId);\n return ctx.registry.get(child.type).toPlainText(child, ctx);\n })\n .join('\\n');\n return children ? `${title}\\n${children}` : title;\n}\n\n/** Only reconstructs top-level <p> children on paste (matches blockquote's fromHTML scope) — deeper nested block types fall back to a single blank paragraph. */\nfunction fromHTML(node, ctx) {\n if (node.tagName !== 'DETAILS') return null;\n const summary = [...node.children].find((c) => c.tagName === 'SUMMARY');\n const headingEl = summary?.querySelector('h1,h2,h3,h4,h5,h6');\n const level = headingEl ? Math.min(6, Math.max(1, Number(headingEl.tagName[1]))) : 2;\n const titleRuns = headingEl ? domInlineToRuns(headingEl, ctx) : [{ id: genId(), type: 'text', value: '', marks: {} }];\n\n const blockId = genId();\n const childBlocks = [];\n const childRuns = [];\n const contentIds = [];\n for (const child of node.children) {\n if (child === summary || child.tagName !== 'P') continue;\n const runs = domInlineToRuns(child, ctx);\n const pBlock = { id: genId(), type: 'paragraph', parentId: blockId, contentIds: runs.map((r) => r.id), props: {} };\n childBlocks.push(pBlock);\n childRuns.push(...runs);\n contentIds.push(pBlock.id);\n }\n if (contentIds.length === 0) {\n const { block: fallback, runs } = createTextLeafBlock('paragraph')(blockId);\n childBlocks.push(fallback);\n childRuns.push(...runs);\n contentIds.push(fallback.id);\n }\n\n const block = {\n id: blockId,\n type: 'toggleHeading',\n parentId: null,\n contentIds,\n props: { level, collapsed: !node.hasAttribute('open'), titleRunIds: titleRuns.map((r) => r.id) },\n };\n return { block, runs: [...titleRuns, ...childRuns], subtreeBlocks: childBlocks };\n}\n\nexport const toggleHeadingBlockType = {\n component: ToggleHeadingBlock,\n isLeaf: false,\n defaultProps: { level: 2, collapsed: false, titleRunIds: [] },\n toHTML,\n toPlainText,\n fromHTML,\n slashCommands: [1, 2, 3].map((level) => ({\n label: `Toggle heading ${level}`,\n icon: ChevronRightIcon,\n // Deliberately does NOT include \"h1\"/\"h2\"/\"h3\" — those short forms\n // already belong exclusively to the plain heading commands (see\n // heading/index.js); duplicating them here would make \"/h3\" ambiguous\n // between \"Heading 3\" and \"Toggle heading 3\".\n keywords: ['toggle', 'heading', 'collapse', 'section'],\n run: (store, ctx) => trimSlashQueryAndInsertAfter(store, ctx, createToggleHeadingBlock({ level })),\n })),\n};\n","import { useEffect } from 'react';\n\n/**\n * Minimal, dependency-free modal dialog: a fixed backdrop + centered panel.\n * Closes on Escape or a click directly on the backdrop (not bubbled up from\n * inside the panel, which is why the backdrop's onMouseDown checks\n * `event.target === event.currentTarget`). No focus trap — the whole\n * editor package is deliberately zero-dependency, and dialogs here are\n * short, single-purpose forms, not deep navigable UI.\n */\nexport function Modal({ isOpen, onClose, title, children }) {\n useEffect(() => {\n if (!isOpen) return undefined;\n const handleKeyDown = (event) => {\n if (event.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [isOpen, onClose]);\n\n if (!isOpen) return null;\n\n return (\n <div\n className=\"be-modal-overlay\"\n onMouseDown={(event) => {\n if (event.target === event.currentTarget) onClose();\n }}\n >\n <div className=\"be-modal\" role=\"dialog\" aria-modal=\"true\" aria-label={title}>\n {title && <div className=\"be-modal-title\">{title}</div>}\n {children}\n </div>\n </div>\n );\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport { Modal } from '../../react/Modal.jsx';\nimport { updateBlockProps, setBlockRuns } from '../../store/operations.js';\nimport { genId } from '../../utils/idGen.js';\nimport { XIcon } from '../../react/icons.jsx';\n\nconst COLORS = [\n { label: 'Blue', value: '#2b6fd6' },\n { label: 'Green', value: '#2f9e44' },\n { label: 'Red', value: '#e03131' },\n { label: 'Purple', value: '#9c36b5' },\n { label: 'Gray', value: '#495057' },\n { label: 'Black', value: '#1a1a1a' },\n];\n\nfunction applyOps(store, ops) {\n if (typeof store.performBatch === 'function') store.performBatch(ops);\n else for (const op of ops) store.applyOperation(op);\n}\n\n/**\n * One-stop editor for a button block: label text, link URL, pill color,\n * and an open-ended list of custom key/value attributes (rendered as\n * data-* attributes on the button's own DOM node — see ButtonBlock — so a\n * host app can hook its own CSS/JS onto a button by whatever attribute\n * name it likes, without this package needing to know what for).\n *\n * Renaming the label here replaces the block's runs with a single plain\n * text run (see the save handler) — the inline contentEditable label\n * (click directly into the button's text) is still there and still keeps\n * full rich-text/marks support; this is just a faster, consolidated way to\n * set everything about the button in one place, matching how every other\n * \"edit this block's settings\" affordance in this package works.\n */\nexport function ButtonEditModal({ isOpen, onClose, store, blockId }) {\n const [label, setLabel] = useState('');\n const [href, setHref] = useState('');\n const [color, setColor] = useState(COLORS[0].value);\n const [attrs, setAttrs] = useState([{ key: '', value: '' }]);\n\n useEffect(() => {\n if (!isOpen) return;\n const block = store.getBlock(blockId);\n if (!block) return;\n const text = block.contentIds.map((runId) => store.getRun(runId)?.value ?? '').join('');\n const existingAttrs = block.props?.customAttrs ?? [];\n setLabel(text);\n setHref(block.props?.href ?? '');\n setColor(block.props?.color ?? COLORS[0].value);\n setAttrs([...existingAttrs, { key: '', value: '' }]);\n }, [isOpen, blockId, store]);\n\n const updateAttrRow = useCallback((index, patch) => {\n setAttrs((rows) => {\n const next = rows.map((row, i) => (i === index ? { ...row, ...patch } : row));\n const last = next[next.length - 1];\n if (last.key.trim() || last.value.trim()) next.push({ key: '', value: '' }); // always keep one trailing blank row to add more\n return next;\n });\n }, []);\n\n const removeAttrRow = useCallback((index) => {\n setAttrs((rows) => rows.filter((_, i) => i !== index));\n }, []);\n\n const handleSave = useCallback(() => {\n const newRun = { id: genId(), type: 'text', value: label, marks: {} };\n const customAttrs = attrs.filter((row) => row.key.trim());\n\n applyOps(store, [\n setBlockRuns(blockId, [newRun]),\n updateBlockProps(blockId, { href: href.trim(), color, customAttrs }),\n ]);\n onClose();\n }, [store, blockId, label, href, color, attrs, onClose]);\n\n return (\n <Modal isOpen={isOpen} onClose={onClose} title=\"Edit button\">\n <label className=\"be-modal-field\">\n <span>Label</span>\n <input type=\"text\" value={label} onChange={(event) => setLabel(event.target.value)} placeholder=\"Button\" />\n </label>\n\n <label className=\"be-modal-field\">\n <span>Link URL</span>\n <input\n type=\"url\"\n value={href}\n onChange={(event) => setHref(event.target.value)}\n placeholder=\"https://example.com\"\n />\n </label>\n\n <div className=\"be-modal-field\">\n <span>Color</span>\n <div className=\"be-modal-color-row\">\n {COLORS.map((c) => (\n <button\n key={c.value}\n type=\"button\"\n className={`be-modal-color-swatch${color === c.value ? ' be-modal-color-swatch-active' : ''}`}\n style={{ backgroundColor: c.value }}\n title={c.label}\n aria-label={c.label}\n onClick={() => setColor(c.value)}\n />\n ))}\n </div>\n </div>\n\n <div className=\"be-modal-field\">\n <span>Custom attributes</span>\n {attrs.map((row, index) => (\n <div className=\"be-modal-attr-row\" key={index}>\n <input\n type=\"text\"\n placeholder=\"name\"\n value={row.key}\n onChange={(event) => updateAttrRow(index, { key: event.target.value })}\n />\n <input\n type=\"text\"\n placeholder=\"value\"\n value={row.value}\n onChange={(event) => updateAttrRow(index, { value: event.target.value })}\n />\n {(row.key || row.value) && (\n <button type=\"button\" className=\"be-modal-attr-remove\" onClick={() => removeAttrRow(index)} aria-label=\"Remove attribute\">\n <XIcon size={14} />\n </button>\n )}\n </div>\n ))}\n </div>\n\n <div className=\"be-modal-actions\">\n <button type=\"button\" className=\"be-modal-cancel\" onClick={onClose}>\n Cancel\n </button>\n <button type=\"button\" className=\"be-modal-save\" onClick={handleSave}>\n Save\n </button>\n </div>\n </Modal>\n );\n}\n","import { useCallback, useState } from 'react';\nimport { EditableBlockContent } from '../../react/EditableBlockContent.jsx';\nimport { useBlock } from '../../react/useBlock.js';\nimport { useEditorStore, useSelectedBlock } from '../../react/EditorProvider.jsx';\nimport { insertSiblingSplitAtCaretAndFocus } from '../shared/blockCommands.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\nimport { mergeWithPreviousOrDelete } from '../shared/mergeCommands.js';\nimport { isRunsEmpty } from '../shared/blockEmpty.js';\nimport { focusAfterMerge } from '../shared/focusAfterMerge.js';\nimport { focusAdjacentBlock } from '../shared/navigationCommands.js';\nimport { ButtonEditModal } from './ButtonEditModal.jsx';\n\nconst DEFAULT_COLOR = '#2b6fd6';\n\n/**\n * A leaf block (own runs, same mechanism as paragraph/heading) styled as a\n * clickable button, with `href`/`color`/`customAttrs` props. Editing the\n * label inline (click into the text, type, format, etc.) and *activating*\n * the button (following its link) are kept as two entirely separate\n * controls — a plain click inside the label only ever places the caret,\n * the same as any other block's text, and never navigates; the small\n * \"open ↗\" button is the only thing that does. The \"⚙\" button opens a\n * one-stop modal for label/link/color/custom-attributes (see\n * ButtonEditModal) as a faster consolidated alternative to editing the\n * label inline and there being nowhere else to set the rest.\n *\n * `customAttrs` (arbitrary name/value pairs from the modal) render as\n * data-* attributes directly on the pill element, not as raw injected\n * HTML/JS — a host app can hook its own CSS or event delegation onto\n * whatever attribute name it likes without this package needing to know\n * what for, without any injection risk.\n *\n * Enter creates a plain paragraph sibling (not another button), matching\n * heading's own convention — a run of several consecutive buttons from\n * repeated Enter isn't a sensible default.\n */\nexport function ButtonBlock({ id }) {\n const store = useEditorStore();\n const block = useBlock(id);\n const { setSelectedBlockId } = useSelectedBlock();\n const [isEditModalOpen, setIsEditModalOpen] = useState(false);\n\n const handleEnter = useCallback(() => {\n insertSiblingSplitAtCaretAndFocus(store, id, block?.contentIds ?? [], createTextLeafBlock('paragraph'));\n }, [store, id, block]);\n\n const handleBackspaceAtStart = useCallback(() => {\n const focusBlockId = mergeWithPreviousOrDelete(store, id);\n focusAfterMerge(store, focusBlockId, id, setSelectedBlockId);\n }, [store, id, setSelectedBlockId]);\n\n const handleArrowUp = useCallback(() => focusAdjacentBlock(store, id, 'up'), [store, id]);\n const handleArrowDown = useCallback(() => focusAdjacentBlock(store, id, 'down'), [store, id]);\n\n const openLink = useCallback(() => {\n const href = block?.props?.href;\n if (href) window.open(href, '_blank', 'noopener,noreferrer');\n }, [block?.props?.href]);\n\n if (!block) return null;\n const href = block.props?.href ?? '';\n const color = block.props?.color ?? DEFAULT_COLOR;\n const customAttrs = block.props?.customAttrs ?? [];\n const isEmpty = isRunsEmpty(store, block.contentIds);\n\n const dataAttrs = {};\n for (const { key, value } of customAttrs) {\n if (key.trim()) dataAttrs[`data-${key.trim()}`] = value;\n }\n\n return (\n <div className=\"be-button-block\" data-block-id={id}>\n <div className=\"be-button-block-pill\" style={{ backgroundColor: color }} {...dataAttrs}>\n <span className=\"be-button-block-label\" data-empty={isEmpty ? '' : undefined} data-placeholder=\"Button\">\n <EditableBlockContent\n blockId={id}\n runIds={block.contentIds}\n onEnter={handleEnter}\n onBackspaceAtStart={handleBackspaceAtStart}\n onArrowUp={handleArrowUp}\n onArrowDown={handleArrowDown}\n />\n </span>\n <button\n type=\"button\"\n className=\"be-button-block-open\"\n onClick={openLink}\n disabled={!href}\n title={href || 'No link set'}\n aria-label=\"Open link\"\n >\n ↗\n </button>\n <button\n type=\"button\"\n className=\"be-button-block-settings\"\n onClick={() => setIsEditModalOpen(true)}\n aria-label=\"Edit button\"\n title=\"Edit label, link, color…\"\n >\n ⚙\n </button>\n </div>\n <ButtonEditModal isOpen={isEditModalOpen} onClose={() => setIsEditModalOpen(false)} store={store} blockId={id} />\n </div>\n );\n}\n","import { genId } from '../../utils/idGen.js';\n\n/**\n * factory(parentId, initialRuns?) -> {block, runs} for a button — a plain\n * leaf (contentIds are its own run ids, exactly like paragraph/heading),\n * plus a `href` prop. Not in MERGEABLE_TEXT_TYPES (see mergeCommands.js):\n * concatenating a button's label into a preceding paragraph would silently\n * drop its href, so it's excluded the same way table/listItem/callout are.\n */\nexport function createButtonBlock({ href = '', label = 'Button', color = '', customAttrs = [] } = {}) {\n return function factory(parentId, initialRuns) {\n const blockId = genId();\n const runs = initialRuns?.length ? initialRuns : [{ id: genId(), type: 'text', value: label, marks: {} }];\n return {\n block: { id: blockId, type: 'button', parentId, contentIds: runs.map((r) => r.id), props: { href, color, customAttrs } },\n runs,\n };\n };\n}\n","import { ButtonBlock } from './ButtonBlock.jsx';\nimport { runToHTML, runToPlainText, escapeAttr } from '../../inline/marks.js';\nimport { domInlineToRuns } from '../../inline/runOps.js';\nimport { genId } from '../../utils/idGen.js';\nimport { trimSlashQueryAndInsertAfter } from '../shared/blockCommands.js';\nimport { createButtonBlock } from './createButtonBlock.js';\nimport { ButtonIcon } from '../../react/icons.jsx';\n\n// Distinctive class (not just a bare <a>) so this never collides with an\n// ordinary link pasted from elsewhere — walkDomToBlocks's generic matcher\n// loop only claims an anchor as a button when this exact marker is present;\n// any other <a> falls through to the normal inline-link-within-a-paragraph\n// handling, which is what plain link pasting should do.\nconst MARKER_CLASS = 'be-button-block-link';\n\nfunction toHTML(block, ctx) {\n const runs = block.contentIds.map((runId) => ctx.store.getRun(runId));\n const href = block.props?.href ?? '';\n const color = block.props?.color;\n const style = color ? ` style=\"background-color:${escapeAttr(color)}\"` : '';\n const customAttrs = block.props?.customAttrs ?? [];\n const attrHTML = customAttrs\n .filter((a) => a.key?.trim())\n .map((a) => ` data-${escapeAttr(a.key.trim())}=\"${escapeAttr(a.value ?? '')}\"`)\n .join('');\n return `<a class=\"${MARKER_CLASS}\" href=\"${escapeAttr(href)}\"${style}${attrHTML}>${runs.map((r) => runToHTML(r, ctx)).join('')}</a>`;\n}\n\nfunction toPlainText(block, ctx) {\n return block.contentIds.map((runId) => runToPlainText(ctx.store.getRun(runId), ctx)).join('');\n}\n\nfunction fromHTML(node, ctx) {\n if (node.tagName !== 'A' || !node.classList.contains(MARKER_CLASS)) return null;\n const runs = domInlineToRuns(node, ctx);\n const customAttrs = [];\n for (const attr of node.attributes) {\n if (attr.name.startsWith('data-')) customAttrs.push({ key: attr.name.slice(5), value: attr.value });\n }\n const block = {\n id: genId(),\n type: 'button',\n parentId: null,\n contentIds: runs.map((r) => r.id),\n props: {\n href: node.getAttribute('href') ?? '',\n color: node.style?.backgroundColor || undefined,\n customAttrs,\n },\n };\n return { block, runs };\n}\n\nexport const buttonBlockType = {\n component: ButtonBlock,\n isLeaf: true,\n defaultProps: { href: '', color: '', customAttrs: [] },\n toHTML,\n toPlainText,\n fromHTML,\n slashCommand: {\n label: 'Button',\n icon: ButtonIcon,\n keywords: ['button', 'link', 'cta', 'action'],\n run: (store, ctx) => trimSlashQueryAndInsertAfter(store, ctx, createButtonBlock()),\n },\n};\n","import { useCallback, useRef, useState } from 'react';\nimport { useBlock } from '../../react/useBlock.js';\nimport { useEditorStore } from '../../react/EditorProvider.jsx';\nimport { updateBlockProps } from '../../store/operations.js';\nimport { PaperclipIcon, AlignLeftIcon, AlignCenterIcon, AlignRightIcon } from '../../react/icons.jsx';\n\nfunction readFileAsDataURL(file) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(file);\n });\n}\n\nconst KIND_LABEL = { image: 'image', video: 'video', audio: 'audio', file: 'file' };\nconst KIND_ACCEPT = { image: 'image/*', video: 'video/*', audio: 'audio/*', file: '*/*' };\nconst MIN_WIDTH = 20;\nconst MAX_WIDTH = 100;\nconst ALIGN_OPTIONS = [\n { value: 'left', Icon: AlignLeftIcon, label: 'Align left' },\n { value: 'center', Icon: AlignCenterIcon, label: 'Align center' },\n { value: 'right', Icon: AlignRightIcon, label: 'Align right' },\n];\n\nfunction clampWidth(pct) {\n return Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, Math.round(pct)));\n}\n\nfunction EmbedPreview({ kind, src, name }) {\n if (kind === 'image') return <img className=\"be-embed-image\" src={src} alt={name || ''} />;\n if (kind === 'video') return <video className=\"be-embed-video\" src={src} controls />;\n if (kind === 'audio') return <audio className=\"be-embed-audio\" src={src} controls />;\n return (\n <a className=\"be-embed-file-link\" href={src} download={name || undefined} target=\"_blank\" rel=\"noopener noreferrer\">\n <PaperclipIcon size={14} /> {name || src}\n </a>\n );\n}\n\n/**\n * A pure \"widget\" block — no runs/text at all (contentIds always []), same\n * shape as DividerBlock — so it participates in cross-block select/copy/\n * cut/delete for free via the exact same generic mechanisms already\n * exercised by divider: it's \"contentless\" the same way, so backspacing\n * into it from a following block clears it as the nearest obstacle,\n * matching every other contentless block (see mergeWithPreviousOrDelete).\n *\n * There is no upload-to-a-server endpoint here — this is a zero-runtime-\n * dependency package with no backend component at all — so a local file\n * picked via the file input or dropped is read via FileReader straight\n * into a data: URL and stored directly in props.src. That keeps the\n * document fully self-contained (works offline, round-trips through copy/\n * paste and undo/redo like any other prop) at the cost of bloating the\n * document for large media; a host app that wants real upload-to-a-server\n * behavior should intercept this at a higher level (e.g. wrapping\n * createEmbedBlock/this component with its own), which is as far as a\n * dependency-free package can reasonably go on its own.\n *\n * `align` positions the whole widget within the line (a flex row on\n * `.be-embed-preview`, matching Notion's own media alignment). `width` is a\n * percentage, dragged via `.be-embed-resize-handle` — only image/video\n * kinds get the handle (an audio player or a file-download pill don't have\n * a meaningful \"shrink the visual\" concept the same way). The drag itself\n * only updates local state (`dragWidth`) for a live preview; the store is\n * only written once, on mouseup, so dragging doesn't spam undo history\n * with one step per pixel of mouse movement.\n */\nexport function EmbedBlock({ id }) {\n const store = useEditorStore();\n const block = useBlock(id);\n const [urlInput, setUrlInput] = useState('');\n const [isDragOver, setIsDragOver] = useState(false);\n const [dragWidth, setDragWidth] = useState(null);\n const previewRef = useRef(null);\n const frameRef = useRef(null);\n\n const setMedia = useCallback((patch) => store.applyOperation(updateBlockProps(id, patch)), [store, id]);\n\n const handleFileChange = useCallback(\n async (event) => {\n const file = event.target.files?.[0];\n if (!file) return;\n const src = await readFileAsDataURL(file);\n setMedia({ src, name: file.name, mimeType: file.type });\n },\n [setMedia],\n );\n\n const handleDrop = useCallback(\n async (event) => {\n event.preventDefault();\n setIsDragOver(false);\n const file = event.dataTransfer.files?.[0];\n if (!file) return;\n const src = await readFileAsDataURL(file);\n setMedia({ src, name: file.name, mimeType: file.type });\n },\n [setMedia],\n );\n\n const handleDragOver = useCallback((event) => {\n event.preventDefault();\n setIsDragOver(true);\n }, []);\n\n const handleDragLeave = useCallback(() => setIsDragOver(false), []);\n\n const commitUrl = useCallback(() => {\n const trimmed = urlInput.trim();\n if (!trimmed) return;\n setMedia({ src: trimmed, name: trimmed });\n setUrlInput('');\n }, [urlInput, setMedia]);\n\n const clearMedia = useCallback(() => setMedia({ src: '', name: '', mimeType: '' }), [setMedia]);\n\n const handleResizeStart = useCallback(\n (event) => {\n event.preventDefault();\n const containerEl = previewRef.current;\n const frameEl = frameRef.current;\n if (!containerEl || !frameEl) return;\n const containerWidth = containerEl.getBoundingClientRect().width;\n const startWidth = frameEl.getBoundingClientRect().width;\n const startX = event.clientX;\n\n const computePct = (moveEvent) => clampWidth(((startWidth + (moveEvent.clientX - startX)) / containerWidth) * 100);\n\n const handleMouseMove = (moveEvent) => setDragWidth(computePct(moveEvent));\n const handleMouseUp = (upEvent) => {\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n setMedia({ width: computePct(upEvent) });\n setDragWidth(null);\n };\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n },\n [setMedia],\n );\n\n if (!block) return null;\n const { kind = 'file', src, name, align = 'left', width = 100 } = block.props;\n const canResize = kind === 'image' || kind === 'video';\n const effectiveWidth = dragWidth ?? width;\n\n return (\n // tabIndex={-1}: focusable via .focus() (see setSelectedBlockId in\n // EditorProvider.jsx) without joining the normal Tab order — keeps the\n // surface's keydown listener capturing subsequent Backspace/Delete\n // presses once this block becomes selected, even when whatever\n // previously had focus was just removed from the DOM entirely.\n <div className=\"be-embed\" data-block-id={id} data-kind={kind} contentEditable={false} tabIndex={-1}>\n {src ? (\n <div ref={previewRef} className={`be-embed-preview be-embed-align-${align}`}>\n <div\n ref={frameRef}\n className=\"be-embed-frame\"\n style={canResize ? { width: `${effectiveWidth}%` } : undefined}\n >\n <div className=\"be-embed-toolbar\" contentEditable={false}>\n {ALIGN_OPTIONS.map(({ value, Icon, label }) => (\n <button\n key={value}\n type=\"button\"\n className={`be-embed-toolbar-btn${align === value ? ' be-embed-toolbar-btn-active' : ''}`}\n title={label}\n aria-label={label}\n aria-pressed={align === value}\n onClick={() => setMedia({ align: value })}\n >\n <Icon size={14} />\n </button>\n ))}\n <button type=\"button\" className=\"be-embed-remove\" onClick={clearMedia} aria-label={`Remove ${KIND_LABEL[kind]}`}>\n Remove\n </button>\n </div>\n <EmbedPreview kind={kind} src={src} name={name} />\n {canResize && (\n <div\n className=\"be-embed-resize-handle\"\n onMouseDown={handleResizeStart}\n role=\"slider\"\n aria-label={`Resize ${KIND_LABEL[kind]}`}\n aria-valuemin={MIN_WIDTH}\n aria-valuemax={MAX_WIDTH}\n aria-valuenow={effectiveWidth}\n />\n )}\n </div>\n </div>\n ) : (\n <div\n className={`be-embed-dropzone${isDragOver ? ' be-embed-dropzone-active' : ''}`}\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n >\n <label className=\"be-embed-upload-btn\">\n Upload {KIND_LABEL[kind]}\n <input type=\"file\" accept={KIND_ACCEPT[kind]} onChange={handleFileChange} hidden />\n </label>\n <span className=\"be-embed-dropzone-hint\">or drop a file, or paste a URL below</span>\n <div className=\"be-embed-url-row\">\n <input\n type=\"text\"\n className=\"be-embed-url-input\"\n placeholder={`https://... ${KIND_LABEL[kind]} URL`}\n value={urlInput}\n onChange={(event) => setUrlInput(event.target.value)}\n onKeyDown={(event) => event.key === 'Enter' && commitUrl()}\n />\n <button type=\"button\" className=\"be-embed-url-commit\" onClick={commitUrl}>\n Embed\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n","import { genId } from '../../utils/idGen.js';\n\n/**\n * factory(parentId) -> {block, runs} for a media embed — a pure \"widget\"\n * block with no runs at all (contentIds always []), same shape as divider:\n * `kind` is one of 'image' | 'video' | 'audio' | 'file'; `src` is either an\n * external URL or a data: URL (for a locally-uploaded file — see\n * EmbedBlock.jsx for why there's no upload-to-a-server path in a\n * zero-runtime-dependency package with no backend); `name` is the original\n * filename or the URL itself, used as alt text / download name / link text\n * depending on kind. `align` ('left' | 'center' | 'right') positions the\n * whole widget within the line; `width` (a percentage, 20-100) is only\n * meaningful for image/video kinds — see EmbedBlock's resize handle.\n */\nexport function createEmbedBlock({ kind = 'file', src = '', name = '', mimeType = '', align = 'left', width = 100 } = {}) {\n return function factory(parentId) {\n return {\n block: { id: genId(), type: 'embed', parentId, contentIds: [], props: { kind, src, name, mimeType, align, width } },\n runs: [],\n };\n };\n}\n","import { EmbedBlock } from './EmbedBlock.jsx';\nimport { genId } from '../../utils/idGen.js';\nimport { escapeAttr, escapeHTML } from '../../inline/marks.js';\nimport { insertSiblingAfter, insertSiblingAfterAndFocus } from '../shared/blockCommands.js';\nimport { createTextLeafBlock } from '../shared/leafBlockFactory.js';\nimport { createEmbedBlock } from './createEmbedBlock.js';\nimport { updateRun } from '../../store/operations.js';\nimport { ImageIcon, VideoIcon, AudioIcon, PaperclipIcon } from '../../react/icons.jsx';\n\nconst KIND_ICONS = { image: ImageIcon, video: VideoIcon, audio: AudioIcon, file: PaperclipIcon };\n\n// Distinctive marker class for the 'file' kind's <a> — same reasoning as\n// the button block: an ordinary pasted link must never be mistaken for a\n// file embed.\nconst FILE_MARKER_CLASS = 'be-embed-file-link';\n\n// Only image/video kinds ever carry a non-default align/width (see\n// EmbedBlock's resize handle/alignment toolbar) — the inline `style`\n// attribute is only ever emitted for those, and only when it actually\n// differs from the default, so a plain default-aligned embed's HTML output\n// is byte-identical to before this existed.\nfunction alignWidthStyle(kind, align, width) {\n if (kind !== 'image' && kind !== 'video') return '';\n const declarations = [];\n if (width !== 100) declarations.push(`width:${width}%`);\n if (align === 'center') declarations.push('display:block', 'margin-left:auto', 'margin-right:auto');\n else if (align === 'right') declarations.push('display:block', 'margin-left:auto');\n return declarations.length ? ` style=\"${declarations.join(';')}\"` : '';\n}\n\nfunction parseAlignWidth(node) {\n const styleWidth = node.style?.width;\n const width = styleWidth && styleWidth.endsWith('%') ? parseInt(styleWidth, 10) : 100;\n let align = 'left';\n if (node.style?.marginLeft === 'auto' && node.style?.marginRight === 'auto') align = 'center';\n else if (node.style?.marginLeft === 'auto') align = 'right';\n return { align, width: Number.isFinite(width) ? width : 100 };\n}\n\nfunction toHTML(block) {\n const { kind, src, name, align = 'left', width = 100 } = block.props;\n if (!src) return '<p></p>'; // nothing embedded yet: nothing meaningful to export\n const style = alignWidthStyle(kind, align, width);\n if (kind === 'image') return `<img src=\"${escapeAttr(src)}\" alt=\"${escapeAttr(name || '')}\"${style}>`;\n if (kind === 'video') return `<video src=\"${escapeAttr(src)}\" controls${style}></video>`;\n if (kind === 'audio') return `<audio src=\"${escapeAttr(src)}\" controls></audio>`;\n return `<a class=\"${FILE_MARKER_CLASS}\" href=\"${escapeAttr(src)}\">${escapeHTML(name || src)}</a>`;\n}\n\nfunction toPlainText(block) {\n const { kind, src, name } = block.props;\n return src ? `[${kind}: ${name || src}]` : '';\n}\n\nfunction fromHTML(node) {\n if (node.tagName === 'IMG') {\n return blockOf('image', node.getAttribute('src') ?? '', node.getAttribute('alt') ?? '', parseAlignWidth(node));\n }\n if (node.tagName === 'VIDEO') {\n return blockOf('video', node.getAttribute('src') ?? '', '', parseAlignWidth(node));\n }\n if (node.tagName === 'AUDIO') {\n return blockOf('audio', node.getAttribute('src') ?? '', '');\n }\n if (node.tagName === 'A' && node.classList.contains(FILE_MARKER_CLASS)) {\n return blockOf('file', node.getAttribute('href') ?? '', node.textContent ?? '');\n }\n return null;\n}\n\nfunction blockOf(kind, src, name, { align = 'left', width = 100 } = {}) {\n return {\n block: { id: genId(), type: 'embed', parentId: null, contentIds: [], props: { kind, src, name, align, width } },\n runs: [],\n };\n}\n\n/** Same pattern as divider's slash command: an embed has no run of its own to focus into, so seed and focus a following paragraph. */\nfunction insertEmbedCommand(kind) {\n return (store, { blockId, runId, sliceStart, sliceEnd }) => {\n const run = store.getRun(runId);\n const value = run?.value ?? '';\n store.applyOperation(updateRun(runId, { value: value.slice(0, sliceStart) + value.slice(sliceEnd) }));\n const embedId = insertSiblingAfter(store, blockId, createEmbedBlock({ kind }));\n insertSiblingAfterAndFocus(store, embedId, createTextLeafBlock('paragraph'));\n return embedId;\n };\n}\n\nexport const embedBlockType = {\n component: EmbedBlock,\n isLeaf: true, // contentIds always [] — a pure widget, same convention as divider\n defaultProps: { kind: 'file', src: '', name: '', mimeType: '', align: 'left', width: 100 },\n toHTML,\n toPlainText,\n fromHTML,\n slashCommands: ['image', 'video', 'audio', 'file'].map((kind) => ({\n label: kind.charAt(0).toUpperCase() + kind.slice(1),\n icon: KIND_ICONS[kind],\n keywords: ['embed', 'upload', 'insert', kind],\n run: insertEmbedCommand(kind),\n })),\n};\n","import { paragraphBlockType } from './paragraph/index.js';\nimport { headingBlockType } from './heading/index.js';\nimport { listItemBlockType } from './listItem/index.js';\nimport { tableBlockType, tableRowBlockType, tableCellBlockType } from './table/index.js';\nimport { layoutBlockType, layoutColumnBlockType } from './layout/index.js';\nimport { dividerBlockType } from './divider/index.js';\nimport { calloutBlockType } from './callout/index.js';\nimport { blockquoteBlockType } from './blockquote/index.js';\nimport { codeBlockType } from './code/index.js';\nimport { toggleHeadingBlockType } from './toggleHeading/index.js';\nimport { buttonBlockType } from './button/index.js';\nimport { embedBlockType } from './embed/index.js';\n\n/** Registers every built-in block type on the given registry. */\nexport function registerBuiltInBlocks(registry) {\n registerBlocks(registry, {\n paragraph: paragraphBlockType,\n heading: headingBlockType,\n listItem: listItemBlockType,\n ...TABLE_BLOCKS,\n ...LAYOUT_BLOCKS,\n divider: dividerBlockType,\n callout: calloutBlockType,\n blockquote: blockquoteBlockType,\n code: codeBlockType,\n toggleHeading: toggleHeadingBlockType,\n button: buttonBlockType,\n embed: embedBlockType,\n });\n}\n\n/**\n * Registers only the block types you name — the opt-in counterpart to\n * `registerBuiltInBlocks`, for a consumer who wants (say) just paragraph,\n * heading, and table, with nothing else's code even reachable from their\n * bundle. `blocksByType` is `{ [type]: blockTypeEntry }`; every built-in\n * block type object below (`paragraphBlockType`, `tableBlockType`, ...) is\n * published individually for exactly this purpose — plain, tree-shakeable\n * values, not something living only inside this file's own registration\n * call.\n *\n * `table` and `layout` are each three/two block types that only work\n * together (a table with no `tableRow`/`tableCell` registered can't render\n * its own rows) — see `TABLE_BLOCKS`/`LAYOUT_BLOCKS` below, spread the\n * whole group in rather than picking pieces of one apart.\n */\nexport function registerBlocks(registry, blocksByType) {\n for (const [type, entry] of Object.entries(blocksByType)) {\n registry.register(type, entry);\n }\n}\n\n/** `table` needs its row/cell block types registered alongside it — spread this whole group in together. */\nexport const TABLE_BLOCKS = {\n table: tableBlockType,\n tableRow: tableRowBlockType,\n tableCell: tableCellBlockType,\n};\n\n/** `layout` needs its column block type registered alongside it — spread this whole group in together. */\nexport const LAYOUT_BLOCKS = {\n layout: layoutBlockType,\n layoutColumn: layoutColumnBlockType,\n};\n\nexport {\n paragraphBlockType,\n headingBlockType,\n listItemBlockType,\n tableBlockType,\n tableRowBlockType,\n tableCellBlockType,\n layoutBlockType,\n layoutColumnBlockType,\n dividerBlockType,\n calloutBlockType,\n blockquoteBlockType,\n codeBlockType,\n toggleHeadingBlockType,\n buttonBlockType,\n embedBlockType,\n};\n","import { useCallback } from 'react';\nimport { useRun } from '../../react/useBlock.js';\nimport { useEditorStore } from '../../react/EditorProvider.jsx';\nimport { updateRun } from '../../store/operations.js';\nimport { Select } from '../../react/Select.jsx';\n\n/**\n * An atomic inline \"chip\" mixed directly into running text — e.g. a\n * diagnosis/complaint picker inside a paragraph, exactly like the old\n * notevo schema's inline `type: 'select'` runs. `EditableBlockContent`\n * mounts this into an imperatively-managed host element that carries\n * `data-run-id`/`contentEditable={false}` itself (via a React portal) — this\n * component only renders its own inner content/styling.\n *\n * Renders the shared searchable `Select` combobox — no inline add/remove-\n * option UI. A chip inserted via the `/select` command starts with an empty\n * options list (see index.js's slashCommand); populating/editing that list\n * is left to a host app's own options-source integration (see\n * createSelectFieldType for a full, named/reusable version of that idea),\n * to be revisited later.\n */\nexport function SelectInlineNode({ id }) {\n const store = useEditorStore();\n const run = useRun(id);\n\n const handleChange = useCallback(\n (selectedValue) => {\n store.applyOperation(updateRun(id, { data: { ...run?.data, selectedValue } }));\n },\n [store, id, run?.data],\n );\n\n if (!run) return null;\n const { options = [], selectedValue = '', placeholder = 'Select…' } = run.data ?? {};\n\n return (\n <span\n className=\"be-inline-select\"\n // preventDefault too, not just stopPropagation: the browser's default\n // mousedown action collapses the surrounding paragraph's text\n // selection/caret to wherever was clicked, even for a click that\n // lands on a nested non-text control like the Select's trigger\n // button or its search input — without this, that default caret-\n // collapse wins the timing race against Select's own\n // inputRef.current.focus() (called from a useEffect once the\n // popover mounts), so the very first character typed lands back in\n // the paragraph instead of the search box (same rationale as\n // FloatingToolbar's identical onMouseDown preventDefault).\n onMouseDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n // React re-dispatches bubbling synthetic events along the *React*\n // tree, not the physical DOM tree — since this chip is mounted via a\n // portal, a keydown on the Select below would otherwise still reach\n // EditableBlockContent's own onKeyDown and can be misread as e.g.\n // \"Backspace next to this chip\", deleting the whole chip instead of\n // just interacting with the dropdown.\n onKeyDown={(event) => event.stopPropagation()}\n >\n <Select value={selectedValue} options={options} onChange={handleChange} placeholder={placeholder} ariaLabel=\"Select an option\" />\n </span>\n );\n}\n","import { genId } from '../../utils/idGen.js';\nimport { replaceRunSpan } from '../../store/operations.js';\nimport { focusRunEnd } from '../../react/focusRun.js';\n\n/**\n * Splices a newly-created inline run in at the *exact* cursor position\n * (sliceStart/sliceEnd bracket the \"/query\" text that triggered it) —\n * splitting the triggering run into three: whatever came before the \"/\",\n * the new atomic chip, and whatever came after the cursor. This is what\n * makes the chip land where you actually typed \"/\", not always at the end\n * of the block — a run with only \"before\" text and no \"after\" (cursor was\n * at the end) still gets an empty trailing run so there's somewhere to\n * keep typing past the chip. The \"before\" run keeps the original run's id\n * so its DOM span isn't remounted.\n */\nexport function insertInlineRunAtCursor(store, { blockId, runId, sliceStart, sliceEnd }, createInlineRun) {\n const currentRun = store.getRun(runId);\n const value = currentRun?.value ?? '';\n const beforeText = value.slice(0, sliceStart);\n const afterText = value.slice(sliceEnd);\n\n const inlineRun = createInlineRun();\n const beforeRun = { ...currentRun, value: beforeText };\n const afterRun = { id: genId(), type: 'text', value: afterText, marks: { ...currentRun?.marks } };\n\n store.applyOperation(replaceRunSpan(blockId, [runId], [beforeRun, inlineRun, afterRun]));\n focusRunEnd(afterRun.id);\n}\n","import { SelectInlineNode } from './SelectInlineNode.jsx';\nimport { genId } from '../../utils/idGen.js';\nimport { insertInlineRunAtCursor } from '../shared/insertInlineRun.js';\nimport { SelectIcon } from '../../react/icons.jsx';\n\nfunction escapeAttr(str) {\n return String(str).replace(/&/g, '&amp;').replace(/\"/g, '&quot;');\n}\n\nfunction selectedLabel(run) {\n const { options = [], selectedValue = '' } = run.data ?? {};\n return options.find((opt) => opt.value === selectedValue)?.label ?? '';\n}\n\nfunction toHTML(run) {\n const label = selectedLabel(run) || run.data?.placeholder || '';\n return `<span data-inline-type=\"select\" data-selected-value=\"${escapeAttr(run.data?.selectedValue ?? '')}\">${label}</span>`;\n}\n\nfunction toPlainText(run) {\n return selectedLabel(run);\n}\n\n/**\n * Only claims nodes carrying our own `data-inline-type=\"select\"` marker —\n * i.e. lossless same-editor round-trips (the app-specific clipboard JSON\n * path already round-trips runs directly without going through HTML at\n * all; this fromHTML exists for the text/html clipboard fallback). Foreign\n * HTML from another app has no such marker and correctly falls through to\n * plain text, since there's no way to know what a \"select\" from another\n * app's DOM even means.\n */\nfunction fromHTML(node) {\n if (node.getAttribute?.('data-inline-type') !== 'select') return null;\n return {\n id: genId(),\n type: 'select',\n value: '',\n marks: {},\n data: {\n options: [],\n selectedValue: node.getAttribute('data-selected-value') ?? '',\n },\n };\n}\n\nexport const selectInlineType = {\n component: SelectInlineNode,\n isAtomic: true,\n toHTML,\n toPlainText,\n fromHTML,\n slashCommand: {\n label: 'Select',\n icon: SelectIcon,\n keywords: ['select', 'dropdown', 'choice', 'picker'],\n run: (store, { blockId, runId, sliceStart, sliceEnd }) =>\n insertInlineRunAtCursor(store, { blockId, runId, sliceStart, sliceEnd }, () => ({\n id: genId(),\n type: 'select',\n value: '',\n marks: {},\n data: { options: [], selectedValue: '', placeholder: 'Select…' },\n })),\n },\n};\n","import { useCallback } from 'react';\nimport { useRun } from '../../react/useBlock.js';\nimport { useEditorStore } from '../../react/EditorProvider.jsx';\nimport { updateRun } from '../../store/operations.js';\n\n/**\n * An atomic date chip — a real <input type=\"date\">, proving the inline\n * mechanism generalizes to arbitrary native controls, not just <select>\n * (see selectInlineType). `EditableBlockContent` mounts this into an\n * imperatively-managed host element that carries `data-run-id`/\n * `contentEditable={false}` itself (via a React portal) — this component\n * only renders its own inner content/styling.\n */\nexport function DateInlineNode({ id }) {\n const store = useEditorStore();\n const run = useRun(id);\n\n const handleChange = useCallback(\n (event) => {\n store.applyOperation(updateRun(id, { data: { ...run?.data, isoDate: event.target.value } }));\n },\n [store, id, run?.data],\n );\n\n if (!run) return null;\n const { isoDate = '' } = run.data ?? {};\n\n return (\n <span\n className=\"be-inline-date\"\n onMouseDown={(event) => event.stopPropagation()}\n // See SelectInlineNode's onKeyDown comment: without this, a keydown on\n // the date input (e.g. Backspace while editing it) still reaches\n // EditableBlockContent's onKeyDown via React's portal-following\n // synthetic bubbling, and can be misread as deleting this whole chip.\n onKeyDown={(event) => event.stopPropagation()}\n >\n <input type=\"date\" value={isoDate} onChange={handleChange} />\n </span>\n );\n}\n","import { DateInlineNode } from './DateInlineNode.jsx';\nimport { genId } from '../../utils/idGen.js';\nimport { insertInlineRunAtCursor } from '../shared/insertInlineRun.js';\nimport { DateIcon } from '../../react/icons.jsx';\n\nfunction escapeAttr(str) {\n return String(str).replace(/&/g, '&amp;').replace(/\"/g, '&quot;');\n}\n\nfunction formatDate(isoDate) {\n if (!isoDate) return '';\n const parsed = new Date(`${isoDate}T00:00:00`);\n if (Number.isNaN(parsed.getTime())) return isoDate;\n return parsed.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });\n}\n\nfunction toHTML(run) {\n const isoDate = run.data?.isoDate ?? '';\n return `<span data-inline-type=\"date\" data-iso-date=\"${escapeAttr(isoDate)}\">${formatDate(isoDate)}</span>`;\n}\n\nfunction toPlainText(run) {\n return formatDate(run.data?.isoDate ?? '');\n}\n\n/** Only claims our own `data-inline-type=\"date\"` marker — see select's fromHTML for why. */\nfunction fromHTML(node) {\n if (node.getAttribute?.('data-inline-type') !== 'date') return null;\n return {\n id: genId(),\n type: 'date',\n value: '',\n marks: {},\n data: { isoDate: node.getAttribute('data-iso-date') ?? '' },\n };\n}\n\nfunction todayIso() {\n return new Date().toISOString().slice(0, 10);\n}\n\nexport const dateInlineType = {\n component: DateInlineNode,\n isAtomic: true,\n toHTML,\n toPlainText,\n fromHTML,\n slashCommand: {\n label: 'Date',\n icon: DateIcon,\n keywords: ['date', 'when', 'schedule', 'calendar'],\n run: (store, { blockId, runId, sliceStart, sliceEnd }) =>\n insertInlineRunAtCursor(store, { blockId, runId, sliceStart, sliceEnd }, () => ({\n id: genId(),\n type: 'date',\n value: '',\n marks: {},\n data: { isoDate: todayIso() },\n })),\n },\n};\n","import { useCallback } from 'react';\nimport { useRun } from '../../react/useBlock.js';\nimport { useEditorStore } from '../../react/EditorProvider.jsx';\nimport { updateRun } from '../../store/operations.js';\n\n/**\n * An atomic checkbox-with-label chip — pairs a toggle with its own free-text\n * label (e.g. \"Diagnosis confirmed ☑\") in one unit, distinct from a to-do\n * list item's `props.checked` (that's block-level state for a whole line;\n * this is inline content mixed into running text or, more commonly, a\n * table cell — see the \"checkbox\" table column type).\n */\nexport function CheckboxInlineNode({ id }) {\n const store = useEditorStore();\n const run = useRun(id);\n\n const handleCheckedChange = useCallback(\n (event) => {\n store.applyOperation(updateRun(id, { data: { ...run?.data, checked: event.target.checked } }));\n },\n [store, id, run?.data],\n );\n\n const handleLabelChange = useCallback(\n (event) => {\n store.applyOperation(updateRun(id, { data: { ...run?.data, label: event.target.value } }));\n },\n [store, id, run?.data],\n );\n\n if (!run) return null;\n const { checked = false, label = '' } = run.data ?? {};\n\n return (\n <span\n className=\"be-inline-checkbox\"\n onMouseDown={(event) => event.stopPropagation()}\n // See SelectInlineNode's onKeyDown comment for why this is needed.\n onKeyDown={(event) => event.stopPropagation()}\n >\n <input type=\"checkbox\" checked={checked} onChange={handleCheckedChange} />\n <input\n type=\"text\"\n className=\"be-inline-checkbox-label\"\n value={label}\n onChange={handleLabelChange}\n placeholder=\"Label…\"\n />\n </span>\n );\n}\n","import { CheckboxInlineNode } from './CheckboxInlineNode.jsx';\nimport { genId } from '../../utils/idGen.js';\nimport { insertInlineRunAtCursor } from '../shared/insertInlineRun.js';\nimport { CheckboxIcon } from '../../react/icons.jsx';\n\nfunction escapeHTML(str) {\n return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n\nfunction escapeAttr(str) {\n return escapeHTML(str).replace(/\"/g, '&quot;');\n}\n\nfunction toHTML(run) {\n const { checked = false, label = '' } = run.data ?? {};\n return `<span data-inline-type=\"checkbox\" data-checked=\"${checked}\">${checked ? '☑' : '☐'} ${escapeHTML(label)}</span>`;\n}\n\nfunction toPlainText(run) {\n const { checked = false, label = '' } = run.data ?? {};\n return `${checked ? '[x]' : '[ ]'} ${label}`.trim();\n}\n\n/** Only claims our own `data-inline-type=\"checkbox\"` marker — see select's fromHTML for why. */\nfunction fromHTML(node) {\n if (node.getAttribute?.('data-inline-type') !== 'checkbox') return null;\n return {\n id: genId(),\n type: 'checkbox',\n value: '',\n marks: {},\n data: { checked: node.getAttribute('data-checked') === 'true', label: (node.textContent ?? '').replace(/^[☑☐]\\s*/, '') },\n };\n}\n\nexport const checkboxInlineType = {\n component: CheckboxInlineNode,\n isAtomic: true,\n toHTML,\n toPlainText,\n fromHTML,\n slashCommand: {\n label: 'Checkbox',\n icon: CheckboxIcon,\n keywords: ['checkbox', 'todo', 'check', 'toggle'],\n run: (store, { blockId, runId, sliceStart, sliceEnd }) =>\n insertInlineRunAtCursor(store, { blockId, runId, sliceStart, sliceEnd }, () => ({\n id: genId(),\n type: 'checkbox',\n value: '',\n marks: {},\n data: { checked: false, label: '' },\n })),\n },\n};\n","import { useCallback } from 'react';\nimport { useRun, useBlock } from '../../react/useBlock.js';\nimport { useEditorStore } from '../../react/EditorProvider.jsx';\nimport { updateRun } from '../../store/operations.js';\nimport { resolveColumns } from '../../blocks/table/tableColumns.js';\nimport { pickTagColor } from '../../blocks/table/tagColors.js';\nimport { Select } from '../../react/Select.jsx';\n\n/**\n * The atomic chip for a table's \"select\" column type — deliberately a\n * *different* inline type from the general-purpose `select` (used for\n * ad-hoc dropdown chips mixed into paragraph text), not a reuse of it. The\n * general one owns its options per-run with its own add/remove-option UI,\n * which is right for an independent inline chip but wrong for a table\n * column: every cell in a \"select\" column should offer the *same* choices\n * and stay in sync when an option is added, renamed, or removed. That\n * shared list lives on the table's own `props.columns[i].options` (see\n * tableColumns.js) — configured once from the column header's menu, not\n * per cell — so this component is intentionally table-aware (it resolves\n * its own containing cell -> row -> table via `blockId`, a coupling the\n * general inline types don't need and don't have).\n *\n * `useBlock(tableId)` (not a one-off `store.getBlock`) is what makes this\n * re-render when the column's options change elsewhere (the header menu)\n * even though this run itself didn't change.\n */\nexport function TableSelectInlineNode({ id, blockId }) {\n const store = useEditorStore();\n const run = useRun(id);\n\n const cell = blockId ? store.getBlock(blockId) : null;\n const row = cell ? store.getBlock(cell.parentId) : null;\n const tableId = row?.parentId ?? null;\n const table = useBlock(tableId);\n\n const colIndex = row ? row.contentIds.indexOf(blockId) : -1;\n const columns = table && row ? resolveColumns(table, row.contentIds.length) : [];\n // Fallback for options created before per-option colors existed: derive\n // one by position rather than leaving it uncolored, same convention as\n // TableHeaderRow's own SelectOptionsManager swatch fallback.\n const options = (columns[colIndex]?.options ?? []).map((option, i) => ({\n ...option,\n color: option.color ?? pickTagColor(i),\n }));\n\n const handleChange = useCallback(\n (selectedValue, option) => {\n store.applyOperation(updateRun(id, { data: { selectedValue, selectedLabel: option?.label ?? '' } }));\n },\n [store, id],\n );\n\n if (!run) return null;\n const { selectedValue = '' } = run.data ?? {};\n\n return (\n <span\n className=\"be-inline-table-select\"\n // preventDefault too, not just stopPropagation — see SelectInlineNode's\n // onMouseDown comment: without it, the browser's default caret-\n // collapse-to-click-position wins the race against Select's own\n // focus() call, and the first typed character lands in the\n // surrounding cell/paragraph instead of the search box.\n onMouseDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n // See SelectInlineNode's onKeyDown comment for why this is needed.\n onKeyDown={(event) => event.stopPropagation()}\n >\n <Select\n value={selectedValue}\n options={options}\n onChange={handleChange}\n placeholder=\"Select…\"\n ariaLabel=\"Select an option\"\n variant=\"tag\"\n />\n </span>\n );\n}\n","import { TableSelectInlineNode } from './TableSelectInlineNode.jsx';\nimport { genId } from '../../utils/idGen.js';\n\nfunction escapeHTML(str) {\n return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n\nfunction escapeAttr(str) {\n return escapeHTML(str).replace(/\"/g, '&quot;');\n}\n\n// `run.data.selectedLabel` is a denormalized cache of the currently\n// selected option's label (kept in sync by TableSelectInlineNode's\n// onChange and by setColumnOptions whenever the column's shared options\n// change) — deliberately redundant with the column's own options list, so\n// toHTML/toPlainText/fromHTML never need table/column context (which\n// serialization call sites don't have) to render a sensible value.\nfunction toHTML(run) {\n const { selectedValue = '', selectedLabel = '' } = run.data ?? {};\n return `<span data-inline-type=\"tableSelect\" data-selected-value=\"${escapeAttr(selectedValue)}\">${escapeHTML(selectedLabel)}</span>`;\n}\n\nfunction toPlainText(run) {\n return run.data?.selectedLabel ?? '';\n}\n\n/**\n * Only claims nodes carrying our own `data-inline-type=\"tableSelect\"`\n * marker (see select's fromHTML for why). The reconstructed run has no\n * knowledge of which column it'll end up in on paste — the pasted label\n * is taken at face value, and its `selectedValue` will only match an\n * actual column option again if the destination table happens to have one\n * with the same id, which is possible but not guaranteed for a same-editor\n * paste; a cross-editor paste always lands as an unmatched value anyway.\n */\nfunction fromHTML(node) {\n if (node.getAttribute?.('data-inline-type') !== 'tableSelect') return null;\n return {\n id: genId(),\n type: 'tableSelect',\n value: '',\n marks: {},\n data: {\n selectedValue: node.getAttribute('data-selected-value') ?? '',\n selectedLabel: node.textContent ?? '',\n },\n };\n}\n\nexport const tableSelectInlineType = {\n component: TableSelectInlineNode,\n isAtomic: true,\n toHTML,\n toPlainText,\n fromHTML,\n // No slashCommand: unlike select/date/custom field types, this type is never\n // inserted ad-hoc into a paragraph — it only exists inside a table cell\n // whose column type has been set to \"select\" (see setColumnType).\n};\n","/**\n * Not an atomic run type at all — an emoji is inserted as plain text (the\n * literal unicode character), exactly as selectable/deletable/editable as\n * anything else typed there, not a persistent chip. So there's no\n * `component`/`toHTML`/`fromHTML`/`slashCommands` here — emoji has its own\n * dedicated \":\" trigger (see useEmojiMenuTrigger + emojiCommands.js)\n * instead of contributing to the shared \"/\" slash-command list, so this\n * entry is registered only for consistency/discoverability (host code that\n * enumerates `inlineRegistry` sees an 'emoji' entry) even though it\n * currently does nothing on its own.\n */\nexport const emojiInlineType = {};\n","import { selectInlineType } from './select/index.js';\nimport { dateInlineType } from './date/index.js';\nimport { checkboxInlineType } from './checkbox/index.js';\nimport { tableSelectInlineType } from './tableSelect/index.js';\nimport { emojiInlineType } from './emoji/index.js';\n\n/**\n * Registers every built-in inline type on the given inline registry. Not\n * on this list: \"mention\"-style @-someone chips — those are now just an\n * ordinary use of createSelectFieldType with `triggers: ['slash', 'at']`\n * (see the example app's \"Assignee\" field type), rather than a separate\n * hardcoded built-in, since a real app's roster/search always needs to be\n * host-supplied anyway.\n */\nexport function registerBuiltInInlineTypes(inlineRegistry) {\n registerInlineTypes(inlineRegistry, {\n select: selectInlineType,\n date: dateInlineType,\n checkbox: checkboxInlineType,\n ...TABLE_SELECT_INLINE_TYPES,\n emoji: emojiInlineType,\n });\n}\n\n/** Opt-in counterpart to `registerBuiltInInlineTypes` — see registerBlocks's own doc comment, same idea for inline types. */\nexport function registerInlineTypes(inlineRegistry, typesByType) {\n for (const [type, entry] of Object.entries(typesByType)) {\n inlineRegistry.register(type, entry);\n }\n}\n\n/** Only relevant alongside TABLE_BLOCKS (see blocks/index.js) — powers a table column set to \"select\" type. */\nexport const TABLE_SELECT_INLINE_TYPES = { tableSelect: tableSelectInlineType };\n\nexport { selectInlineType, dateInlineType, checkboxInlineType, tableSelectInlineType, emojiInlineType };\n","import { useCallback, useSyncExternalStore } from 'react';\nimport { useEditorStore } from './EditorProvider.jsx';\n\nconst FIELD_TYPES_KEY = '$fieldTypes';\n\n/**\n * Subscribes to the store's persisted, user-created field type definitions\n * (see createSelectFieldType / registerStoredFieldTypes) — reactive so a\n * \"manage field types\" list re-renders after add/update/remove, the same\n * way useBlock re-renders on a single block's change. Not used by the\n * slash menu itself: that reads inlineRegistry.listSlashCommands() fresh\n * on every trigger, so a newly-registered type shows up there without any\n * separate subscription.\n *\n * store.getFieldTypes() returns a referentially-stable array (cached,\n * invalidated only by a fieldTypes op) — required by useSyncExternalStore,\n * same contract as useBlock/useRun.\n */\nexport function useFieldTypes() {\n const store = useEditorStore();\n const subscribe = useCallback((onStoreChange) => store.subscribe(FIELD_TYPES_KEY, onStoreChange), [store]);\n const getSnapshot = useCallback(() => store.getFieldTypes(), [store]);\n return useSyncExternalStore(subscribe, getSnapshot);\n}\n","import { useCallback, useSyncExternalStore } from 'react';\nimport { useEditorContext } from './EditorProvider.jsx';\n\nconst STABLE_STATE = { canUndo: false, canRedo: false };\n\n/**\n * Subscribes to undo/redo availability, for wiring up toolbar buttons.\n * Returns null if the editor was created without a History instance (i.e.\n * the provider was given a plain EditorStore).\n */\nexport function useHistory() {\n const { history } = useEditorContext();\n\n const subscribe = useCallback(\n (onChange) => (history ? history.subscribeToHistory(onChange) : () => {}),\n [history],\n );\n const getSnapshot = useCallback(\n () => (history ? history.getUndoRedoSnapshot() : STABLE_STATE),\n [history],\n );\n\n const state = useSyncExternalStore(subscribe, getSnapshot);\n if (!history) return null;\n\n return {\n ...state,\n undo: () => history.undo(),\n redo: () => history.redo(),\n getHistoryLog: () => history.getHistoryLog(),\n };\n}\n","// Custom clipboard MIME type for lossless same-editor copy/paste round-trips.\n// Reliable via the synchronous ClipboardEvent path used in useClipboardHandlers;\n// NOT guaranteed via the async navigator.clipboard.write/ClipboardItem API —\n// if a toolbar \"Copy\" button is added later, restrict it to text/plain+text/html.\nexport const APP_MIME = 'application/x-block-editor-blocks+json';\n","import { domInlineToRuns } from '../inline/runOps.js';\nimport { genId } from '../utils/idGen.js';\n\nexport function textToParagraphs(text) {\n return text\n .split(/\\r\\n|\\r|\\n/)\n .filter((line) => line.length > 0)\n .map((line) => {\n const runId = genId();\n return {\n block: { id: genId(), type: 'paragraph', parentId: null, contentIds: [runId], props: {} },\n runs: [{ id: runId, type: 'text', value: line, marks: {} }],\n };\n });\n}\n\n/**\n * Parses an HTML string and walks its top-level nodes, dispatching each to\n * whichever registered block type's `fromHTML` claims it (first match\n * wins). `<ul>/<ol>` are handled specially here rather than via a matcher,\n * since there's no standalone \"list\" block type in this model — only\n * `listItem` blocks carrying an `ordered` flag, one per `<li>`.\n */\nexport function walkDomToBlocks(html, registry, inlineRegistry) {\n const doc = new DOMParser().parseFromString(html, 'text/html');\n const ctx = { registry, inlineRegistry };\n const matchers = registry.listHtmlMatchers();\n const results = [];\n\n const consumeList = (listNode) => {\n const ordered = listNode.tagName === 'OL';\n const items = [];\n for (const li of listNode.children) {\n if (li.tagName !== 'LI') continue;\n const result = registry.get('listItem')?.fromHTML(li, ctx);\n if (result) {\n result.block.props.ordered = ordered;\n items.push(result);\n }\n }\n return items;\n };\n\n /**\n * A <blockquote> with several nested <p>s (a multi-line quote, matching\n * what serializeHTML's own grouping now emits) becomes one sibling\n * `blockquote` block per <p> — this model keeps multi-line quotes as\n * separate leaf siblings rather than one container block. A <blockquote>\n * with no nested <p> at all (plain external HTML, just inline content\n * directly inside it) falls back to the registered single-block fromHTML.\n */\n const consumeBlockquote = (bqNode) => {\n const paragraphs = Array.from(bqNode.children).filter((c) => c.tagName === 'P');\n if (paragraphs.length === 0) {\n const result = registry.get('blockquote')?.fromHTML(bqNode, ctx);\n return result ? [result] : [];\n }\n return paragraphs.map((p) => {\n const runs = domInlineToRuns(p, ctx);\n return {\n block: { id: genId(), type: 'blockquote', parentId: null, contentIds: runs.map((r) => r.id), props: {} },\n runs,\n };\n });\n };\n\n for (const node of doc.body.childNodes) {\n if (node.nodeType === 3 /* TEXT_NODE */) {\n const text = node.textContent.trim();\n if (text) results.push(...textToParagraphs(text));\n continue;\n }\n if (node.nodeType !== 1 /* ELEMENT_NODE */) continue;\n\n if (node.tagName === 'UL' || node.tagName === 'OL') {\n results.push(...consumeList(node));\n continue;\n }\n\n if (node.tagName === 'BLOCKQUOTE') {\n results.push(...consumeBlockquote(node));\n continue;\n }\n\n let matched = null;\n for (const entry of matchers) {\n const result = entry.fromHTML(node, ctx);\n if (result) {\n matched = result;\n break;\n }\n }\n\n if (matched) {\n results.push(matched);\n } else if (node.textContent.trim()) {\n const runs = domInlineToRuns(node, ctx);\n results.push({\n block: { id: genId(), type: 'paragraph', parentId: null, contentIds: runs.map((r) => r.id), props: {} },\n runs,\n });\n }\n }\n\n return results;\n}\n","import { APP_MIME } from './mimeType.js';\nimport { walkDomToBlocks, textToParagraphs } from './domWalk.js';\nimport { remapSubtreeIds } from './serialize.js';\n\n/**\n * Given a DataTransfer-like object (real ClipboardEvent.clipboardData, or a\n * plain { types, getData } stand-in for tests), returns an array of\n * `{ block, runs, subtreeBlocks }` ready to insert. Prefers the lossless\n * same-editor payload, falls back to HTML (cross-editor), then plain text.\n */\nexport function deserializeClipboard(dataTransfer, registry, inlineRegistry) {\n const types = dataTransfer.types ?? [];\n\n if (types.includes(APP_MIME)) {\n const json = dataTransfer.getData(APP_MIME);\n if (json) return deserializeAppJSON(json);\n }\n\n if (types.includes('text/html')) {\n const html = dataTransfer.getData('text/html');\n if (html) return walkDomToBlocks(html, registry, inlineRegistry);\n }\n\n const text = dataTransfer.getData('text/plain') ?? '';\n return textToParagraphs(text);\n}\n\nfunction deserializeAppJSON(json) {\n const payload = JSON.parse(json);\n return payload.blocks.map((subtree) => remapSubtreeIds(subtree));\n}\n","import { genId } from '../utils/idGen.js';\nimport { setBlockRuns, removeBlock, insertBlock } from '../store/operations.js';\nimport { canMergeTypes } from '../blocks/shared/mergeCommands.js';\nimport { createTextLeafBlock } from '../blocks/shared/leafBlockFactory.js';\n\nfunction getBlockRunIds(store, blockId) {\n const block = store.getBlock(blockId);\n return block.props?.titleRunIds ?? block.contentIds;\n}\n\nfunction blankRun() {\n return { id: genId(), type: 'text', value: '', marks: {} };\n}\n\nfunction applyOps(store, ops) {\n if (typeof store.performBatch === 'function') store.performBatch(ops);\n else for (const op of ops) store.applyOperation(op);\n}\n\n/**\n * Deletes the [startRunId+startOffset, endRunId+endOffset) range from one\n * block's own run list. Unlike mark-toggling (applyMarkOverRunSpan), an\n * atomic (non-text) run anywhere in the range is simply dropped — there's\n * no sensible \"delete the surrounding text but keep the chip\" here. Falls\n * back to one blank run if the deletion would leave zero runs (same \"never\n * leave a caret-less contentEditable region\" guarantee as\n * EditableBlockContent's removeRun/handleInput).\n *\n * Returns `{ blockId, runId, offset }` for the collapsed caret the\n * deletion leaves behind, or null if the range didn't resolve.\n */\nexport function deleteRunRangeInBlock(store, blockId, selection) {\n const { startRunId, startOffset, endRunId, endOffset } = selection;\n const runIds = getBlockRunIds(store, blockId);\n const startIndex = runIds.indexOf(startRunId);\n const endIndex = runIds.indexOf(endRunId);\n if (startIndex === -1 || endIndex === -1) return null;\n\n const [fromIndex, toIndex] = startIndex <= endIndex ? [startIndex, endIndex] : [endIndex, startIndex];\n const fromOffset = startIndex <= endIndex ? startOffset : endOffset;\n const toOffset = startIndex <= endIndex ? endOffset : startOffset;\n\n const beforeRuns = runIds.slice(0, fromIndex).map((id) => store.getRun(id));\n const afterRuns = runIds.slice(toIndex + 1).map((id) => store.getRun(id));\n const spanRuns = runIds.slice(fromIndex, toIndex + 1).map((id) => store.getRun(id));\n\n const survivors = [];\n let caretRunId = null;\n let caretOffset = 0;\n\n if (fromIndex === toIndex) {\n const run = spanRuns[0];\n if (run.type === 'text') {\n const from = Math.max(0, Math.min(fromOffset, toOffset));\n const to = Math.min(run.value.length, Math.max(fromOffset, toOffset));\n const survivor = { ...run, value: run.value.slice(0, from) + run.value.slice(to) };\n survivors.push(survivor);\n caretRunId = survivor.id;\n caretOffset = from;\n } // atomic: dropped entirely, caret resolved from before/after below\n } else {\n spanRuns.forEach((run, i) => {\n if (run.type !== 'text') return; // atomic anywhere in a multi-run range: dropped entirely\n const isFirst = i === 0;\n const isLast = i === spanRuns.length - 1;\n // isFirst/isLast are never both true here — that's the single-run\n // case handled above (fromIndex === toIndex).\n const prefix = isFirst ? run.value.slice(0, fromOffset) : '';\n if (isFirst && prefix) {\n const prefixRun = { ...run, value: prefix };\n survivors.push(prefixRun);\n caretRunId = prefixRun.id;\n caretOffset = prefix.length;\n }\n if (isLast && !isFirst) {\n const suffixValue = run.value.slice(toOffset);\n if (suffixValue) {\n const suffixRun = { id: genId(), type: 'text', value: suffixValue, marks: run.marks };\n survivors.push(suffixRun);\n if (caretRunId === null) {\n caretRunId = suffixRun.id;\n caretOffset = 0;\n }\n }\n }\n });\n }\n\n let finalRuns = [...beforeRuns, ...survivors, ...afterRuns];\n\n if (finalRuns.length === 0) {\n const blank = blankRun();\n finalRuns = [blank];\n caretRunId = blank.id;\n caretOffset = 0;\n } else if (caretRunId === null) {\n // Nothing survived from the deleted span itself (e.g. it was a single\n // atomic run): land at the boundary — end of whatever's right before,\n // or start of whatever's right after.\n const lastBefore = beforeRuns[beforeRuns.length - 1];\n if (lastBefore) {\n caretRunId = lastBefore.id;\n caretOffset = lastBefore.type === 'text' ? lastBefore.value.length : 0;\n } else if (afterRuns[0]) {\n caretRunId = afterRuns[0].id;\n caretOffset = 0;\n }\n }\n\n store.applyOperation(setBlockRuns(blockId, finalRuns));\n return { blockId, runId: caretRunId, offset: caretOffset };\n}\n\n/**\n * Deletes a selection spanning *multiple sibling blocks* under a shared\n * parent (see resolveCrossBlockSelection) — the same range shape\n * toggleMarkOverBlockRange consumes, reused here for deletion instead of\n * mark-toggling. This is also what a \"select all\" (twice-pressed Ctrl+A,\n * which spans every top-level block under root) funnels through: the\n * general logic below naturally handles \"delete the entire document\" as\n * the extreme case of \"delete across several sibling blocks\" — no special\n * casing needed beyond the final \"did this leave one lone empty\n * non-paragraph block?\" check.\n *\n * Fully-covered blocks strictly between the two boundaries are removed\n * outright. The two boundary blocks are trimmed to their surviving prefix/\n * suffix; if they're mergeable text types (see canMergeTypes), those\n * survivors are combined into ONE remaining block (matching\n * mergeWithPreviousOrDelete's merge convention). If they're not mergeable\n * (e.g. the range runs from a paragraph into a table cell), both trimmed\n * blocks are simply left in place rather than guessing at cross-type\n * semantics.\n *\n * One atomic undo step. Returns `{ blockId, runId, offset }` for the\n * resulting caret position, or null if the range didn't resolve.\n */\nexport function deleteOverBlockRange(store, crossSelection) {\n const { blockIds, startBlockId, startRunId, startOffset, endBlockId, endRunId, endOffset } = crossSelection;\n if (!blockIds || blockIds.length === 0) return null;\n\n const startBlockIndex = blockIds.indexOf(startBlockId);\n const endBlockIndex = blockIds.indexOf(endBlockId);\n if (startBlockIndex === -1 || endBlockIndex === -1) return null;\n\n const [fromBlockIndex, toBlockIndex] =\n startBlockIndex <= endBlockIndex ? [startBlockIndex, endBlockIndex] : [endBlockIndex, startBlockIndex];\n const firstIsStart = startBlockIndex <= endBlockIndex;\n const firstRunId = firstIsStart ? startRunId : endRunId;\n const firstOffset = firstIsStart ? startOffset : endOffset;\n const lastRunId = firstIsStart ? endRunId : startRunId;\n const lastOffset = firstIsStart ? endOffset : startOffset;\n\n if (fromBlockIndex === toBlockIndex) {\n return deleteRunRangeInBlock(store, blockIds[fromBlockIndex], {\n startRunId: firstRunId,\n startOffset: firstOffset,\n endRunId: lastRunId,\n endOffset: lastOffset,\n });\n }\n\n const firstBlockId = blockIds[fromBlockIndex];\n const lastBlockId = blockIds[toBlockIndex];\n const firstBlock = store.getBlock(firstBlockId);\n const lastBlock = store.getBlock(lastBlockId);\n\n const firstRunIds = getBlockRunIds(store, firstBlockId);\n const firstIdx = firstRunIds.indexOf(firstRunId);\n const firstPrefixRuns = firstRunIds.slice(0, firstIdx).map((id) => store.getRun(id));\n const firstRun = store.getRun(firstRunId);\n const firstPrefixSurvivor =\n firstRun.type === 'text' && firstOffset > 0 ? { ...firstRun, value: firstRun.value.slice(0, firstOffset) } : null;\n\n const lastRunIds = getBlockRunIds(store, lastBlockId);\n const lastIdx = lastRunIds.indexOf(lastRunId);\n const lastSuffixRuns = lastRunIds.slice(lastIdx + 1).map((id) => store.getRun(id));\n const lastRun = store.getRun(lastRunId);\n const lastSuffixSurvivor =\n lastRun.type === 'text' && lastOffset < lastRun.value.length\n ? { id: genId(), type: 'text', value: lastRun.value.slice(lastOffset), marks: lastRun.marks }\n : null;\n\n const firstSurvivors = [...firstPrefixRuns, ...(firstPrefixSurvivor ? [firstPrefixSurvivor] : [])];\n const lastSurvivors = [...(lastSuffixSurvivor ? [lastSuffixSurvivor] : []), ...lastSuffixRuns];\n\n const ops = [];\n for (let i = fromBlockIndex + 1; i < toBlockIndex; i += 1) ops.push(removeBlock(blockIds[i]));\n\n const mergeable = canMergeTypes(firstBlock.type, lastBlock.type);\n const parent = store.getBlock(firstBlock.parentId);\n // Only the mergeable branch can ever collapse to a single surviving\n // block (the non-mergeable branch always leaves both first and last in\n // place) — \"select all, then delete\" is exactly this shape: the merge\n // leaves nothing behind, and it was the only two blocks under the\n // parent. Every real editor leaves a plain paragraph there, not\n // whatever type happened to survive (a now-empty heading, say). Decided\n // analytically (without mutating the store first) so the swap can be\n // folded into the same ops array — one atomic undo step, not two.\n const removedCount = toBlockIndex - fromBlockIndex - 1 + (mergeable ? 1 : 0);\n const wouldBeOnlyChild = parent && parent.contentIds.length - removedCount === 1;\n\n let caretRunId;\n let caretOffset;\n let survivingBlockId;\n\n if (mergeable) {\n const merged = [...firstSurvivors, ...lastSurvivors];\n\n if (merged.length === 0 && wouldBeOnlyChild && firstBlock.type !== 'paragraph') {\n const { block: fallbackBlock, runs } = createTextLeafBlock('paragraph')(parent.id);\n ops.push({ type: 'insertBlock', block: fallbackBlock, parentId: parent.id, index: 0, subtree: { blocks: [fallbackBlock], runs } });\n ops.push(removeBlock(firstBlockId));\n ops.push(removeBlock(lastBlockId));\n applyOps(store, ops);\n return { blockId: fallbackBlock.id, runId: fallbackBlock.contentIds[0], offset: 0 };\n }\n\n const finalRuns = merged.length ? merged : [blankRun()];\n ops.push(setBlockRuns(firstBlockId, finalRuns));\n ops.push(removeBlock(lastBlockId));\n survivingBlockId = firstBlockId;\n\n if (firstPrefixSurvivor) {\n caretRunId = firstPrefixSurvivor.id;\n caretOffset = firstPrefixSurvivor.value.length;\n } else if (firstPrefixRuns.length) {\n const last = firstPrefixRuns[firstPrefixRuns.length - 1];\n caretRunId = last.id;\n caretOffset = last.type === 'text' ? last.value.length : 0;\n } else if (lastSuffixSurvivor) {\n caretRunId = lastSuffixSurvivor.id;\n caretOffset = 0;\n } else if (lastSuffixRuns.length) {\n caretRunId = lastSuffixRuns[0].id;\n caretOffset = 0;\n } else {\n caretRunId = finalRuns[0].id;\n caretOffset = 0;\n }\n } else {\n const firstFinalRuns = firstSurvivors.length ? firstSurvivors : [blankRun()];\n ops.push(setBlockRuns(firstBlockId, firstFinalRuns));\n ops.push(setBlockRuns(lastBlockId, lastSurvivors.length ? lastSurvivors : [blankRun()]));\n survivingBlockId = firstBlockId;\n\n if (firstPrefixSurvivor) {\n caretRunId = firstPrefixSurvivor.id;\n caretOffset = firstPrefixSurvivor.value.length;\n } else if (firstPrefixRuns.length) {\n const last = firstPrefixRuns[firstPrefixRuns.length - 1];\n caretRunId = last.id;\n caretOffset = last.type === 'text' ? last.value.length : 0;\n } else {\n caretRunId = firstFinalRuns[0].id;\n caretOffset = 0;\n }\n }\n\n applyOps(store, ops);\n return { blockId: survivingBlockId, runId: caretRunId, offset: caretOffset };\n}\n\n/**\n * Deletes every top-level block under the document root and leaves one\n * paragraph behind (blank, or seeded with `replacementText` — typing a\n * character over a \"whole document selected\" state replaces it, matching\n * the standard \"type over a selection\" convention). Deliberately its own,\n * much simpler function rather than routed through deleteOverBlockRange:\n * a whole-document deletion never needs partial-boundary trimming (unlike\n * a cross-sibling-block selection, which stops mid-run at each end), and\n * the top-level blocks can be *any* type — including containers like\n * tables that don't have a run-based content list at all — so there's\n * nothing to trim at the boundaries in the first place, only whole blocks\n * to remove.\n *\n * One atomic undo step. Returns `{ blockId, runId, offset }` for the\n * resulting caret position, or null if the document was already empty.\n */\nexport function deleteEntireDocument(store, replacementText = '') {\n const rootId = store.getRootId();\n const contentIds = store.getBlock(rootId)?.contentIds ?? [];\n if (contentIds.length === 0) return null;\n\n const ops = contentIds.map((id) => removeBlock(id));\n const { block: fallbackBlock, runs } = createTextLeafBlock('paragraph')(rootId);\n if (replacementText) runs[0].value = replacementText;\n ops.push(insertBlock(fallbackBlock, rootId, 0, { blocks: [fallbackBlock], runs }));\n\n applyOps(store, ops);\n return { blockId: fallbackBlock.id, runId: fallbackBlock.contentIds[0], offset: replacementText.length };\n}\n","import { removeBlock, moveBlock, updateBlockProps } from '../../store/operations.js';\n\nfunction applyOps(store, ops) {\n if (typeof store.performBatch === 'function') store.performBatch(ops);\n else for (const op of ops) store.applyOperation(op);\n}\n\n/**\n * Removes every block in `blockIds` (a contiguous run — see\n * useBlockRangeDrag) as ONE atomic undo step, regardless of how many\n * blocks are in the range. Each `removeBlock` op looks its own target's\n * index up fresh at apply time (see EditorStore), so issuing one op per id\n * in document order is correct without any special ordering care.\n */\nexport function deleteBlockRange(store, blockIds) {\n if (blockIds.length === 0) return;\n applyOps(store, blockIds.map((id) => removeBlock(id)));\n}\n\n/**\n * Moves the whole contiguous range up by one sibling position — implemented\n * as swapping the range with its immediately preceding sibling (ONE\n * `moveBlock` op moving that single neighbor to just after the range's new\n * end) rather than moving every block in the range individually. Returns\n * false (no-op) if the range is already at the top.\n */\nexport function moveBlockRangeUp(store, blockIds) {\n if (blockIds.length === 0) return false;\n const first = store.getBlock(blockIds[0]);\n if (!first) return false;\n const parent = store.getBlock(first.parentId);\n if (!parent) return false;\n\n const startIndex = parent.contentIds.indexOf(blockIds[0]);\n const endIndex = parent.contentIds.indexOf(blockIds[blockIds.length - 1]);\n if (startIndex <= 0) return false;\n\n const precedingId = parent.contentIds[startIndex - 1];\n store.applyOperation(moveBlock(precedingId, first.parentId, endIndex));\n return true;\n}\n\n/** Symmetric to moveBlockRangeUp — swaps the range with its immediately following sibling. */\nexport function moveBlockRangeDown(store, blockIds) {\n if (blockIds.length === 0) return false;\n const first = store.getBlock(blockIds[0]);\n if (!first) return false;\n const parent = store.getBlock(first.parentId);\n if (!parent) return false;\n\n const startIndex = parent.contentIds.indexOf(blockIds[0]);\n const endIndex = parent.contentIds.indexOf(blockIds[blockIds.length - 1]);\n if (endIndex === -1 || endIndex >= parent.contentIds.length - 1) return false;\n\n const followingId = parent.contentIds[endIndex + 1];\n store.applyOperation(moveBlock(followingId, first.parentId, startIndex));\n return true;\n}\n\n/** True only if every block in the range is currently hidden — used to decide whether the menu's toggle should read \"Hide\" or \"Show\". */\nexport function isEntireBlockRangeHidden(store, blockIds) {\n return blockIds.length > 0 && blockIds.every((id) => Boolean(store.getBlock(id)?.props?.hidden));\n}\n\n/** Sets props.hidden on every block in the range, one atomic undo step. */\nexport function setBlockRangeHidden(store, blockIds, hidden) {\n if (blockIds.length === 0) return;\n applyOps(store, blockIds.map((id) => updateBlockProps(id, { hidden })));\n}\n\n/**\n * Re-derives a previously-captured id set's DOCUMENT order from the\n * store's current contentIds — used after a move/hide action to keep\n * `selectedBlockRange` valid (same ids, correct order) without the caller\n * needing to know the tree shape itself.\n */\nexport function reorderBlockRangeFromStore(store, blockIds) {\n if (blockIds.length === 0) return [];\n const first = store.getBlock(blockIds[0]);\n const parent = first && store.getBlock(first.parentId);\n if (!parent) return blockIds;\n const idSet = new Set(blockIds);\n return parent.contentIds.filter((id) => idSet.has(id));\n}\n","import { useCallback } from 'react';\nimport { useEditorStore, useBlockRegistry, useInlineRegistry, useWholeDocumentSelection, useBlockRangeSelection } from './EditorProvider.jsx';\nimport { serializeBlockRange } from '../clipboard/serialize.js';\nimport { deserializeClipboard } from '../clipboard/deserialize.js';\nimport { APP_MIME } from '../clipboard/mimeType.js';\nimport { insertBlock, removeBlock, updateRun } from '../store/operations.js';\nimport { resolveMultiRunSelection, resolveCrossBlockSelection, resolveCollapsedCaret } from './selectionResolve.js';\nimport { deleteRunRangeInBlock, deleteOverBlockRange, deleteEntireDocument } from '../inline/deleteCommands.js';\nimport { deleteBlockRange } from '../blocks/shared/blockRangeActions.js';\nimport { focusRunAtOffset } from './focusRun.js';\n\nfunction closestBlockId(node) {\n let el = node?.nodeType === 1 ? node : node?.parentElement;\n while (el && typeof el.hasAttribute === 'function' && !el.hasAttribute('data-block-id')) {\n el = el.parentElement;\n }\n return el?.getAttribute?.('data-block-id') ?? null;\n}\n\n/**\n * v0.1 selection-range resolution: maps the native selection's anchor/focus\n * to the nearest [data-block-id] ancestor and, if they differ, to a\n * contiguous sibling range under their shared parent. Partial-text selection\n * within a single block still copies that block's whole HTML — full\n * character-level range slicing is a follow-up once store/selection.js\n * (logical {blockId, offset} tracking) is built.\n */\nfunction resolveSelectedBlockIds(store) {\n const selection = window.getSelection?.();\n if (!selection || selection.rangeCount === 0) return [];\n\n const startId = closestBlockId(selection.anchorNode);\n const endId = closestBlockId(selection.focusNode);\n if (!startId) return [];\n if (!endId || startId === endId) return [startId];\n\n const startBlock = store.getBlock(startId);\n const parent = startBlock && store.getBlock(startBlock.parentId);\n if (!parent) return [startId];\n\n const ids = parent.contentIds;\n const i1 = ids.indexOf(startId);\n const i2 = ids.indexOf(endId);\n if (i1 === -1 || i2 === -1) return [startId];\n\n const [from, to] = i1 <= i2 ? [i1, i2] : [i2, i1];\n return ids.slice(from, to + 1);\n}\n\n/** Deletes whatever's currently selected (same-block or cross-sibling-block), if anything. Returns the resulting `{ blockId, runId, offset }`, or null if there was no selection to delete. */\nfunction deleteCurrentSelection(store) {\n const same = resolveMultiRunSelection();\n if (same) return deleteRunRangeInBlock(store, same.blockId, same);\n\n const cross = resolveCrossBlockSelection(store);\n if (cross) return deleteOverBlockRange(store, cross);\n\n return null;\n}\n\n/** Splices `text` into an existing text run at `caret.offset` — one atomic undo step, in place, no new block. Returns the resulting caret position, or null if `caret` doesn't point at a plain text run. */\nfunction insertTextAtCaret(store, caret, text) {\n const run = store.getRun(caret.runId);\n if (!run || run.type !== 'text') return null;\n const value = run.value ?? '';\n const newValue = value.slice(0, caret.offset) + text + value.slice(caret.offset);\n store.applyOperation(updateRun(run.id, { value: newValue }));\n return { blockId: caret.blockId, runId: run.id, offset: caret.offset + text.length };\n}\n\nfunction applyOps(store, ops) {\n if (typeof store.performBatch === 'function') store.performBatch(ops);\n else for (const op of ops) store.applyOperation(op);\n}\n\nexport function useClipboardHandlers() {\n const store = useEditorStore();\n const registry = useBlockRegistry();\n const inlineRegistry = useInlineRegistry();\n const [isWholeDocumentSelected, setIsWholeDocumentSelected] = useWholeDocumentSelection();\n const [selectedBlockRange, setSelectedBlockRange] = useBlockRangeSelection();\n\n const onCopy = useCallback(\n (event) => {\n // Priority: whole-document select-all > a drag-selected block range\n // (see useBlockRangeDrag) > the native browser Selection. Only one of\n // these is ever meaningfully active at once in practice (starting\n // any of the others clears the rest), but the order still matters if\n // more than one happens to be non-empty.\n const blockIds = isWholeDocumentSelected\n ? (store.getBlock(store.getRootId())?.contentIds ?? [])\n : selectedBlockRange.length > 0\n ? selectedBlockRange\n : resolveSelectedBlockIds(store);\n if (blockIds.length === 0) return;\n const { html, text, json } = serializeBlockRange(store, registry, blockIds, inlineRegistry);\n event.clipboardData.setData('text/plain', text);\n event.clipboardData.setData('text/html', html);\n event.clipboardData.setData(APP_MIME, json);\n event.preventDefault();\n },\n [store, registry, inlineRegistry, isWholeDocumentSelected, selectedBlockRange],\n );\n\n // Cut = copy, then delete whatever was selected — same \"delete selection\"\n // primitive a cross-block Backspace/Delete keypress uses (see\n // useEditorKeyboardShortcuts), reused here instead of duplicated. One\n // atomic undo step for the deletion (copying doesn't touch the store).\n const onCut = useCallback(\n (event) => {\n onCopy(event);\n if (isWholeDocumentSelected) {\n const result = deleteEntireDocument(store);\n setIsWholeDocumentSelected(false);\n if (result?.runId) focusRunAtOffset(result.runId, result.offset);\n return;\n }\n if (selectedBlockRange.length > 0) {\n deleteBlockRange(store, selectedBlockRange);\n setSelectedBlockRange([]);\n return;\n }\n const result = deleteCurrentSelection(store);\n if (result?.runId) focusRunAtOffset(result.runId, result.offset);\n },\n [onCopy, store, isWholeDocumentSelected, setIsWholeDocumentSelected, selectedBlockRange, setSelectedBlockRange],\n );\n\n const onPaste = useCallback(\n (event) => {\n const inserts = deserializeClipboard(event.clipboardData, registry, inlineRegistry);\n if (inserts.length === 0) return;\n\n if (isWholeDocumentSelected) {\n const rootId = store.getRootId();\n const contentIds = store.getBlock(rootId)?.contentIds ?? [];\n const ops = contentIds.map((id) => removeBlock(id));\n let rootIndex = 0;\n for (const { block, runs, subtreeBlocks = [] } of inserts) {\n block.parentId = rootId;\n ops.push(insertBlock(block, rootId, rootIndex, { blocks: [block, ...subtreeBlocks], runs }));\n rootIndex += 1;\n }\n applyOps(store, ops);\n setIsWholeDocumentSelected(false);\n event.preventDefault();\n return;\n }\n\n // Same idea, scoped to a drag-selected block range instead of the\n // whole document: the range is removed and the pasted block(s) take\n // its place, starting at the range's former position.\n if (selectedBlockRange.length > 0) {\n const first = store.getBlock(selectedBlockRange[0]);\n const parentId = first?.parentId ?? null;\n const parent = parentId && store.getBlock(parentId);\n let index = parent ? parent.contentIds.indexOf(selectedBlockRange[0]) : 0;\n\n const ops = selectedBlockRange.map((id) => removeBlock(id));\n for (const { block, runs, subtreeBlocks = [] } of inserts) {\n block.parentId = parentId;\n ops.push(insertBlock(block, parentId, index, { blocks: [block, ...subtreeBlocks], runs }));\n index += 1;\n }\n applyOps(store, ops);\n setSelectedBlockRange([]);\n event.preventDefault();\n return;\n }\n\n // Pasting over an active selection replaces it, rather than leaving\n // the old selected content sitting next to the newly-inserted\n // blocks — same \"delete selection\" primitive as Cut/cross-block\n // Backspace. Its own atomic undo step, separate from the insertion\n // below.\n const deleteResult = deleteCurrentSelection(store);\n\n // Simple, single-run plain-text paste — by far the common case (a\n // word, a phrase, a URL) — splices directly into the run at the\n // caret instead of always creating a whole new sibling block,\n // matching ProseMirror/TipTap. Multi-block or structured clipboard\n // content (tables, lists, several paragraphs) still inserts as new\n // block(s) after the current one; splitting the current block\n // around it is a further follow-up.\n const isSimpleTextPaste =\n inserts.length === 1 && inserts[0].runs.every((r) => r.type === 'text') && (inserts[0].subtreeBlocks ?? []).length === 0;\n\n if (isSimpleTextPaste) {\n const caret = deleteResult\n ? { blockId: deleteResult.blockId, runId: deleteResult.runId, offset: deleteResult.offset }\n : resolveCollapsedCaret();\n if (caret) {\n const text = inserts[0].runs.map((r) => r.value).join('');\n const result = insertTextAtCaret(store, caret, text);\n if (result) {\n focusRunAtOffset(result.runId, result.offset);\n event.preventDefault();\n return;\n }\n }\n }\n\n const atBlockId = deleteResult?.blockId ?? closestBlockId(window.getSelection?.()?.anchorNode);\n if (!atBlockId) return;\n\n const current = store.getBlock(atBlockId);\n if (!current) return;\n const parent = store.getBlock(current.parentId);\n let index = parent.contentIds.indexOf(atBlockId) + 1;\n\n const insertOps = [];\n for (const { block, runs, subtreeBlocks = [] } of inserts) {\n block.parentId = current.parentId;\n insertOps.push(insertBlock(block, current.parentId, index, { blocks: [block, ...subtreeBlocks], runs }));\n index += 1;\n }\n // One atomic undo step for the whole paste, regardless of how many\n // blocks it inserts — previously each was its own separate step.\n applyOps(store, insertOps);\n\n event.preventDefault();\n },\n [store, registry, inlineRegistry, isWholeDocumentSelected, setIsWholeDocumentSelected, selectedBlockRange, setSelectedBlockRange],\n );\n\n return { onCopy, onCut, onPaste };\n}\n","import { genId } from '../utils/idGen.js';\nimport { replaceRunSpan } from '../store/operations.js';\n\nconst BOOLEAN_MARK_NAMES = ['bold', 'italic', 'underline', 'strike', 'subscript', 'superscript', 'code'];\nconst VALUE_MARK_NAMES = ['color', 'highlight'];\n\nfunction getBlockRunIds(store, blockId) {\n const block = store.getBlock(blockId);\n return block.props?.titleRunIds ?? block.contentIds;\n}\n\nfunction summarizeMarks(runs) {\n const summary = {};\n if (runs.length === 0) return summary;\n for (const name of BOOLEAN_MARK_NAMES) {\n summary[name] = runs.every((r) => r.marks?.[name]);\n }\n for (const name of VALUE_MARK_NAMES) {\n const first = runs[0].marks?.[name] ?? null;\n summary[name] = runs.every((r) => (r.marks?.[name] ?? null) === first) ? first : null;\n }\n return summary;\n}\n\n/**\n * Summarizes which marks are uniformly active across a same-block\n * selection — used by the floating toolbar to show a button as \"pressed\"\n * only when the *entire* selection already has that mark (the same\n * all-or-nothing convention toggleMarkOverSelection's own enable/disable\n * decision uses), and to read the current color/highlight value when it's\n * consistent across the whole selection (null when mixed or unset).\n */\nexport function getMarksSummaryOverSelection(store, blockId, selection) {\n const { startRunId, startOffset, endRunId, endOffset } = selection;\n const runIds = getBlockRunIds(store, blockId);\n const startIndex = runIds.indexOf(startRunId);\n const endIndex = runIds.indexOf(endRunId);\n if (startIndex === -1 || endIndex === -1) return {};\n const [fromIndex, toIndex] = startIndex <= endIndex ? [startIndex, endIndex] : [endIndex, startIndex];\n const runs = runIds\n .slice(fromIndex, toIndex + 1)\n .map((id) => store.getRun(id))\n .filter((r) => r && r.type === 'text');\n return summarizeMarks(runs);\n}\n\n/**\n * Same idea as getMarksSummaryOverSelection but for a cross-block range.\n * Approximates by including every text run in every block the range\n * touches (not clipped to the exact sub-range within the first/last\n * block) — fine for a toolbar's \"is this button pressed\" indicator, which\n * doesn't need character-level precision; the actual mutation\n * (setMarksOverBlockRange) is exact.\n */\nexport function getMarksSummaryOverBlockRange(store, crossSelection) {\n const { blockIds, startBlockId, endBlockId } = crossSelection;\n const startBlockIndex = blockIds.indexOf(startBlockId);\n const endBlockIndex = blockIds.indexOf(endBlockId);\n if (startBlockIndex === -1 || endBlockIndex === -1) return {};\n const [fromBlockIndex, toBlockIndex] =\n startBlockIndex <= endBlockIndex ? [startBlockIndex, endBlockIndex] : [endBlockIndex, startBlockIndex];\n\n const runs = [];\n for (let i = fromBlockIndex; i <= toBlockIndex; i += 1) {\n for (const id of getBlockRunIds(store, blockIds[i])) {\n const run = store.getRun(id);\n if (run && run.type === 'text') runs.push(run);\n }\n }\n return summarizeMarks(runs);\n}\n\n/** Applies a {markName: value} patch to a marks object — value === null/undefined removes that key, anything else sets it. */\nfunction applyMarksPatch(marks, marksPatch) {\n const next = { ...marks };\n for (const [markName, value] of Object.entries(marksPatch)) {\n if (value != null) next[markName] = value;\n else delete next[markName];\n }\n return next;\n}\n\n/** Splits one run at [from, to) and applies `marksPatch` to the middle slice; the rest keeps its existing marks. */\nfunction applyPatchToSingleRun(store, blockId, run, from, to, marksPatch) {\n const nextMarks = applyMarksPatch(run.marks, marksPatch);\n\n if (from === 0 && to === run.value.length) {\n store.applyOperation({ type: 'updateRun', id: run.id, patch: { marks: nextMarks } });\n return run.id;\n }\n\n const before = run.value.slice(0, from);\n const middle = run.value.slice(from, to);\n const after = run.value.slice(to);\n\n const newRuns = [];\n if (before) newRuns.push({ id: genId(), type: 'text', value: before, marks: { ...run.marks } });\n const middleRun = { id: genId(), type: 'text', value: middle, marks: nextMarks };\n newRuns.push(middleRun);\n if (after) newRuns.push({ id: genId(), type: 'text', value: after, marks: { ...run.marks } });\n\n store.applyOperation(replaceRunSpan(blockId, [run.id], newRuns));\n return middleRun.id;\n}\n\n/**\n * Applies `marksPatch` — one or more `{markName: value}` entries, value\n * `null`/`undefined` meaning \"remove this mark\" and anything else meaning\n * \"set it to this value\" — across a run span within one block, which may\n * cover one run or several. Applying several marks in the same patch (e.g.\n * `{ superscript: true, subscript: null }`, so turning superscript on\n * always clears subscript in the same pass) matters because two *sequential*\n * calls would each independently split/replace runs and mint new ids, so\n * the second call's selection (addressed by run id) could already be stale\n * by the time it runs — one patch, one pass, no staleness window.\n *\n * Atomic (non-text) runs in the span are passed through untouched. This is\n * the shared primitive every mark command below (boolean toggle, or a\n * value-based mark like color/highlight) ultimately applies per block.\n */\nfunction applyMarksPatchOverRunSpan(store, blockId, selection, marksPatch) {\n const { startRunId, startOffset, endRunId, endOffset } = selection;\n const runIds = getBlockRunIds(store, blockId);\n const startIndex = runIds.indexOf(startRunId);\n const endIndex = runIds.indexOf(endRunId);\n if (startIndex === -1 || endIndex === -1) return null;\n\n const [fromIndex, toIndex] = startIndex <= endIndex ? [startIndex, endIndex] : [endIndex, startIndex];\n const fromOffset = startIndex <= endIndex ? startOffset : endOffset;\n const toOffset = startIndex <= endIndex ? endOffset : startOffset;\n\n const rangeRunIds = runIds.slice(fromIndex, toIndex + 1);\n const rangeRuns = rangeRunIds.map((id) => store.getRun(id));\n\n if (fromIndex === toIndex) {\n const run = rangeRuns[0];\n if (run.type !== 'text') return run.id;\n const from = Math.max(0, Math.min(fromOffset, toOffset));\n const to = Math.min(run.value.length, Math.max(fromOffset, toOffset));\n if (from === to) return run.id;\n return applyPatchToSingleRun(store, blockId, run, from, to, marksPatch);\n }\n\n const newRuns = [];\n let lastNewRunId = null;\n\n rangeRuns.forEach((run, i) => {\n if (run.type !== 'text') {\n newRuns.push(run); // atomic: pass through untouched\n lastNewRunId = run.id;\n return;\n }\n\n const isFirst = i === 0;\n const isLast = i === rangeRuns.length - 1;\n const sliceStart = isFirst ? fromOffset : 0;\n const sliceEnd = isLast ? toOffset : run.value.length;\n\n const before = run.value.slice(0, sliceStart);\n const middle = run.value.slice(sliceStart, sliceEnd);\n const after = run.value.slice(sliceEnd);\n\n if (before) newRuns.push({ id: genId(), type: 'text', value: before, marks: { ...run.marks } });\n\n const middleRun = { id: genId(), type: 'text', value: middle, marks: applyMarksPatch(run.marks, marksPatch) };\n newRuns.push(middleRun);\n lastNewRunId = middleRun.id;\n\n if (after) newRuns.push({ id: genId(), type: 'text', value: after, marks: { ...run.marks } });\n });\n\n store.applyOperation(replaceRunSpan(blockId, rangeRunIds, newRuns));\n return lastNewRunId;\n}\n\n/** Whether every *text* run covered by the range already has the mark (decides enable vs disable for a boolean toggle). */\nfunction computeShouldEnableForRange(store, blockId, selection, markName) {\n const { startRunId, startOffset, endRunId, endOffset } = selection;\n const runIds = getBlockRunIds(store, blockId);\n const startIndex = runIds.indexOf(startRunId);\n const endIndex = runIds.indexOf(endRunId);\n if (startIndex === -1 || endIndex === -1) return true;\n const [fromIndex, toIndex] = startIndex <= endIndex ? [startIndex, endIndex] : [endIndex, startIndex];\n const textRuns = runIds\n .slice(fromIndex, toIndex + 1)\n .map((id) => store.getRun(id))\n .filter((r) => r.type === 'text');\n if (textRuns.length === 0) return true;\n if (fromIndex === toIndex) {\n const from = Math.max(0, Math.min(startOffset, endOffset));\n const to = Math.min(textRuns[0].value.length, Math.max(startOffset, endOffset));\n if (from === to) return !textRuns[0].marks?.[markName]; // collapsed: mirror toggleMarkOnRunRange's convention\n }\n return !textRuns.every((r) => r.marks?.[markName]);\n}\n\n/**\n * Toggles `markName` on the [startOffset, endOffset) slice of one run's\n * text. Kept as a direct single-run entry point (used when the caller\n * already knows it's exactly one run) — internally now just computes the\n * enable/disable decision and delegates to applyPatchToSingleRun.\n *\n * Returns the id of the run that now contains the toggled middle segment\n * (or the whole run, if no split was needed) — useful for restoring focus.\n */\nexport function toggleMarkOnRunRange(store, blockId, runId, startOffset, endOffset, markName) {\n const run = store.getRun(runId);\n const value = run.value ?? '';\n const from = Math.max(0, Math.min(startOffset, endOffset));\n const to = Math.min(value.length, Math.max(startOffset, endOffset));\n if (from === to) return runId; // collapsed selection: nothing to toggle\n\n const shouldEnable = !run.marks?.[markName];\n return applyPatchToSingleRun(store, blockId, run, from, to, { [markName]: shouldEnable ? true : null });\n}\n\n/**\n * Applies an explicit `{markName: value}` patch (see applyMarksPatchOverRunSpan)\n * over a selection within one block — the entry point for value-based marks\n * (color/highlight, set to a specific picked value) and for any mark whose\n * enable/disable decision the caller has already made (e.g. clearing the\n * opposite of a mutually-exclusive pair like subscript/superscript\n * alongside setting the one being turned on, in the same pass).\n */\nexport function setMarksOverSelection(store, blockId, selection, marksPatch) {\n return applyMarksPatchOverRunSpan(store, blockId, selection, marksPatch);\n}\n\n/**\n * Toggles `markName` over a selection that may span *multiple runs within\n * the same block* — e.g. selecting \"ello wor\" across \"h[ello] [wor]ld\" where\n * the middle word already had a different mark boundary. Atomic (non-text)\n * runs caught in the range are passed through unchanged; marks don't apply\n * to them.\n *\n * The whole-range mark state (enable vs disable) is decided by whether\n * every *text* run currently in range already has the mark: if so, this\n * toggle removes it from all of them; otherwise it adds it to all of them\n * — the standard \"toggle bold over a mixed selection turns it fully on\"\n * rich-text convention.\n *\n * Scope: the selection must resolve to a single block (see\n * resolveMultiRunSelection). A selection spanning multiple blocks is\n * handled by toggleMarkOverBlockRange instead.\n */\nexport function toggleMarkOverSelection(store, blockId, selection, markName) {\n const shouldEnable = computeShouldEnableForRange(store, blockId, selection, markName);\n return setMarksOverSelection(store, blockId, selection, { [markName]: shouldEnable ? true : null });\n}\n\n/**\n * Toggles `markName` over a selection spanning *multiple sibling blocks*\n * (e.g. selecting from the middle of one paragraph through the middle of\n * another, a few blocks down). `crossSelection` comes from\n * resolveCrossBlockSelection: `{ blockIds, startBlockId, startRunId,\n * startOffset, endBlockId, endRunId, endOffset }`, where blockIds is the\n * ordered sibling range under a shared parent.\n *\n * The enable/disable decision is computed ONCE across every text run\n * actually spanned in the whole range (not per block), so toggling bold\n * across three paragraphs turns it fully on/off consistently everywhere,\n * matching toggleMarkOverSelection's same-block convention.\n *\n * Each affected block gets its own REPLACE_RUN_SPAN operation — this is\n * correct but not a single atomic undo step; undoing a cross-block toggle\n * currently takes one undo press per affected block. Fully atomic\n * cross-block undo is a further follow-up.\n */\nexport function toggleMarkOverBlockRange(store, crossSelection, markName) {\n return setMarksOverBlockRange(store, crossSelection, (allMarked) => ({ [markName]: allMarked ? null : true }), markName);\n}\n\n/**\n * Same shape as toggleMarkOverBlockRange, but for an explicit marks patch\n * rather than a single boolean toggle — `marksPatchOrFn` is either a plain\n * `{markName: value}` object (applied identically to every affected block,\n * e.g. a color pick) or a function `(allMarked) => marksPatch` when the\n * patch itself depends on the toggle decision (mirrors\n * toggleMarkOverBlockRange's own \"decide once across the whole range\"\n * semantics — `markNameForDecision` is which mark's presence decides\n * `allMarked`, defaulting to the lookup used by the boolean-toggle case).\n */\nexport function setMarksOverBlockRange(store, crossSelection, marksPatchOrFn, markNameForDecision) {\n const { blockIds, startBlockId, startRunId, startOffset, endBlockId, endRunId, endOffset } = crossSelection;\n if (!blockIds || blockIds.length === 0) return null;\n\n const startBlockIndex = blockIds.indexOf(startBlockId);\n const endBlockIndex = blockIds.indexOf(endBlockId);\n if (startBlockIndex === -1 || endBlockIndex === -1) return null;\n\n const [fromBlockIndex, toBlockIndex] =\n startBlockIndex <= endBlockIndex ? [startBlockIndex, endBlockIndex] : [endBlockIndex, startBlockIndex];\n const firstIsStart = startBlockIndex <= endBlockIndex;\n const firstRunId = firstIsStart ? startRunId : endRunId;\n const firstOffset = firstIsStart ? startOffset : endOffset;\n const lastRunId = firstIsStart ? endRunId : startRunId;\n const lastOffset = firstIsStart ? endOffset : startOffset;\n\n let marksPatch = marksPatchOrFn;\n if (typeof marksPatchOrFn === 'function') {\n let sawText = false;\n let allMarked = true;\n for (let i = fromBlockIndex; i <= toBlockIndex; i += 1) {\n const runs = getBlockRunIds(store, blockIds[i])\n .map((id) => store.getRun(id))\n .filter((r) => r.type === 'text');\n if (runs.length === 0) continue;\n sawText = true;\n if (!runs.every((r) => r.marks?.[markNameForDecision])) allMarked = false;\n }\n marksPatch = marksPatchOrFn(sawText && allMarked);\n }\n\n if (fromBlockIndex === toBlockIndex) {\n return setMarksOverSelection(\n store,\n blockIds[fromBlockIndex],\n { startRunId: firstRunId, startOffset: firstOffset, endRunId: lastRunId, endOffset: lastOffset },\n marksPatch,\n );\n }\n\n let lastNewRunId = null;\n for (let i = fromBlockIndex; i <= toBlockIndex; i += 1) {\n const blockId = blockIds[i];\n const runIds = getBlockRunIds(store, blockId);\n const blockFirstRunId = runIds[0];\n const blockLastRunId = runIds[runIds.length - 1];\n const blockLastRun = store.getRun(blockLastRunId);\n const blockLastOffset = blockLastRun?.value?.length ?? 0;\n\n let selection;\n if (i === fromBlockIndex && i === toBlockIndex) {\n selection = { startRunId: firstRunId, startOffset: firstOffset, endRunId: lastRunId, endOffset: lastOffset };\n } else if (i === fromBlockIndex) {\n selection = { startRunId: firstRunId, startOffset: firstOffset, endRunId: blockLastRunId, endOffset: blockLastOffset };\n } else if (i === toBlockIndex) {\n selection = { startRunId: blockFirstRunId, startOffset: 0, endRunId: lastRunId, endOffset: lastOffset };\n } else {\n selection = { startRunId: blockFirstRunId, startOffset: 0, endRunId: blockLastRunId, endOffset: blockLastOffset };\n }\n\n lastNewRunId = setMarksOverSelection(store, blockId, selection, marksPatch);\n }\n\n return lastNewRunId;\n}\n","import { resolveMultiRunSelection, resolveCollapsedCaret } from './selectionResolve.js';\nimport { isRunsEmpty } from '../blocks/shared/blockEmpty.js';\n\nfunction getBlockRunIds(store, blockId) {\n const block = store.getBlock(blockId);\n return block?.props?.titleRunIds ?? block?.contentIds ?? [];\n}\n\n/**\n * True when the current (non-collapsed) selection exactly spans one\n * block's own content, start to end. The trigger for promoting a second\n * Ctrl+A press from \"select this block\" (already true via native browser\n * behavior — Ctrl+A in a focused contentEditable region selects only that\n * region by default, no code needed) to \"select the whole document\".\n */\nexport function isEntireBlockSelected(store) {\n const selection = resolveMultiRunSelection();\n if (!selection) return false; // collapsed, or already spans multiple blocks\n\n const { blockId, startRunId, startOffset, endRunId, endOffset } = selection;\n const runIds = getBlockRunIds(store, blockId);\n if (runIds.length === 0) return false;\n\n const startIndex = runIds.indexOf(startRunId);\n const endIndex = runIds.indexOf(endRunId);\n if (startIndex === -1 || endIndex === -1) return false;\n\n const [fromIndex, toIndex] = startIndex <= endIndex ? [startIndex, endIndex] : [endIndex, startIndex];\n const fromOffset = startIndex <= endIndex ? startOffset : endOffset;\n const toOffset = startIndex <= endIndex ? endOffset : startOffset;\n if (fromIndex !== 0 || toIndex !== runIds.length - 1 || fromOffset !== 0) return false;\n\n const lastRun = store.getRun(runIds[runIds.length - 1]);\n const lastLength = lastRun?.type === 'text' ? (lastRun.value ?? '').length : 1; // atomic run: one selectable \"unit\"\n return toOffset === lastLength;\n}\n\n/**\n * True when the caret sits in a block with no real content at all — e.g. a\n * heading just created from the slash menu, before anything's been typed\n * into it. An empty block has nothing for native Ctrl+A to actually\n * select, so the resulting selection stays collapsed no matter how many\n * times it's pressed — isEntireBlockSelected requires a *non-collapsed*\n * selection and can never detect \"fully selected\" for it, meaning a\n * second Ctrl+A press would never promote to whole-document mode (the\n * exact bug this fixes: select-all silently doing nothing on a freshly\n * created, still-empty block, while working fine on one that already had\n * text). Treating an empty current block as already \"fully selected\"\n * lets the very first Ctrl+A press jump straight to selecting the whole\n * document instead — there's nothing meaningful to select in between.\n */\nexport function isCurrentBlockEmpty(store) {\n const caret = resolveCollapsedCaret();\n if (!caret) return false;\n return isRunsEmpty(store, getBlockRunIds(store, caret.blockId));\n}\n","import { removeBlock } from '../../store/operations.js';\nimport { isContentlessBlock } from './contentless.js';\nimport { ensureRootNonEmpty } from './ensureRootNonEmpty.js';\nimport { focusRunEnd } from '../../react/focusRun.js';\n\n/**\n * Removes the currently-selected non-editable block (see setSelectedBlockId\n * in EditorProvider.jsx) and resolves what happens to focus next: its\n * previous sibling, or else its next sibling, or else (it was the only\n * block left) whatever ensureRootNonEmpty falls back to. If THAT target is\n * itself contentless (two dividers in a row), it becomes newly selected\n * (and focused, via tabIndex={-1} — see DividerBlock/EmbedBlock) rather\n * than focusing a run that doesn't exist; otherwise its last run is\n * focused normally.\n *\n * Shared by two different call sites that both need this exact resolution:\n * EditableBlockContent's own second-press delete (bubbled from whichever\n * adjacent text block still has focus throughout) and\n * useEditorKeyboardShortcuts' global handler (a Backspace/Delete that\n * lands *directly* on the already-selected, already-focused block itself —\n * there's no EditableBlockContent wrapping a divider/embed for that press\n * to bubble through).\n */\nexport function deleteSelectedBlockAndRefocus(store, selectedId, setSelectedBlockId) {\n const block = store.getBlock(selectedId);\n if (!block) {\n setSelectedBlockId(null);\n return;\n }\n const parent = store.getBlock(block.parentId);\n const idx = parent ? parent.contentIds.indexOf(selectedId) : -1;\n const prevId = idx > 0 ? parent.contentIds[idx - 1] : null;\n const nextId = idx !== -1 && idx < parent.contentIds.length - 1 ? parent.contentIds[idx + 1] : null;\n\n store.applyOperation(removeBlock(selectedId));\n setSelectedBlockId(null);\n const fallbackId = ensureRootNonEmpty(store);\n const landId = prevId ?? nextId ?? fallbackId;\n if (!landId) return;\n\n const landBlock = store.getBlock(landId);\n if (isContentlessBlock(store, landBlock)) {\n setSelectedBlockId(landId);\n requestAnimationFrame(() => document.querySelector(`[data-block-id=\"${landId}\"]`)?.focus());\n return;\n }\n\n const titleRunIds = landBlock?.props?.titleRunIds;\n const lastRunId = landBlock?.contentIds?.[landBlock.contentIds.length - 1] ?? titleRunIds?.[titleRunIds.length - 1];\n if (lastRunId) focusRunEnd(lastRunId);\n}\n","import { useEffect } from 'react';\nimport { useEditorStore, useWholeDocumentSelection, useSelectedBlock } from './EditorProvider.jsx';\nimport { toggleMarkOverSelection, toggleMarkOverBlockRange } from '../inline/markCommands.js';\nimport { deleteOverBlockRange, deleteEntireDocument } from '../inline/deleteCommands.js';\nimport { resolveMultiRunSelection, resolveCrossBlockSelection } from './selectionResolve.js';\nimport { isEntireBlockSelected, isCurrentBlockEmpty } from './selectAllCommand.js';\nimport { focusRunEnd, focusRunAtOffset } from './focusRun.js';\nimport { deleteSelectedBlockAndRefocus } from '../blocks/shared/deleteSelectedBlock.js';\n\nconst MARK_KEYS = { b: 'bold', i: 'italic', u: 'underline' };\n\n/**\n * Wires Ctrl/Cmd+Z (undo), Ctrl/Cmd+Shift+Z or Ctrl/Cmd+Y (redo),\n * Ctrl/Cmd+A (select-all, two-stage — see below), Ctrl/Cmd+B/I/U (toggle\n * bold/italic/underline on the current selection), and Backspace/Delete\n * over a selection spanning multiple blocks, at the container level.\n * Undo/redo are no-ops if `store` is a plain EditorStore rather than a\n * History instance (optional chaining on store.undo/store.redo).\n *\n * Mark toggling tries the same-block resolver first (the common case —\n * spans one or more runs within one block), then falls back to the\n * cross-block resolver for a selection spanning sibling blocks. A\n * selection spanning non-sibling blocks (different nesting depths) still\n * isn't supported.\n *\n * Select-all is two-stage, matching every other block editor (Notion,\n * Google Docs): native Ctrl+A in a focused contentEditable region already\n * selects only that block's own content — no code needed for the first\n * press. Pressing it *again*, once the whole current block is already\n * selected, promotes to a *custom* \"whole document selected\" state (see\n * useWholeDocumentSelection) rather than trying to construct a native\n * Selection/Range spanning every block — browsers don't reliably support a\n * script-constructed Range across multiple independent contentEditable\n * islands (each is its own \"editing host\"), which is exactly why this\n * editor uses one region per block in the first place. Notion's own\n * cross-block \"select all\" highlight isn't native browser text selection\n * either, for the same reason.\n *\n * While the whole document is selected this way: Backspace/Delete clears\n * it (via deleteEntireDocument, falling back to one blank paragraph),\n * typing a printable character replaces it with that character (matching\n * the standard \"type over a selection\" convention), Escape or any other\n * key cancels the mode, and Ctrl/Cmd+C/X pick it up in useClipboardHandlers.\n *\n * Backspace/Delete over an *ordinary* (native, same- or cross-sibling-\n * block) selection is handled separately below: a same-block selection is\n * left to the existing native-typing + reconcileDomToRuns/beforeinput\n * pipeline in EditableBlockContent, which already handles it correctly —\n * letting the browser delete across *multiple separate* contentEditable\n * regions is what isn't safe.\n */\nexport function useEditorKeyboardShortcuts(containerRef) {\n const store = useEditorStore();\n const [isWholeDocumentSelected, setIsWholeDocumentSelected] = useWholeDocumentSelection();\n const { getSelectedBlockId, setSelectedBlockId } = useSelectedBlock();\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return undefined;\n\n const handleKeyDown = (event) => {\n // A non-editable block (image/divider/...) selected pending a second\n // Backspace/Delete (see EditableBlockContent's\n // selectOrDeleteContentlessNeighbor). Two different situations reach\n // here:\n // - The keydown bubbled up from an adjacent TEXT block's own\n // EditableBlockContent, which already fully handled it (selected\n // or deleted, and called preventDefault) — event.defaultPrevented\n // is already true, so there's nothing left to do here.\n // - The keydown landed *directly* on the already-selected, already-\n // focused block itself (a divider/embed has no EditableBlockContent\n // of its own to bubble through — see focusAfterMerge, which moves\n // real DOM focus onto it once the block that used to hold it was\n // deleted for being empty) — event.defaultPrevented is still\n // false, so this is the only place that can delete it.\n if (getSelectedBlockId() && (event.key === 'Backspace' || event.key === 'Delete') && !event.defaultPrevented) {\n event.preventDefault();\n // This listener is native (added via addEventListener below) on an\n // ancestor of the React root's own delegated event target, so it\n // fires *before* React's synthetic onKeyDown dispatch during the\n // bubble phase. preventDefault() alone doesn't stop that dispatch —\n // without stopPropagation, the same keydown would also reach\n // whichever EditableBlockContent still has focus and be handled a\n // second time (e.g. re-evaluating its own now-stale neighbor check\n // after the divider this call just removed is already gone,\n // wrongly merging into the previous block instead of doing nothing).\n event.stopPropagation();\n deleteSelectedBlockAndRefocus(store, getSelectedBlockId(), setSelectedBlockId);\n return;\n }\n\n // Any other key cancels a pending selection, matching\n // isWholeDocumentSelected's own \"anything else cancels\" convention\n // below.\n if (getSelectedBlockId() && event.key !== 'Backspace' && event.key !== 'Delete') {\n setSelectedBlockId(null);\n }\n\n const mod = event.metaKey || event.ctrlKey;\n\n if (mod) {\n const key = event.key.toLowerCase();\n\n if (key === 'z' && !event.shiftKey) {\n event.preventDefault();\n store.undo?.();\n return;\n }\n if ((key === 'z' && event.shiftKey) || key === 'y') {\n event.preventDefault();\n store.redo?.();\n return;\n }\n if (key === 'a') {\n if (isWholeDocumentSelected) return; // already fully selected\n if (isEntireBlockSelected(store) || isCurrentBlockEmpty(store)) {\n event.preventDefault();\n // Deliberately leave the native selection alone (still\n // highlighting just the current block) rather than clearing\n // it — Ctrl+C/X/V are native browser commands that need an\n // active selection/focus target to even dispatch a copy/cut/\n // paste event to us at all. Our onCopy/onCut/onPaste always\n // check isWholeDocumentSelected first and use every top-level\n // block when it's set, so the leftover single-block native\n // selection's actual content is never used for anything.\n setIsWholeDocumentSelected(true);\n }\n return; // first press: let native Ctrl+A select the current block\n }\n if (MARK_KEYS[key]) {\n if (isWholeDocumentSelected) return; // formatting over \"select all\" isn't supported yet\n event.preventDefault();\n const markName = MARK_KEYS[key];\n\n const sameBlockSelection = resolveMultiRunSelection();\n if (sameBlockSelection) {\n const newRunId = toggleMarkOverSelection(store, sameBlockSelection.blockId, sameBlockSelection, markName);\n if (newRunId) focusRunEnd(newRunId);\n return;\n }\n\n const crossBlockSelection = resolveCrossBlockSelection(store);\n if (crossBlockSelection) {\n const newRunId = toggleMarkOverBlockRange(store, crossBlockSelection, markName);\n if (newRunId) focusRunEnd(newRunId);\n }\n }\n return;\n }\n\n if (isWholeDocumentSelected) {\n if (event.key === 'Backspace' || event.key === 'Delete') {\n event.preventDefault();\n event.stopPropagation();\n const result = deleteEntireDocument(store);\n setIsWholeDocumentSelected(false);\n if (result?.runId) focusRunAtOffset(result.runId, result.offset);\n return;\n }\n if (event.key.length === 1) {\n // typing a printable character over \"select all\" replaces the\n // whole document with it, matching every editor's \"type over a\n // selection\" convention.\n event.preventDefault();\n event.stopPropagation();\n const result = deleteEntireDocument(store, event.key);\n setIsWholeDocumentSelected(false);\n if (result?.runId) focusRunAtOffset(result.runId, result.offset);\n return;\n }\n // Escape, arrows, or anything else not explicitly handled: just\n // cancel the mode and let the key proceed normally.\n setIsWholeDocumentSelected(false);\n if (event.key === 'Escape') return;\n }\n\n if (event.key === 'Backspace' || event.key === 'Delete') {\n const crossSelection = resolveCrossBlockSelection(store);\n if (!crossSelection) return; // same-block/collapsed: leave to EditableBlockContent's own handling\n\n event.preventDefault();\n event.stopPropagation(); // this block's own Backspace/Delete handler must not also run\n const result = deleteOverBlockRange(store, crossSelection);\n if (result?.runId) focusRunAtOffset(result.runId, result.offset);\n }\n };\n\n const handleMouseDown = () => {\n if (isWholeDocumentSelected) setIsWholeDocumentSelected(false);\n if (getSelectedBlockId()) setSelectedBlockId(null);\n };\n\n container.addEventListener('keydown', handleKeyDown);\n container.addEventListener('mousedown', handleMouseDown);\n return () => {\n container.removeEventListener('keydown', handleKeyDown);\n container.removeEventListener('mousedown', handleMouseDown);\n };\n }, [containerRef, store, isWholeDocumentSelected, setIsWholeDocumentSelected, getSelectedBlockId, setSelectedBlockId]);\n}\n","import { serializeBlockRange } from './serialize.js';\n\n/**\n * Writes a block range to the system clipboard via the async\n * `navigator.clipboard` API — used by BlockRangeActionMenu's Copy/Cut\n * buttons, which aren't a native `copy`/`cut` ClipboardEvent (those go\n * through useClipboardHandlers' synchronous, `event.clipboardData` path\n * instead, which is the only one that can carry the app's own lossless\n * MIME type — see serialize.js's own doc comment on that risk). The async\n * API's `ClipboardItem` support for arbitrary MIME types is inconsistent\n * across browsers, so this deliberately only ever writes `text/plain` and\n * `text/html` — a paste elsewhere (or back into this editor) still works\n * via the same text/html -> domWalk fallback path an external app's copy\n * would use, just without the same-editor lossless round-trip.\n */\nexport async function copyBlockRangeToClipboard(store, registry, inlineRegistry, blockIds) {\n const { html, text } = serializeBlockRange(store, registry, blockIds, inlineRegistry);\n if (typeof ClipboardItem !== 'undefined' && navigator.clipboard?.write) {\n await navigator.clipboard.write([\n new ClipboardItem({\n 'text/plain': new Blob([text], { type: 'text/plain' }),\n 'text/html': new Blob([html], { type: 'text/html' }),\n }),\n ]);\n return;\n }\n await navigator.clipboard?.writeText?.(text);\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useEditorStore, useBlockRegistry, useInlineRegistry, useBlockRangeSelection } from './EditorProvider.jsx';\nimport { copyBlockRangeToClipboard } from '../clipboard/copyBlockRange.js';\nimport {\n deleteBlockRange,\n moveBlockRangeUp,\n moveBlockRangeDown,\n isEntireBlockRangeHidden,\n setBlockRangeHidden,\n reorderBlockRangeFromStore,\n} from '../blocks/shared/blockRangeActions.js';\nimport { CopyIcon, ScissorsIcon, TrashIcon, ArrowUpIcon, ArrowDownIcon, EyeIcon, EyeOffIcon } from './icons.jsx';\n\n/**\n * The action menu that appears once a gutter-margin drag (see\n * useBlockRangeDrag) finishes selecting a run of blocks — Copy, Cut,\n * Delete, Move up/down, Hide/Show in preview, all applied to the whole\n * range as one atomic undo step apiece. Mount this once anywhere under\n * EditorProvider (it reads useBlockRangeSelection itself, same pattern as\n * FieldTypeEditorModal); it renders nothing while nothing is range-selected.\n *\n * Positioned off the LAST selected block's own row — recomputed on every\n * range change (including live, mid-drag), so it visibly follows a\n * growing/shrinking selection rather than only appearing once, stale, at\n * mouseup.\n *\n * Outside-click/Escape/Delete are handled with a bespoke listener here\n * rather than the shared useOutsideClickAndEscape hook: a click on a\n * *different* block's gutter must start a brand-new drag (BlockGutterRow's\n * own onMouseDown → startDrag) rather than being swallowed as \"outside\n * click, clear the old selection\" — since both listeners are native\n * `mousedown` handlers, a generic ref-based exemption can't express \"except\n * anywhere with a `.be-block-gutter` ancestor\" the way this needs.\n */\nexport function BlockRangeActionMenu() {\n const store = useEditorStore();\n const registry = useBlockRegistry();\n const inlineRegistry = useInlineRegistry();\n const [selectedBlockRange, setSelectedBlockRange] = useBlockRangeSelection();\n const [rect, setRect] = useState(null);\n const menuRef = useRef(null);\n\n const isOpen = selectedBlockRange.length > 0;\n const clear = useCallback(() => setSelectedBlockRange([]), [setSelectedBlockRange]);\n\n useEffect(() => {\n if (!isOpen) {\n setRect(null);\n return;\n }\n const lastId = selectedBlockRange[selectedBlockRange.length - 1];\n const el = document.querySelector(`[data-block-row-id=\"${lastId}\"]`);\n setRect(el?.getBoundingClientRect() ?? null);\n }, [isOpen, selectedBlockRange]);\n\n useEffect(() => {\n if (!isOpen) return undefined;\n\n const handlePointerDown = (event) => {\n if (menuRef.current?.contains(event.target)) return;\n if (event.target.closest?.('.be-block-gutter')) return; // let that gutter's own drag-start take over\n clear();\n };\n const handleKeyDown = (event) => {\n if (event.key === 'Escape') {\n clear();\n } else if (event.key === 'Delete' || event.key === 'Backspace') {\n event.preventDefault();\n deleteBlockRange(store, selectedBlockRange);\n clear();\n }\n };\n document.addEventListener('mousedown', handlePointerDown);\n document.addEventListener('keydown', handleKeyDown);\n return () => {\n document.removeEventListener('mousedown', handlePointerDown);\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [isOpen, store, selectedBlockRange, clear]);\n\n const handleCopy = useCallback(() => {\n copyBlockRangeToClipboard(store, registry, inlineRegistry, selectedBlockRange);\n }, [store, registry, inlineRegistry, selectedBlockRange]);\n\n const handleCut = useCallback(async () => {\n await copyBlockRangeToClipboard(store, registry, inlineRegistry, selectedBlockRange);\n deleteBlockRange(store, selectedBlockRange);\n clear();\n }, [store, registry, inlineRegistry, selectedBlockRange, clear]);\n\n const handleDelete = useCallback(() => {\n deleteBlockRange(store, selectedBlockRange);\n clear();\n }, [store, selectedBlockRange, clear]);\n\n const handleMoveUp = useCallback(() => {\n if (moveBlockRangeUp(store, selectedBlockRange)) {\n setSelectedBlockRange(reorderBlockRangeFromStore(store, selectedBlockRange));\n }\n }, [store, selectedBlockRange, setSelectedBlockRange]);\n\n const handleMoveDown = useCallback(() => {\n if (moveBlockRangeDown(store, selectedBlockRange)) {\n setSelectedBlockRange(reorderBlockRangeFromStore(store, selectedBlockRange));\n }\n }, [store, selectedBlockRange, setSelectedBlockRange]);\n\n const isHidden = isEntireBlockRangeHidden(store, selectedBlockRange);\n const handleToggleHidden = useCallback(() => {\n setBlockRangeHidden(store, selectedBlockRange, !isHidden);\n // This component isn't subscribed to individual blocks' own props (only\n // to selectedBlockRange itself), so a plain store mutation like the one\n // above doesn't by itself trigger a re-render — a fresh array with the\n // same ids does, which is enough to make `isHidden` above re-evaluate\n // against the store's now-updated props.\n setSelectedBlockRange((ids) => [...ids]);\n }, [store, selectedBlockRange, isHidden, setSelectedBlockRange]);\n\n if (!isOpen || !rect) return null;\n\n return createPortal(\n <div\n ref={menuRef}\n role=\"menu\"\n aria-label=\"Selected blocks options\"\n className=\"be-block-range-menu\"\n style={{ position: 'fixed', top: rect.bottom + 4, left: rect.left }}\n >\n <button type=\"button\" role=\"menuitem\" className=\"be-block-range-menu-item\" onClick={handleCopy}>\n <CopyIcon size={15} /> Copy\n </button>\n <button type=\"button\" role=\"menuitem\" className=\"be-block-range-menu-item\" onClick={handleCut}>\n <ScissorsIcon size={15} /> Cut\n </button>\n <button type=\"button\" role=\"menuitem\" className=\"be-block-range-menu-item\" onClick={handleMoveUp}>\n <ArrowUpIcon size={15} /> Move up\n </button>\n <button type=\"button\" role=\"menuitem\" className=\"be-block-range-menu-item\" onClick={handleMoveDown}>\n <ArrowDownIcon size={15} /> Move down\n </button>\n <button type=\"button\" role=\"menuitem\" className=\"be-block-range-menu-item\" onClick={handleToggleHidden}>\n {isHidden ? <EyeIcon size={15} /> : <EyeOffIcon size={15} />}\n {isHidden ? 'Show in preview' : 'Hide in preview'}\n </button>\n <button type=\"button\" role=\"menuitem\" className=\"be-block-range-menu-item be-block-range-menu-item-danger\" onClick={handleDelete}>\n <TrashIcon size={15} /> Delete\n </button>\n </div>,\n document.body,\n );\n}\n","import { useCallback, useEffect, useRef } from 'react';\nimport { useEditorStore, useBlockRangeSelection } from './EditorProvider.jsx';\n\n// Minimum pointer movement (px) before a press counts as an actual drag —\n// below this, mouseup fires with nothing selected at all. Keeps a plain\n// click in the margin (mousedown+mouseup with no real movement) from\n// selecting a block; only a genuine drag gesture does.\nconst DRAG_THRESHOLD_PX = 4;\n\n/** Ids of `anchorId`..`hoverId` inclusive, in document order, among their shared parent's siblings. */\nfunction computeRange(store, anchorId, hoverId) {\n const anchorBlock = store.getBlock(anchorId);\n if (!anchorBlock) return [];\n const parent = store.getBlock(anchorBlock.parentId);\n if (!parent) return [anchorId];\n\n const ids = parent.contentIds;\n const anchorIndex = ids.indexOf(anchorId);\n const hoverIndex = hoverId ? ids.indexOf(hoverId) : anchorIndex;\n if (anchorIndex === -1) return [anchorId];\n const [from, to] = hoverIndex === -1 ? [anchorIndex, anchorIndex] : [Math.min(anchorIndex, hoverIndex), Math.max(anchorIndex, hoverIndex)];\n return ids.slice(from, to + 1);\n}\n\nfunction isCoarsePointer() {\n return typeof window !== 'undefined' && window.matchMedia?.('(pointer: coarse)')?.matches === true;\n}\n\n/**\n * Notion-style \"drag in the margin to select a run of blocks\" mechanic.\n * Call this ONCE (e.g. in EditorSurface), passing the same containerRef the\n * rest of the surface's own trigger hooks use — it registers a single\n * document-level mousedown listener that decides, per press, whether it\n * landed somewhere that COULD start a block-range drag:\n *\n * - Inside a block row's own DOM box (data-block-row-id) but OUTSIDE its\n * rendered content (be-block-row-content) — covers both the narrow\n * per-block gutter (the +/grip buttons sit there too, so those are\n * explicitly excluded) and any empty space to a short block's right.\n * - Entirely outside every row's own box, but still within this editor's\n * container — covers the wide blank page margins on either side of the\n * content column (`.be-surface`'s own `max-width` centering), found by\n * whichever row's vertical span contains the click's Y coordinate.\n *\n * That press only becomes an actual selection once the pointer has moved\n * at least DRAG_THRESHOLD_PX from where it went down — a plain click\n * (mousedown immediately followed by mouseup, no real movement) selects\n * nothing at all. This is a genuine drag-to-select gesture, not a\n * click-to-select one; a single block can still be selected by dragging a\n * few pixels within its own row.\n *\n * A press directly on the actual editable content (inside\n * be-block-row-content) is deliberately left alone either way, so normal\n * click-to-place-caret and native text selection are never hijacked.\n *\n * Disabled entirely on coarse-pointer (touch) devices — dragging in the\n * margin would fight the page's own scroll gesture there, and there's no\n * equivalent \"hover to reveal the gutter\" affordance on touch anyway.\n */\nexport function useBlockRangeDrag(containerRef) {\n const store = useEditorStore();\n const [, setSelectedBlockRange] = useBlockRangeSelection();\n const anchorIdRef = useRef(null); // set from mousedown onward, whether or not the drag has \"armed\" yet\n const isArmedRef = useRef(false); // true only once movement has passed DRAG_THRESHOLD_PX\n const startPointRef = useRef(null);\n\n const handleMouseMove = useCallback(\n (event) => {\n if (!anchorIdRef.current) return;\n\n if (!isArmedRef.current) {\n const { x, y } = startPointRef.current ?? { x: event.clientX, y: event.clientY };\n const movedPx = Math.hypot(event.clientX - x, event.clientY - y);\n if (movedPx < DRAG_THRESHOLD_PX) return;\n isArmedRef.current = true;\n // Suppresses native text selection for the rest of this drag —\n // preventDefault alone isn't enough once the pointer has crossed\n // into real block content: the browser may have already latched\n // onto that content as a fresh selection anchor. `user-select:none`\n // on the document root is the standard belt-and-braces fix (see\n // `.be-block-range-dragging` in the example app's CSS), removed the\n // instant the drag ends.\n document.documentElement.classList.add('be-block-range-dragging');\n window.getSelection?.()?.removeAllRanges();\n }\n // Also keep clearing it on every subsequent move — some browsers\n // still extend a selection that started a frame earlier even with\n // user-select:none applied mid-gesture.\n window.getSelection?.()?.removeAllRanges();\n event.preventDefault();\n\n const el = document.elementFromPoint(event.clientX, event.clientY)?.closest('[data-block-row-id]');\n const hoverId = el?.getAttribute('data-block-row-id') ?? null;\n setSelectedBlockRange(computeRange(store, anchorIdRef.current, hoverId));\n },\n [store, setSelectedBlockRange],\n );\n\n const handleMouseUp = useCallback(() => {\n anchorIdRef.current = null;\n isArmedRef.current = false;\n startPointRef.current = null;\n document.documentElement.classList.remove('be-block-range-dragging');\n }, []);\n\n const armDrag = useCallback((blockId, event) => {\n anchorIdRef.current = blockId;\n isArmedRef.current = false;\n startPointRef.current = { x: event.clientX, y: event.clientY };\n }, []);\n\n const handleMouseDown = useCallback(\n (event) => {\n if (event.button !== 0) return; // left click only\n if (isCoarsePointer()) return;\n if (event.target.closest?.('button, input, textarea, select')) return;\n\n const row = event.target.closest('[data-block-row-id]');\n if (row) {\n const contentEl = row.querySelector('.be-block-row-content');\n const contentRect = contentEl?.getBoundingClientRect();\n if (contentRect && event.clientX >= contentRect.left && event.clientX <= contentRect.right) return;\n armDrag(row.getAttribute('data-block-row-id'), event);\n return;\n }\n\n // The press landed entirely outside every row's own DOM box — the\n // wide blank page margin on either side of `.be-surface`'s centered\n // content column (that margin is never inside any row's own element,\n // since each row is only ever as wide as the content column itself).\n // Scoped to THIS editor's own rows via containerRef, deliberately\n // NOT via container.contains(event.target) — a blank-margin click's\n // target is by definition outside the container's own narrower box.\n const container = containerRef?.current;\n if (!container) return;\n const rows = [...container.querySelectorAll('[data-block-row-id]')];\n const hovered = rows.find((el) => {\n const r = el.getBoundingClientRect();\n return event.clientY >= r.top && event.clientY <= r.bottom;\n });\n if (hovered) {\n armDrag(hovered.getAttribute('data-block-row-id'), event);\n }\n },\n [containerRef, armDrag],\n );\n\n useEffect(() => {\n document.addEventListener('mousedown', handleMouseDown);\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n return () => {\n document.removeEventListener('mousedown', handleMouseDown);\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n document.documentElement.classList.remove('be-block-range-dragging'); // in case unmounted mid-drag\n };\n }, [handleMouseDown, handleMouseMove, handleMouseUp]);\n}\n","import { useCallback } from 'react';\nimport { useEditorStore, usePreviewMode } from './EditorProvider.jsx';\nimport { insertSiblingAfterAndFocus } from '../blocks/shared/blockCommands.js';\nimport { createTextLeafBlock } from '../blocks/shared/leafBlockFactory.js';\nimport { focusBlockEnd } from '../blocks/shared/navigationCommands.js';\nimport { ensureRootNonEmpty } from '../blocks/shared/ensureRootNonEmpty.js';\n\n/**\n * Matches every real editor's \"click below the last block to keep writing\"\n * affordance (Notion, Google Docs, ...): a plain clickable strip below the\n * document's own content, sized so there's always somewhere to click even\n * when the last block fills the viewport. If the last top-level block is\n * already a paragraph, clicking here just moves the caret to its end —\n * clicking below your own last paragraph shouldn't create a new empty one\n * under it. For anything else (a heading, list, table, embed, ...), there's\n * nothing to place a text caret in at that position, so a fresh paragraph\n * is inserted after it and focused instead.\n *\n * A no-op in preview mode (see usePreviewMode) — a preview isn't something\n * you edit, so clicking below its content shouldn't create a new block.\n */\nexport function EditorTrailingSpace({ minHeight = 180, className = 'be-trailing-space' }) {\n const store = useEditorStore();\n const [isPreviewMode] = usePreviewMode();\n\n const handleClick = useCallback(() => {\n if (isPreviewMode) return;\n const rootId = store.getRootId();\n const root = store.getBlock(rootId);\n const lastId = root?.contentIds?.[root.contentIds.length - 1];\n\n if (!lastId) {\n const fallbackId = ensureRootNonEmpty(store);\n if (fallbackId) focusBlockEnd(store, fallbackId);\n return;\n }\n\n const lastBlock = store.getBlock(lastId);\n if (lastBlock?.type === 'paragraph') {\n focusBlockEnd(store, lastId);\n } else {\n insertSiblingAfterAndFocus(store, lastId, createTextLeafBlock('paragraph'));\n }\n }, [store, isPreviewMode]);\n\n return <div className={className} style={{ minHeight }} onClick={handleClick} />;\n}\n","import { useEffect, useRef, useState } from 'react';\n\n/**\n * Focus deliberately stays in the run's contentEditable (moving it into the\n * menu would exit typing) — so this follows the ARIA \"listbox with\n * aria-activedescendant\" pattern: the actively-selected option lives in\n * `aria-activedescendant` on whatever *does* have focus (the triggering run\n * element), not on the listbox itself. `runId` is what identifies that\n * element; its `aria-expanded`/`aria-activedescendant` are set/cleared here\n * rather than threaded through every block type, since only this component\n * knows the listbox's ids and open/active state.\n */\nfunction useActiveDescendantWiring(isOpen, runId, activeOptionId, menuId) {\n useEffect(() => {\n if (!isOpen || !runId) return undefined;\n const runEl = document.querySelector(`[data-run-id=\"${runId}\"]`);\n if (!runEl) return undefined;\n\n runEl.setAttribute('aria-expanded', 'true');\n runEl.setAttribute('aria-haspopup', 'listbox');\n runEl.setAttribute('aria-controls', menuId);\n if (activeOptionId) runEl.setAttribute('aria-activedescendant', activeOptionId);\n\n return () => {\n runEl.removeAttribute('aria-expanded');\n runEl.removeAttribute('aria-haspopup');\n runEl.removeAttribute('aria-controls');\n runEl.removeAttribute('aria-activedescendant');\n };\n }, [isOpen, runId, activeOptionId, menuId]);\n}\n\n/**\n * Generic filterable command popover — not slash-specific despite the name\n * (kept for backward compatibility), also used as-is for the \":\" emoji menu\n * (see useEmojiMenuTrigger). Pass a distinct `menuId`/`ariaLabel` for a\n * second simultaneously-mounted instance so DOM ids and\n * aria-controls/aria-activedescendant wiring never collide between them.\n */\nexport function SlashMenu({\n isOpen,\n rect,\n commands,\n runId,\n onSelect,\n onClose,\n menuId = 'be-slash-menu',\n ariaLabel = 'Slash commands',\n}) {\n const [activeIndex, setActiveIndex] = useState(0);\n const activeItemRef = useRef(null);\n\n useEffect(() => {\n setActiveIndex(0);\n }, [commands.length]);\n\n // Keeps the keyboard-active item visible as Arrow Up/Down moves it past\n // the edge of the scrollable list — without this, arrowing past the\n // bottom (or top) leaves the highlighted item scrolled out of view with\n // nothing on screen showing which one is currently selected.\n useEffect(() => {\n activeItemRef.current?.scrollIntoView?.({ block: 'nearest' });\n }, [activeIndex]);\n\n useEffect(() => {\n if (!isOpen) return undefined;\n\n const handleKeyDown = (event) => {\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n event.stopPropagation();\n setActiveIndex((i) => Math.min(i + 1, Math.max(commands.length - 1, 0)));\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n event.stopPropagation();\n setActiveIndex((i) => Math.max(i - 1, 0));\n } else if (event.key === 'Enter') {\n event.preventDefault();\n event.stopPropagation();\n if (commands[activeIndex]) onSelect(commands[activeIndex]);\n } else if (event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n onClose();\n }\n };\n\n // capture phase: must win over EditableBlockContent's own onKeyDown (Enter/etc.)\n document.addEventListener('keydown', handleKeyDown, true);\n return () => document.removeEventListener('keydown', handleKeyDown, true);\n }, [isOpen, commands, activeIndex, onSelect, onClose]);\n\n const activeCommand = commands[activeIndex];\n const activeOptionId = activeCommand ? `${menuId}-option-${activeIndex}` : null;\n useActiveDescendantWiring(isOpen, runId, activeOptionId, menuId);\n\n if (!isOpen || commands.length === 0 || !rect) return null;\n\n return (\n <div\n id={menuId}\n role=\"listbox\"\n aria-label={ariaLabel}\n className=\"be-slash-menu\"\n style={{ position: 'fixed', top: rect.bottom + 4, left: rect.left, zIndex: 1000 }}\n >\n {commands.map((command, i) => {\n const Icon = command.icon;\n return (\n <div\n key={command.label}\n ref={i === activeIndex ? activeItemRef : undefined}\n id={`${menuId}-option-${i}`}\n role=\"option\"\n aria-selected={i === activeIndex}\n className={`be-slash-menu-item${i === activeIndex ? ' be-slash-menu-item-active' : ''}`}\n onMouseDown={(event) => {\n event.preventDefault();\n onSelect(command);\n }}\n onMouseEnter={() => setActiveIndex(i)}\n >\n {Icon && (\n <span className=\"be-slash-menu-item-icon\">\n <Icon size={16} />\n </span>\n )}\n <span className=\"be-slash-menu-item-label\">{command.label}</span>\n </div>\n );\n })}\n </div>\n );\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport { useEditorStore } from '../react/EditorProvider.jsx';\nimport { stripEmptyRunPlaceholder } from '../react/domRunSync.js';\n\nfunction matchesQuery(command, query) {\n if (!query) return true;\n const q = query.toLowerCase();\n return command.label.toLowerCase().includes(q) || command.keywords?.some((k) => k.toLowerCase().includes(q));\n}\n\n/**\n * Resolves the caret's logical offset within `runEl`'s text (with the\n * empty-run placeholder stripped), regardless of whether the browser's\n * selection anchors on the run's text node directly or on the run element\n * itself (e.g. a not-yet-populated node). Falls back to \"end of text\" if\n * the selection isn't actually inside this element.\n */\nfunction caretOffsetInRun(runEl, selection) {\n const node = selection.anchorNode;\n const rawOffset = selection.anchorOffset;\n let rawTextBeforeCaret;\n\n if (node === runEl) {\n rawTextBeforeCaret = '';\n for (let i = 0; i < rawOffset && i < runEl.childNodes.length; i += 1) {\n rawTextBeforeCaret += runEl.childNodes[i].textContent ?? '';\n }\n } else if (node && node.parentElement === runEl) {\n rawTextBeforeCaret = (node.textContent ?? '').slice(0, rawOffset);\n } else {\n rawTextBeforeCaret = runEl.textContent ?? '';\n }\n\n return stripEmptyRunPlaceholder(rawTextBeforeCaret).length;\n}\n\n/**\n * Shared machinery behind both useSlashMenuTrigger (\"/\") and\n * useEmojiMenuTrigger (\":\") — watches for `regex` matching the text up to\n * the caret within any run inside `containerRef`, and resolves the matching\n * commands via `getCommands()`. Each caller only differs in its trigger\n * regex and its command source; the caret-resolution/query-matching/\n * keyboard-dismiss logic (this file) is identical either way.\n *\n * `regex` must have exactly two capture groups: group 1 is whatever\n * precedes the trigger character (start-of-string or whitespace, so it\n * isn't consumed as part of the query), group 2 is the query typed after\n * the trigger character.\n */\nexport function useTriggerMenu(containerRef, regex, getCommands) {\n const store = useEditorStore();\n const [state, setState] = useState(null); // { query, blockId, runId, sliceStart, sliceEnd, rect }\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return undefined;\n\n const handleInput = () => {\n const selection = window.getSelection?.();\n const anchorNode = selection?.anchorNode;\n let el = anchorNode?.nodeType === 1 ? anchorNode : anchorNode?.parentElement;\n while (el && typeof el.hasAttribute === 'function' && !el.hasAttribute('data-run-id')) {\n el = el.parentElement;\n }\n const runId = el?.getAttribute?.('data-run-id');\n if (!runId || !selection) {\n setState(null);\n return;\n }\n\n const caretOffset = caretOffsetInRun(el, selection);\n const textBeforeCaret = stripEmptyRunPlaceholder(el.textContent).slice(0, caretOffset);\n const match = regex.exec(textBeforeCaret);\n if (!match) {\n setState(null);\n return;\n }\n\n const blockId = el.closest?.('[data-block-id]')?.getAttribute('data-block-id');\n if (!blockId) {\n setState(null);\n return;\n }\n const sliceStart = match.index + match[1].length; // position of the trigger character itself\n setState({ query: match[2], blockId, runId, sliceStart, sliceEnd: caretOffset, rect: el.getBoundingClientRect() });\n };\n\n const handleKeyDown = (event) => {\n if (event.key === 'Escape') setState(null);\n };\n\n container.addEventListener('input', handleInput);\n container.addEventListener('keydown', handleKeyDown);\n return () => {\n container.removeEventListener('input', handleInput);\n container.removeEventListener('keydown', handleKeyDown);\n };\n }, [containerRef, regex]);\n\n const commands = state ? getCommands().filter((cmd) => matchesQuery(cmd, state.query)) : [];\n\n const selectCommand = useCallback(\n (command) => {\n if (!state) return;\n // Deliberately does NOT trim the query text here: a block command\n // just wants it gone (trimSlashQueryAndInsertAfter handles that), but\n // an inline command needs the untouched sliceStart/sliceEnd to splice\n // its chip/text in at the exact cursor position — pre-merging before/\n // after text here would destroy that split point.\n command.run(store, {\n blockId: state.blockId,\n runId: state.runId,\n sliceStart: state.sliceStart,\n sliceEnd: state.sliceEnd,\n });\n setState(null);\n },\n [state, store],\n );\n\n const close = useCallback(() => setState(null), []);\n\n return {\n isOpen: Boolean(state),\n query: state?.query ?? '',\n rect: state?.rect ?? null,\n runId: state?.runId ?? null,\n commands,\n selectCommand,\n close,\n };\n}\n","import { useCallback } from 'react';\nimport { useBlockRegistry, useInlineRegistry } from '../react/EditorProvider.jsx';\nimport { useTriggerMenu } from './useTriggerMenu.js';\n\n// Matches a \"/\" at the very start of the text, or right after whitespace,\n// followed by any word characters, anchored to the END of the string passed\n// in — the caller passes only the text *up to the caret*, which is what\n// lets \"/\" work with content after the cursor too (\"hello /table| world\"),\n// not just when the caret happens to be at the very end of the run.\nconst SLASH_RE = /(^|\\s)\\/(\\w*)$/;\n\n/**\n * Watches for \"/\" typed anywhere inside a run within `containerRef` and\n * tracks the query typed after it — works mid-block, with other text both\n * before and after the trigger in the same run, not just when the caret is\n * at the very end of otherwise-empty content. Commands come from both the\n * block registry (insert a new block after the current one) and the\n * inline-type registry (splice an atomic element in at the cursor) — see\n * each type's own `run(store, {blockId, runId})`. Only the matched\n * \"/query\" substring is removed on selection (preserving whatever comes\n * before *and after* it in the run), not the whole run.\n *\n * Emoji is its own separate \":\" trigger (see useEmojiMenuTrigger) — not\n * merged in here — so it doesn't crowd out every other \"/\" command with\n * ~60 emoji entries.\n *\n * See useTriggerMenu for the shared caret-resolution/query-matching\n * machinery this and useEmojiMenuTrigger both build on.\n */\nexport function useSlashMenuTrigger(containerRef) {\n const registry = useBlockRegistry();\n const inlineRegistry = useInlineRegistry();\n\n const getCommands = useCallback(\n () => [...registry.listSlashCommands(), ...(inlineRegistry?.listSlashCommands() ?? [])],\n [registry, inlineRegistry],\n );\n\n return useTriggerMenu(containerRef, SLASH_RE, getCommands);\n}\n","/**\n * A curated, hardcoded set of common emoji — no external emoji-data\n * package (matches this project's zero-runtime-dependency constraint).\n * Each entry's `name` doubles as its slash-command label/search keyword;\n * `keywords` adds a couple of common synonyms so \"/fire\", \"/heart\", etc.\n * find the right one directly, without having to type \"/emoji\" first.\n */\nexport const EMOJI_LIST = [\n { char: '😀', name: 'grinning face', keywords: ['smile', 'happy'] },\n { char: '😂', name: 'face with tears of joy', keywords: ['laugh', 'lol'] },\n { char: '😍', name: 'heart eyes', keywords: ['love', 'crush'] },\n { char: '😎', name: 'cool', keywords: ['sunglasses'] },\n { char: '🤔', name: 'thinking face', keywords: ['hmm'] },\n { char: '😉', name: 'winking face', keywords: ['wink'] },\n { char: '😢', name: 'crying face', keywords: ['sad', 'tear'] },\n { char: '😡', name: 'angry face', keywords: ['mad', 'rage'] },\n { char: '😱', name: 'screaming face', keywords: ['shock', 'scared'] },\n { char: '🥳', name: 'party face', keywords: ['celebrate', 'birthday'] },\n { char: '🙏', name: 'folded hands', keywords: ['please', 'pray', 'thanks'] },\n { char: '👍', name: 'thumbs up', keywords: ['approve', 'yes', 'like'] },\n { char: '👎', name: 'thumbs down', keywords: ['disapprove', 'no'] },\n { char: '👏', name: 'clapping hands', keywords: ['applause', 'congrats'] },\n { char: '🙌', name: 'raised hands', keywords: ['hooray', 'yay'] },\n { char: '👋', name: 'waving hand', keywords: ['hello', 'bye'] },\n { char: '✌️', name: 'victory hand', keywords: ['peace'] },\n { char: '💪', name: 'flexed biceps', keywords: ['strong', 'muscle'] },\n { char: '🤝', name: 'handshake', keywords: ['deal', 'agree'] },\n { char: '❤️', name: 'red heart', keywords: ['love'] },\n { char: '🔥', name: 'fire', keywords: ['hot', 'lit'] },\n { char: '⭐', name: 'star', keywords: ['favorite'] },\n { char: '✨', name: 'sparkles', keywords: ['shiny', 'magic'] },\n { char: '🎉', name: 'party popper', keywords: ['celebrate', 'congrats'] },\n { char: '🎊', name: 'confetti ball', keywords: ['celebrate'] },\n { char: '💡', name: 'light bulb', keywords: ['idea', 'tip'] },\n { char: '✅', name: 'check mark', keywords: ['done', 'yes', 'complete'] },\n { char: '❌', name: 'cross mark', keywords: ['no', 'wrong', 'delete'] },\n { char: '⚠️', name: 'warning', keywords: ['caution', 'alert'] },\n { char: '❓', name: 'question mark', keywords: ['question', 'help'] },\n { char: '❗', name: 'exclamation mark', keywords: ['important', 'alert'] },\n { char: '🚀', name: 'rocket', keywords: ['launch', 'fast', 'ship'] },\n { char: '🐛', name: 'bug', keywords: ['bug', 'issue'] },\n { char: '🔧', name: 'wrench', keywords: ['fix', 'tool', 'settings'] },\n { char: '📌', name: 'pushpin', keywords: ['pin', 'note'] },\n { char: '📎', name: 'paperclip', keywords: ['attachment', 'clip'] },\n { char: '📅', name: 'calendar', keywords: ['date', 'schedule'] },\n { char: '⏰', name: 'alarm clock', keywords: ['time', 'reminder'] },\n { char: '📈', name: 'chart increasing', keywords: ['growth', 'stats'] },\n { char: '📉', name: 'chart decreasing', keywords: ['decline', 'stats'] },\n { char: '💰', name: 'money bag', keywords: ['money', 'cash'] },\n { char: '💬', name: 'speech balloon', keywords: ['comment', 'chat'] },\n { char: '📝', name: 'memo', keywords: ['note', 'write'] },\n { char: '📚', name: 'books', keywords: ['reading', 'docs'] },\n { char: '🔗', name: 'link', keywords: ['url', 'chain'] },\n { char: '🔒', name: 'locked', keywords: ['private', 'secure'] },\n { char: '🔑', name: 'key', keywords: ['password', 'access'] },\n { char: '☕', name: 'coffee', keywords: ['coffee', 'break'] },\n { char: '🍕', name: 'pizza', keywords: ['food'] },\n { char: '🎂', name: 'birthday cake', keywords: ['birthday', 'cake'] },\n { char: '🎁', name: 'gift', keywords: ['present'] },\n { char: '🌟', name: 'glowing star', keywords: ['star', 'shiny'] },\n { char: '🌈', name: 'rainbow', keywords: ['colorful'] },\n { char: '☀️', name: 'sun', keywords: ['sunny', 'weather'] },\n { char: '🌧️', name: 'rain cloud', keywords: ['rainy', 'weather'] },\n { char: '🐶', name: 'dog face', keywords: ['dog', 'pet'] },\n { char: '🐱', name: 'cat face', keywords: ['cat', 'pet'] },\n { char: '🌍', name: 'globe', keywords: ['world', 'earth'] },\n { char: '🎯', name: 'direct hit', keywords: ['target', 'goal'] },\n { char: '🏆', name: 'trophy', keywords: ['win', 'award'] },\n { char: '🕐', name: 'clock', keywords: ['time'] },\n { char: '📣', name: 'megaphone', keywords: ['announce', 'shout'] },\n { char: '🧠', name: 'brain', keywords: ['smart', 'idea', 'mind'] },\n { char: '👀', name: 'eyes', keywords: ['look', 'watching'] },\n];\n","import { updateRun } from '../../store/operations.js';\nimport { focusRunAtOffset } from '../../react/focusRun.js';\n\n/**\n * Replaces the [sliceStart, sliceEnd) \"/query\" span in `runId`'s own text\n * with literal `text` — unlike insertInlineRunAtCursor, this never creates\n * a new run at all: the inserted content is ordinary text (an emoji\n * character), not an atomic chip, so it's just as selectable/deletable/\n * editable as anything else typed there. Used by the emoji slash commands.\n */\nexport function insertPlainTextAtCursor(store, { runId, sliceStart, sliceEnd }, text) {\n const run = store.getRun(runId);\n const value = run?.value ?? '';\n const newValue = value.slice(0, sliceStart) + text + value.slice(sliceEnd);\n store.applyOperation(updateRun(runId, { value: newValue }));\n focusRunAtOffset(runId, sliceStart + text.length);\n}\n","import { EMOJI_LIST } from './emojiList.js';\nimport { insertPlainTextAtCursor } from '../shared/insertPlainText.js';\n\n/**\n * One command per emoji, shared between however many trigger surfaces want\n * it (currently just the \":\" emoji menu — see useEmojiMenuTrigger). Kept as\n * its own module, separate from emojiList.js's raw data and index.js's\n * (now-empty) inline-type registration, so it's reusable without pulling in\n * anything registry-specific.\n */\nexport const EMOJI_COMMANDS = EMOJI_LIST.map(({ char, name, keywords }) => ({\n label: `${char} ${name}`,\n keywords,\n run: (store, ctx) => insertPlainTextAtCursor(store, ctx, char),\n}));\n","import { useTriggerMenu } from './useTriggerMenu.js';\nimport { EMOJI_COMMANDS } from '../inlineTypes/emoji/emojiCommands.js';\n\n// Matches a \":\" at the very start of the text, or right after whitespace,\n// followed by any word characters — same shape as the slash trigger, just a\n// different character, so \":fire\" narrows to 🔥 without colliding with \"/\"\n// commands typed in the same run.\nconst EMOJI_RE = /(^|\\s):(\\w*)$/;\n\nconst getEmojiCommands = () => EMOJI_COMMANDS;\n\n/**\n * Watches for \":\" typed anywhere inside a run within `containerRef` and\n * tracks the query typed after it, resolving against the built-in emoji\n * list — its own dedicated trigger, deliberately separate from \"/\" (see\n * useSlashMenuTrigger's doc comment), so emoji don't crowd out every other\n * slash command. Render the SAME `SlashMenu` component against this hook's\n * return value (it's a generic filterable command popover, not slash-\n * specific) — pass distinct `menuId`/`ariaLabel` props so the two popovers\n * (this one and the \"/\" one) never collide if both happen to be mounted at\n * once.\n */\nexport function useEmojiMenuTrigger(containerRef) {\n return useTriggerMenu(containerRef, EMOJI_RE, getEmojiCommands);\n}\n","import { useCallback } from 'react';\nimport { useInlineRegistry } from '../react/EditorProvider.jsx';\nimport { useTriggerMenu } from './useTriggerMenu.js';\n\n// Same shape as SLASH_RE/EMOJI_RE (see useSlashMenuTrigger/useEmojiMenuTrigger)\n// with \"@\" as the trigger character instead.\nconst AT_RE = /(^|\\s)@(\\w*)$/;\n\n/**\n * Watches for \"@\" typed anywhere inside a run within `containerRef` and\n * tracks the query typed after it, resolving against every inline type\n * that opted into `atCommand`/`atCommands` (see InlineRegistry's doc\n * comment) — its own dedicated trigger, deliberately separate from \"/\"\n * (same rationale as useEmojiMenuTrigger's own \":\" trigger: doesn't crowd\n * out every other slash command, and \"@\" carries its own well-understood\n * meaning from Notion/TipTap/Slack that \"/\" doesn't).\n *\n * Not every inline type shows up here — only ones that asked to (e.g. a\n * host-defined \"Assignee\" field type registered with\n * `createSelectFieldType({ ..., triggers: ['slash', 'at'] })`). A generic\n * \"Priority\"/\"Status\" dropdown, for instance, would usually stay slash-only\n * since \"@Priority\" doesn't read naturally the way \"@Assignee\" does.\n *\n * Render the SAME `SlashMenu` component against this hook's return value\n * (it's a generic filterable command popover, not slash-specific) — pass a\n * distinct `menuId`/`ariaLabel`, same as the emoji menu, so the popovers\n * never collide if more than one happens to be mounted at once.\n */\nexport function useAtMenuTrigger(containerRef) {\n const inlineRegistry = useInlineRegistry();\n const getAtCommands = useCallback(() => inlineRegistry?.listAtCommands() ?? [], [inlineRegistry]);\n return useTriggerMenu(containerRef, AT_RE, getAtCommands);\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n toggleMarkOverSelection,\n toggleMarkOverBlockRange,\n setMarksOverSelection,\n setMarksOverBlockRange,\n} from '../inline/markCommands.js';\nimport { focusRunEnd } from '../react/focusRun.js';\nimport { BoldIcon, ItalicIcon, UnderlineIcon, StrikethroughIcon } from '../react/icons.jsx';\n\nconst BOOLEAN_BUTTONS = [\n { markName: 'bold', Icon: BoldIcon, title: 'Bold (Ctrl+B)' },\n { markName: 'italic', Icon: ItalicIcon, title: 'Italic (Ctrl+I)' },\n { markName: 'underline', Icon: UnderlineIcon, title: 'Underline (Ctrl+U)' },\n { markName: 'strike', Icon: StrikethroughIcon, title: 'Strikethrough' },\n];\n\nconst TEXT_COLORS = [\n { label: 'Default', value: null },\n { label: 'Red', value: '#e03131' },\n { label: 'Orange', value: '#e8590c' },\n { label: 'Green', value: '#2f9e44' },\n { label: 'Blue', value: '#1971c2' },\n { label: 'Purple', value: '#9c36b5' },\n];\n\nconst HIGHLIGHT_COLORS = [\n { label: 'None', value: null },\n { label: 'Yellow', value: '#fff3bf' },\n { label: 'Green', value: '#d3f9d8' },\n { label: 'Blue', value: '#d0ebff' },\n { label: 'Pink', value: '#ffdeeb' },\n { label: 'Gray', value: '#e9ecef' },\n];\n\n/**\n * Notion/TipTap-style format bar that appears above a non-collapsed text\n * selection (see useFloatingToolbarTrigger). Every action goes through the\n * same setMarksOverSelection/setMarksOverBlockRange primitives the keyboard\n * shortcuts use — this is just another caller, not a parallel code path —\n * so copy/cut/paste/undo/serialization all already work correctly for\n * anything applied here, with zero extra wiring.\n *\n * The whole bar has one onMouseDown that calls preventDefault: the browser's\n * default mousedown action is what collapses the text selection and shifts\n * focus to whatever you clicked — preventing it here (before any button's\n * own onClick even fires) is what lets a toolbar button apply formatting to\n * a selection that's still fully intact, exactly like every other\n * mousedown-then-click toolbar (Google Docs, Notion, etc.).\n */\nexport function FloatingToolbar({ isOpen, rect, kind, selection, crossSelection, marks, store }) {\n const [openPicker, setOpenPicker] = useState(null); // 'color' | 'highlight' | null\n const rootRef = useRef(null);\n\n useEffect(() => {\n if (!openPicker) return undefined;\n const handlePointerDown = (event) => {\n if (rootRef.current && !rootRef.current.contains(event.target)) setOpenPicker(null);\n };\n const handleKeyDown = (event) => {\n if (event.key === 'Escape') setOpenPicker(null);\n };\n document.addEventListener('mousedown', handlePointerDown);\n document.addEventListener('keydown', handleKeyDown);\n return () => {\n document.removeEventListener('mousedown', handlePointerDown);\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [openPicker]);\n\n // Closing the picker (not the whole toolbar) whenever the selection this\n // toolbar was built for changes out from under it — same rect/kind means\n // the same live selection is still current.\n useEffect(() => {\n setOpenPicker(null);\n }, [rect, kind]);\n\n const applyPatch = useCallback(\n (marksPatch) => {\n const newRunId =\n kind === 'same-block'\n ? setMarksOverSelection(store, selection.blockId, selection, marksPatch)\n : setMarksOverBlockRange(store, crossSelection, marksPatch);\n if (newRunId) focusRunEnd(newRunId);\n setOpenPicker(null);\n },\n [store, kind, selection, crossSelection],\n );\n\n const toggleBoolean = useCallback(\n (markName) => {\n const newRunId =\n kind === 'same-block'\n ? toggleMarkOverSelection(store, selection.blockId, selection, markName)\n : toggleMarkOverBlockRange(store, crossSelection, markName);\n if (newRunId) focusRunEnd(newRunId);\n },\n [store, kind, selection, crossSelection],\n );\n\n // Subscript/superscript are mutually exclusive — enabling one always\n // clears the other in the SAME patch (one pass over the run span), not\n // two sequential calls, which would risk the second call addressing runs\n // by an id the first call's split already made stale (see\n // applyMarksPatchOverRunSpan's doc comment in markCommands.js).\n const setSubSuper = useCallback(\n (markName) => {\n const opposite = markName === 'subscript' ? 'superscript' : 'subscript';\n const enable = !marks[markName];\n applyPatch({ [markName]: enable ? true : null, [opposite]: null });\n },\n [marks, applyPatch],\n );\n\n if (!isOpen || !rect) return null;\n\n return (\n <div\n ref={rootRef}\n className=\"be-floating-toolbar\"\n role=\"toolbar\"\n aria-label=\"Text formatting\"\n style={{ position: 'fixed', top: rect.top - 44, left: rect.left + rect.width / 2, transform: 'translateX(-50%)' }}\n onMouseDown={(event) => event.preventDefault()}\n >\n {BOOLEAN_BUTTONS.map(({ markName, Icon, title }) => (\n <button\n key={markName}\n type=\"button\"\n className={`be-floating-toolbar-btn${marks[markName] ? ' be-floating-toolbar-btn-active' : ''}`}\n title={title}\n aria-label={title}\n aria-pressed={Boolean(marks[markName])}\n onClick={() => toggleBoolean(markName)}\n >\n <Icon />\n </button>\n ))}\n\n <button\n type=\"button\"\n className={`be-floating-toolbar-btn${marks.subscript ? ' be-floating-toolbar-btn-active' : ''}`}\n title=\"Subscript\"\n aria-pressed={Boolean(marks.subscript)}\n onClick={() => setSubSuper('subscript')}\n >\n X₂\n </button>\n <button\n type=\"button\"\n className={`be-floating-toolbar-btn${marks.superscript ? ' be-floating-toolbar-btn-active' : ''}`}\n title=\"Superscript\"\n aria-pressed={Boolean(marks.superscript)}\n onClick={() => setSubSuper('superscript')}\n >\n X²\n </button>\n\n <span className=\"be-floating-toolbar-divider\" />\n\n <div className=\"be-floating-toolbar-picker-wrap\">\n <button\n type=\"button\"\n className=\"be-floating-toolbar-btn\"\n title=\"Text color\"\n aria-haspopup=\"true\"\n aria-expanded={openPicker === 'color'}\n onClick={() => setOpenPicker((p) => (p === 'color' ? null : 'color'))}\n >\n <span style={{ color: marks.color || 'inherit', fontWeight: 700 }}>A</span>\n </button>\n {openPicker === 'color' && (\n <div className=\"be-floating-toolbar-picker\" role=\"menu\" aria-label=\"Text color\">\n {TEXT_COLORS.map((c) => (\n <button\n key={c.label}\n type=\"button\"\n role=\"menuitem\"\n className=\"be-floating-toolbar-swatch\"\n title={c.label}\n onClick={() => applyPatch({ color: c.value })}\n >\n <span style={{ color: c.value || '#1a1a1a', fontWeight: 700 }}>A</span>\n </button>\n ))}\n </div>\n )}\n </div>\n\n <div className=\"be-floating-toolbar-picker-wrap\">\n <button\n type=\"button\"\n className=\"be-floating-toolbar-btn\"\n title=\"Highlight\"\n aria-haspopup=\"true\"\n aria-expanded={openPicker === 'highlight'}\n onClick={() => setOpenPicker((p) => (p === 'highlight' ? null : 'highlight'))}\n >\n <span\n style={{ backgroundColor: marks.highlight || 'transparent', padding: '0 2px', borderRadius: 2 }}\n >\n H\n </span>\n </button>\n {openPicker === 'highlight' && (\n <div className=\"be-floating-toolbar-picker\" role=\"menu\" aria-label=\"Highlight color\">\n {HIGHLIGHT_COLORS.map((c) => (\n <button\n key={c.label}\n type=\"button\"\n role=\"menuitem\"\n className=\"be-floating-toolbar-swatch\"\n style={{ backgroundColor: c.value || 'transparent' }}\n title={c.label}\n onClick={() => applyPatch({ highlight: c.value })}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n","import { useEffect, useState } from 'react';\nimport { useEditorStore } from '../react/EditorProvider.jsx';\nimport { resolveMultiRunSelection, resolveCrossBlockSelection } from '../react/selectionResolve.js';\nimport { getMarksSummaryOverSelection, getMarksSummaryOverBlockRange } from '../inline/markCommands.js';\n\n/**\n * Shows a floating format toolbar whenever the current selection is a real\n * (non-collapsed) text range within `containerRef` — same-block or\n * cross-block, reusing the exact same resolvers useEditorKeyboardShortcuts'\n * Ctrl+B/I already rely on, so \"can this selection be formatted at all\" is\n * answered identically everywhere in the codebase, not re-derived here.\n *\n * Listens on `document`'s `selectionchange` (selection state can change from\n * a mouseup/keyup that fires outside this exact container, e.g. releasing a\n * drag over another block) rather than a local mouseup/keyup — this mirrors\n * how real editors track selection, and is the only event that reliably\n * fires for every way a selection can change (mouse drag, shift+arrow,\n * double/triple-click, select-all, programmatic).\n *\n * Position is read directly off `Range.getBoundingClientRect()` — a\n * `position: fixed` box anchored to that rect stays correct regardless of\n * page scroll, so this also recomputes on window scroll/resize (capture\n * phase, since an inner scrollable region's scroll event doesn't bubble to\n * window by default).\n */\nexport function useFloatingToolbarTrigger(containerRef) {\n const store = useEditorStore();\n const [state, setState] = useState(null); // { rect, kind: 'same-block' | 'cross-block', selection/crossSelection, marks }\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return undefined;\n\n const recompute = () => {\n const selection = window.getSelection?.();\n if (!selection || selection.rangeCount === 0 || selection.isCollapsed) {\n setState(null);\n return;\n }\n if (!container.contains(selection.anchorNode) || !container.contains(selection.focusNode)) {\n setState(null);\n return;\n }\n\n // jsdom (used by this package's own test suite) implements\n // Element.prototype.getBoundingClientRect but not\n // Range.prototype.getBoundingClientRect at all — falling back to a\n // zero rect keeps this hook's logic testable without a real layout\n // engine, the same way a zero-size rect from a real browser (a\n // genuinely empty range) is already handled fine by callers.\n const rect = selection.getRangeAt(0).getBoundingClientRect?.() ?? { top: 0, left: 0, right: 0, bottom: 0, width: 0, height: 0 };\n\n const sameBlock = resolveMultiRunSelection();\n if (sameBlock) {\n setState({\n kind: 'same-block',\n rect,\n selection: sameBlock,\n marks: getMarksSummaryOverSelection(store, sameBlock.blockId, sameBlock),\n });\n return;\n }\n\n const crossBlock = resolveCrossBlockSelection(store);\n if (crossBlock) {\n setState({\n kind: 'cross-block',\n rect,\n crossSelection: crossBlock,\n marks: getMarksSummaryOverBlockRange(store, crossBlock),\n });\n return;\n }\n\n setState(null);\n };\n\n document.addEventListener('selectionchange', recompute);\n window.addEventListener('scroll', recompute, true);\n window.addEventListener('resize', recompute);\n return () => {\n document.removeEventListener('selectionchange', recompute);\n window.removeEventListener('scroll', recompute, true);\n window.removeEventListener('resize', recompute);\n };\n }, [containerRef, store]);\n\n return {\n isOpen: Boolean(state),\n rect: state?.rect ?? null,\n kind: state?.kind ?? null,\n selection: state?.selection ?? null,\n crossSelection: state?.crossSelection ?? null,\n marks: state?.marks ?? {},\n close: () => setState(null),\n };\n}\n","import { useCallback } from 'react';\nimport { useRun } from '../../react/useBlock.js';\nimport { useEditorStore } from '../../react/EditorProvider.jsx';\nimport { updateRun } from '../../store/operations.js';\nimport { Select } from '../../react/Select.jsx';\n\n/**\n * The atomic chip for one instance of a named custom select field type\n * (see createSelectFieldType) — same mounting contract as SelectInlineNode\n * (host+portal, contentEditable=false, stopPropagation on mousedown/\n * keydown so the surrounding paragraph never steals focus/keys from it).\n *\n * Unlike SelectInlineNode, `options` here comes from the field type's OWN\n * config (closed over by the factory), not from `run.data` — every chip of\n * a given field type shares the same options source, matching how a\n * table's select column works (one shared list, not one per cell). Only\n * the resolved selection is ever written back to the run.\n */\nexport function CustomSelectInlineNode({ id, label, placeholder, variant, options, onManage }) {\n const store = useEditorStore();\n const run = useRun(id);\n\n const handleChange = useCallback(\n (selectedValue, option) => {\n store.applyOperation(\n updateRun(id, {\n data: { selectedValue, selectedLabel: option?.label ?? '', selectedColor: option?.color },\n }),\n );\n },\n [store, id],\n );\n\n if (!run) return null;\n const { selectedValue = '', selectedLabel = '', selectedColor } = run.data ?? {};\n\n return (\n <span\n className=\"be-inline-select\"\n onMouseDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n onKeyDown={(event) => event.stopPropagation()}\n >\n <Select\n value={selectedValue}\n selectedLabel={selectedLabel}\n selectedColor={selectedColor}\n options={options}\n onChange={handleChange}\n placeholder={placeholder}\n variant={variant}\n ariaLabel={label}\n onManageOptions={onManage}\n />\n </span>\n );\n}\n","import { CustomSelectInlineNode } from './CustomSelectInlineNode.jsx';\nimport { genId } from '../../utils/idGen.js';\nimport { insertInlineRunAtCursor } from '../shared/insertInlineRun.js';\n\nfunction escapeHTML(str) {\n return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n\nfunction escapeAttr(str) {\n return escapeHTML(str).replace(/\"/g, '&quot;');\n}\n\n/**\n * Builds a full InlineRegistry entry for one named \"select field type\" —\n * the mechanism behind BOTH halves of the custom-field-type system:\n *\n * - a host app calling this directly at setup time with its own `options`\n * (a plain array, OR a `(query) => Option[] | Promise<Option[]>`\n * resolver for DB/API-backed search — see Select.jsx) — never persisted,\n * the host re-registers it every load, same as registering any other\n * built-in inline type;\n * - the in-editor \"new field type\" UI (see FieldTypeEditorModal), which\n * can only ever produce STATIC options (there's no way to author a\n * fetch function through a form) and whose definition IS persisted via\n * the store's fieldTypes collection — see registerStoredFieldTypes,\n * which calls this same factory to re-register each one after load.\n *\n * Only the resolved `{ value, label }` of whatever got picked is ever\n * stored on the run (`data.selectedValue`/`data.selectedLabel`, plus\n * `data.selectedColor` for the tag variant) — never the live options list\n * itself, so a dynamic (DB-backed) type's run never embeds a stale\n * snapshot of someone else's database. This is exactly tableSelect's own\n * denormalized-label convention, applied here per-field-type instead of\n * per-table-column.\n *\n * `onManage`, if given, is threaded down to every chip as a \"Manage\n * options…\" footer entry in its popover (see Select's onManageOptions) —\n * registerStoredFieldTypes passes one that opens FieldTypeEditorModal\n * pre-filled for this type's stored id, so any chip can jump straight to\n * editing/deleting the type it belongs to. Not something a host app\n * calling this directly typically needs, since its own config lives in\n * code, not the store.\n *\n * `triggers` (default `['slash']`) decides which trigger-character menu(s)\n * this type's command shows up under — `'slash'` for useSlashMenuTrigger's\n * \"/\" menu, `'at'` for useAtMenuTrigger's \"@\" menu, or both. The command\n * object itself (label/icon/keywords/run) is identical either way — only\n * which InlineRegistry list (slashCommand vs atCommand) it's assigned to\n * differs — so opting a type into \"@\" is a one-line config change, not a\n * separate implementation. Left slash-only by default since not every\n * field type reads naturally after \"@\" (an \"Assignee\" or \"Reviewer\" type\n * does; a generic \"Priority\"/\"Status\" dropdown usually doesn't).\n */\nexport function createSelectFieldType({\n type,\n label,\n placeholder = 'Select…',\n variant = 'default',\n icon,\n options,\n onManage,\n triggers = ['slash'],\n}) {\n function toHTML(run) {\n const text = run.data?.selectedLabel || '';\n return `<span data-inline-type=\"${escapeAttr(type)}\" data-selected-value=\"${escapeAttr(run.data?.selectedValue ?? '')}\">${escapeHTML(text)}</span>`;\n }\n\n function toPlainText(run) {\n return run.data?.selectedLabel ?? '';\n }\n\n function fromHTML(node) {\n if (node.getAttribute?.('data-inline-type') !== type) return null;\n return {\n id: genId(),\n type,\n value: '',\n marks: {},\n data: {\n selectedValue: node.getAttribute('data-selected-value') ?? '',\n selectedLabel: node.textContent ?? '',\n },\n };\n }\n\n function Component({ id }) {\n return (\n <CustomSelectInlineNode\n id={id}\n label={label}\n placeholder={placeholder}\n variant={variant}\n options={options}\n onManage={onManage}\n />\n );\n }\n\n const command = {\n label,\n icon,\n keywords: [label.toLowerCase(), 'select', 'field'],\n run: (store, { blockId, runId, sliceStart, sliceEnd }) =>\n insertInlineRunAtCursor(store, { blockId, runId, sliceStart, sliceEnd }, () => ({\n id: genId(),\n type,\n value: '',\n marks: {},\n data: { selectedValue: '', selectedLabel: '', selectedColor: undefined },\n })),\n };\n\n return {\n component: Component,\n isAtomic: true,\n toHTML,\n toPlainText,\n fromHTML,\n slashCommand: triggers.includes('slash') ? command : undefined,\n atCommand: triggers.includes('at') ? command : undefined,\n };\n}\n","import { createSelectFieldType } from './createSelectFieldType.jsx';\n\n/**\n * Re-registers every persisted, user-created field type (store.getFieldTypes())\n * into the given inline registry — the rehydration step that makes a\n * previously-created custom select type usable again after a fresh page\n * load/store construction, without the host app needing to know what\n * types exist ahead of time (unlike code-defined types, which the host\n * itself registers via createSelectFieldType at setup time).\n *\n * `onManage(id)`, if given, becomes each type's \"Manage options…\" chip\n * affordance (see createSelectFieldType's own `onManage` param) — pass\n * `useFieldTypeEditor().openEdit` from React (see useRegisterFieldTypes,\n * which wraps this reactively). Safe to call directly, outside React too\n * (e.g. right after `new EditorStore(doc)`, or in tests) when no \"manage\"\n * UI is needed.\n */\nexport function registerStoredFieldTypes(store, inlineRegistry, { onManage } = {}) {\n for (const fieldType of store.getFieldTypes()) {\n inlineRegistry.register(\n fieldType.id,\n createSelectFieldType({\n type: fieldType.id,\n label: fieldType.label,\n placeholder: fieldType.placeholder,\n variant: fieldType.variant,\n options: fieldType.options ?? [],\n onManage: onManage ? () => onManage(fieldType.id) : undefined,\n }),\n );\n }\n}\n","import { useEffect, useRef } from 'react';\nimport { useEditorStore, useInlineRegistry, useFieldTypeEditor } from '../../react/EditorProvider.jsx';\nimport { useFieldTypes } from '../../react/useFieldTypes.js';\nimport { registerStoredFieldTypes } from './registerStoredFieldTypes.js';\n\n/**\n * Keeps the inline registry in sync with the store's persisted field types\n * for the lifetime of a mounted editor: re-registers on every add/rename/\n * options-edit (registerStoredFieldTypes overwrites in place, cheap), and\n * unregisters any id that's disappeared from the list (a deleted type) so\n * its InlineRegistry entry doesn't linger with a \"Manage options…\" pointing\n * at a record that no longer exists. Each chip's onManage opens\n * FieldTypeEditorModal via useFieldTypeEditor().openEdit.\n *\n * Called once by FieldTypeEditorModal itself, so mounting that single\n * component is enough to get both the create/edit UI and this rehydration/\n * live-sync behavior — a host app never needs to call this directly.\n */\nexport function useRegisterFieldTypes() {\n const store = useEditorStore();\n const inlineRegistry = useInlineRegistry();\n const fieldTypes = useFieldTypes();\n const { openEdit } = useFieldTypeEditor();\n const previousIdsRef = useRef([]);\n\n useEffect(() => {\n if (!inlineRegistry) return;\n const currentIds = new Set(fieldTypes.map((f) => f.id));\n for (const id of previousIdsRef.current) {\n if (!currentIds.has(id)) inlineRegistry.unregister(id);\n }\n registerStoredFieldTypes(store, inlineRegistry, { onManage: openEdit });\n previousIdsRef.current = [...currentIds];\n }, [store, inlineRegistry, fieldTypes, openEdit]);\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport { Modal } from '../../react/Modal.jsx';\nimport { useEditorStore, useFieldTypeEditor } from '../../react/EditorProvider.jsx';\nimport { addFieldType, updateFieldType, removeFieldType } from '../../store/operations.js';\nimport { genId } from '../../utils/idGen.js';\nimport { XIcon } from '../../react/icons.jsx';\nimport { pickTagColor } from '../../blocks/table/tagColors.js';\nimport { useRegisterFieldTypes } from './useRegisterFieldTypes.js';\n\n/**\n * Create/edit/delete UI for a user-created custom select field type — the\n * in-editor counterpart to a host app's code-only createSelectFieldType\n * calls. Mount this once anywhere under EditorProvider (it reads\n * useFieldTypeEditor() itself, so no props are required); wire a \"+ New\n * field type\" button to `useFieldTypeEditor().openCreate()`, and each\n * type's own chips reach the edit flow via their popover's \"Manage\n * options…\" entry (see createSelectFieldType's `onManage`).\n *\n * Reuses the same add/rename/remove-option-row shape as the table\n * column's SelectOptionsManager, plus a name field and Save/Cancel/Delete\n * — closer to ButtonEditModal's \"load a draft, commit on Save\" flow than\n * SelectOptionsManager's instant-write one, since creating a brand-new\n * type has no store record to write into until Save.\n *\n * Also owns useRegisterFieldTypes() — mounting this component is what\n * keeps the inline registry in sync with the store's fieldTypes list for\n * the whole session (rehydration + live add/edit/delete), not just what\n * renders the dialog.\n */\nexport function FieldTypeEditorModal() {\n useRegisterFieldTypes();\n const store = useEditorStore();\n const { target, close } = useFieldTypeEditor();\n const isOpen = target !== null;\n const isEditing = isOpen && target !== 'new';\n\n const [name, setName] = useState('');\n const [options, setOptions] = useState([]);\n const [draft, setDraft] = useState('');\n\n useEffect(() => {\n if (!isOpen) return;\n if (isEditing) {\n const existing = store.getFieldType(target);\n setName(existing?.label ?? '');\n setOptions(existing?.options ?? []);\n } else {\n setName('');\n setOptions([]);\n }\n setDraft('');\n }, [isOpen, isEditing, target, store]);\n\n const handleRename = useCallback((value, label) => {\n setOptions((rows) => rows.map((o) => (o.value === value ? { ...o, label } : o)));\n }, []);\n\n const handleRemoveOption = useCallback((value) => {\n setOptions((rows) => rows.filter((o) => o.value !== value));\n }, []);\n\n const handleAddOption = useCallback(() => {\n const label = draft.trim();\n setDraft('');\n if (!label) return;\n setOptions((rows) => [...rows, { value: genId(), label, color: pickTagColor(rows.length) }]);\n }, [draft]);\n\n const handleSave = useCallback(() => {\n const label = name.trim();\n if (!label) return;\n if (isEditing) {\n store.applyOperation(updateFieldType(target, { label, options }));\n } else {\n store.applyOperation(\n addFieldType({ id: genId(), label, placeholder: 'Select…', variant: 'tag', options }),\n );\n }\n close();\n }, [store, isEditing, target, name, options, close]);\n\n const handleDelete = useCallback(() => {\n if (isEditing) store.applyOperation(removeFieldType(target));\n close();\n }, [store, isEditing, target, close]);\n\n return (\n <Modal isOpen={isOpen} onClose={close} title={isEditing ? 'Edit field type' : 'New field type'}>\n <label className=\"be-modal-field\">\n <span>Name</span>\n <input\n type=\"text\"\n value={name}\n onChange={(event) => setName(event.target.value)}\n placeholder=\"e.g. Priority, Status…\"\n autoFocus\n />\n </label>\n\n <div className=\"be-modal-field\">\n <span>Options</span>\n {options.map((option, i) => (\n <div key={option.value} className=\"be-table-header-menu-option-row\">\n <span\n className=\"be-table-header-menu-option-swatch\"\n style={{ background: (option.color ?? pickTagColor(i)).bg }}\n aria-hidden=\"true\"\n />\n <input\n className=\"be-table-header-menu-option-input\"\n value={option.label}\n onChange={(event) => handleRename(option.value, event.target.value)}\n aria-label={`Rename option ${option.label}`}\n />\n <button\n type=\"button\"\n className=\"be-table-header-menu-option-remove\"\n onClick={() => handleRemoveOption(option.value)}\n aria-label={`Remove option ${option.label}`}\n >\n <XIcon size={14} />\n </button>\n </div>\n ))}\n <div className=\"be-table-header-menu-option-row\">\n <input\n className=\"be-table-header-menu-option-input\"\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n placeholder=\"New option…\"\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n handleAddOption();\n }\n }}\n />\n <button type=\"button\" className=\"be-table-header-menu-option-add\" onClick={handleAddOption} aria-label=\"Add option\">\n +\n </button>\n </div>\n </div>\n\n <div className=\"be-modal-actions\">\n {isEditing && (\n <button type=\"button\" className=\"be-modal-delete\" onClick={handleDelete}>\n Delete field type\n </button>\n )}\n <button type=\"button\" className=\"be-modal-cancel\" onClick={close}>\n Cancel\n </button>\n <button type=\"button\" className=\"be-modal-save\" onClick={handleSave}>\n Save\n </button>\n </div>\n </Modal>\n );\n}\n"],"names":["OP","insertBlock","block","parentId","index","subtree","removeBlock","id","moveBlock","toParentId","toIndex","updateBlockProps","patch","updateRun","setBlockContentIds","blockId","contentIds","replaceRunSpan","oldRunIds","newRuns","setBlockRuns","runs","addFieldType","fieldType","updateFieldType","removeFieldType","FIELD_TYPES_KEY","EditorStore","doc","b","r","f","listener","set","touchedIds","rootId","blocks","walk","childId","runId","_a","op","run","previousPatch","key","parent","newContentIds","target","cid","fromParentId","fromParent","fromIndex","trimmedFromContentIds","toParent","newToContentIds","touched","previousContentIds","inContentIds","sourceArray","startIndex","removedRuns","newArray","usesTitleRunIds","previousRunIds","previousRuns","newRunIds","existing","ops","IDLE_MS","History","store","idleMs","canUndo","canRedo","meta","actorId","timestamp","inverses","inverse","value","batchKey","withinIdle","entry","BlockRegistry","type","commands","createBlockRegistry","InlineRegistry","createInlineRegistry","EditorContext","createContext","EditorProvider","registry","inlineRegistry","history","children","isWholeDocumentSelected","setIsWholeDocumentSelected","useState","selectedBlockRange","setSelectedBlockRange","isPreviewMode","setIsPreviewMode","fieldTypeEditorTarget","setFieldTypeEditorTarget","openCreateFieldType","useCallback","openEditFieldType","closeFieldTypeEditor","selectedBlockIdRef","useRef","getSelectedBlockId","setSelectedBlockId","prevId","useMemo","jsx","useEditorContext","ctx","useContext","useEditorStore","useBlockRegistry","useInlineRegistry","useWholeDocumentSelection","useBlockRangeSelection","useSelectedBlock","usePreviewMode","useFieldTypeEditor","useBlock","subscribe","onStoreChange","getSnapshot","useSyncExternalStore","useRun","genId","EMPTY_RUN_PLACEHOLDER","ZERO_WIDTH_SPACE_RE","stripEmptyRunPlaceholder","text","readRunText","node","reconcileDomToRuns","containerEl","currentRuns","byId","seen","nextRuns","sameIdentityAndOrder","newValue","changed","i","isRunBlank","isRunsEmpty","runIds","isContentlessBlock","hasRuns","hasTitleRuns","_b","focusRunAt","atStart","el","range","selection","focusRunEnd","focusRunStart","focusRunAtOffset","offset","textNode","clamped","syncEmptyAttr","container","wrapper","marksToStyle","marks","TextRunSpan","host","onValueSynced","useLayoutEffect","style","findAdjacentAtomicRunId","getRun","backward","anchorNode","anchorOffset","neighborAtomicId","caretRunId","idx","neighborId","neighborRun","child","runEl","_c","findWhollySelectedAtomicRunId","resolveRangeBoundary","childIndex","charOffset","computeRunsAfterRangeDeletion","start","end","n","touchesAtomic","insertionIndex","beforeStart","afterEnd","isStartChild","isEndChild","survivor","prefix","suffix","isCaretAtContainerStart","firstChild","probe","maxStartOffset","isCaretAtContainerEnd","lastChild","textLength","findAdjacentContentlessSiblingId","direction","adjacentIndex","adjacentId","RunNode","Component","getOrCreateHost","hostsMap","EditableBlockContent","onEnter","onBackspaceAtStart","onDeleteAtEnd","onArrowUp","onArrowDown","onTab","onShiftTab","onAutoformat","containerRef","isComposingRef","hostsRef","liveIds","previous","expectedNext","handleInput","onlyValueChanges","syncEmptyFromStore","handleCompositionStart","handleCompositionEnd","removeRun","selectOrDeleteContentlessNeighbor","handleBeforeInput","event","inputType","isDelete","isReplaceTyped","targetRanges","result","focusRunId","focusAtStart","typedRun","finalRuns","landingRunId","useEffect","handleKeyDown","wholeId","atomicId","createPortal","adjacentSiblingId","resolveAdjacentFocusTarget","currentId","resolveBlockLastRun","resolveBlockFirstRun","focusAdjacentBlock","targetRunId","firstId","focusBlockStart","lastId","focusBlockEnd","resolveRunSelection","blockEl","rawText","resolveContainerLevelSelection","atEnd","resolveRunAndOffset","containerLevel","resolveCollapsedCaret","resolveMultiRunSelection","anchor","focus","resolveCrossBlockSelection","startBlock","ids","i1","i2","from","to","insertSiblingAfter","currentBlockId","factory","subtreeBlocks","insertSiblingAfterAndFocus","newBlockId","insertFirstChildAndFocus","parentBlockId","applyOps","splitRunsAtCaret","caretOffset","caretRun","before","after","leftValue","rightValue","leftRuns","rightRuns","insertSiblingSplitAtCaretAndFocus","currentRunIds","current","splitAndInsertAtCaret","insertFirstChildSplitAtCaretAndFocus","insertParentId","insertIndex","fallback","caret","split","survivingLeftRuns","getOwnRunIds","hasNestedChildren","replaceBlockInPlace","trimSlashQueryAndInsertAfter","sliceStart","sliceEnd","ownRunIds","createTextLeafBlock","props","initialRuns","ensureRootNonEmpty","root","UNWRAP_WHEN_SOLE_CHILD_EMPTIED","MERGEABLE_TEXT_TYPES","canMergeTypes","prevType","blockType","mergeWithPreviousOrDelete","isEmpty","isBlankRun","unwrapEmptyContainer","fallbackBlock","prev","mergedContentIds","grandParent","nextId","fallbackId","focusAfterMerge","focusBlockId","focusBlock","lastRunId","convertBlockType","targetUsesTitleRunIds","sourceUsesTitleRunIds","newBlock","transferOp","detachOp","RULES","m","applyMarkdownShortcut","rule","match","strippedValue","EXITABLE_PARENT_TYPES","ParagraphBlock","handleEnter","isLastChild","handleBackspaceAtStart","isSoleChild","titleRunIds","lastTitleRunId","handleArrowUp","handleArrowDown","handleAutoformat","escapeHTML","str","escapeAttr","runToHTML","html","runToPlainText","TAG_TO_MARK","domInlineToRuns","activeMarks","nextMarks","markName","Icon","size","strokeWidth","rest","ChevronRightIcon","ChevronDownIcon","XIcon","jsxs","PaperclipIcon","PlusIcon","BoldIcon","ItalicIcon","UnderlineIcon","StrikethroughIcon","AlignLeftIcon","AlignCenterIcon","AlignRightIcon","GripVerticalIcon","cy","cx","TrashIcon","CopyIcon","ArrowUpIcon","ArrowDownIcon","ScissorsIcon","TextIcon","HeadingIcon","level","Heading1Icon","Heading2Icon","Heading3Icon","QuoteIcon","CodeIcon","DividerIcon","CalloutIcon","ButtonIcon","TableIcon","ColumnsIcon","BulletedListIcon","NumberedListIcon","CheckboxIcon","DateIcon","SelectIcon","ImageIcon","VideoIcon","EyeIcon","EyeOffIcon","AudioIcon","toHTML","toPlainText","fromHTML","paragraphBlockType","HeadingBlock","Tag","HEADING_ICONS","TAG_TO_LEVEL","headingBlockType","EMPTY_CONTENT_IDS","useBlockChildren","BlockErrorBoundary","__publicField","error","info","s","Fragment","BlockRenderer","memo","useOutsideClickAndEscape","refs","isOpen","onClose","refList","handlePointerDown","ref","serializeBlockRange","blockIds","serializeHTML","captureSubtree","ordered","itemsHTML","j","candidate","tag","linesHTML","remapSubtreeIds","idMap","remap","newBlocks","newRootId","duplicateBlock","original","moveBlockUp","moveBlockDown","deleteBlockAndFocusSibling","targetId","BlockGutterRow","isMenuOpen","setIsMenuOpen","rect","setRect","triggerRef","menuRef","outsideRefs","isRangeSelected","closeMenu","openMenu","handleAdd","handleDuplicate","handleMoveUp","handleMoveDown","handleDelete","isHidden","handleToggleHidden","BlockChildren","isTopLevel","visibleIds","ALPHA_START","ROMAN_TABLE","toAlpha","out","toRoman","symbol","isPlainMarkerItem","listItemDepth","depth","orderedItemIndex","siblingIds","pos","count","sibling","orderedMarkerText","BULLET_GLYPHS","bulletMarkerText","createListItemBlock","checked","collapsed","allRuns","childBlock","childRuns","indentListItem","outdentListItem","currentParent","grandParentId","parentIndex","isBlankTitle","isBodyEmpty","childIds","onlyChild","mergeListItemOrOutdent","empty","mergedTitleRunIds","exitListItemToParagraph","paragraphBlock","ListItemBlock","isTodo","isToggle","_d","_e","handleTab","handleShiftTab","toggleChecked","toggleCollapsed","titleText","titleHTML","childrenHTML","nested","fromLiNode","liNode","inlineNodes","nestedListNodes","titleRuns","childBlocks","listNode","li","listItemBlockType","COLUMN_TYPES","DEFAULT_COLUMN_TYPE","DEFAULT_COLUMN_WIDTH","MIN_COLUMN_WIDTH","defaultColumnLabel","createDefaultColumns","_","resolveColumns","table","colCount","columns","c","width","blankRunForType","createCellForColumn","column","convertRunToType","newType","parsed","isoDate","removeTableAndFocusSibling","tableIndex","fallbackParagraphId","parentAfter","siblingId","insertRowAfter","rowId","row","rowIndex","newRowId","cellBlocks","cell","newRow","deleteRow","updatedTable","targetRowIndex","targetRowId","insertColumnAfter","tableId","colIndex","currentColumns","newColumn","firstNewCellId","nextColumns","deleteColumn","firstRow","updatedFirstRow","targetColIndex","targetCellId","setColumnWidth","renameColumn","label","cellRunsForColumn","cellId","runPlainText","buildSelectColumnConversion","cellRuns","options","optionByLabel","option","setColumnType","oldRun","newRun","setColumnOptions","optionById","o","selectedValue","nextSelectedValue","nextSelectedLabel","matchesQuery","query","Select","onChange","placeholder","ariaLabel","className","variant","selectedLabel","selectedColor","onManageOptions","manageOptionsLabel","setIsOpen","setQuery","activeIndex","setActiveIndex","asyncOptions","setAsyncOptions","isLoading","setIsLoading","loadError","setLoadError","rootRef","buttonRef","popoverRef","inputRef","activeOptionRef","isTag","isDynamic","staticSelected","selected","filtered","cancelled","timer","close","open","selectOption","handleSearchKeyDown","TAG_COLORS","pickTagColor","TYPE_LABELS","TYPE_OPTIONS","SelectOptionsManager","draft","setDraft","handleRename","optionValue","handleRemove","ColumnHeaderCell","dragWidth","setDragWidth","thRef","handleLabelChange","handleInsertLeft","handleInsertRight","handleTypeChange","handleResizeStart","col","startWidth","startX","computeWidth","moveEvent","handleMouseMove","handleMouseUp","upEvent","TableHeaderRow","TableBlock","handleAddRow","lastRowId","TableRowBlock","handleDeleteRow","locateCell","resolveAdjacentCellTarget","delta","nextColIndex","nextRowIndex","targetRow","exitTableForward","moveToAdjacentCell","targetCell","TableCellBlock","createRow","createTableBlock","rows","cols","rowIds","cellToHTML","cellToPlainText","cellFromHTML","rowToHTML","cellBlock","rowToPlainText","rowFromHTML","cellNodes","cellNode","tableToHTML","theadHTML","rowsHTML","rowBlock","tableToPlainText","tableFromHTML","theadRow","bodyRowNodes","tr","rowNode","headerCells","tableCellBlockType","tableRowBlockType","tableBlockType","LayoutBlock","LayoutColumnBlock","createLayoutBlock","layoutId","columnIds","columnId","columnBlock","containerToHTML","tagOpen","tagClose","containerToPlainText","layoutColumnBlockType","layoutBlockType","DividerBlock","createDividerBlock","dividerBlockType","dividerId","DEFAULT_CALLOUT_ICON","createCalloutBlock","icon","calloutId","CalloutBlock","editingIcon","setEditingIcon","commitIcon","next","handleIconKeyDown","childrenToHTML","inner","calloutBlockType","BlockquoteBlock","blockquoteBlockType","LANGUAGES","LANGUAGE_OPTIONS","lang","insertLiteralTextAtCaret","CodeBlock","handleLanguageChange","language","codeEl","codeBlockType","mergeToggleHeadingOrNoop","ToggleHeadingBlock","createToggleHeadingBlock","title","summary","headingEl","pBlock","toggleHeadingBlockType","Modal","COLORS","ButtonEditModal","setLabel","href","setHref","color","setColor","attrs","setAttrs","existingAttrs","updateAttrRow","last","removeAttrRow","handleSave","customAttrs","DEFAULT_COLOR","ButtonBlock","isEditModalOpen","setIsEditModalOpen","openLink","dataAttrs","createButtonBlock","MARKER_CLASS","attrHTML","a","attr","buttonBlockType","readFileAsDataURL","file","resolve","reject","reader","KIND_LABEL","KIND_ACCEPT","MIN_WIDTH","MAX_WIDTH","ALIGN_OPTIONS","clampWidth","pct","EmbedPreview","kind","src","name","EmbedBlock","urlInput","setUrlInput","isDragOver","setIsDragOver","previewRef","frameRef","setMedia","handleFileChange","handleDrop","handleDragOver","handleDragLeave","commitUrl","trimmed","clearMedia","frameEl","containerWidth","computePct","align","canResize","effectiveWidth","createEmbedBlock","mimeType","KIND_ICONS","FILE_MARKER_CLASS","alignWidthStyle","declarations","parseAlignWidth","styleWidth","blockOf","insertEmbedCommand","embedId","embedBlockType","registerBuiltInBlocks","registerBlocks","TABLE_BLOCKS","LAYOUT_BLOCKS","blocksByType","SelectInlineNode","handleChange","insertInlineRunAtCursor","createInlineRun","currentRun","beforeText","afterText","inlineRun","beforeRun","afterRun","opt","selectInlineType","DateInlineNode","formatDate","todayIso","dateInlineType","CheckboxInlineNode","handleCheckedChange","checkboxInlineType","TableSelectInlineNode","tableSelectInlineType","emojiInlineType","registerBuiltInInlineTypes","registerInlineTypes","TABLE_SELECT_INLINE_TYPES","typesByType","useFieldTypes","STABLE_STATE","useHistory","state","APP_MIME","textToParagraphs","line","walkDomToBlocks","matchers","results","consumeList","items","consumeBlockquote","bqNode","paragraphs","p","matched","deserializeClipboard","dataTransfer","types","json","deserializeAppJSON","getBlockRunIds","blankRun","deleteRunRangeInBlock","startRunId","startOffset","endRunId","endOffset","endIndex","fromOffset","toOffset","beforeRuns","afterRuns","spanRuns","survivors","isFirst","isLast","prefixRun","suffixValue","suffixRun","blank","lastBefore","deleteOverBlockRange","crossSelection","startBlockId","endBlockId","startBlockIndex","endBlockIndex","fromBlockIndex","toBlockIndex","firstIsStart","firstRunId","firstOffset","lastOffset","firstBlockId","lastBlockId","firstBlock","lastBlock","firstRunIds","firstIdx","firstPrefixRuns","firstRun","firstPrefixSurvivor","lastRunIds","lastIdx","lastSuffixRuns","lastRun","lastSuffixSurvivor","firstSurvivors","lastSurvivors","mergeable","removedCount","wouldBeOnlyChild","survivingBlockId","merged","firstFinalRuns","deleteEntireDocument","replacementText","deleteBlockRange","moveBlockRangeUp","first","precedingId","moveBlockRangeDown","followingId","isEntireBlockRangeHidden","setBlockRangeHidden","hidden","reorderBlockRangeFromStore","idSet","closestBlockId","resolveSelectedBlockIds","startId","endId","deleteCurrentSelection","same","cross","insertTextAtCaret","useClipboardHandlers","onCopy","onCut","onPaste","inserts","rootIndex","deleteResult","atBlockId","insertOps","BOOLEAN_MARK_NAMES","VALUE_MARK_NAMES","summarizeMarks","getMarksSummaryOverSelection","getMarksSummaryOverBlockRange","applyMarksPatch","marksPatch","applyPatchToSingleRun","middle","middleRun","applyMarksPatchOverRunSpan","rangeRunIds","rangeRuns","lastNewRunId","computeShouldEnableForRange","textRuns","toggleMarkOnRunRange","shouldEnable","setMarksOverSelection","toggleMarkOverSelection","toggleMarkOverBlockRange","setMarksOverBlockRange","allMarked","marksPatchOrFn","markNameForDecision","sawText","blockFirstRunId","blockLastRunId","blockLastRun","blockLastOffset","isEntireBlockSelected","lastLength","isCurrentBlockEmpty","deleteSelectedBlockAndRefocus","selectedId","landId","landBlock","MARK_KEYS","useEditorKeyboardShortcuts","sameBlockSelection","newRunId","crossBlockSelection","handleMouseDown","copyBlockRangeToClipboard","BlockRangeActionMenu","clear","handleCopy","handleCut","DRAG_THRESHOLD_PX","computeRange","anchorId","hoverId","anchorBlock","anchorIndex","hoverIndex","isCoarsePointer","useBlockRangeDrag","anchorIdRef","isArmedRef","startPointRef","x","y","armDrag","contentEl","contentRect","hovered","EditorTrailingSpace","minHeight","handleClick","useActiveDescendantWiring","activeOptionId","menuId","SlashMenu","onSelect","activeItemRef","command","q","k","caretOffsetInRun","rawOffset","rawTextBeforeCaret","useTriggerMenu","regex","getCommands","setState","textBeforeCaret","cmd","selectCommand","SLASH_RE","useSlashMenuTrigger","EMOJI_LIST","insertPlainTextAtCursor","EMOJI_COMMANDS","char","keywords","EMOJI_RE","getEmojiCommands","useEmojiMenuTrigger","AT_RE","useAtMenuTrigger","getAtCommands","BOOLEAN_BUTTONS","TEXT_COLORS","HIGHLIGHT_COLORS","FloatingToolbar","openPicker","setOpenPicker","applyPatch","toggleBoolean","setSubSuper","opposite","enable","useFloatingToolbarTrigger","recompute","sameBlock","crossBlock","CustomSelectInlineNode","onManage","createSelectFieldType","triggers","registerStoredFieldTypes","useRegisterFieldTypes","fieldTypes","openEdit","previousIdsRef","currentIds","FieldTypeEditorModal","isEditing","setName","setOptions","handleRemoveOption","handleAddOption"],"mappings":"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"}