@domternal/extension-block-controls 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -0
- package/dist/index.cjs +2903 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +488 -0
- package/dist/index.d.ts +488 -0
- package/dist/index.js +2878 -0
- package/dist/index.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/FloatingMenu.ts","../src/helpers/findTopLevelBlock.ts","../src/helpers/expandToEmptyWrappers.ts","../src/helpers/rejoinAtSeam.ts","../src/helpers/moveBlock.ts","../src/helpers/moveBlockAsNestedChild.ts","../src/helpers/dropSlots.ts","../src/helpers/dragGhost.ts","../src/helpers/clampCoords.ts","../src/helpers/gutterBias.ts","../src/helpers/defaultMatchers.ts","../src/helpers/resolveDragTarget.ts","../src/BlockHandle.ts","../src/KeyboardReorder.ts","../src/helpers/blockOperations.ts","../src/helpers/turnIntoWrapper.ts","../src/BlockContextMenu.ts","../src/createSlashSuggestionRenderer.ts","../src/SlashCommand.ts","../src/SmartPaste.ts"],"names":["Extension","defaultFloatingMenuShouldShow","createFloatingMenuPlugin","floatingMenuPluginKey","node","canJoin","LIST_WRAPPER_TYPES","Fragment","at","LIST_ITEM_TYPES","insertAsListItemChild","PluginKey","defaultIcons","state","TextSelection","showFloatingMenu","NodeSelection","Plugin","writeToClipboard","EditorState","liftCurrentListItem","stripInlineColorConflicts","positionFloatingOnce","DecorationSet","Decoration","groupFloatingMenuItems","ReplaceStep","FloatingMenuController","Selection"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * FloatingMenu extension: registers the floating-menu plugin under the shared\n * `floatingMenuPluginKey`. The plugin machinery (visibility, positioning,\n * dismiss, keyboard entry) lives in `@domternal/core` so framework wrappers\n * can build their menus without depending on this package; everything is\n * re-exported here for backward compatibility.\n */\nimport {\n Extension,\n createFloatingMenuPlugin,\n floatingMenuPluginKey,\n defaultFloatingMenuShouldShow,\n} from '@domternal/core';\nimport type { Editor, FloatingMenuOptions } from '@domternal/core';\n\nexport {\n createFloatingMenuPlugin,\n floatingMenuPluginKey,\n showFloatingMenu,\n hideFloatingMenu,\n FLOATING_MENU_META,\n} from '@domternal/core';\nexport type {\n FloatingMenuOptions,\n CreateFloatingMenuPluginOptions,\n FloatingMenuKeymap,\n} from '@domternal/core';\n\nexport const FloatingMenu = Extension.create<FloatingMenuOptions>({\n name: 'floatingMenu',\n\n addOptions() {\n return {\n element: null,\n shouldShow: defaultFloatingMenuShouldShow,\n offset: 0,\n requireExplicitTrigger: false,\n };\n },\n\n addProseMirrorPlugins() {\n const { element, shouldShow, offset, keymap, requireExplicitTrigger } = this.options;\n if (!element) return [];\n const editor = this.editor as Editor | null;\n if (!editor) return [];\n\n return [\n createFloatingMenuPlugin({\n pluginKey: floatingMenuPluginKey,\n editor,\n element,\n shouldShow,\n offset,\n keymap,\n ...(requireExplicitTrigger !== undefined && { requireExplicitTrigger }),\n }),\n ];\n },\n});\n","import type { Node } from '@domternal/pm/model';\nimport type { EditorView } from '@domternal/pm/view';\n\nimport type { BlockCandidate, BlockMatcher } from './blockMatcher.js';\n\n/** Information about a top-level block in the document. */\nexport interface TopLevelBlock {\n /** The block node. */\n node: Node;\n /** Absolute position of the block (its start). */\n pos: number;\n /** Absolute position one past the block end (= pos + node.nodeSize). */\n end: number;\n /** Zero-based index among doc children. */\n index: number;\n}\n\n/**\n * Resolves the top-level block (direct child of the document) that contains\n * a given absolute position. Returns `null` when `pos` resolves to the\n * document itself (depth 0) or is out of bounds.\n */\nexport function findTopLevelBlock(doc: Node, pos: number): TopLevelBlock | null {\n if (pos < 0 || pos > doc.content.size) return null;\n const $pos = doc.resolve(pos);\n\n // Position exactly at a top-level boundary; `doc.nodeAt(pos)` returns the\n // node starting here.\n if ($pos.depth === 0) {\n const node = doc.nodeAt(pos);\n if (!node) return null;\n return {\n node,\n pos,\n end: pos + node.nodeSize,\n index: $pos.index(0),\n };\n }\n\n const node = $pos.node(1);\n const blockPos = $pos.before(1);\n const index = $pos.index(0);\n return {\n node,\n pos: blockPos,\n end: blockPos + node.nodeSize,\n index,\n };\n}\n\n/**\n * Resolves the deepest ancestor whose type name appears in `draggableTypes`,\n * falling back to `findTopLevelBlock` if none match. Used by `BlockHandle` in\n * `nested` mode, where the handle targets individual list/task items rather than\n * the whole list. Walks deepest-first so nested lists resolve to the innermost\n * matching item.\n */\nexport function findDraggableBlock(\n doc: Node,\n pos: number,\n draggableTypes: string[],\n): TopLevelBlock | null {\n if (pos < 0 || pos > doc.content.size) return null;\n if (draggableTypes.length === 0) return findTopLevelBlock(doc, pos);\n const $pos = doc.resolve(pos);\n\n // Walk ancestors deepest to shallowest (skip depth 0 = doc).\n for (let depth = $pos.depth; depth >= 1; depth--) {\n const node = $pos.node(depth);\n if (draggableTypes.includes(node.type.name)) {\n const blockPos = $pos.before(depth);\n // Index within the direct parent, as the sibling-reorder logic expects.\n const index = $pos.index(depth - 1);\n return {\n node,\n pos: blockPos,\n end: blockPos + node.nodeSize,\n index,\n };\n }\n }\n\n // No matching ancestor: fall back to the top-level block so hover/drag still\n // works for plain paragraphs outside any container.\n return findTopLevelBlock(doc, pos);\n}\n\n/** Spatial result returned by {@link findDeepestBlockAtY}. */\nexport interface DeepestBlockMatch {\n node: Node;\n pos: number;\n dom: HTMLElement;\n rect: DOMRect;\n}\n\n/**\n * Hysteresis options for {@link findDeepestBlockAtY}, keeping the target stable\n * so it doesn't flip-flop near a nested-list boundary.\n */\nexport interface FindDeepestBlockOptions {\n /**\n * The previous dragover's resolved block. Its containment test is widened by\n * `hysteresisBand` so the cursor must move decisively out before a different\n * block (outer<->inner list item) takes over. Ranking unchanged; only\n * eligibility widens.\n */\n incumbentPos?: number | null;\n /** Sticky margin (px) for the incumbent's containment test. `0` disables. */\n hysteresisBand?: number;\n}\n\n/**\n * Finds the deepest (smallest-height) `allowedTypes` block whose vertical rect\n * contains `clientY`. X is ignored on purpose: the handle sits in the left\n * gutter, so X-based resolution would pick the outer block; Y anchors on the row\n * the cursor is actually in. `matchers` can `'reject'` candidates (e.g. a list\n * item's label paragraph). The gutter-bias alternative is Mode C\n * ({@link ./resolveDragTarget resolveDragTarget}). Returns `null` when nothing\n * matches (caller falls through to top-level).\n */\nexport function findDeepestBlockAtY(\n view: EditorView,\n clientY: number,\n allowedTypes: string[],\n matchers: readonly BlockMatcher[] = [],\n options: FindDeepestBlockOptions = {},\n): DeepestBlockMatch | null {\n if (allowedTypes.length === 0) return null;\n const incumbentPos = options.incumbentPos ?? null;\n // Band only engages when there's an incumbent to be sticky about.\n const band = incumbentPos !== null ? Math.max(0, options.hysteresisBand ?? 0) : 0;\n let best: DeepestBlockMatch | null = null;\n view.state.doc.descendants((node, pos, parent, index) => {\n const dom = view.nodeDOM(pos);\n if (!(dom instanceof HTMLElement)) return true;\n const rect = dom.getBoundingClientRect();\n // Prune the subtree when the cursor is outside this node (walk stays\n // O(depth)). Widened by `band` so the incumbent's ancestors stay walkable.\n if (clientY < rect.top - band || clientY > rect.bottom + band) return false;\n if (allowedTypes.includes(node.type.name)) {\n if (matchers.length > 0 && isRejectedByMatchers(view, node, pos, parent, index, matchers)) {\n return true;\n }\n // Normal candidates must strictly contain the cursor; the incumbent wins\n // within the banded extent. Ranking still uses the real height.\n const strictlyContains = clientY >= rect.top && clientY <= rect.bottom;\n const incumbentContains =\n pos === incumbentPos && clientY >= rect.top - band && clientY <= rect.bottom + band;\n if ((strictlyContains || incumbentContains) && (best === null || rect.height < best.rect.height)) {\n best = { node, pos, dom, rect };\n }\n }\n return true;\n });\n return best;\n}\n\nfunction isRejectedByMatchers(\n view: EditorView,\n node: Node,\n pos: number,\n parent: Node | null,\n index: number,\n matchers: readonly BlockMatcher[],\n): boolean {\n const $pos = view.state.doc.resolve(pos);\n const candidate: BlockCandidate = {\n block: node,\n documentPos: pos,\n // `pos` sits right BEFORE `node`, so $pos.depth is the parent's depth and\n // `node` lives one level deeper.\n treeDepth: $pos.depth + 1,\n container: parent,\n positionInContainer: index,\n isFirstChild: index === 0,\n isLastChild: parent !== null ? index === parent.childCount - 1 : true,\n resolvedPos: $pos,\n editorView: view,\n };\n for (const matcher of matchers) {\n if (matcher.test(candidate) === 'reject') return true;\n }\n return false;\n}\n","import type { Node } from '@domternal/pm/model';\n\n/**\n * Walks up from `[from, to]` widening the range while removing the source from\n * each ancestor would leave it effectively empty. Stops at the first ancestor\n * with meaningful sibling content (or the doc root). Shared by `moveBlock` and\n * `deleteBlock`. Without it:\n *\n * - Move: dragging the only `<li>` out of a nested `<ul>` leaves PM fitting an\n * empty `<li>` placeholder to satisfy `bulletList -> listItem+`.\n * - Delete: deleting the only listItem either leaves that placeholder or (worse,\n * per fitter) unwraps and silently deletes the whole list.\n *\n * Two collapse cases:\n *\n * 1. Single-child wrapper (`block+`): parent holds only the source; walking up\n * removes the empty wrapper outright.\n * 2. Single-meaningful-child wrapper (Notion-strict `paragraph block*` list\n * items): parent holds the source plus an auto-injected empty filler\n * paragraph (PM prepends one to keep the item schema-valid). Treating that\n * filler as discardable keeps the chain collapsing as under `block+`.\n */\nexport function expandToEmptyWrappers(\n doc: Node,\n from: number,\n to: number,\n): { from: number; to: number } {\n let curFrom = from;\n let curTo = to;\n let $pos = doc.resolve(curFrom);\n while ($pos.depth > 0 && isCollapsibleParent($pos.node($pos.depth), $pos.index($pos.depth))) {\n curFrom = $pos.before($pos.depth);\n curTo = $pos.after($pos.depth);\n $pos = doc.resolve(curFrom);\n }\n return { from: curFrom, to: curTo };\n}\n\n/**\n * Parent collapses if removing the source leaves no meaningful content.\n * `sourceIndex` locates the source among the parent's children so we can find\n * the OTHER child when checking for a filler paragraph.\n */\nfunction isCollapsibleParent(parent: Node, sourceIndex: number): boolean {\n if (parent.childCount === 1) return true;\n if (parent.childCount !== 2) return false;\n const otherIndex = sourceIndex === 0 ? 1 : 0;\n const other = parent.child(otherIndex);\n return other.type.name === 'paragraph' && other.content.size === 0;\n}\n","import { canJoin } from '@domternal/pm/transform';\nimport type { Transaction } from '@domternal/pm/state';\n\nconst LIST_WRAPPER_TYPES = new Set(['bulletList', 'orderedList', 'taskList']);\n\n/**\n * Joins two list wrappers that ended up directly adjacent at `seam` (a position\n * in the CURRENT `tr.doc`, already mapped through any prior steps by the caller).\n * Restricted to two wrappers of the SAME type: a bullet and an ordered list share\n * `listItem` content and would otherwise `canJoin`, silently converting one kind\n * into the other. Adjacent paragraphs are joinable too, but merging them on a\n * reorder/delete would be wrong, hence the wrapper gate.\n *\n * `tr.join` keeps the FIRST wrapper's attrs, so a stale ordered-list `start` on\n * the second half is discarded and numbering stays continuous. Shared by\n * `moveBlock`, `moveBlockAsNestedChild`, and `deleteBlock` so every gesture that\n * can leave two same-type lists touching heals them the same way.\n */\nexport function rejoinAtSeam(tr: Transaction, seam: number): void {\n if (seam <= 0 || seam >= tr.doc.content.size) return;\n const $seam = tr.doc.resolve(seam);\n const before = $seam.nodeBefore;\n const after = $seam.nodeAfter;\n if (!before || !after) return;\n if (before.type !== after.type) return;\n if (!LIST_WRAPPER_TYPES.has(before.type.name)) return;\n if (canJoin(tr.doc, seam)) tr.join(seam);\n}\n","import { Fragment } from '@domternal/pm/model';\nimport type { ResolvedPos } from '@domternal/pm/model';\nimport type { Transaction } from '@domternal/pm/state';\nimport { expandToEmptyWrappers } from './expandToEmptyWrappers.js';\nimport { rejoinAtSeam } from './rejoinAtSeam.js';\n\nconst LIST_ITEM_TYPES = new Set(['listItem', 'taskItem']);\nconst LIST_WRAPPER_TYPES = new Set(['bulletList', 'orderedList', 'taskList']);\n\n/**\n * Move a top-level block from `sourcePos` to `targetPos` in-place. Single source\n * of truth for block reorder position math (BlockHandle drag-drop, KeyboardReorder).\n *\n * A list item keeps its OWN list kind everywhere (Notion: kind travels with the\n * block, never with the destination). It JOINS only a list of the same kind;\n * dropped into a list of a different kind, or at a non-list gap, it is re-wrapped\n * in a fresh same-kind list (so a numbered item among bullets stays its own\n * one-item ordered list). A non-list block dropped at a sibling gap inside a list\n * splits the list around it (see `insertBlockSplittingList`). The deletion range\n * first expands outward to swallow single-child wrapper ancestors (else PM's\n * fitter leaves an empty `<li>` placeholder). Same-type lists left touching after\n * the move are healed by `rejoinAtSeam` at both the source seam and the\n * destination. Self-drops (target inside the expanded deletion range) return the\n * transaction unchanged.\n */\nexport function moveBlock(\n tr: Transaction,\n sourcePos: number,\n targetPos: number,\n): Transaction {\n if (sourcePos < 0 || sourcePos >= tr.doc.content.size) return tr;\n const sourceNode = tr.doc.nodeAt(sourcePos);\n if (!sourceNode) return tr;\n const sourceEnd = sourcePos + sourceNode.nodeSize;\n // The source item's OWN list wrapper type, captured before the delete: a list\n // item keeps this kind when dropped into a different-kind list or at a non-list\n // gap, instead of adopting the destination's kind.\n const sourceWrapperType = tr.doc.resolve(sourcePos).parent.type;\n\n const { from, to } = expandToEmptyWrappers(tr.doc, sourcePos, sourceEnd);\n if (targetPos >= from && targetPos <= to) return tr;\n\n const stepsBefore = tr.steps.length;\n // Slice ONLY the source node, not the redundant single-child wrappers we're\n // about to remove (they shouldn't travel with the source to its new location).\n const slice = tr.doc.slice(sourcePos, sourceEnd);\n tr.delete(from, to);\n const adjustedTarget = targetPos > from\n ? targetPos - (to - from)\n : targetPos;\n\n const $target = tr.doc.resolve(adjustedTarget);\n const targetParent = $target.parent;\n\n // A list item JOINS only a list of its OWN kind (same wrapper type). Every\n // other case keeps the item's kind: a different-kind list splits around a fresh\n // same-kind wrapper, a non-list block splits the list directly. A matching-kind\n // item (and any non-list-gap target) falls through to the join/insert branch.\n const targetWrapperName = LIST_WRAPPER_TYPES.has(targetParent.type.name) ? targetParent.type.name : null;\n const sourceIsListItem = LIST_ITEM_TYPES.has(sourceNode.type.name);\n const splitsList = targetWrapperName !== null\n && (!sourceIsListItem || sourceWrapperType.name !== targetWrapperName);\n if (splitsList) {\n const content = sourceIsListItem\n ? Fragment.from(sourceWrapperType.create(null, slice.content))\n : slice.content;\n insertBlockSplittingList(tr, $target, content);\n } else {\n // Same-kind list item joins as a sibling. A list item dropped at a NON-list\n // gap (top-level, blockquote, children zone) keeps its kind as a fresh\n // one-item list instead of letting PM's fitter pick a wrapper by schema\n // registration order. Other blocks insert as-is.\n const adaptedContent = sourceIsListItem && targetWrapperName === null\n ? Fragment.from(sourceWrapperType.create(null, slice.content))\n : slice.content;\n tr.insert(adjustedTarget, adaptedContent);\n // Destination heal: a same-kind list dropped flush against another merges\n // into one run (whole-list reorder, or a re-wrapped item beside its old\n // list). Trailing edge first so the leading edge position stays valid.\n rejoinAtSeam(tr, adjustedTarget + adaptedContent.size);\n rejoinAtSeam(tr, adjustedTarget);\n }\n\n // Source-seam heal: removing the block may leave two same-type lists touching\n // where it sat (e.g. a heading that split a list in two, dragged back out),\n // clearing any stale ordered-list `start` on the second half.\n rejoinAtSeam(tr, tr.mapping.slice(stepsBefore).map(from));\n return tr;\n}\n\n/**\n * Inserts `content` (the dragged block, type preserved) at the sibling gap\n * `$gap` points at inside a list wrapper, splitting the wrapper so the block\n * lands at its PARENT level (the document or enclosing list item). The list\n * breaks around the block (Notion behaviour).\n *\n * - gap before the first item -> insert before the whole wrapper\n * - gap after the last item -> insert after the whole wrapper\n * - gap between two items -> split the wrapper, insert in between\n *\n * The trailing half of a split ordered list restarts at 1 (Notion breaks a\n * numbered run at any interrupter), which is just the default `start` PM's split\n * copies; no renumbering is applied. Exported for SmartPaste, which splits the\n * host list the same way when a pasted block can't join it. Returns the position\n * right before the inserted content (for caret placement).\n */\nexport function insertBlockSplittingList(tr: Transaction, $gap: ResolvedPos, content: Fragment): number {\n const wrapper = $gap.parent;\n const index = $gap.index();\n if (index === 0) {\n const at = $gap.before();\n tr.insert(at, content);\n return at;\n }\n if (index === wrapper.childCount) {\n const at = $gap.after();\n tr.insert(at, content);\n return at;\n }\n const splitPos = $gap.pos;\n tr.split(splitPos, 1);\n const at = splitPos + 1;\n tr.insert(at, content);\n return at;\n}\n","import { Fragment } from '@domternal/pm/model';\nimport type { Node as PMNode } from '@domternal/pm/model';\nimport type { Transaction } from '@domternal/pm/state';\nimport { insertAsListItemChild } from '@domternal/core';\nimport { expandToEmptyWrappers } from './expandToEmptyWrappers.js';\nimport { rejoinAtSeam } from './rejoinAtSeam.js';\n\nconst LIST_ITEM_TYPES = new Set(['listItem', 'taskItem']);\n\n/**\n * Moves the block at `sourcePos` into the list item at `targetItemPos` (wrapper\n * `wrapperPos`) at `childIndex` (default: append last). Used by `performBlockDrop`\n * for `mode: 'nested'`.\n *\n * A non-list block inserts directly; a listItem/taskItem keeps its OWN list kind\n * (Notion: nesting never changes type, and a to-do keeps its checked state) by\n * being wrapped in a fresh same-kind list, then merged with an adjacent\n * same-kind sublist so it doesn't form a redundant second list. Returns `false`\n * (no mutation) on invalid source, self-drop, or schema reject.\n */\nexport function moveBlockAsNestedChild(\n tr: Transaction,\n sourcePos: number,\n wrapperPos: number,\n targetItemPos: number,\n childIndex?: number,\n): boolean {\n if (sourcePos < 0 || sourcePos >= tr.doc.content.size) return false;\n const sourceNode = tr.doc.nodeAt(sourcePos);\n if (!sourceNode) return false;\n const sourceEnd = sourcePos + sourceNode.nodeSize;\n\n // Self-drop guard: don't move A into its own subtree.\n if (targetItemPos >= sourcePos && targetItemPos < sourceEnd) return false;\n if (wrapperPos >= sourcePos && wrapperPos < sourceEnd) return false;\n\n // The source item's OWN list wrapper type: a list item keeps its kind (and a\n // to-do keeps its checked state) when nested, instead of adopting the target's.\n const sourceWrapperType = tr.doc.resolve(sourcePos).parent.type;\n\n const stepsBefore = tr.steps.length;\n // Widen the deletion so a single-child wrapper collapses with the source.\n const { from: expandedFrom, to: expandedTo } = expandToEmptyWrappers(tr.doc, sourcePos, sourceEnd);\n\n // A list-item source is wrapped in a fresh list of its OWN kind (the item slot\n // expects a block, not a bare listItem); other blocks go in as-is.\n let blockNode: PMNode;\n const wrapped = LIST_ITEM_TYPES.has(sourceNode.type.name);\n if (wrapped) {\n blockNode = sourceWrapperType.create(null, Fragment.from(sourceNode));\n } else {\n blockNode = sourceNode;\n }\n\n const result = insertAsListItemChild({\n tr,\n wrapperPos,\n targetItemPos,\n blockNode,\n sourceRange: { from: expandedFrom, to: expandedTo },\n // Spread: exactOptionalPropertyTypes forbids passing `childIndex: undefined`.\n ...(childIndex !== undefined ? { childIndex } : {}),\n });\n if (!result.ok || result.insertedAt === undefined) return result.ok;\n\n // Merge with an adjacent same-KIND sublist instead of forming a second list.\n // `rejoinAtSeam` gates on equal wrapper types, so an ordered sublist nested\n // beside a bullet one is NOT silently re-converted (both share `listItem`\n // content, so a bare `canJoin` would merge them). Trailing boundary first\n // (higher pos) so the leading one stays valid.\n if (wrapped) {\n rejoinAtSeam(tr, result.insertedAt + blockNode.nodeSize);\n rejoinAtSeam(tr, result.insertedAt);\n }\n\n // Source-seam heal: removing the source may leave two same-type lists touching\n // where it sat (matches moveBlock; e.g. a to-do lifted out of a bullet run).\n rejoinAtSeam(tr, tr.mapping.slice(stepsBefore).map(expandedFrom));\n return true;\n}\n","import type { Node, ResolvedPos } from '@domternal/pm/model';\nimport type { EditorView } from '@domternal/pm/view';\n\nconst LIST_ITEM_TYPES = new Set(['listItem', 'taskItem']);\nconst LIST_WRAPPER_TYPES = new Set(['bulletList', 'orderedList', 'taskList']);\n\n/** Indent per nesting level (px), used as the X guide for the deepest nest option. */\nexport const DROP_SLOT_INDENT_PX = 24;\n\n/**\n * One visible drop row: a top-level block, or the LABEL row of a list/task item\n * (its content row, excluding nested children which are their own rows). Emitted\n * in document order, which equals visual top-to-bottom for normal flow content.\n */\nexport interface DropRow {\n /** Position right BEFORE the block/item node (nodeAt convention). */\n pos: number;\n /** `pos + node.nodeSize` (end of the whole subtree, including nested children). */\n end: number;\n node: Node;\n /** A list/task item (vs a plain top-level block). */\n isItem: boolean;\n /** List-nesting level: 0 = top-level block, 1 = top-level list item, 2 = nested once, ... */\n level: number;\n /** Client-coord rect of the ROW (the label row for items, the block rect otherwise). */\n top: number;\n bottom: number;\n /** Client-coord left edge of the row (the item's marker left, used as the indent guide). */\n left: number;\n /** Client-coord right edge of the row's content column (drives indicator width). */\n right: number;\n}\n\n/**\n * Collect every drop row in document order. List items contribute their LABEL\n * row (parent item and nested children are distinct rows); nested wrappers are\n * recursed into. Rows whose DOM is missing are skipped. With `nestedEnabled =\n * false` (top-level-only mode) list wrappers stay one row and aren't descended.\n */\nexport function collectRows(view: EditorView, nestedEnabled = true): DropRow[] {\n const rows: DropRow[] = [];\n const doc = view.state.doc;\n\n const pushItem = (itemPos: number, item: Node, level: number): void => {\n const itemDom = view.nodeDOM(itemPos);\n const labelDom = view.nodeDOM(itemPos + 1); // child 0 = label paragraph\n const rectEl = labelDom instanceof HTMLElement ? labelDom : itemDom;\n if (!(rectEl instanceof HTMLElement) || !(itemDom instanceof HTMLElement)) return;\n const labelRect = rectEl.getBoundingClientRect();\n const itemRect = itemDom.getBoundingClientRect();\n rows.push({\n pos: itemPos,\n end: itemPos + item.nodeSize,\n node: item,\n isItem: true,\n level,\n top: labelRect.top,\n bottom: labelRect.bottom,\n left: itemRect.left,\n right: itemRect.right,\n });\n // Recurse into nested list wrappers among the item's children.\n let childPos = itemPos + 1;\n for (let j = 0; j < item.childCount; j++) {\n const child = item.child(j);\n if (LIST_WRAPPER_TYPES.has(child.type.name)) walkWrapper(childPos, child, level + 1);\n childPos += child.nodeSize;\n }\n };\n\n function walkWrapper(wrapperPos: number, wrapper: Node, level: number): void {\n let itemPos = wrapperPos + 1;\n for (let i = 0; i < wrapper.childCount; i++) {\n const item = wrapper.child(i);\n if (LIST_ITEM_TYPES.has(item.type.name)) pushItem(itemPos, item, level);\n itemPos += item.nodeSize;\n }\n }\n\n let pos = 0;\n for (let i = 0; i < doc.childCount; i++) {\n const node = doc.child(i);\n if (nestedEnabled && LIST_WRAPPER_TYPES.has(node.type.name)) {\n walkWrapper(pos, node, 1);\n } else {\n const dom = view.nodeDOM(pos);\n if (dom instanceof HTMLElement) {\n const r = dom.getBoundingClientRect();\n rows.push({ pos, end: pos + node.nodeSize, node, isItem: false, level: 0, top: r.top, bottom: r.bottom, left: r.left, right: r.right });\n }\n }\n pos += node.nodeSize;\n }\n return rows;\n}\n\n/** How to perform the insertion for a chosen slot option. */\nexport type DropSlotInsert =\n /** Insert AT an absolute position (between siblings / top-level). */\n | { kind: 'sibling'; pos: number }\n /** Insert as a child of `targetItemPos` (in `wrapperPos`) at `childIndex` (>= 1; 0 is the label). */\n | { kind: 'nested'; wrapperPos: number; targetItemPos: number; childIndex: number };\n\n/** One depth option at a gap, shallow (small level) to deep (large level). */\nexport interface DropSlotOption {\n level: number;\n /** Client-X where the line starts AND the X threshold to select this option (they coincide). */\n lineLeft: number;\n /** Indicator line width (px). */\n lineWidth: number;\n insert: DropSlotInsert;\n}\n\nexport interface DropSlot {\n /** Client-Y of the indicator line (the gap boundary). */\n gapY: number;\n /** The chosen option (by cursor X). */\n option: DropSlotOption;\n /** All options at this gap, shallow to deep. */\n options: DropSlotOption[];\n /** Upper/lower row positions bounding the gap (null at doc edges); for hysteresis. */\n upperPos: number | null;\n lowerPos: number | null;\n}\n\n/** Last dragover's resolved gap + depth, for the stickiness dead-bands. */\nexport interface DropSlotIncumbent {\n upperPos: number | null;\n lowerPos: number | null;\n level: number | null;\n}\n\n/** Find the row whose rect contains `clientY`, else the nearest by vertical distance. */\nfunction nearestRow(rows: DropRow[], clientY: number): number {\n let best = -1;\n let bestDist = Infinity;\n for (let i = 0; i < rows.length; i++) {\n const r = rows[i];\n if (!r) continue;\n if (clientY >= r.top && clientY <= r.bottom) return i;\n const d = clientY < r.top ? r.top - clientY : clientY - r.bottom;\n if (d < bestDist) {\n bestDist = d;\n best = i;\n }\n }\n return best;\n}\n\nfunction siblingOption(row: DropRow, insertPos: number, level: number): DropSlotOption {\n return {\n level,\n lineLeft: row.left,\n lineWidth: Math.max(0, row.right - row.left),\n insert: { kind: 'sibling', pos: insertPos },\n };\n}\n\n/**\n * Options for inserting AFTER `upper` (which ends at this gap): a sibling after\n * it at its level, then one per ancestor that is a LAST child (drag-left\n * outdent), all sharing the gap's Y since a last-child's bottom edge coincides\n * with its ancestor's. Stops at the top-level list item (no full escape out of\n * lists). Plain top-level blocks yield a single option.\n */\nfunction closeChain(view: EditorView, upper: DropRow): DropSlotOption[] {\n const doc = view.state.doc;\n if (!upper.isItem) return [siblingOption(upper, upper.end, 0)];\n\n const opts: DropSlotOption[] = [];\n const $: ResolvedPos = doc.resolve(upper.pos + 1); // inside the item; node($.depth) === item\n let depth = $.depth;\n let level = upper.level;\n while (depth >= 1) {\n const item = $.node(depth);\n if (!LIST_ITEM_TYPES.has(item.type.name)) break;\n const itemPos = $.before(depth);\n const dom = view.nodeDOM(itemPos);\n const rect = dom instanceof HTMLElement ? dom.getBoundingClientRect() : null;\n const left = rect ? rect.left : upper.left;\n const right = rect ? rect.right : upper.right;\n opts.push({\n level,\n lineLeft: left,\n lineWidth: Math.max(0, right - left),\n insert: { kind: 'sibling', pos: itemPos + item.nodeSize },\n });\n // Outdent only while this item is the LAST child of its wrapper and that\n // wrapper is itself inside a parent list item.\n if ($.index(depth - 1) !== $.node(depth - 1).childCount - 1) break;\n if (depth - 2 < 0 || !LIST_ITEM_TYPES.has($.node(depth - 2).type.name)) break;\n depth -= 2;\n level -= 1;\n }\n return opts;\n}\n\n/** The deepest option: nest the dragged block INTO `item` at `childIndex`. */\nfunction nestOption(view: EditorView, item: DropRow, childIndex: number, indentStep: number): DropSlotOption | null {\n const doc = view.state.doc;\n const $item = doc.resolve(item.pos);\n if (!LIST_WRAPPER_TYPES.has($item.parent.type.name)) return null;\n const wrapperPos = $item.before();\n const lineLeft = item.left + indentStep;\n return {\n level: item.level + 1,\n lineLeft,\n lineWidth: Math.max(0, item.right - lineLeft),\n insert: { kind: 'nested', wrapperPos, targetItemPos: item.pos, childIndex },\n };\n}\n\n/** Child index for appending as `item`'s LAST child (one past its block children). */\nfunction lastChildIndex(view: EditorView, item: DropRow): number {\n const node = view.state.doc.nodeAt(item.pos);\n return node ? node.childCount : 1;\n}\n\n/**\n * Client-X column + type of the list WRAPPER that `insertPos` falls inside.\n * A block that SPLITS the list lands at the wrapper's parent content column;\n * since a wrapper's box starts at its container's content-left, the wrapper's\n * own rect IS that column. Null when `insertPos` isn't directly in a wrapper.\n */\nfunction wrapperColumn(view: EditorView, insertPos: number): { left: number; width: number; type: string } | null {\n const $p = view.state.doc.resolve(insertPos);\n if (!LIST_WRAPPER_TYPES.has($p.parent.type.name)) return null;\n const dom = view.nodeDOM($p.before());\n if (!(dom instanceof HTMLElement)) return null;\n const r = dom.getBoundingClientRect();\n return { left: r.left, width: Math.max(0, r.right - r.left), type: $p.parent.type.name };\n}\n\n/** Dedup options sharing the same resolved insertion target; keep the shallowest. */\nfunction dedupeOptions(options: (DropSlotOption | null)[]): DropSlotOption[] {\n const seen = new Set<string>();\n const out: DropSlotOption[] = [];\n for (const o of options.filter((x): x is DropSlotOption => x !== null).sort((a, b) => a.level - b.level)) {\n const i = o.insert;\n const key = i.kind === 'sibling'\n ? `s:${String(i.pos)}`\n : `n:${String(i.targetItemPos)}:${String(i.childIndex)}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(o);\n }\n return out;\n}\n\nexport interface ResolveDropSlotArgs {\n view: EditorView;\n clientX: number;\n clientY: number;\n /** Precomputed rows (collected once per dragover); falls back to `collectRows`. */\n rows?: DropRow[];\n /** Pixels of indent for the deepest (nest-into-item) option. */\n indentStep?: number;\n /** Whether to descend into lists (resolve individual items vs whole lists). */\n nestedEnabled?: boolean;\n /** Whether the deepest \"nest into the item\" option is offered (nestThreshold > 0). */\n offerNest?: boolean;\n /**\n * The dragged source's list WRAPPER type, driving sibling-column geometry:\n * - `undefined`: keep the list-item column for every sibling (stateless callers).\n * - `null` (non-list block): every in-list sibling draws at the list's PARENT\n * column, since the block splits the list and lifts out.\n * - `'bulletList'` / `'orderedList'` / `'taskList'`: a sibling over a list of the\n * SAME kind JOINS (keeps the item column); a different kind (e.g. an ordered\n * item over a bullet list) SPLITS and draws at the parent column. Matches\n * `moveBlock`, which keeps a list item's own kind across a cross-kind drop.\n */\n sourceWrapperName?: string | null;\n /** Previous dragover's gap + depth, for the stickiness dead-bands. */\n incumbent?: DropSlotIncumbent | null;\n /** Y dead-band (px) around a row's mid so the gap doesn't flip on a wobble; 0 disables. */\n bandY?: number;\n /** X dead-band (px) around a depth guide so the level doesn't flicker; 0 disables. */\n bandX?: number;\n}\n\n/**\n * Gap-first drop resolver. Cursor Y picks the nearest gap between rows; cursor X\n * picks the depth among the options available at that gap (nest deeper rightward,\n * outdent leftward, but only where a shallower boundary really coincides). The\n * indicator always sits at the gap near the cursor, never jumping to a distant\n * list edge. Returns `null` for an empty document.\n */\nexport function resolveDropSlot(args: ResolveDropSlotArgs): DropSlot | null {\n const { view, clientX, clientY } = args;\n const indentStep = args.indentStep ?? DROP_SLOT_INDENT_PX;\n const nestedEnabled = args.nestedEnabled ?? true;\n const offerNest = (args.offerNest ?? true) && nestedEnabled;\n const incumbent = args.incumbent ?? null;\n const bandY = args.bandY ?? 0;\n const bandX = args.bandX ?? 0;\n const sourceWrapperName = args.sourceWrapperName;\n const rows = args.rows ?? collectRows(view, nestedEnabled);\n if (rows.length === 0) return null;\n\n const idx = nearestRow(rows, clientY);\n if (idx < 0) return null;\n const row = rows[idx];\n if (!row) return null;\n\n // Y dead-band: near the row's mid (before/after flip point) hold the\n // incumbent side so a wobble can't swap the resolved gap.\n const rowMid = (row.top + row.bottom) / 2;\n let after = clientY >= rowMid;\n if (bandY > 0 && incumbent && Math.abs(clientY - rowMid) <= bandY) {\n if (incumbent.upperPos === row.pos) after = true;\n else if (incumbent.lowerPos === row.pos) after = false;\n }\n const upper = after ? row : rows[idx - 1] ?? null;\n const lower = after ? rows[idx + 1] ?? null : row;\n const gapY = upper?.bottom ?? lower?.top ?? row.bottom;\n\n let options: DropSlotOption[];\n if (upper && lower && lower.pos < upper.end) {\n // `lower` is inside `upper`'s subtree: the gap sits between the upper item's\n // label and its first nested child. `upper` doesn't close here, so the\n // shallowest option is a sibling before `lower` (stays nested); deeper nests\n // into `lower`. No outdent offered here.\n options = dedupeOptions([\n siblingOption(lower, lower.pos, lower.level),\n lower.isItem && offerNest ? nestOption(view, lower, 1, indentStep) : null,\n ]);\n } else {\n options = dedupeOptions([\n ...(upper ? closeChain(view, upper) : []),\n lower ? siblingOption(lower, lower.pos, lower.level) : null,\n upper?.isItem && offerNest ? nestOption(view, upper, lastChildIndex(view, upper), indentStep) : null,\n ]);\n }\n if (options.length === 0) return null;\n\n // A sibling drop that SPLITS the list lifts the block out, so its line + X\n // guide sit at the wrapper's PARENT column, not the bullet-indented item\n // column. A sibling that JOINS (same list kind) keeps the item column.\n // Insert position is unchanged (`moveBlock` does the split); nest is untouched.\n if (sourceWrapperName !== undefined) {\n options = options.map((o) => {\n if (o.insert.kind !== 'sibling') return o;\n const col = wrapperColumn(view, o.insert.pos);\n if (!col) return o;\n const joins = sourceWrapperName !== null && sourceWrapperName === col.type;\n return joins ? o : { ...o, lineLeft: col.left, lineWidth: col.width };\n });\n }\n\n // Pick the deepest option whose indent guide X has reached; floor at the\n // shallowest when X is left of every guide (the common gutter drag).\n const byGuide = [...options].sort((a, b) => a.lineLeft - b.lineLeft);\n let chosen = byGuide[0];\n if (!chosen) return null;\n for (const o of byGuide) {\n if (clientX >= o.lineLeft) chosen = o;\n }\n\n // X dead-band: hold the incumbent level within `bandX` of the guide boundary\n // to the freshly chosen level, so depth doesn't flicker.\n if (bandX > 0 && incumbent && incumbent.level !== null) {\n const inc = byGuide.find((o) => o.level === incumbent.level);\n if (inc && inc !== chosen && Math.abs(chosen.level - inc.level) === 1) {\n const deeper = chosen.lineLeft >= inc.lineLeft ? chosen : inc;\n if (Math.abs(clientX - deeper.lineLeft) <= bandX) chosen = inc;\n }\n }\n\n return { gapY, option: chosen, options: byGuide, upperPos: upper?.pos ?? null, lowerPos: lower?.pos ?? null };\n}\n","/**\n * Build an off-screen \"ghost\" of a block for HTML5 `dataTransfer.setDragImage`.\n *\n * The browser snapshots the passed element at call time with ambient transforms,\n * scroll offsets, and ancestor clipping; inherited styles that don't survive a\n * detached clone are lost. Workaround: deep-clone the node, then copy each\n * element's resolved `getComputedStyle().cssText` onto its clone's inline style,\n * so it paints identically when detached. The clone sits in an absolutely\n * positioned wrapper far above the viewport (invisible during the snapshot),\n * removed on dragend/drop.\n */\n\nexport interface DragGhost {\n /** Wrapper element to pass to `setDragImage`. */\n wrapper: HTMLElement;\n}\n\n/**\n * Create a styled ghost of `source` and append the wrapper to\n * `document.body`. Caller must remove the wrapper when the drag ends.\n */\nexport function createDragGhost(source: HTMLElement): DragGhost {\n const wrapper = makeWrapper(source);\n const clone = deepCloneWithStyles(source);\n wrapper.appendChild(clone);\n document.body.appendChild(wrapper);\n return { wrapper };\n}\n\nfunction makeWrapper(source: HTMLElement): HTMLElement {\n const w = document.createElement('div');\n w.setAttribute('aria-hidden', 'true');\n Object.assign(w.style, {\n position: 'absolute',\n top: '-10000px',\n left: '-10000px',\n pointerEvents: 'none',\n width: `${String(source.getBoundingClientRect().width)}px`,\n });\n return w;\n}\n\nfunction deepCloneWithStyles(source: HTMLElement): HTMLElement {\n const clone = source.cloneNode(true) as HTMLElement;\n freezeStylesIntoClone(source, clone);\n return clone;\n}\n\nfunction freezeStylesIntoClone(src: Element, dst: Element): void {\n if (src instanceof HTMLElement && dst instanceof HTMLElement) {\n dst.style.cssText = getComputedStyle(src).cssText;\n }\n const srcKids = src.children;\n const dstKids = dst.children;\n const n = Math.min(srcKids.length, dstKids.length);\n for (let i = 0; i < n; i++) {\n const s = srcKids.item(i);\n const d = dstKids.item(i);\n if (s !== null && d !== null) freezeStylesIntoClone(s, d);\n }\n}\n","/**\n * Clamp a (clientX, clientY) pair into the editor's content rect so position\n * resolution still works when the cursor is in the side gutter (where the handle\n * lives) or above/below the first/last block.\n *\n * X clamps to `view.dom.firstElementChild`'s edges (the actual content rect),\n * not `view.dom`'s padded box, so a wide editor with `padding-left: 4rem` still\n * anchors to where text lives.\n *\n * Y is clamped only when the cursor is OUTSIDE the editor's vertical span; inside\n * it passes through unchanged, else clipping the edges would hide thin nested\n * blocks like a 2px-tall hr at the very bottom. The `inset` snaps an\n * out-of-bounds cursor just inside the content edge.\n *\n * Returns `null` for an empty document (caller bails and hides the handle).\n */\nimport type { EditorView } from '@domternal/pm/view';\n\nconst DEFAULT_INSET_PX = 5;\n\nexport function clampToContent(\n view: EditorView,\n clientX: number,\n clientY: number,\n inset: number = DEFAULT_INSET_PX,\n): { x: number; y: number } | null {\n const first = view.dom.firstElementChild;\n const last = view.dom.lastElementChild;\n if (!first || !last) return null;\n\n const topRect = first.getBoundingClientRect();\n const bottomRect = last.getBoundingClientRect();\n\n // Out-of-bounds clamp ONLY: a cursor inside the vertical span keeps its exact\n // Y so nested elements at the very edge stay reachable.\n let clampedY = clientY;\n if (clientY < topRect.top) clampedY = topRect.top + inset;\n else if (clientY > bottomRect.bottom) clampedY = bottomRect.bottom - inset;\n\n // Clamp X into the first block's horizontal extent. Multi-column layouts with\n // varied widths aren't supported; fine for our linear, uniform-width schema.\n const minX = topRect.left + inset;\n const maxX = topRect.right - inset;\n const clampedX = Math.max(minX, Math.min(clientX, maxX));\n\n return { x: clampedX, y: clampedY };\n}\n","/**\n * Gutter-bias resolution for nested drag-target selection.\n *\n * When the cursor sits near a configured edge of a candidate's rect, that\n * candidate counts as \"in the gutter\" and its rank is reduced proportionally to\n * its depth, so shallower ancestors win against deeper descendants in the gutter\n * zone. \"Deepest-match\" mode skips this bias and returns the innermost allowed\n * block under the cursor.\n */\n\n/** Cardinal edge of a candidate's bounding rect. */\nexport type GutterEdge = 'left' | 'right' | 'top' | 'bottom';\n\n/**\n * Named presets for the bias config:\n * - `'left'` → ['left', 'top'] (left gutter, default)\n * - `'right'` → ['right', 'top'] (right gutter, RTL-friendly)\n * - `'both'` → ['left', 'right', 'top']\n * - `'none'` → no gutter bias (deepest match wins)\n */\nexport type GutterBiasPreset = 'left' | 'right' | 'both' | 'none';\n\nexport interface GutterBiasConfig {\n /** Edges that constitute the \"gutter\" zone. */\n edges: GutterEdge[];\n /** Pixel distance from the edge at which the bias activates. */\n threshold: number;\n /** Bias factor applied per depth level when in the gutter. */\n strength: number;\n}\n\nconst PRESET_DEFAULT: GutterBiasConfig = {\n edges: ['left', 'top'],\n threshold: 12,\n strength: 500,\n};\n\nconst PRESET_RIGHT: GutterBiasConfig = { ...PRESET_DEFAULT, edges: ['right', 'top'] };\nconst PRESET_BOTH: GutterBiasConfig = { ...PRESET_DEFAULT, edges: ['left', 'right', 'top'] };\n\n/**\n * Resolve the user-facing `promoteOnEdge` input into a bias config, or `null`\n * when disabled (`undefined`, `false`, or `'none'`: deepest-match wins).\n */\nexport function resolveGutterBias(\n input: boolean | GutterBiasPreset | Partial<GutterBiasConfig> | undefined,\n): GutterBiasConfig | null {\n switch (input) {\n case undefined:\n case false:\n case 'none':\n return null;\n case true:\n case 'left':\n return { ...PRESET_DEFAULT };\n case 'right':\n return { ...PRESET_RIGHT };\n case 'both':\n return { ...PRESET_BOTH };\n default:\n return {\n edges: input.edges ?? PRESET_DEFAULT.edges,\n threshold: input.threshold ?? PRESET_DEFAULT.threshold,\n strength: input.strength ?? PRESET_DEFAULT.strength,\n };\n }\n}\n\n/**\n * True when `(x, y)` falls in the gutter zone: the union of strips `threshold`\n * px wide along each configured edge of `rect`.\n */\nexport function isInGutter(\n x: number,\n y: number,\n rect: DOMRect,\n config: GutterBiasConfig,\n): boolean {\n const t = config.threshold;\n for (const edge of config.edges) {\n if (edge === 'left' && x - rect.left <= t) return true;\n if (edge === 'right' && rect.right - x <= t) return true;\n if (edge === 'top' && y - rect.top <= t) return true;\n if (edge === 'bottom' && rect.bottom - y <= t) return true;\n }\n return false;\n}\n\n/**\n * Rank-weight penalty for a candidate at `depth` in the gutter zone; 0 when\n * outside the gutter.\n */\nexport function gutterBiasWeight(\n x: number,\n y: number,\n rect: DOMRect,\n depth: number,\n config: GutterBiasConfig,\n): number {\n return isInGutter(x, y, rect, config) ? config.strength * depth : 0;\n}\n","/**\n * Built-in eligibility matchers. They constrain the drag resolver to\n * user-visible block units (paragraphs, headings, list/task items, images) and\n * exclude structural plumbing (table cells, inline text, list containers whose\n * items are draggable individually). Hosts can disable them with\n * `defaultMatchers: false` and supply their own via `matchers`.\n */\nimport type { BlockMatcher } from './blockMatcher.js';\n\nconst LIST_ITEM_NODE_TYPES = new Set(['listItem', 'taskItem']);\nconst TABLE_PLUMBING_TYPES = new Set(['tableRow', 'tableCell', 'tableHeader']);\nconst OPAQUE_CONTAINER_TYPES = new Set(['details', 'detailsContent', 'blockquote']);\n\n/**\n * Reject a paragraph that is the first child of a list/task item. Dragging it\n * alone would split the item; rejecting sends the resolver up to the item itself.\n */\nconst firstChildOfListItem: BlockMatcher = {\n name: 'firstChildOfListItem',\n test(candidate) {\n if (!candidate.isFirstChild) return 'allow';\n const parent = candidate.container;\n if (parent === null) return 'allow';\n return LIST_ITEM_NODE_TYPES.has(parent.type.name) ? 'reject' : 'allow';\n },\n};\n\n/**\n * Reject a list/task container whose direct children are list items, else the\n * resolver locks onto the wrapping list near the first item's top edge.\n */\nconst listContainerSkip: BlockMatcher = {\n name: 'listContainerSkip',\n test(candidate) {\n const firstChild = candidate.block.firstChild;\n if (firstChild === null) return 'allow';\n return LIST_ITEM_NODE_TYPES.has(firstChild.type.name) ? 'reject' : 'allow';\n },\n};\n\n/**\n * Reject table-internal nodes (rows, cells, headers): the Table extension\n * manages those via its own UI; the block handle is for top-level blocks only.\n */\nconst tableInternals: BlockMatcher = {\n name: 'tableInternals',\n test(candidate) {\n if (TABLE_PLUMBING_TYPES.has(candidate.block.type.name)) return 'reject';\n if (candidate.container?.type.name === 'tableHeader') return 'reject';\n return 'allow';\n },\n};\n\n/** Reject inline-level nodes; the handle targets block-level content only. */\nconst inlineNodes: BlockMatcher = {\n name: 'inlineNodes',\n test(candidate) {\n const { block } = candidate;\n return block.isText || block.isInline ? 'reject' : 'allow';\n },\n};\n\n/**\n * Reject any block nested inside an opaque container (details / blockquote).\n * The drop resolver offers no slots INSIDE those containers (they stay\n * sibling-only), so letting their children be drag SOURCES would be a one-way\n * door: a block could be dragged OUT but never back in, silently ejecting it.\n * Rejecting both directions keeps moves reversible. The container itself (at any\n * level) stays draggable - only its contents are excluded.\n */\nconst insideOpaqueContainer: BlockMatcher = {\n name: 'insideOpaqueContainer',\n test(candidate) {\n const $pos = candidate.editorView.state.doc.resolve(candidate.documentPos);\n for (let d = $pos.depth; d >= 1; d--) {\n if (OPAQUE_CONTAINER_TYPES.has($pos.node(d).type.name)) return 'reject';\n }\n return 'allow';\n },\n};\n\nexport const DEFAULT_BLOCK_MATCHERS: readonly BlockMatcher[] = Object.freeze([\n firstChildOfListItem,\n listContainerSkip,\n tableInternals,\n inlineNodes,\n insideOpaqueContainer,\n]);\n","/**\n * Two-stage drag target resolver: filter candidates by matcher verdicts, then\n * rank survivors by depth (and optional gutter bias).\n *\n * Algorithm:\n * 1. Resolve cursor to a doc position via `posAtCoords`.\n * 2. Walk ancestors deepest (innermost) outward, checking type/container\n * constraints then every matcher's `test()`; any 'reject' drops it.\n * 3. Atom leaves (image, hr) aren't ancestors of the resolved position; they\n * live at `$pos.nodeAfter`. A separate pass adds them at depth + 1.\n * 4. Rank survivors: no gutter bias means deepest wins; with bias each rank is\n * `treeDepth - gutterPenalty` (`strength * depth` for in-gutter rects, else\n * 0). Highest rank wins; ties break by deeper depth.\n */\nimport type { Node, ResolvedPos } from '@domternal/pm/model';\nimport type { EditorView } from '@domternal/pm/view';\n\nimport type { BlockCandidate, BlockMatcher, MatchVerdict } from './blockMatcher.js';\nimport { gutterBiasWeight } from './gutterBias.js';\nimport type { GutterBiasConfig } from './gutterBias.js';\n\nexport interface ResolveDragTargetOptions {\n /** Matchers applied to every candidate. Empty array = no filtering. */\n matchers: readonly BlockMatcher[];\n /** Active gutter-bias config, or `null` to disable. */\n gutterBias: GutterBiasConfig | null;\n /** Allow-list of node type names; when non-empty, only these can be targets. */\n allowedTypes?: readonly string[];\n /**\n * Required ancestor types. When non-empty, the candidate's chain must contain\n * at least one ancestor whose type name appears here.\n */\n requiredAncestorTypes?: readonly string[];\n}\n\nexport interface DragTarget {\n pos: number;\n rect: DOMRect;\n dom: HTMLElement;\n /** Tree depth at which the target sits. */\n depth: number;\n /** Effective rank used to pick this candidate. Exposed for tests. */\n rank: number;\n /** The PM node at `pos`. */\n node: Node;\n}\n\ninterface RankedCandidate extends DragTarget {}\n\n/**\n * Find the best drag target for cursor `(x, y)`, or `null` when no candidate\n * survives the matcher pass.\n */\nexport function resolveDragTarget(\n view: EditorView,\n x: number,\n y: number,\n options: ResolveDragTargetOptions,\n): DragTarget | null {\n const coord = view.posAtCoords({ left: x, top: y });\n if (coord === null) return null;\n\n const $pos = view.state.doc.resolve(coord.pos);\n const survivors: RankedCandidate[] = [];\n\n collectAncestors($pos, view, options, survivors);\n collectAtomLeaf($pos, view, options, survivors);\n\n if (survivors.length === 0) return null;\n applyGutterBias(survivors, x, y, options.gutterBias);\n return chooseWinner(survivors);\n}\n\nfunction collectAncestors(\n $pos: ResolvedPos,\n view: EditorView,\n options: ResolveDragTargetOptions,\n out: RankedCandidate[],\n): void {\n for (let depth = $pos.depth; depth >= 1; depth--) {\n const block = $pos.node(depth);\n const documentPos = $pos.before(depth);\n const container = depth > 0 ? $pos.node(depth - 1) : null;\n const positionInContainer = depth > 0 ? $pos.index(depth - 1) : 0;\n const containerSize = container?.childCount ?? 1;\n\n if (!passesScopeFilters(block, $pos, depth, options)) continue;\n\n const candidate: BlockCandidate = {\n block,\n documentPos,\n treeDepth: depth,\n container,\n positionInContainer,\n isFirstChild: positionInContainer === 0,\n isLastChild: positionInContainer === containerSize - 1,\n resolvedPos: $pos,\n editorView: view,\n };\n\n if (rejectedByMatchers(candidate, options.matchers)) continue;\n\n const dom = view.nodeDOM(documentPos);\n if (!(dom instanceof HTMLElement)) continue;\n\n out.push({\n pos: documentPos,\n rect: dom.getBoundingClientRect(),\n dom,\n depth,\n rank: depth,\n node: block,\n });\n }\n}\n\nfunction collectAtomLeaf(\n $pos: ResolvedPos,\n view: EditorView,\n options: ResolveDragTargetOptions,\n out: RankedCandidate[],\n): void {\n const leaf = $pos.nodeAfter;\n if (leaf === null) return;\n if (!leaf.isAtom || leaf.isInline) return;\n\n const synthDepth = $pos.depth + 1;\n if (!passesScopeFilters(leaf, $pos, synthDepth, options)) return;\n\n const parent = $pos.parent;\n const positionInContainer = $pos.index();\n const containerSize = parent.childCount;\n\n const candidate: BlockCandidate = {\n block: leaf,\n documentPos: $pos.pos,\n treeDepth: synthDepth,\n container: parent,\n positionInContainer,\n isFirstChild: positionInContainer === 0,\n isLastChild: positionInContainer === containerSize - 1,\n resolvedPos: $pos,\n editorView: view,\n };\n\n if (rejectedByMatchers(candidate, options.matchers)) return;\n\n const dom = view.nodeDOM($pos.pos);\n if (!(dom instanceof HTMLElement)) return;\n\n out.push({\n pos: $pos.pos,\n rect: dom.getBoundingClientRect(),\n dom,\n depth: synthDepth,\n rank: synthDepth,\n node: leaf,\n });\n}\n\nfunction passesScopeFilters(\n block: Node,\n $pos: ResolvedPos,\n depth: number,\n options: ResolveDragTargetOptions,\n): boolean {\n const { allowedTypes, requiredAncestorTypes } = options;\n\n if (allowedTypes !== undefined && allowedTypes.length > 0) {\n if (!allowedTypes.includes(block.type.name)) return false;\n }\n\n if (requiredAncestorTypes !== undefined && requiredAncestorTypes.length > 0) {\n if (!hasMatchingAncestor($pos, depth, requiredAncestorTypes)) return false;\n }\n\n return true;\n}\n\nfunction hasMatchingAncestor(\n $pos: ResolvedPos,\n depth: number,\n acceptableTypes: readonly string[],\n): boolean {\n for (let d = depth - 1; d >= 1; d--) {\n const ancestor = $pos.node(d);\n if (acceptableTypes.includes(ancestor.type.name)) return true;\n }\n return false;\n}\n\nfunction rejectedByMatchers(\n candidate: BlockCandidate,\n matchers: readonly BlockMatcher[],\n): boolean {\n for (const matcher of matchers) {\n const verdict: MatchVerdict = matcher.test(candidate);\n if (verdict === 'reject') return true;\n }\n return false;\n}\n\nfunction applyGutterBias(\n candidates: RankedCandidate[],\n x: number,\n y: number,\n config: GutterBiasConfig | null,\n): void {\n if (config === null) return;\n for (const c of candidates) {\n const penalty = gutterBiasWeight(x, y, c.rect, c.depth, config);\n c.rank = c.depth - penalty;\n }\n}\n\nfunction chooseWinner(candidates: readonly RankedCandidate[]): DragTarget {\n // Caller guarantees `candidates.length > 0`; `reduce` keeps type narrowing\n // happy without non-null assertions on indexed access.\n return candidates.reduce((best, c) => {\n if (c.rank > best.rank) return c;\n if (c.rank === best.rank && c.depth > best.depth) return c;\n return best;\n });\n}\n","/**\n * BlockHandle Extension\n *\n * Notion-style gutter handle on the left of each top-level block, shown on\n * hover. Two buttons:\n *\n * 1. `⋮⋮` drag handle (click → opens BlockContextMenu, drag → reorder)\n * 2. `+` insert button (inserts an empty paragraph below; FloatingMenu\n * picks up the empty-line state and auto-shows its insert menu)\n *\n * This plugin owns visibility + drag + context-menu trigger; the menu UI\n * lives in `BlockContextMenu.ts`, which listens for the\n * `dm:block-context-menu-open` event dispatched here.\n *\n * Styles ship via `@domternal/theme` (`_block-handle.scss`). The plugin adds\n * a `dm-editor--has-block-handle` class so the theme can widen `.ProseMirror`\n * padding-left for gutter space inside the `overflow:hidden` wrapper.\n */\nimport { Extension, defaultIcons } from '@domternal/core';\nimport type { Editor } from '@domternal/core';\nimport { NodeSelection, Plugin, PluginKey, TextSelection } from '@domternal/pm/state';\nimport type { Transaction } from '@domternal/pm/state';\nimport type { EditorView } from '@domternal/pm/view';\nimport type { Node, Slice } from '@domternal/pm/model';\nimport { findDeepestBlockAtY } from './helpers/findTopLevelBlock.js';\nimport { moveBlock } from './helpers/moveBlock.js';\nimport { moveBlockAsNestedChild } from './helpers/moveBlockAsNestedChild.js';\nimport { resolveDropSlot, DROP_SLOT_INDENT_PX } from './helpers/dropSlots.js';\nimport { createDragGhost } from './helpers/dragGhost.js';\nimport { clampToContent } from './helpers/clampCoords.js';\nimport { resolveGutterBias } from './helpers/gutterBias.js';\nimport type { GutterBiasConfig, GutterBiasPreset } from './helpers/gutterBias.js';\nimport { DEFAULT_BLOCK_MATCHERS } from './helpers/defaultMatchers.js';\nimport { resolveDragTarget } from './helpers/resolveDragTarget.js';\nimport type { BlockMatcher } from './helpers/blockMatcher.js';\nimport { showFloatingMenu } from './FloatingMenu.js';\n\n/** Default list of nodes treated as drag-targetable when `nested: true`. */\nexport const DEFAULT_NESTED_NODES: string[] = ['listItem', 'taskItem'];\n\n/**\n * Node types that accept a nested-child drop. When the resolver lands on one\n * and `clientX` exceeds `nestThreshold` from the left edge,\n * `computeDropPlacement` returns `mode: 'nested'`. Other containers (blockquote,\n * codeBlock, details) have their own content rules and stay sibling-only.\n */\nconst LIST_ITEM_TYPES = new Set(['listItem', 'taskItem']);\n\n/**\n * Default px threshold from a list item's left edge past which a drop commits\n * to nested-child mode. Roughly the bullet/checkbox marker width (~24px) plus a\n * small buffer so the boundary sits just past the marker.\n */\nexport const DEFAULT_NEST_THRESHOLD = 28;\n\n/** Sticky Y dead-band (px) so a wobble near a nested-list boundary can't flip the resolved target. */\nexport const DROP_HYSTERESIS_Y_PX = 6;\n\n/** Sticky X dead-band (px) around `nestThreshold` so the sibling<->nested mode doesn't flicker. */\nexport const DROP_HYSTERESIS_X_PX = 8;\n\n/** Nested-indicator inset from the block's left edge; mirrors `--dm-block-children-indent` (≈24px). */\nconst NESTED_INDICATOR_INDENT_PX = 24;\n\n/**\n * Drop-zone tolerance in CSS px. The zone extends `DROP_ZONE_TOL_LEFT` past the\n * left edge (so the gutter where the handle sits counts as droppable) and\n * `DROP_ZONE_TOL` on every other edge (subpixel jitter + margins outside\n * `.dm-editor`). Hardcoded so the gate is predictable regardless of wrapper\n * styling; override via `dropIndicator: false` + your own visual.\n */\nconst DROP_ZONE_TOL_LEFT = 80;\nconst DROP_ZONE_TOL = 16;\n\nexport const blockHandlePluginKey = new PluginKey<BlockHandlePluginState>('blockHandle');\n\nexport interface BlockHandleOptions {\n /**\n * Ms to wait before hiding the handle after the mouse leaves the editor, so\n * users can move onto the handle without it vanishing.\n * @default 200\n */\n hideDelay?: number;\n /**\n * Disable drag-to-reorder while still showing the plus/drag buttons\n * (drag becomes a no-op, click opens context menu only).\n * @default false\n */\n disableDrag?: boolean;\n /**\n * Auto-scroll the nearest scrollable ancestor when dragging near the\n * top/bottom edge. Disable if the host app manages its own drag scroll.\n * @default true\n */\n autoScroll?: boolean;\n /**\n * Distance in CSS px from the top/bottom edge that triggers auto-scroll.\n * @default 48\n */\n autoScrollThreshold?: number;\n /**\n * Peak scroll speed in CSS px per frame. Ramps linearly from 0 at the\n * threshold to this value at the edge.\n * @default 18\n */\n autoScrollMaxSpeed?: number;\n /**\n * Whether the handle should resolve to nested block containers (list\n * items, task items, and optionally others) instead of always the\n * top-level block.\n *\n * - `false` - only top-level blocks are hoverable / draggable (default).\n * - `true` - list items and task items resolve individually (Notion behaviour).\n * - object - fine-grained config; see `NestedConfig`.\n *\n * @default false\n */\n nested?: boolean | NestedConfig;\n /**\n * Px threshold from a list item's LEFT edge past which a drop becomes\n * nested-child (dragged block becomes a child of that item) instead of\n * sibling. Mirrors Notion's \"drop indented = nested, drop on the marker =\n * sibling\" UX. Set to `0` to disable nested-drop (every drop is sibling).\n *\n * X-detection only fires when nested mode is on AND the target is a\n * `listItem`/`taskItem`; other containers stay sibling-only.\n *\n * @default 28\n */\n nestThreshold?: number;\n /**\n * Custom drop indicator that mirrors exactly where a handle-drag lands.\n * Replaces `prosemirror-dropcursor` for handle drags (PM's `posAtCoords` can\n * disagree with our resolver in the gutter / inter-block gap). During a drag\n * the editor gets a `dm-block-handle-dragging` class so the theme can hide\n * the native dropcursor for this drag only; non-handle drags (text selection,\n * file drops) keep it. Set `false` to use the native dropcursor.\n * @default true\n */\n dropIndicator?: boolean;\n}\n\n/**\n * Configuration for nested resolution. Backwards-compatible with the\n * earlier `{ allowedNodes }` literal - every field is optional.\n */\nexport interface NestedConfig {\n /**\n * Node type names treated as drag targets when nested mode is on.\n * @default ['listItem', 'taskItem']\n */\n allowedNodes?: string[];\n /**\n * Restrict resolution to nodes that have at least one ancestor of one\n * of these type names. Use to scope nested mode to specific structures\n * (e.g. only inside `table`). Empty / omitted → no restriction.\n */\n allowedContainers?: string[];\n /**\n * \"Promote to parent at the gutter\": within `threshold` px of a configured\n * edge, a candidate's score drops by `strength * depth`, so a shallower\n * ancestor (e.g. the wrapping list) wins near the boundary.\n *\n * - `false` / `undefined` / `'none'` → deepest match wins.\n * - `true` / `'left'` → defaults: edges `['left','top']`, threshold 12, strength 500.\n * - `'right'` / `'both'` → preset variants.\n * - object → custom config (any field optional, merged over defaults).\n *\n * @default false\n */\n promoteOnEdge?: boolean | GutterBiasPreset | Partial<GutterBiasConfig>;\n /**\n * Append custom block matchers. Default matchers still apply unless\n * `defaultMatchers: false` is also set.\n */\n matchers?: BlockMatcher[];\n /**\n * Set `false` to disable the built-in matchers (firstChildOfListItem,\n * listContainerSkip, tableInternals, inlineNodes). Almost always wanted;\n * opt out only for testing or specialised host editors.\n * @default true\n */\n defaultMatchers?: boolean;\n}\n\nexport interface BlockHandlePluginState {\n /** Absolute position of the top-level block currently under the cursor, or null. */\n hoveredPos: number | null;\n /**\n * Source position of the block being dragged (set on dragstart, cleared on\n * dragend). `handleDrop` uses it to tell whether the drop came from our handle.\n */\n draggedFrom: number | null;\n}\n\n/**\n * Minimal shape for PM's internal `view.dragging`. Assigning it tells PM a drag\n * is in progress and which slice moves; PM's default drop handler reads this.\n *\n * `node` is undocumented but critical: when present, PM's drop handler deletes\n * the old location from this selection instead of `view.state.selection`. The\n * browser can shift the selection mid-drag (e.g. user clicks elsewhere), and\n * without `node` the original block survives the drop. We set it from the\n * `NodeSelection` created on dragstart.\n */\ninterface PMViewWithDragging {\n dragging: { slice: Slice; move: boolean; node?: NodeSelection } | null;\n}\n\n/** Casts `EditorView` to expose PM's internal `dragging` field. */\nfunction asDragView(view: EditorView): PMViewWithDragging {\n return view as unknown as PMViewWithDragging;\n}\n\n/**\n * Internal, fully-resolved view of `NestedConfig`: plain arrays + optional edge\n * config so the resolver doesn't interpret presets at hover time.\n */\nexport interface NestedResolution {\n /** Allowed drag targets. Empty array → top-level-only mode. */\n allowedNodes: string[];\n /** Optional ancestor whitelist; empty array → no restriction. */\n allowedContainers: string[];\n /** Gutter bias config; `null` → deepest match wins. */\n gutterBias: GutterBiasConfig | null;\n /** Effective matcher list (defaults + user, or just user when defaults off). */\n matchers: BlockMatcher[];\n}\n\nexport interface CreateBlockHandlePluginOptions {\n pluginKey: PluginKey<BlockHandlePluginState>;\n editor: Editor;\n hideDelay: number;\n disableDrag: boolean;\n autoScroll: boolean;\n autoScrollThreshold: number;\n autoScrollMaxSpeed: number;\n nested: NestedResolution;\n dropIndicator: boolean;\n /**\n * Pixel threshold for nested-drop X-detection (see `BlockHandleOptions.nestThreshold`).\n * `0` disables nested-drop.\n */\n nestThreshold: number;\n}\n\n/**\n * Nearest ancestor of `el` that actually scrolls vertically. Returns `null`\n * when none exists, so the caller skips its RAF scroll loop and lets the\n * browser's native drag-edge autoscroll handle the page (running both\n * double-scrolls and janks).\n */\nfunction findScrollableAncestor(el: HTMLElement): HTMLElement | null {\n let cur: HTMLElement | null = el;\n while (cur) {\n const style = getComputedStyle(cur);\n const overflowY = style.overflowY;\n if ((overflowY === 'auto' || overflowY === 'scroll') && cur.scrollHeight > cur.clientHeight) {\n return cur;\n }\n cur = cur.parentElement;\n }\n return null;\n}\n\n/**\n * Finds the block under the given client coordinates.\n *\n * With allowed nested nodes, \"nested mode\" resolves the deepest allowed block\n * (list/task item) at the cursor row so users drag individual items, not the\n * whole list:\n *\n * - Mode B (deepest-match, default): spatial Y-walk via `findDeepestBlockAtY`.\n * `posAtCoords` would resolve to whatever sits at the cursor's X, which in the\n * gutter is OUTER content (inner items are indented further right). The Y-walk\n * anchors on the cursor's row regardless of X.\n * - Mode C (gutter-bias ranking): `resolveDragTarget` with gutter bias, where\n * gutter-X promotes to OUTER by design. Opt in via `promoteOnEdge`.\n *\n * With no allowed nodes (Mode A), classic behaviour: walk doc children by Y.\n */\nfunction resolveBlockAtCoords(\n view: EditorView,\n clientX: number,\n clientY: number,\n nested: NestedResolution,\n incumbentPos: number | null = null,\n): { pos: number; rect: DOMRect; dom: HTMLElement } | null {\n // Mode A - top-level only. Walk doc children by Y; X is ignored so the handle\n // still surfaces in the side gutter.\n if (nested.allowedNodes.length === 0) {\n return resolveTopLevelByY(view, clientY);\n }\n\n // Nested modes: clamp into the editor's content rect so resolution survives\n // cursor-in-gutter and above/below edges (where `posAtCoords` returns null).\n const clamped = clampToContent(view, clientX, clientY);\n if (!clamped) return null;\n\n // Mode C - gutter-bias ranking.\n if (nested.gutterBias) {\n const target = resolveDragTarget(view, clamped.x, clamped.y, {\n matchers: nested.matchers,\n gutterBias: nested.gutterBias,\n allowedTypes: nested.allowedNodes,\n requiredAncestorTypes: nested.allowedContainers,\n });\n if (target) {\n return { pos: target.pos, rect: target.rect, dom: target.dom };\n }\n // Ranking picked nothing: fall through to top-level so the handle still\n // surfaces on the outer block.\n return resolveTopLevelByY(view, clamped.y);\n }\n\n // Mode B - deepest allowed block at the cursor row (X ignored).\n // `nested.matchers` is forwarded so rejection logic (e.g. firstChildOfListItem)\n // matches Mode C: hosts adding `paragraph` to allowedNodes get label-paragraph\n // rejection for free.\n const found = findDeepestBlockAtY(view, clamped.y, nested.allowedNodes, nested.matchers, {\n incumbentPos,\n hysteresisBand: DROP_HYSTERESIS_Y_PX,\n });\n if (found) {\n return { pos: found.pos, rect: found.rect, dom: found.dom };\n }\n return resolveTopLevelByY(view, clamped.y);\n}\n\n/**\n * Top-level fallback for every mode: walk the doc's direct children and return\n * the one whose vertical range contains `clientY` (X ignored, so it resolves\n * even with the cursor outside the editor's horizontal bounds).\n *\n * When none strictly contains `clientY` (inter-block gap, above first, below\n * last), falls back to the closest top-level block by vertical distance. A prior\n * `posAtCoords({ left: 0, top })` fallback returned `null` when X=0 was outside\n * the content area, silently failing drop-in-gap. Closest-by-Y is robust and\n * matches Notion's \"drop sticks to the nearest block\" UX.\n */\nfunction resolveTopLevelByY(\n view: EditorView,\n clientY: number,\n): { pos: number; rect: DOMRect; dom: HTMLElement } | null {\n const doc = view.state.doc;\n let offset = 0;\n let closest: { pos: number; rect: DOMRect; dom: HTMLElement; dist: number } | null = null;\n for (let i = 0; i < doc.childCount; i++) {\n const child = doc.child(i);\n const dom = view.nodeDOM(offset);\n if (dom instanceof HTMLElement) {\n const rect = dom.getBoundingClientRect();\n if (clientY >= rect.top && clientY <= rect.bottom) {\n return { pos: offset, rect, dom };\n }\n const dist = clientY < rect.top ? rect.top - clientY : clientY - rect.bottom;\n if (closest === null || dist < closest.dist) {\n closest = { pos: offset, rect, dom, dist };\n }\n }\n offset += child.nodeSize;\n }\n if (closest) return { pos: closest.pos, rect: closest.rect, dom: closest.dom };\n return null;\n}\n\nconst LIST_WRAPPER_TYPE_NAMES = new Set(['bulletList', 'orderedList', 'taskList']);\n\n\ninterface ResolvedBlock { pos: number; rect: DOMRect; dom: HTMLElement }\n\n/**\n * Among the direct list-item children of the wrapper at `wrapperPos`, pick the\n * one whose row the cursor is nearest (distance 0 when strictly contained).\n */\nfunction nearestChildItem(\n view: EditorView,\n wrapperPos: number,\n wrapper: Node,\n clientY: number,\n): ResolvedBlock | null {\n let childPos = wrapperPos + 1;\n let best: { block: ResolvedBlock; dist: number } | null = null;\n for (let i = 0; i < wrapper.childCount; i++) {\n const child = wrapper.child(i);\n if (LIST_ITEM_TYPES.has(child.type.name)) {\n const dom = view.nodeDOM(childPos);\n if (dom instanceof HTMLElement) {\n const rect = dom.getBoundingClientRect();\n const dist = clientY < rect.top ? rect.top - clientY : clientY > rect.bottom ? clientY - rect.bottom : 0;\n if (best === null || dist < best.dist) best = { block: { pos: childPos, rect, dom }, dist };\n }\n }\n childPos += child.nodeSize;\n }\n return best?.block ?? null;\n}\n\n/** The direct nested list-wrapper child of the item at `itemPos`, if any. */\nfunction findNestedListChild(\n view: EditorView,\n itemPos: number,\n item: Node,\n): { pos: number; node: Node; rect: DOMRect } | null {\n let childPos = itemPos + 1;\n for (let i = 0; i < item.childCount; i++) {\n const child = item.child(i);\n if (LIST_WRAPPER_TYPE_NAMES.has(child.type.name)) {\n const dom = view.nodeDOM(childPos);\n if (dom instanceof HTMLElement) return { pos: childPos, node: child, rect: dom.getBoundingClientRect() };\n return null;\n }\n childPos += child.nodeSize;\n }\n return null;\n}\n\n/**\n * Anchor the handle on the list/task ITEM whose row the cursor is nearest,\n * descending through nesting. `findDeepestBlockAtY` resolves to the containing\n * ANCESTOR when the cursor sits in a gap between sibling items, parking the\n * handle far above; this walks down to the nearest child so it tracks the real\n * row. Stays put when the cursor is on an item's own label row.\n */\nexport function descendToNearestHoverItem(view: EditorView, resolved: ResolvedBlock, clientY: number): ResolvedBlock {\n let current = resolved;\n for (let guard = 0; guard < 20; guard++) {\n const node = view.state.doc.nodeAt(current.pos);\n if (!node) return current;\n if (LIST_WRAPPER_TYPE_NAMES.has(node.type.name)) {\n const next = nearestChildItem(view, current.pos, node, clientY);\n if (!next || next.pos === current.pos) return current;\n current = next;\n continue;\n }\n if (LIST_ITEM_TYPES.has(node.type.name)) {\n const nested = findNestedListChild(view, current.pos, node);\n // No nested list, or the cursor is on this item's own label row (above\n // the nested list): the item itself is the right anchor.\n if (!nested || clientY < nested.rect.top) return current;\n const next = nearestChildItem(view, nested.pos, nested.node, clientY);\n if (!next || next.pos === current.pos) return current;\n current = next;\n continue;\n }\n return current;\n }\n return current;\n}\n\n/** Client-coord gap rect an indicator line draws into. */\ninterface ChildGapRect {\n top: number;\n bottom: number;\n left: number;\n width: number;\n}\n\n/**\n * Resolved drop target, shared by `handleDrop` and `updateDropIndicator` so the\n * indicator draws where the drop lands. `mode` is `'sibling'` (drop via\n * `moveBlock`) or `'nested'` (child of `targetItemPos` inside `wrapperPos`).\n */\nexport interface DropPlacement {\n /** Position right BEFORE the resolved block (same convention as `nodeAt`). */\n pos: number;\n /** Bounding rect of the resolved block, used to draw the indicator line. */\n rect: DOMRect;\n /** `true` -> drop AFTER the block, `false` -> BEFORE (Y-mid). Ignored when nested. */\n insertAfter: boolean;\n /** Sibling drop vs nested-child drop. */\n mode: 'sibling' | 'nested';\n /** Target list item (nested only). */\n targetItemPos?: number;\n /** Containing list wrapper (nested only). */\n wrapperPos?: number;\n /**\n * Child index a nested drop lands at, in `[1, childCount]` (index 0 is the\n * label; `=== childCount` means append). Picks first/between/last slot.\n */\n childIndex?: number;\n /** Client-coord gap the chosen `childIndex` slot occupies (drives the line). */\n nestedGapRect?: ChildGapRect;\n /**\n * Absolute position to insert AT for a sibling drop (slot model). When set,\n * `handleDrop` uses it directly instead of deriving from `pos`/`insertAfter`.\n */\n insertPos?: number;\n /**\n * Explicit client-coord indicator line `{ top, left, width }` from the slot\n * resolver. When set, `updateDropIndicator` draws it directly instead of\n * deriving geometry from `rect`/`mode`.\n */\n indicatorLine?: { top: number; left: number; width: number };\n /** Resolved gap bounds + depth, fed back next dragover for the dead-bands. */\n gapUpperPos?: number | null;\n gapLowerPos?: number | null;\n depthLevel?: number;\n}\n\n/**\n * Per-drag hysteresis state threaded into {@link computeDropPlacement}.\n * Omitted by pure callers (tests) so the resolver stays stateless.\n */\nexport interface DropPlacementOptions {\n /** Previous dragover's gap upper/lower row, for the Y-gap dead-band. */\n incumbentUpperPos?: number | null;\n incumbentLowerPos?: number | null;\n /** Previous dragover's depth level, for the X-depth dead-band. */\n incumbentLevel?: number | null;\n /** Previous dragover's child slot, for the nested child-slot dead-band. */\n incumbentChildIndex?: number | null;\n /** Enable the dead-bands (off for unit callers, `true` from the plugin). */\n hysteresis?: boolean;\n /**\n * The dragged source's list WRAPPER type (`'bulletList'`/`'orderedList'`/\n * `'taskList'`), or `null` for a non-list block. Drives the sibling indicator\n * column: a drop that splits the list (a non-list block, or a list item of a\n * different kind) draws at the list's parent column; one that joins (same list\n * kind) keeps the item column. Omit for stateless callers. See\n * {@link resolveDropSlot}.\n */\n sourceWrapperName?: string | null;\n}\n\n/**\n * Computes the final drop placement, returned by BOTH the drop handler and the\n * indicator so the line draws where the drop lands. `null` when no candidate\n * (e.g. empty doc).\n *\n * Gap-first: {@link resolveDropSlot} picks the nearest gap by Y and the depth\n * available there by X, so the line stays near the cursor. A `nested` option is\n * refined by Y via {@link resolveChildSlot} for the child slot inside the item.\n */\nexport function computeDropPlacement(\n view: EditorView,\n clientX: number,\n clientY: number,\n nested: NestedResolution,\n nestThreshold: number = DEFAULT_NEST_THRESHOLD,\n options: DropPlacementOptions = {},\n): DropPlacement | null {\n const incumbent = options.hysteresis\n ? { upperPos: options.incumbentUpperPos ?? null, lowerPos: options.incumbentLowerPos ?? null, level: options.incumbentLevel ?? null }\n : null;\n const slot = resolveDropSlot({\n view,\n clientX,\n clientY,\n indentStep: nestThreshold > 0 ? nestThreshold : DROP_SLOT_INDENT_PX,\n nestedEnabled: nested.allowedNodes.length > 0,\n offerNest: nestThreshold > 0,\n incumbent,\n bandY: options.hysteresis ? DROP_HYSTERESIS_Y_PX : 0,\n bandX: options.hysteresis ? DROP_HYSTERESIS_X_PX : 0,\n ...(options.sourceWrapperName !== undefined ? { sourceWrapperName: options.sourceWrapperName } : {}),\n });\n if (!slot) return null;\n const opt = slot.option;\n const feedback = {\n gapUpperPos: slot.upperPos,\n gapLowerPos: slot.lowerPos,\n depthLevel: opt.level,\n };\n\n if (opt.insert.kind === 'nested') {\n const itemPos = opt.insert.targetItemPos;\n const itemNode = view.state.doc.nodeAt(itemPos);\n const itemDom = view.nodeDOM(itemPos);\n const itemRect = itemDom instanceof HTMLElement ? itemDom.getBoundingClientRect() : null;\n // Refine the child slot by cursor Y among the item's children; falls back\n // to the slot's childIndex when no rect.\n let childIndex = opt.insert.childIndex;\n let gapRect: ChildGapRect = { top: slot.gapY, bottom: slot.gapY, left: opt.lineLeft - NESTED_INDICATOR_INDENT_PX, width: opt.lineWidth + NESTED_INDICATOR_INDENT_PX };\n if (itemNode && itemRect) {\n const childBand = options.hysteresis ? DROP_HYSTERESIS_Y_PX : 0;\n const cs = resolveChildSlot(view, itemNode, itemPos, itemRect, clientY, options.incumbentChildIndex ?? null, childBand);\n childIndex = cs.childIndex;\n gapRect = cs.gapRect;\n }\n return {\n pos: itemPos,\n rect: itemRect ?? new DOMRect(opt.lineLeft, slot.gapY, opt.lineWidth, 0),\n insertAfter: false,\n mode: 'nested',\n targetItemPos: itemPos,\n wrapperPos: opt.insert.wrapperPos,\n childIndex,\n nestedGapRect: gapRect,\n indicatorLine: { top: gapRect.top, left: gapRect.left + NESTED_INDICATOR_INDENT_PX, width: Math.max(0, gapRect.width - NESTED_INDICATOR_INDENT_PX) },\n ...feedback,\n };\n }\n\n const insertPos = opt.insert.pos;\n return {\n pos: insertPos,\n rect: new DOMRect(opt.lineLeft, slot.gapY, opt.lineWidth, 0),\n insertAfter: false,\n mode: 'sibling',\n insertPos,\n indicatorLine: { top: slot.gapY, left: opt.lineLeft, width: opt.lineWidth },\n ...feedback,\n };\n}\n\n/**\n * Build the transaction a drop at `placement` would dispatch, given the dragged\n * block at `draggedFrom`. Mirrors `performBlockDrop`'s move logic (nested-child,\n * self-drop bail, sibling fallback, sibling) so both the live drop AND the\n * \"would this actually move anything?\" probe share ONE source of truth. The\n * returned transaction is left UNCHANGED when the move is a no-op (e.g. the\n * block already sits in this exact slot, or a self-drop), so callers can detect\n * it with `tr.doc.eq(view.state.doc)`.\n */\nexport function buildDropTr(\n view: EditorView,\n draggedFrom: number,\n sourceNode: Node,\n placement: DropPlacement,\n): Transaction {\n const tr = view.state.tr;\n if (\n placement.mode === 'nested'\n && placement.targetItemPos !== undefined\n && placement.wrapperPos !== undefined\n ) {\n const ok = moveBlockAsNestedChild(\n tr,\n draggedFrom,\n placement.wrapperPos,\n placement.targetItemPos,\n placement.childIndex,\n );\n if (ok) return tr;\n // Helper bailed. A SELF-drop (source/target overlap) is a no-op: leave the\n // transaction unchanged. A true schema reject (no overlap) falls through to\n // the sibling move below.\n const targetItem = view.state.doc.nodeAt(placement.targetItemPos);\n const targetItemEnd = targetItem\n ? placement.targetItemPos + targetItem.nodeSize\n : placement.targetItemPos;\n const sourceEnd = draggedFrom + sourceNode.nodeSize;\n const sourceInTarget = draggedFrom >= placement.targetItemPos && draggedFrom < targetItemEnd;\n const targetInSource = placement.targetItemPos >= draggedFrom && placement.targetItemPos < sourceEnd;\n if (sourceInTarget || targetInSource) return tr;\n }\n\n // Slot model supplies an absolute `insertPos`; legacy callers derive it.\n let targetPos = placement.insertPos;\n if (targetPos === undefined) {\n const targetNode = view.state.doc.nodeAt(placement.pos);\n const targetEnd = targetNode ? placement.pos + targetNode.nodeSize : placement.pos;\n targetPos = placement.insertAfter ? targetEnd : placement.pos;\n }\n moveBlock(tr, draggedFrom, targetPos);\n return tr;\n}\n\ninterface ChildSlot {\n /** Child-array index to insert at, in `[1, childCount]`. */\n childIndex: number;\n /** Client-coord gap the chosen slot occupies (drives the indicator line). */\n gapRect: ChildGapRect;\n}\n\n/**\n * Picks which child slot of a list item the cursor's Y lands in. `childIndex` is\n * `1 + (children whose mid-line is at/above the cursor)`, clamped to\n * `[1, childCount]` (index 0 is the label). `band > 0` keeps\n * `incumbentChildIndex` sticky within `band` px of a boundary. Degrades to\n * append-last when a rect is missing. All gaps share the item's content column.\n */\nfunction resolveChildSlot(\n view: EditorView,\n item: Node,\n itemStart: number,\n itemRect: DOMRect,\n clientY: number,\n incumbentChildIndex: number | null,\n band: number,\n): ChildSlot {\n const childCount = item.childCount;\n const gap = (top: number, bottom: number): ChildGapRect => ({\n top,\n bottom,\n left: itemRect.left,\n width: itemRect.width,\n });\n const append: ChildSlot = { childIndex: childCount, gapRect: gap(itemRect.bottom, itemRect.bottom) };\n\n // Measure each child's rect; `posAtIndex` gives the position before child i.\n const $item = view.state.doc.resolve(itemStart + 1);\n const rects: DOMRect[] = [];\n for (let i = 0; i < childCount; i++) {\n const dom = view.nodeDOM($item.posAtIndex(i, $item.depth));\n if (!(dom instanceof HTMLElement)) return append; // degrade on first missing rect\n rects.push(dom.getBoundingClientRect());\n }\n\n const label = rects[0];\n if (!label) return append;\n if (childCount === 1) return { childIndex: 1, gapRect: gap(label.bottom, label.bottom) };\n\n let index = 1;\n for (let i = 1; i < childCount; i++) {\n const r = rects[i];\n if (r && clientY >= (r.top + r.bottom) / 2) index = i + 1;\n }\n index = Math.min(Math.max(index, 1), childCount);\n\n // Dead-band: keep the incumbent within `band` px of the shared boundary.\n if (\n band > 0 &&\n incumbentChildIndex !== null &&\n incumbentChildIndex >= 1 &&\n incumbentChildIndex <= childCount &&\n Math.abs(index - incumbentChildIndex) === 1\n ) {\n const r = rects[Math.min(index, incumbentChildIndex)];\n if (r && Math.abs(clientY - (r.top + r.bottom) / 2) <= band) index = incumbentChildIndex;\n }\n\n const above = rects[index - 1];\n const below = index < childCount ? rects[index] : undefined;\n if (!above) return append;\n return { childIndex: index, gapRect: gap(above.bottom, below ? below.top : above.bottom) };\n}\n\n/**\n * Creates a standalone BlockHandle PM plugin. Exported so framework wrappers can\n * build on it without the Extension factory.\n */\nexport function createBlockHandlePlugin(\n options: CreateBlockHandlePluginOptions,\n): Plugin<BlockHandlePluginState> {\n const { pluginKey, editor, hideDelay, disableDrag, autoScroll, autoScrollThreshold, autoScrollMaxSpeed, nested, dropIndicator, nestThreshold } = options;\n\n // --- Build DOM once. Buttons use the shared Phosphor icons.\n const root = document.createElement('div');\n root.className = 'dm-block-handle';\n root.setAttribute('data-dm-editor-ui', '');\n\n const dragBtn = document.createElement('button');\n dragBtn.type = 'button';\n dragBtn.className = 'dm-block-handle-btn dm-block-handle-drag';\n dragBtn.setAttribute('aria-label', 'Drag to reorder, click for options');\n dragBtn.setAttribute('draggable', 'true');\n dragBtn.innerHTML = defaultIcons['dotsSixVertical'] ?? '';\n\n const plusBtn = document.createElement('button');\n plusBtn.type = 'button';\n plusBtn.className = 'dm-block-handle-btn dm-block-handle-plus';\n plusBtn.setAttribute('aria-label', 'Add block below');\n plusBtn.innerHTML = defaultIcons['plus'] ?? '';\n\n root.appendChild(dragBtn);\n root.appendChild(plusBtn);\n\n // --- Drop indicator: thin horizontal line at the resolved drop target during\n // a drag. Built once, hidden by default, appended into `.dm-editor`.\n const indicator = document.createElement('div');\n indicator.className = 'dm-block-drop-indicator';\n indicator.setAttribute('data-dm-editor-ui', '');\n\n let editorEl: HTMLElement | null = null;\n // Hover-capture element, usually `editorEl.parentElement` so the listener also\n // catches mouse moves in the side gutter where the handle visually sits.\n // Falls back to `editorEl` when there's no parent.\n let hoverEl: HTMLElement | null = null;\n let hideTimer: number | null = null;\n\n // Hover-tick state, rAF-coalesced so the handle stays smooth even when\n // mousemove fires ~240Hz. One rAF at a time; latest coords win.\n // `currentHoveredPos` is the identity gate: repaint only when the PM position\n // under the cursor changes, not on every micro-move within a block.\n let hoverRaf: number | null = null;\n let pendingHoverCoords: { x: number; y: number } | null = null;\n let currentHoveredPos: number | null = null;\n // Set on drag-button `mousedown`, cleared on `mouseup`/`dragend`. While truthy,\n // hover updates pause so the handle doesn't jump to a neighbour during the\n // browser's click-vs-drag window; otherwise it slides out from under the\n // cursor before `dragstart` fires (\"click and hold does nothing\").\n let dragPressActive = false;\n\n // Active drag preview wrapper, built on dragstart, removed on drop/dragend.\n let dragPreview: HTMLElement | null = null;\n\n // SYNC source position captured in `onDragStart`. Needed because PM clears\n // `view.dragging` BEFORE the `handleDrop` hook fires, AND plugin-state\n // `draggedFrom` is committed via a deferred `setTimeout(0)` (see `onDragStart`)\n // that may not have run by drop time on fast drags. Closure scope is\n // independent of both. Cleared on dragend so it never lingers.\n let pendingDraggedFrom: number | null = null;\n\n // Drop-indicator drag-session state. Like the hover path: rAF-coalesced,\n // repainted only when the line moves (`currentDropKey`). `dragHyst` carries\n // the previous resolution forward for Y/X/child-slot hysteresis, bundled so\n // every reset is atomic.\n let dropRaf: number | null = null;\n let pendingDropCoords: { x: number; y: number } | null = null;\n let currentDropKey: string | null = null;\n const dragHyst: { upperPos: number | null; lowerPos: number | null; level: number | null; childIndex: number | null } = {\n upperPos: null,\n lowerPos: null,\n level: null,\n childIndex: null,\n };\n\n const resetDragHyst = (): void => {\n dragHyst.upperPos = null;\n dragHyst.lowerPos = null;\n dragHyst.level = null;\n dragHyst.childIndex = null;\n };\n\n const resetDropState = (): void => {\n if (dropRaf !== null) {\n cancelAnimationFrame(dropRaf);\n dropRaf = null;\n }\n pendingDropCoords = null;\n currentDropKey = null;\n resetDragHyst();\n };\n\n // Auto-scroll state machine (populated during a drag, reset by\n // `resetAutoScroll`). One object so every reset clears every field.\n //\n // `lastAt` (`performance.now()`) is a dead-man switch: if no dragover arrives\n // for `DRAGOVER_SILENCE_MS`, assume the drag was cancelled (browser ate\n // dragend, OS abort) and stop the loop. 1.5s tolerates holding still mid-drag\n // yet recovers quickly when events are dropped.\n const DRAGOVER_SILENCE_MS = 1500;\n const autoScrollState: {\n raf: number | null;\n target: HTMLElement | null;\n lastClientY: number | null;\n lastAt: number;\n } = { raf: null, target: null, lastClientY: null, lastAt: 0 };\n\n const resetAutoScroll = (): void => {\n if (autoScrollState.raf !== null) {\n cancelAnimationFrame(autoScrollState.raf);\n }\n autoScrollState.raf = null;\n autoScrollState.target = null;\n autoScrollState.lastClientY = null;\n autoScrollState.lastAt = 0;\n };\n\n const clearHideTimer = (): void => {\n if (hideTimer !== null) {\n window.clearTimeout(hideTimer);\n hideTimer = null;\n }\n };\n\n const hide = (): void => {\n root.removeAttribute('data-show');\n currentHoveredPos = null;\n };\n\n const scheduleHide = (): void => {\n // Context-menu pin: same gate as `onMouseMove`.\n if (editorEl?.hasAttribute('data-block-context-menu-open')) return;\n clearHideTimer();\n hideTimer = window.setTimeout(() => {\n hide();\n hideTimer = null;\n }, hideDelay);\n };\n\n const show = (blockEl: HTMLElement, blockRect: DOMRect, editorRect: DOMRect): void => {\n // Center the handle on the block's FIRST LINE, not its top edge. For tall\n // blocks (e.g. H1 with line-height 2.8rem) the top edge sits well above the\n // text, leaving the handle floating above the title. First-line center\n // matches Notion regardless of font size.\n const cs = getComputedStyle(blockEl);\n let lineHeight = parseFloat(cs.lineHeight);\n if (!Number.isFinite(lineHeight)) {\n // `line-height: normal` returns a non-numeric string; fall back to ~1.2x\n // the font size (the browser default for `normal`).\n const fontSize = parseFloat(cs.fontSize) || 16;\n lineHeight = fontSize * 1.2;\n }\n const handleHeight = root.offsetHeight || 24;\n const offsetIntoBlock = Math.max(0, (lineHeight - handleHeight) / 2);\n const top = blockRect.top - editorRect.top + offsetIntoBlock;\n root.style.top = `${String(top)}px`;\n root.setAttribute('data-show', '');\n };\n\n const updateHoverState = (view: EditorView, pos: number | null): void => {\n const current = pluginKey.getState(view.state)?.hoveredPos ?? null;\n if (current === pos) return;\n view.dispatch(view.state.tr.setMeta(pluginKey, { hoveredPos: pos }));\n };\n\n const setDraggedFrom = (view: EditorView, pos: number | null): void => {\n view.dispatch(view.state.tr.setMeta(pluginKey, { draggedFrom: pos }));\n };\n\n // mousemove is the hottest event on the editor (240+Hz on high-refresh\n // pointers). Running `posAtCoords` + `getBoundingClientRect` + `style.top`\n // every tick causes visible wobble (each read forces sync layout). Coalescing\n // to one rAF/frame and gating reposition on PM-position identity fixes both.\n const onMouseMove = (event: MouseEvent): void => {\n if (!editorEl) return;\n // Freeze the handle while the drag button is pressed; moving it would slide\n // the button out from under the cursor before the browser commits to a drag.\n if (dragPressActive) return;\n // Pin to the source block while the BlockContextMenu is open (it's the\n // menu's visual anchor).\n if (editorEl.hasAttribute('data-block-context-menu-open')) return;\n pendingHoverCoords = { x: event.clientX, y: event.clientY };\n if (hoverRaf !== null) return;\n hoverRaf = requestAnimationFrame(() => {\n hoverRaf = null;\n const coords = pendingHoverCoords;\n pendingHoverCoords = null;\n if (!coords || !editorEl) return;\n // Re-check the pin gate: a mousemove queued pre-open can fire after\n // `open()` and otherwise reposition the handle.\n if (editorEl.hasAttribute('data-block-context-menu-open')) return;\n const initial = resolveBlockAtCoords(editor.view, coords.x, coords.y, nested);\n if (!initial) {\n scheduleHide();\n return;\n }\n // Gap hovers resolve to an ancestor; descend to the nearest leaf row.\n const resolved = descendToNearestHoverItem(editor.view, initial, coords.y);\n clearHideTimer();\n // Keep `updateHoverState` unconditional (it's a no-op when state already\n // matches): if a prior docChanged cleared `hoveredPos`, the next tick\n // re-asserts it. Skipping this caused \"click on drag handle does nothing\"\n // after a color-swatch change, since the next click bailed on null.\n updateHoverState(editor.view, resolved.pos);\n // Identity gate for the visual reposition only: skip style.top + data-show\n // when still over the same block. This is the measurable smoothness win.\n if (resolved.pos === currentHoveredPos && root.hasAttribute('data-show')) {\n return;\n }\n currentHoveredPos = resolved.pos;\n const editorRect = editorEl.getBoundingClientRect();\n show(resolved.dom, resolved.rect, editorRect);\n });\n };\n\n const onMouseLeave = (): void => {\n scheduleHide();\n };\n\n const onMouseEnter = (): void => {\n clearHideTimer();\n };\n\n const onDismissOverlays = (): void => {\n // BlockContextMenu fires this while opening to close other overlays; keep\n // the handle visible since it anchors the menu. The attribute is set by\n // `open()` before the dispatch, so its presence means \"menu opening\".\n if (editorEl?.hasAttribute('data-block-context-menu-open')) return;\n hide();\n updateHoverState(editor.view, null);\n };\n\n // --- Plus button: insert an empty paragraph after the hovered block, focus,\n // then explicitly trigger the FloatingMenu. Order matters:\n // 1. Dispatch `dm:dismiss-overlays` FIRST to close BubbleMenu / ContextMenu /\n // SlashCommand / any open FloatingMenu, before our own explicit-trigger\n // flag so the dismissal can't clear it.\n // 2. Insert the paragraph + move the caret + focus.\n // 3. `showFloatingMenu(view)` - required for instances with\n // `requireExplicitTrigger: true`; default instances auto-show anyway.\n const onPlusClick = (event: MouseEvent): void => {\n event.preventDefault();\n event.stopPropagation();\n if (!editor.isEditable) return;\n const state = pluginKey.getState(editor.view.state);\n const pos = state?.hoveredPos ?? null;\n if (pos === null) return;\n const node = editor.view.state.doc.nodeAt(pos);\n if (!node) return;\n\n const paragraphType = editor.view.state.schema.nodes['paragraph'];\n if (!paragraphType) return;\n\n // (1) Close anything else open.\n editorEl?.dispatchEvent(new Event('dm:dismiss-overlays', { bubbles: false }));\n\n // (2) Insert the paragraph + park the caret inside it.\n const blockEnd = pos + node.nodeSize;\n const tr = editor.view.state.tr;\n tr.insert(blockEnd, paragraphType.create());\n const sel = TextSelection.near(tr.doc.resolve(blockEnd + 1));\n tr.setSelection(sel);\n editor.view.dispatch(tr.scrollIntoView());\n editor.view.focus();\n\n // (3) Mark this as an explicit \"user wants the menu\" gesture.\n showFloatingMenu(editor.view);\n };\n\n // Plus button: `preventDefault` on mousedown keeps editor focus (the button\n // doesn't grab it) so the auto-appearing FloatingMenu reads the right state.\n //\n // Drag button must NOT preventDefault on mousedown: a `draggable=\"true\"`\n // element needs the default mousedown to initiate a drag, and cancelling it\n // silently kills drag-to-reorder in Chrome/Safari. Focus is restored after\n // context-menu actions via `editor.view.focus()`.\n const onPlusBtnMouseDown = (event: MouseEvent): void => {\n event.preventDefault();\n };\n\n // Lock the handle from mousedown through dragend (or mouseup without drag) so\n // the rAF hover loop can't reposition it during the click-vs-drag window.\n //\n // Mouseup is a lazy one-shot ONLY for the click-without-drag path (button\n // pressed but drag-init threshold never crossed); the dragend path calls\n // `releaseDragPress` directly. A lifetime listener (prior design) leaked a\n // global handler firing on every click in the document.\n const onDragBtnMouseDown = (): void => {\n dragPressActive = true;\n document.addEventListener('mouseup', releaseDragPress, { once: true });\n };\n const releaseDragPress = (): void => {\n dragPressActive = false;\n // dragend may fire BEFORE mouseup (the common drag-success path); remove the\n // once-listener so a later stray mouseup doesn't hit an already-released lock.\n document.removeEventListener('mouseup', releaseDragPress);\n };\n\n // --- Drag handle: click opens context menu, drag reorders the block.\n // Browser semantics: with `draggable=\"true\"`, press+release under ~3px fires\n // `click` and no `dragstart`; moving past the threshold fires `dragstart` and\n // no `click`. A free, reliable click-vs-drag split, no custom tracking needed.\n\n const onDragBtnClick = (event: MouseEvent): void => {\n event.preventDefault();\n event.stopPropagation();\n if (!editor.isEditable) return;\n const state = pluginKey.getState(editor.view.state);\n const pos = state?.hoveredPos ?? null;\n if (pos === null) return;\n // Notify the BlockContextMenu plugin; the detail carries the source block\n // and the anchor element for positioning.\n editorEl?.dispatchEvent(new CustomEvent('dm:block-context-menu-open', {\n bubbles: false,\n detail: { blockPos: pos, anchorElement: dragBtn },\n }));\n };\n\n // --- Auto-scroll during drag.\n // One RAF loop runs for the whole drag. Each frame reads the last dragover Y\n // and, when within `autoScrollThreshold` of the target's top/bottom edge,\n // nudges scroll by a ramped speed (0 at the threshold to `autoScrollMaxSpeed`\n // at the edge). Self-terminates after `DRAGOVER_SILENCE_MS` of silence, a\n // failsafe against the browser skipping `dragend` on some OS/browser combos.\n\n const onDocumentDragover = (event: DragEvent): void => {\n autoScrollState.lastClientY = event.clientY;\n autoScrollState.lastAt = performance.now();\n const inZone = isCursorOverDropZone(event.clientX, event.clientY);\n // CRITICAL: in our drop zone (incl. the gutter outside `.ProseMirror`'s\n // padding box) we MUST preventDefault on dragover, or the browser won't fire\n // `drop` on non-PM targets (notion-page, body) and the release is a silent\n // no-op. With it, drop fires and bubbles to our document drop listener.\n if (inZone) event.preventDefault();\n if (!dropIndicator) return;\n if (!inZone) {\n // Left the zone: hide and drop the hysteresis incumbents so re-entry\n // resolves fresh (no stale nest-latch across a round-trip out).\n if (dropRaf !== null) {\n cancelAnimationFrame(dropRaf);\n dropRaf = null;\n }\n pendingDropCoords = null;\n currentDropKey = null;\n resetDragHyst();\n indicator.removeAttribute('data-show');\n return;\n }\n // Coalesce the repaint to one rAF/frame; preventDefault + auto-scroll above\n // stay synchronous.\n pendingDropCoords = { x: event.clientX, y: event.clientY };\n if (dropRaf !== null) return;\n dropRaf = requestAnimationFrame(() => {\n dropRaf = null;\n const coords = pendingDropCoords;\n pendingDropCoords = null;\n if (coords) updateDropIndicator(coords.x, coords.y);\n });\n };\n\n /**\n * Document-level drop listener for drops OUTSIDE `.ProseMirror` (handle\n * gutter, notion-page padding) but INSIDE our indicator zone, where the user\n * saw a \"drop lands here\" line and expects the release to take effect.\n *\n * Bubbles after PM's own handler; if PM already handled it we see\n * `defaultPrevented === true` and bail. Otherwise (cursor in the gutter,\n * target `.notion-page` etc.) we run the same drop logic ourselves.\n */\n const onDocumentDrop = (event: DragEvent): void => {\n if (event.defaultPrevented) return;\n const view = editor.view;\n const dragging = asDragView(view).dragging;\n if (!dragging) return;\n if (!isCursorOverDropZone(event.clientX, event.clientY)) return;\n performBlockDrop(event.clientX, event.clientY);\n // Consume our own drag within the drop zone even when the drop was a no-op,\n // so the browser doesn't run a native default drop for a gutter/margin\n // release. (`performBlockDrop` returns false for a no-op now.)\n event.preventDefault();\n };\n\n /**\n * Shared drop logic, run by both PM's `handleDrop` (cursor over `.ProseMirror`)\n * and our document-level drop listener (cursor in gutter/margin but inside the\n * indicator zone). Returns `true` when a move was dispatched.\n */\n const performBlockDrop = (clientX: number, clientY: number): boolean => {\n const view = editor.view;\n const state = pluginKey.getState(view.state);\n // Tiered source-position fallback:\n // 1. Plugin state `draggedFrom` - canonical, but set via the deferred\n // dispatch in `onDragStart`, so it MAY be null on fast drops.\n // 2. `pendingDraggedFrom` - set SYNCHRONOUSLY in `onDragStart`, independent\n // of both the deferred dispatch and `view.dragging` (which PM clears\n // before the `handleDrop` hook).\n // 3. `view.dragging.node.from` - last resort for callers that fire `drop`\n // without our `onDragStart` (synthetic e2e events bypass the handle).\n const draggedFrom = state?.draggedFrom\n ?? pendingDraggedFrom\n ?? asDragView(view).dragging?.node?.from\n ?? null;\n if (draggedFrom === null) return false;\n const sourceNode = view.state.doc.nodeAt(draggedFrom);\n if (!sourceNode) return false;\n // Same hysteresis state the indicator last used, so the drop lands on the line.\n const placement = computeDropPlacement(view, clientX, clientY, nested, nestThreshold, {\n incumbentUpperPos: dragHyst.upperPos,\n incumbentLowerPos: dragHyst.lowerPos,\n incumbentLevel: dragHyst.level,\n incumbentChildIndex: dragHyst.childIndex,\n hysteresis: true,\n sourceWrapperName: LIST_ITEM_TYPES.has(sourceNode.type.name)\n ? view.state.doc.resolve(draggedFrom).parent.type.name\n : null,\n });\n if (!placement) return false;\n const tr = buildDropTr(view, draggedFrom, sourceNode, placement);\n // No-op drop (self-drop, or the block already sits in exactly this slot):\n // nothing to dispatch. `handleDrop` still consumes the event, so PM's\n // default drop never runs and the undo stack isn't polluted with a\n // do-nothing entry. The indicator is also suppressed for these slots (see\n // `updateDropIndicator`), so a release here should be rare.\n if (tr.doc.eq(view.state.doc)) return false;\n view.dispatch(tr.scrollIntoView());\n return true;\n };\n\n /**\n * Rectangle in which a drop succeeds: `.dm-editor`'s box extended by\n * `DROP_ZONE_TOL_LEFT` on the left (gutter) and `DROP_ZONE_TOL` elsewhere.\n * See the constant declarations at the top of the file.\n */\n const isCursorOverDropZone = (clientX: number, clientY: number): boolean => {\n if (!editorEl) return false;\n const rect = editorEl.getBoundingClientRect();\n return clientX >= rect.left - DROP_ZONE_TOL_LEFT\n && clientX <= rect.right + DROP_ZONE_TOL\n && clientY >= rect.top - DROP_ZONE_TOL\n && clientY <= rect.bottom + DROP_ZONE_TOL;\n };\n\n /**\n * List WRAPPER type of the dragged block (`'bulletList'`/`'orderedList'`/\n * `'taskList'`), or `null` for a non-list block. Drives source-aware drop\n * geometry: a splitting drop (non-list block, or a different list kind) sits at\n * the list's parent column, a joining one keeps the item column. Reads the same\n * tiered source as `performBlockDrop` so indicator and drop agree.\n */\n const draggedSourceWrapperName = (): string | null => {\n const from = pluginKey.getState(editor.view.state)?.draggedFrom ?? pendingDraggedFrom;\n if (from === null) return null;\n const node = editor.view.state.doc.nodeAt(from);\n if (!node || !LIST_ITEM_TYPES.has(node.type.name)) return null;\n return editor.view.state.doc.resolve(from).parent.type.name;\n };\n\n /**\n * Reposition the drop-indicator line where `handleDrop` would land; hide it\n * when nothing resolves. `data-mode` lets theme CSS draw a solid sibling line\n * vs a dashed indented nested line.\n */\n const updateDropIndicator = (clientX: number, clientY: number): void => {\n if (!editorEl) return;\n const placement = computeDropPlacement(editor.view, clientX, clientY, nested, nestThreshold, {\n incumbentUpperPos: dragHyst.upperPos,\n incumbentLowerPos: dragHyst.lowerPos,\n incumbentLevel: dragHyst.level,\n incumbentChildIndex: dragHyst.childIndex,\n hysteresis: true,\n sourceWrapperName: draggedSourceWrapperName(),\n });\n if (!placement) {\n indicator.removeAttribute('data-show');\n currentDropKey = null;\n return;\n }\n // Carry forward for the next dragover's hysteresis, even if the repaint is\n // gated below.\n dragHyst.upperPos = placement.gapUpperPos ?? null;\n dragHyst.lowerPos = placement.gapLowerPos ?? null;\n dragHyst.level = placement.depthLevel ?? null;\n dragHyst.childIndex = placement.mode === 'nested' ? placement.childIndex ?? null : null;\n\n // Suppress the indicator when a release here would NOT move anything: the\n // block already occupies exactly this slot (e.g. a block dragged onto the\n // gap right after its own list, where several outdent options collapse onto\n // its current position), or a self-drop. Drawing a line the drop then\n // silently ignores is misleading; hide it so only real targets light up.\n const indicatorDraggedFrom = pluginKey.getState(editor.view.state)?.draggedFrom ?? pendingDraggedFrom;\n if (indicatorDraggedFrom !== null) {\n const indicatorSource = editor.view.state.doc.nodeAt(indicatorDraggedFrom);\n if (\n indicatorSource\n && buildDropTr(editor.view, indicatorDraggedFrom, indicatorSource, placement).doc.eq(editor.view.state.doc)\n ) {\n indicator.removeAttribute('data-show');\n currentDropKey = null;\n return;\n }\n }\n\n const editorRect = editorEl.getBoundingClientRect();\n\n let lineY: number;\n let left: number;\n let width: number;\n if (placement.indicatorLine) {\n // Slot model: the resolver supplies the exact client-coord line.\n lineY = placement.indicatorLine.top - editorRect.top;\n left = placement.indicatorLine.left - editorRect.left;\n width = placement.indicatorLine.width;\n } else if (placement.mode === 'nested') {\n // Anchor on the gap's TOP edge, indented to the children zone (the theme's\n // `translateY` tuck is uniform, so JS owns no CSS-coupled offset). Fall\n // back to the item bottom when `nestedGapRect` is absent.\n const indent = NESTED_INDICATOR_INDENT_PX;\n const gap = placement.nestedGapRect ?? {\n top: placement.rect.bottom,\n left: placement.rect.left,\n width: placement.rect.width,\n };\n lineY = gap.top - editorRect.top;\n left = gap.left - editorRect.left + indent;\n width = Math.max(0, gap.width - indent);\n } else {\n // Sibling line at the rect's top/bottom edge, full width.\n lineY = (placement.insertAfter ? placement.rect.bottom : placement.rect.top) - editorRect.top;\n left = placement.rect.left - editorRect.left;\n width = placement.rect.width;\n }\n // Identity gate: skip DOM writes when the drawn line is unchanged. Keyed on\n // geometry + child slot (so a slot change at the same row still repaints).\n const slotPart = placement.mode === 'nested' ? String(placement.childIndex ?? -1) : 's';\n const key = `${placement.mode}|${slotPart}|${String(Math.round(lineY))}|${String(Math.round(left))}|${String(Math.round(width))}`;\n if (key === currentDropKey && indicator.hasAttribute('data-show')) return;\n currentDropKey = key;\n\n indicator.style.top = `${String(lineY)}px`;\n indicator.style.left = `${String(left)}px`;\n indicator.style.width = `${String(width)}px`;\n indicator.setAttribute('data-show', '');\n indicator.setAttribute('data-mode', placement.mode);\n };\n\n const stopAutoScroll = (): void => {\n resetAutoScroll();\n };\n\n const hideDropIndicator = (): void => {\n indicator.removeAttribute('data-show');\n // Drop the identity gate so the next show repaints from scratch.\n currentDropKey = null;\n };\n\n let dragoverAttached = false;\n /** Register document-level dragover + drop listeners for the drag. Shared by\n * auto-scroll, drop-indicator, and gutter-area drop handling so they stay in\n * lockstep without double-listening. */\n const startDragListeners = (): void => {\n if (dragoverAttached) return;\n document.addEventListener('dragover', onDocumentDragover);\n document.addEventListener('drop', onDocumentDrop);\n dragoverAttached = true;\n };\n const stopDragListeners = (): void => {\n if (!dragoverAttached) return;\n document.removeEventListener('dragover', onDocumentDragover);\n document.removeEventListener('drop', onDocumentDrop);\n dragoverAttached = false;\n // Every teardown path funnels through here, so no stale state leaks.\n resetDropState();\n };\n\n const autoScrollTick = (): void => {\n const target = autoScrollState.target;\n if (target === null) {\n autoScrollState.raf = null;\n return;\n }\n // Dead-man switch: no dragover events means the drag is effectively over\n // (some OS/browser combos eat `dragend`). Tear down what `onDragEnd` would so\n // we don't leak the document listeners or leave a stale indicator visible.\n if (autoScrollState.lastAt > 0 && performance.now() - autoScrollState.lastAt > DRAGOVER_SILENCE_MS) {\n stopAutoScroll();\n stopDragListeners();\n hideDropIndicator();\n return;\n }\n if (autoScrollState.lastClientY !== null) {\n // `findScrollableAncestor` returns only bounded elements, so we measure\n // against the scrollable rect directly. Page-level scroll is the browser's\n // own drag-edge autoscroll (running both would double-scroll and jank).\n const rect = target.getBoundingClientRect();\n const distFromTop = autoScrollState.lastClientY - rect.top;\n const distFromBottom = rect.bottom - autoScrollState.lastClientY;\n let delta = 0;\n if (distFromTop < autoScrollThreshold && distFromTop >= 0) {\n // Ramp: at the edge (dist=0) speed is maxSpeed; at threshold speed is 0.\n delta = -Math.round(autoScrollMaxSpeed * (1 - distFromTop / autoScrollThreshold));\n } else if (distFromBottom < autoScrollThreshold && distFromBottom >= 0) {\n delta = Math.round(autoScrollMaxSpeed * (1 - distFromBottom / autoScrollThreshold));\n }\n if (delta !== 0) {\n target.scrollBy(0, delta);\n }\n }\n autoScrollState.raf = requestAnimationFrame(autoScrollTick);\n };\n\n const startAutoScroll = (): void => {\n if (!autoScroll) return;\n if (!editorEl) return;\n const target = findScrollableAncestor(editorEl);\n if (!target) return;\n autoScrollState.target = target;\n autoScrollState.lastClientY = null;\n autoScrollState.lastAt = performance.now();\n autoScrollState.raf = requestAnimationFrame(autoScrollTick);\n };\n\n const onDragStart = (event: DragEvent): void => {\n if (disableDrag || !editor.isEditable) {\n event.preventDefault();\n return;\n }\n const state = pluginKey.getState(editor.view.state);\n const pos = state?.hoveredPos ?? null;\n if (pos === null) {\n event.preventDefault();\n return;\n }\n // Capture source pos SYNCHRONOUSLY for `performBlockDrop`: it needs the value\n // before the deferred plugin-state commit (setTimeout(0) below) and after PM\n // clears `view.dragging` in its drop handler.\n pendingDraggedFrom = pos;\n const node = editor.view.state.doc.nodeAt(pos);\n if (!node) {\n event.preventDefault();\n return;\n }\n\n const sourceEnd = pos + node.nodeSize;\n const slice = editor.view.state.doc.slice(pos, sourceEnd);\n const nodeSelection = NodeSelection.create(editor.view.state.doc, pos);\n\n // Set the drag preview BEFORE any PM dispatch: the browser only honours\n // `setDragImage` during the initial dragstart tick, and a dispatch first\n // re-renders PM, possibly replacing the captured nodeDOM.\n if (event.dataTransfer) {\n event.dataTransfer.effectAllowed = 'move';\n // `text/plain` fallback: Firefox cancels the drag if no data is set.\n event.dataTransfer.setData('text/plain', node.textContent);\n const dom = editor.view.nodeDOM(pos);\n if (dom instanceof HTMLElement) {\n // Off-screen styled clone as the preview. Passing live DOM to\n // setDragImage captures ancestor transforms/clip/scroll; the clone stays\n // crisp.\n const ghost = createDragGhost(dom);\n dragPreview = ghost.wrapper;\n event.dataTransfer.setDragImage(ghost.wrapper, 10, 10);\n }\n }\n\n // Tell PM a drag is in progress. `node` is critical: PM's drop handler\n // deletes the source via this NodeSelection rather than the view selection,\n // which can shift mid-drag; without it the block sometimes survives the drop\n // (the \"phantom source\" bug). Sync-only, no DOM mutation, safe in dragstart.\n asDragView(editor.view).dragging = {\n slice,\n move: true,\n node: nodeSelection,\n };\n\n // CRITICAL: do NOT move this back into the sync dragstart tick. Chrome\n // commits the drag in the microtask after `dragstart` returns; any DOM\n // mutation of the source between dragstart and that commit aborts the drag\n // and fires `dragend` INSTANTLY (\"click and hold does nothing\"; crbug/168544,\n // react-dnd #1085). The concrete trigger: a sync `setSelection +\n // setMeta(draggedFrom)` made PM add `.ProseMirror-selectednode`, killing the\n // drag. `setTimeout(0)` runs after the commit, so the mutations are safe.\n //\n // Skip the dispatch if the drag already ended (fast drags where dragstart →\n // drop → dragend run in one JS task before the timer). `onDragEnd` nulls\n // `pendingDraggedFrom`, our \"drag still alive?\" signal; otherwise the stale\n // `nodeSelection` would hit a changed doc and PM throws \"Selection passed to\n // setSelection must point at the current document\".\n window.setTimeout(() => {\n if (pendingDraggedFrom === null) return;\n editor.view.dispatch(\n editor.view.state.tr\n .setSelection(nodeSelection)\n .setMeta(pluginKey, { draggedFrom: pos }),\n );\n editorEl?.dispatchEvent(new Event('dm:dismiss-overlays', { bubbles: false }));\n hide();\n }, 0);\n\n // Start with clean hysteresis state so the first dragover resolves freely.\n resetDropState();\n\n // Track dragover Y and ramp scroll near viewport edges (no-op when off).\n startAutoScroll();\n // Shared document-level dragover listener powers both auto-scroll and the\n // drop-indicator. Attached once per drag, removed in dragend.\n startDragListeners();\n\n // Theme hides native `.prosemirror-dropcursor-*` while this class is set.\n if (dropIndicator) editorEl?.classList.add('dm-block-handle-dragging');\n };\n\n const teardownDragPreview = (): void => {\n if (dragPreview) {\n dragPreview.remove();\n dragPreview = null;\n }\n };\n\n const onDragEnd = (): void => {\n asDragView(editor.view).dragging = null;\n setDraggedFrom(editor.view, null);\n pendingDraggedFrom = null;\n stopAutoScroll();\n stopDragListeners();\n hideDropIndicator();\n teardownDragPreview();\n releaseDragPress();\n editorEl?.classList.remove('dm-block-handle-dragging');\n };\n\n return new Plugin<BlockHandlePluginState>({\n key: pluginKey,\n\n state: {\n init: (): BlockHandlePluginState => ({ hoveredPos: null, draggedFrom: null }),\n apply(tr, prev): BlockHandlePluginState {\n const meta = tr.getMeta(pluginKey) as Partial<BlockHandlePluginState> | undefined;\n let next = prev;\n if (meta) {\n if ('hoveredPos' in meta) {\n next = { ...next, hoveredPos: meta.hoveredPos ?? null };\n }\n if ('draggedFrom' in meta) {\n next = { ...next, draggedFrom: meta.draggedFrom ?? null };\n }\n }\n // Map positions through doc changes so transactions while hovering or\n // dragging don't leave us on the wrong block. assoc=1 (forward bias) so\n // `setNodeMarkup` on the hovered block (same type, new attrs) doesn't\n // treat the left boundary as deleted; without it, BlockColor's swatch\n // click wipes `hoveredPos` and the next handle click bails silently.\n if (tr.docChanged) {\n if (next.hoveredPos !== null) {\n const mapped = tr.mapping.mapResult(next.hoveredPos, 1);\n next = { ...next, hoveredPos: mapped.deleted ? null : mapped.pos };\n }\n if (next.draggedFrom !== null) {\n const mapped = tr.mapping.mapResult(next.draggedFrom, 1);\n next = { ...next, draggedFrom: mapped.deleted ? null : mapped.pos };\n }\n }\n return next;\n },\n },\n\n props: {\n // Custom drop handler for Notion-like block semantics (above-mid → insert\n // before, below-mid → after), instead of PM's default `posAtCoords +\n // dropPoint` which rounds short paragraphs to an arbitrary neighbour.\n // `moveBlock` does the delete+insert + position fix so the block keeps its\n // attrs (UniqueID, colors).\n handleDrop(_view, event, _slice, moved): boolean {\n if (!moved) return false;\n // Shared with the document-level drop listener, so the same logic runs\n // whether drop fired on `.ProseMirror` (here) or surrounding chrome.\n if (performBlockDrop(event.clientX, event.clientY)) {\n event.preventDefault();\n return true;\n }\n // No source/placement: still consume the event so PM doesn't fall back\n // to its default drop logic.\n event.preventDefault();\n return true;\n },\n },\n\n view: (editorView) => {\n editorEl = editorView.dom.closest('.dm-editor');\n if (!editorEl) {\n // No `.dm-editor` container → plugin inert.\n return { destroy: () => { /* noop */ } };\n }\n\n editorEl.classList.add('dm-editor--has-block-handle');\n editorEl.appendChild(root);\n if (dropIndicator) {\n editorEl.appendChild(indicator);\n }\n hide();\n hideDropIndicator();\n\n // Hover detection lives on `.dm-editor`'s parent (the page wrapper) so the\n // listener also catches movement in the side gutter where the handle sits.\n // `resolveBlockAtCoords` falls back to a Y-range walk when the cursor's X\n // is outside `.ProseMirror`, so the block still resolves.\n hoverEl = editorEl.parentElement ?? editorEl;\n hoverEl.addEventListener('mousemove', onMouseMove);\n hoverEl.addEventListener('mouseleave', onMouseLeave);\n hoverEl.addEventListener('mouseenter', onMouseEnter);\n editorEl.addEventListener('dm:dismiss-overlays', onDismissOverlays);\n\n plusBtn.addEventListener('mousedown', onPlusBtnMouseDown);\n plusBtn.addEventListener('click', onPlusClick);\n // dragBtn mousedown must NOT preventDefault (native drag init relies on\n // `draggable=\"true\"`); it only sets the hover-freeze lock so the handle\n // doesn't slide away before the drag threshold. (mouseup is attached\n // lazily inside `onDragBtnMouseDown` - see its comment.)\n dragBtn.addEventListener('mousedown', onDragBtnMouseDown);\n dragBtn.addEventListener('click', onDragBtnClick);\n dragBtn.addEventListener('dragstart', onDragStart);\n dragBtn.addEventListener('dragend', onDragEnd);\n\n return {\n destroy: () => {\n clearHideTimer();\n // If destroyed mid-drag, stop the RAF loop and drop the document-level\n // dragover listener immediately.\n stopAutoScroll();\n stopDragListeners();\n hideDropIndicator();\n indicator.remove();\n teardownDragPreview();\n if (hoverRaf !== null) {\n cancelAnimationFrame(hoverRaf);\n hoverRaf = null;\n }\n hoverEl?.removeEventListener('mousemove', onMouseMove);\n hoverEl?.removeEventListener('mouseleave', onMouseLeave);\n hoverEl?.removeEventListener('mouseenter', onMouseEnter);\n editorEl?.removeEventListener('dm:dismiss-overlays', onDismissOverlays);\n plusBtn.removeEventListener('mousedown', onPlusBtnMouseDown);\n plusBtn.removeEventListener('click', onPlusClick);\n dragBtn.removeEventListener('mousedown', onDragBtnMouseDown);\n document.removeEventListener('mouseup', releaseDragPress);\n dragBtn.removeEventListener('click', onDragBtnClick);\n dragBtn.removeEventListener('dragstart', onDragStart);\n dragBtn.removeEventListener('dragend', onDragEnd);\n editorEl?.classList.remove('dm-editor--has-block-handle');\n editorEl?.classList.remove('dm-block-handle-dragging');\n root.remove();\n editorEl = null;\n hoverEl = null;\n },\n };\n },\n });\n}\n\nexport const BlockHandle = Extension.create<BlockHandleOptions>({\n name: 'blockHandle',\n\n addOptions() {\n return {\n hideDelay: 200,\n disableDrag: false,\n autoScroll: true,\n autoScrollThreshold: 48,\n autoScrollMaxSpeed: 18,\n nested: false,\n dropIndicator: true,\n nestThreshold: DEFAULT_NEST_THRESHOLD,\n };\n },\n\n addProseMirrorPlugins() {\n const editor = this.editor as Editor | null;\n if (!editor) return [];\n return [\n createBlockHandlePlugin({\n pluginKey: blockHandlePluginKey,\n editor,\n hideDelay: this.options.hideDelay ?? 200,\n disableDrag: this.options.disableDrag ?? false,\n autoScroll: this.options.autoScroll ?? true,\n autoScrollThreshold: this.options.autoScrollThreshold ?? 48,\n autoScrollMaxSpeed: this.options.autoScrollMaxSpeed ?? 18,\n nested: resolveNestedConfig(this.options.nested),\n dropIndicator: this.options.dropIndicator ?? true,\n nestThreshold: this.options.nestThreshold ?? DEFAULT_NEST_THRESHOLD,\n }),\n ];\n },\n});\n\n/**\n * Normalises the user-facing `nested` option into `NestedResolution`:\n *\n * - `false` / `undefined` → top-level-only (mode A).\n * - `true` → default list/task items, Notion-style (mode B).\n * - object → explicit config; defaults fill missing fields.\n */\nexport function resolveNestedConfig(nested: BlockHandleOptions['nested']): NestedResolution {\n if (nested === true) {\n return {\n allowedNodes: [...DEFAULT_NESTED_NODES],\n allowedContainers: [],\n gutterBias: null,\n matchers: [...DEFAULT_BLOCK_MATCHERS],\n };\n }\n if (nested && typeof nested === 'object') {\n const allowedNodes = nested.allowedNodes ?? DEFAULT_NESTED_NODES;\n if (allowedNodes.length === 0) {\n return { allowedNodes: [], allowedContainers: [], gutterBias: null, matchers: [] };\n }\n const useDefaults = nested.defaultMatchers ?? true;\n const matchers: BlockMatcher[] = [];\n if (useDefaults) matchers.push(...DEFAULT_BLOCK_MATCHERS);\n if (nested.matchers) matchers.push(...nested.matchers);\n return {\n allowedNodes: [...allowedNodes],\n allowedContainers: nested.allowedContainers ? [...nested.allowedContainers] : [],\n gutterBias: resolveGutterBias(nested.promoteOnEdge),\n matchers,\n };\n }\n return { allowedNodes: [], allowedContainers: [], gutterBias: null, matchers: [] };\n}\n","/**\n * `Mod-Shift-ArrowUp` / `Mod-Shift-ArrowDown` move the top-level block\n * containing the selection. Accessibility companion to BlockHandle drag.\n * Shares `moveBlock` so position math and self-move rejection match.\n */\nimport { Extension } from '@domternal/core';\nimport type { Editor } from '@domternal/core';\nimport { TextSelection } from '@domternal/pm/state';\nimport { findTopLevelBlock } from './helpers/findTopLevelBlock.js';\nimport { moveBlock } from './helpers/moveBlock.js';\n\nexport const KeyboardReorder = Extension.create({\n name: 'keyboardReorder',\n\n addKeyboardShortcuts() {\n const { editor } = this;\n return {\n 'Mod-Shift-ArrowUp': () => moveCurrentBlock(editor as Editor | null, 'up'),\n 'Mod-Shift-ArrowDown': () => moveCurrentBlock(editor as Editor | null, 'down'),\n };\n },\n});\n\n/**\n * Moves the top-level block containing the selection up or down. Returns `true`\n * when a move happened, else `false` (so the browser handles the shortcut).\n */\nfunction moveCurrentBlock(editor: Editor | null, direction: 'up' | 'down'): boolean {\n if (!editor || editor.isDestroyed) return false;\n if (!editor.isEditable) return false;\n const { state, view } = editor;\n const { $from } = state.selection;\n\n const topLevel = findTopLevelBlock(state.doc, $from.pos);\n if (!topLevel) return false;\n\n if (direction === 'up' && topLevel.index === 0) return false;\n if (direction === 'down' && topLevel.index >= state.doc.childCount - 1) return false;\n\n // Selection offset within the source block. Absolute-position math (not\n // depth-based) so it survives nested containers like list-item/details-content.\n const selectionOffsetInBlock = Math.max(\n 0,\n Math.min($from.pos - topLevel.pos, topLevel.node.nodeSize - 1),\n );\n\n let targetPos: number;\n if (direction === 'up') {\n targetPos = state.doc.resolve(topLevel.pos).posAtIndex(topLevel.index - 1, 0);\n } else {\n const nextSibling = state.doc.child(topLevel.index + 1);\n const nextStart = state.doc.resolve(topLevel.pos).posAtIndex(topLevel.index + 1, 0);\n targetPos = nextStart + nextSibling.nodeSize;\n }\n\n const tr = state.tr;\n moveBlock(tr, topLevel.pos, targetPos);\n\n // Restore selection inside the moved block. `moveBlock` deletes then inserts,\n // so the new start is `targetPos` moving up, `targetPos - source.nodeSize` down.\n const newBlockPos = direction === 'up'\n ? targetPos\n : targetPos - topLevel.node.nodeSize;\n const selectionPos = Math.min(\n newBlockPos + selectionOffsetInBlock,\n Math.max(0, tr.doc.content.size - 1),\n );\n tr.setSelection(TextSelection.near(tr.doc.resolve(selectionPos)));\n\n view.dispatch(tr.scrollIntoView());\n return true;\n}\n","import type { Attrs, NodeType } from '@domternal/pm/model';\nimport type { Transaction } from '@domternal/pm/state';\nimport { TextSelection } from '@domternal/pm/state';\nimport { expandToEmptyWrappers } from './expandToEmptyWrappers.js';\nimport { rejoinAtSeam } from './rejoinAtSeam.js';\n\n/**\n * Block-level transaction helpers for BlockContextMenu commands (Delete,\n * Duplicate, Turn into) and other features operating on a top-level block.\n * All helpers mutate and return the given transaction (chainable).\n */\n\n/**\n * Removes the block at `blockPos` entirely. Two correctness properties:\n *\n * 1. Single-child wrapper expansion: deleting an inner block whose parent had it\n * as sole child would leave PM fitting an empty placeholder (a `<ul>` with one\n * blank `<li>`) to satisfy `bulletList -> listItem+`; worse, some fitters\n * unwrap the parent so \"delete killed the whole list\". We expand the deletion\n * range outward through such wrappers (like `moveBlock`) to remove the orphan\n * chain atomically.\n *\n * 2. Doc-empty fallback: if the expanded range covers the whole doc, deleting\n * would violate `block+` on the doc. We replace with a fresh paragraph so the\n * editor stays usable (Notion behaviour).\n *\n * 3. Seam heal: deleting a block that sat between two same-type lists leaves them\n * touching; `rejoinAtSeam` merges them (clearing a stale ordered `start`) so\n * numbering stays continuous, matching `moveBlock`.\n */\nexport function deleteBlock(tr: Transaction, blockPos: number): Transaction {\n if (blockPos < 0 || blockPos >= tr.doc.content.size) return tr;\n const node = tr.doc.nodeAt(blockPos);\n if (!node) return tr;\n const blockEnd = blockPos + node.nodeSize;\n\n const { from, to } = expandToEmptyWrappers(tr.doc, blockPos, blockEnd);\n\n // Would the doc be left empty? Equality with the full content range means we\n // covered every top-level child via single-child wrapper chains.\n const wouldEmptyDoc = from === 0 && to === tr.doc.content.size;\n if (wouldEmptyDoc) {\n const paragraphType = tr.doc.type.schema.nodes['paragraph'];\n if (!paragraphType) {\n // No `paragraph` type in the schema - bail rather than risk an invalid replacement.\n return tr;\n }\n const replacement = paragraphType.createAndFill();\n if (!replacement) return tr;\n tr.replaceWith(from, to, replacement);\n tr.setSelection(TextSelection.near(tr.doc.resolve(from + 1)));\n return tr;\n }\n\n tr.delete(from, to);\n // The block's removal may bring two same-type lists flush together.\n rejoinAtSeam(tr, from);\n return tr;\n}\n\n/**\n * Duplicates the block at `blockPos`, inserting a copy immediately after it.\n * The copy preserves content, attrs, AND node-level marks (needed for\n * annotation / comment extensions that attach marks to blocks).\n *\n * @param transformAttrs Optional mapper on the source attrs to produce the\n * copy's attrs. Use it to regenerate unique IDs so the duplicate doesn't\n * collide (e.g. `{ ...attrs, id: uuid() }`).\n */\nexport function duplicateBlock(\n tr: Transaction,\n blockPos: number,\n transformAttrs?: (attrs: Attrs) => Attrs,\n): Transaction {\n if (blockPos < 0 || blockPos >= tr.doc.content.size) return tr;\n const node = tr.doc.nodeAt(blockPos);\n if (!node) return tr;\n const blockEnd = blockPos + node.nodeSize;\n const attrs = transformAttrs ? transformAttrs(node.attrs) : node.attrs;\n // `type.create(attrs, content, marks)` preserves all three; `node.copy(content)`\n // drops node marks, breaking block-level annotations.\n const copy = node.type.create(attrs, node.content, node.marks);\n tr.insert(blockEnd, copy);\n return tr;\n}\n\n/**\n * Transforms the block at `blockPos` into a different textblock type, preserving\n * inline content AND any attrs valid on the target. Without this, `setBlockType`\n * resets global attrs (bgColor, textColor, id, ...) to defaults, so \"Turn into\"\n * would lose a block's color and identity.\n *\n * Attrs present on BOTH source and target carry over; source-only attrs (e.g.\n * `level` on a Heading turning into Paragraph) drop since the target doesn't\n * declare them. The explicit `attrs` arg (e.g. `{ level: 2 }`) wins on key clash.\n *\n * Returns the transaction unchanged if the target isn't a textblock or the node\n * can't be transformed.\n */\nexport function turnIntoBlock(\n tr: Transaction,\n blockPos: number,\n targetType: NodeType,\n attrs?: Attrs,\n): Transaction {\n if (blockPos < 0 || blockPos >= tr.doc.content.size) return tr;\n const node = tr.doc.nodeAt(blockPos);\n if (!node) return tr;\n // `setBlockType` requires a textblock target.\n if (!targetType.isTextblock) return tr;\n const blockEnd = blockPos + node.nodeSize;\n\n // Preserve source attrs the target also declares, then overlay caller attrs.\n // `targetType.spec.attrs` is the schema truth on which attrs are valid here.\n const validKeys = Object.keys(targetType.spec.attrs ?? {});\n const preserved: Record<string, unknown> = {};\n const sourceAttrs = node.attrs as Record<string, unknown>;\n for (const key of validKeys) {\n if (key in sourceAttrs) preserved[key] = sourceAttrs[key];\n }\n const mergedAttrs = attrs ? { ...preserved, ...attrs } : preserved;\n\n tr.setBlockType(blockPos, blockEnd, targetType, mergedAttrs);\n return tr;\n}\n","import { TextSelection } from '@domternal/pm/state';\nimport type { Editor } from '@domternal/core';\n\n/** Wrapper-style \"Turn into\" commands, each from the matching node extension.\n * Lists use the per-item `turnInto*` commands (Notion turn-into: convert only\n * the targeted block and split the run); the whole-list `toggle*List` commands\n * stay reserved for the toolbar button and Mod-Shift shortcut. */\nexport type WrapperCommand =\n | 'turnIntoBulletList'\n | 'turnIntoOrderedList'\n | 'turnIntoTaskList'\n | 'toggleBlockquote';\n\n/**\n * Wrap-style \"Turn into\" for non-textblock targets (lists, blockquote).\n * Textblock targets go through `turnIntoBlock`/`setBlockType`; wrappers can't,\n * since the inner block stays put and only its parent changes. So this helper:\n *\n * 1. (Optionally) downgrades the source to paragraph. ListItem/TaskItem\n * declare `content: 'paragraph block*'`, so a list item's FIRST child must\n * be a paragraph; a bare heading/codeBlock would be schema-rejected on wrap.\n * Blockquote (`block+`) accepts any block, so step-down only applies to lists.\n * 2. Moves the selection into the (now-paragraph) block.\n * 3. Dispatches the wrapper command. `toggleList`/`toggleBlockquote` act on\n * `state.selection`, so the selection must be set before the command runs.\n *\n * The step-down and wrapper command produce two undo steps; merging them would\n * mean re-implementing toggleList inline, an acceptable tradeoff for the rare\n * heading/codeBlock -> list path.\n */\nexport function turnIntoWrapper(\n editor: Editor,\n blockPos: number,\n command: WrapperCommand,\n): boolean {\n const { state } = editor.view;\n if (blockPos < 0 || blockPos >= state.doc.content.size) return false;\n const node = state.doc.nodeAt(blockPos);\n if (!node?.type.isTextblock) return false;\n\n const isListTarget = command !== 'toggleBlockquote';\n const needsStepDown = isListTarget && node.type.name !== 'paragraph';\n\n const tr = state.tr;\n if (needsStepDown) {\n const paragraphType = state.schema.nodes['paragraph'];\n if (!paragraphType) return false;\n tr.setBlockType(blockPos, blockPos + node.nodeSize, paragraphType);\n }\n // blockPos points at the block's OPENING token; +1 lands inside its inline\n // content (or the empty cursor position for an empty textblock).\n tr.setSelection(TextSelection.create(tr.doc, blockPos + 1));\n editor.view.dispatch(tr);\n\n // Dispatch via the commands map. It's typed `Record<string, (...) => boolean>`,\n // so switch on the discriminant to keep type-safety without a wide cast.\n switch (command) {\n case 'turnIntoBulletList':\n return editor.commands.turnIntoBulletList();\n case 'turnIntoOrderedList':\n return editor.commands.turnIntoOrderedList();\n case 'turnIntoTaskList':\n return editor.commands.turnIntoTaskList();\n case 'toggleBlockquote':\n return editor.commands.toggleBlockquote();\n }\n}\n","/**\n * Popup menu opened by clicking the BlockHandle drag handle without dragging.\n * Offers Delete, Duplicate, and Turn into (change block type) for the target.\n *\n * Triggered by the `dm:block-context-menu-open` event from BlockHandle, with\n * payload `{ blockPos, anchorElement }`. Mirrors FloatingMenu / SlashCommand\n * styling: `role=\"menu\"`, `role=\"menuitem\"`, `data-show`, positionFloatingOnce.\n */\nimport { Extension, defaultIcons, liftCurrentListItem, positionFloatingOnce, stripInlineColorConflicts, writeToClipboard } from '@domternal/core';\nimport type { Editor } from '@domternal/core';\nimport { Plugin, PluginKey, TextSelection, EditorState } from '@domternal/pm/state';\nimport type { Transaction } from '@domternal/pm/state';\nimport type { Attrs } from '@domternal/pm/model';\nimport { Decoration, DecorationSet } from '@domternal/pm/view';\nimport {\n deleteBlock,\n duplicateBlock,\n turnIntoBlock,\n} from './helpers/blockOperations.js';\nimport { turnIntoWrapper, type WrapperCommand } from './helpers/turnIntoWrapper.js';\n\n/**\n * Subset of `uniqueID` options we read. Avoids importing `UniqueIDOptions`\n * from core, which would couple this to an otherwise-optional feature.\n */\ninterface UniqueIDOptionsShape {\n attributeName?: string;\n generateID?: () => string;\n}\n\n/** Subset of `blockColor` options. Not imported directly so the Colors UI degrades gracefully when the extension isn't loaded. */\ninterface BlockColorOptionsShape {\n types?: string[];\n bgColors?: string[];\n textColors?: string[];\n}\n\n/**\n * `props.decorations` applies the `dm-block-context-active` class via a PM\n * Decoration (not inline classList) so the highlight survives view rerenders\n * from other transactions, e.g. UniqueID stamping `id` via setNodeMarkup.\n */\nexport interface BlockContextMenuPluginState {\n activeBlockPos: number | null;\n}\n\nexport const blockContextMenuPluginKey = new PluginKey<BlockContextMenuPluginState>('blockContextMenu');\n\nconst LIST_WRAPPER_TYPES = new Set(['bulletList', 'orderedList', 'taskList']);\n\n/** A block type offered by the \"Turn into\" submenu. */\nexport interface TurnIntoTarget {\n /** Display label, e.g. \"Heading 1\". */\n label: string;\n /** Icon key resolved against `defaultIcons`. */\n icon: string;\n /** Schema node name, e.g. \"heading\", \"paragraph\", \"blockquote\". */\n nodeType: string;\n /** Optional node attributes (e.g. `{ level: 1 }` for Heading 1). */\n attrs?: Attrs;\n /**\n * Command for wrapper (non-textblock) targets like lists and blockquote.\n * When set, runTurnInto routes through `turnIntoWrapper` instead of\n * `setBlockType`. Leave undefined for textblock targets (paragraph,\n * heading, codeBlock).\n */\n command?: WrapperCommand;\n}\n\nconst DEFAULT_TURN_INTO: TurnIntoTarget[] = [\n { label: 'Paragraph', icon: 'textT', nodeType: 'paragraph' },\n { label: 'Heading 1', icon: 'textHOne', nodeType: 'heading', attrs: { level: 1 } },\n { label: 'Heading 2', icon: 'textHTwo', nodeType: 'heading', attrs: { level: 2 } },\n { label: 'Heading 3', icon: 'textHThree', nodeType: 'heading', attrs: { level: 3 } },\n { label: 'Bullet list', icon: 'listBullets', nodeType: 'bulletList', command: 'turnIntoBulletList' },\n { label: 'Ordered list', icon: 'listNumbers', nodeType: 'orderedList', command: 'turnIntoOrderedList' },\n { label: 'To-do list', icon: 'listChecks', nodeType: 'taskList', command: 'turnIntoTaskList' },\n { label: 'Quote', icon: 'quotes', nodeType: 'blockquote', command: 'toggleBlockquote' },\n { label: 'Code block', icon: 'codeBlock', nodeType: 'codeBlock' },\n];\n\nexport interface BlockContextMenuOptions {\n /**\n * Show the \"Turn into\" section of the menu. Disable to limit operations\n * to Delete + Duplicate.\n * @default true\n */\n turnIntoEnabled?: boolean;\n /**\n * Block types offered by \"Turn into\". Override to curate the list or\n * add project-specific block types.\n * @default DEFAULT_TURN_INTO\n */\n turnIntoTargets?: TurnIntoTarget[];\n /**\n * Show \"Copy link\" when the target block has an id attribute AND the\n * `UniqueID` extension is loaded. No effect without UniqueID.\n * @default true\n */\n copyLinkEnabled?: boolean;\n /**\n * Builds the URL written to the clipboard on \"Copy link\". Default appends\n * `#<id>` to the current pathname+search (works for static pages); apps\n * with client-side routing should provide a callback matching their scheme.\n */\n onCopyLink?: (blockId: string, editor: Editor) => string;\n /**\n * Show the Colors section (text + background) when the `BlockColor`\n * extension is loaded and the target block is in its `types` list.\n * @default true\n */\n blockColorEnabled?: boolean;\n}\n\nexport interface CreateBlockContextMenuPluginOptions {\n pluginKey: PluginKey<BlockContextMenuPluginState>;\n editor: Editor;\n turnIntoEnabled: boolean;\n turnIntoTargets: TurnIntoTarget[];\n copyLinkEnabled: boolean;\n onCopyLink: (blockId: string, editor: Editor) => string;\n blockColorEnabled: boolean;\n}\n\n/** Default \"Copy link\" URL: appends `#<blockId>` to the current pathname+search. SPA hosts override via `onCopyLink`. */\nfunction defaultCopyLinkUrl(blockId: string): string {\n if (typeof window === 'undefined') return `#${blockId}`;\n const { pathname, search } = window.location;\n return `${pathname}${search}#${blockId}`;\n}\n\n/** Detail of the `dm:block-context-menu-open` event from BlockHandle. */\ninterface BlockContextMenuOpenDetail {\n blockPos: number;\n anchorElement: HTMLElement;\n}\n\n/**\n * Selector to re-locate an anchor button if its DOM identity changes (e.g.\n * the bubble menu rebuilding buttons via `replaceChildren`). Returns `null`\n * for anchors we can't reliably re-resolve (e.g. the BlockHandle drag button,\n * keyed by absolute position, not class).\n */\nfunction matchingSelectorFor(anchor: HTMLElement): string | null {\n const ariaLabel = anchor.getAttribute('aria-label');\n if (ariaLabel) {\n const escaped = ariaLabel.replace(/\"/g, '\\\\\"');\n return `button[aria-label=\"${escaped}\"]`;\n }\n return null;\n}\n\n/**\n * Builds the popup DOM, listens for `dm:block-context-menu-open` on\n * `.dm-editor`, and runs block operations via `helpers/blockOperations.ts`.\n */\nexport function createBlockContextMenuPlugin(\n options: CreateBlockContextMenuPluginOptions,\n): Plugin {\n const { pluginKey, editor, turnIntoEnabled, turnIntoTargets, copyLinkEnabled, onCopyLink, blockColorEnabled } = options;\n\n // Detect optional extensions once at construction (extensions + options are\n // immutable for the editor's lifetime). `null` means not loaded, so the\n // matching menu section is hidden.\n // CONSTRAINT: runtime re-registration / live-mutation of `uniqueID` /\n // `blockColor` options won't be reflected. If ever needed, move these reads\n // into `renderItems()` so each open re-resolves fresh state.\n const uniqueIDExt = editor.extensionManager.extensions.find((ext) => ext.name === 'uniqueID');\n const uniqueIDAttrName: string | null = uniqueIDExt\n ? ((uniqueIDExt.options as UniqueIDOptionsShape).attributeName ?? 'id')\n : null;\n const uniqueIDGenerate: (() => string) | null = uniqueIDExt\n ? ((uniqueIDExt.options as UniqueIDOptionsShape).generateID ?? null)\n : null;\n\n const blockColorExt = editor.extensionManager.extensions.find((ext) => ext.name === 'blockColor');\n const blockColorOpts = blockColorExt\n ? (blockColorExt.options as BlockColorOptionsShape)\n : null;\n const blockColorTypes: string[] | null = blockColorOpts?.types ?? null;\n const blockBgPalette: string[] = blockColorOpts?.bgColors ?? [];\n const blockTextPalette: string[] = blockColorOpts?.textColors ?? [];\n\n // Build popup DOM once.\n const root = document.createElement('div');\n root.className = 'dm-block-context-menu';\n root.setAttribute('role', 'menu');\n root.setAttribute('aria-label', 'Block options');\n root.setAttribute('data-dm-editor-ui', '');\n\n let editorEl: HTMLElement | null = null;\n let cleanupFloating: (() => void) | null = null;\n let currentBlockPos: number | null = null;\n // Roving tabindex: currently-focused menuitem. Starts at 0 (auto-focused on open).\n let focusedIndex = 0;\n let menuItemButtons: HTMLButtonElement[] = [];\n // rAF id for the initial focus, so `hide()` can cancel it if the menu closes\n // before the frame fires (else the callback races teardown and focuses a stale button).\n let initialFocusRaf: number | null = null;\n // Idempotency guard for the page-scroll-lock wheel/touchmove listeners.\n let scrollLocked = false;\n\n const isOpen = (): boolean => root.hasAttribute('data-show');\n\n /**\n * Suppresses page scroll while the menu is open. Scroll inside the menu is\n * allowed only when it has scrollable overflow, else wheel events would\n * bubble through and scroll the page. The theme's `overscroll-behavior:\n * contain` stops chaining at the menu's scroll edges.\n */\n const onBlockScroll = (event: Event): void => {\n const target = event.target;\n if (target instanceof Node && root.contains(target)) {\n const hasOverflow = root.scrollHeight > root.clientHeight;\n if (hasOverflow) return;\n }\n event.preventDefault();\n };\n\n const lockScroll = (): void => {\n if (scrollLocked) return;\n scrollLocked = true;\n // `passive: false` so preventDefault() takes effect (browsers default\n // wheel/touchmove to passive for scroll perf).\n document.addEventListener('wheel', onBlockScroll, { passive: false });\n document.addEventListener('touchmove', onBlockScroll, { passive: false });\n };\n\n const unlockScroll = (): void => {\n if (!scrollLocked) return;\n scrollLocked = false;\n document.removeEventListener('wheel', onBlockScroll);\n document.removeEventListener('touchmove', onBlockScroll);\n };\n\n const hide = (): void => {\n if (initialFocusRaf !== null) {\n cancelAnimationFrame(initialFocusRaf);\n initialFocusRaf = null;\n }\n cleanupFloating?.();\n cleanupFloating = null;\n unlockScroll();\n editorEl?.removeAttribute('data-block-context-menu-open');\n // `editor.view` is undefined during the first `hide()` at plugin init - skip dispatch.\n const view = editor.view as typeof editor.view | undefined;\n if (view) {\n const tr = view.state.tr.setMeta(pluginKey, { activeBlockPos: null });\n tr.setMeta('addToHistory', false);\n view.dispatch(tr);\n }\n root.removeAttribute('data-show');\n currentBlockPos = null;\n menuItemButtons = [];\n focusedIndex = 0;\n };\n\n const focusItem = (index: number): void => {\n if (menuItemButtons.length === 0) return;\n const clamped = Math.max(0, Math.min(index, menuItemButtons.length - 1));\n // Roving tabindex: only the focused item stays in the Tab order, else\n // Tab-away-and-back lands on the wrong item (WAI-ARIA menu pattern).\n for (let i = 0; i < menuItemButtons.length; i++) {\n const btn = menuItemButtons[i];\n if (btn) btn.tabIndex = i === clamped ? 0 : -1;\n }\n focusedIndex = clamped;\n menuItemButtons[clamped]?.focus();\n };\n\n /** Runs a block operation, then closes the menu and refocuses the editor. */\n const runAndClose = (apply: (tr: Transaction) => void): void => {\n const tr = editor.view.state.tr;\n try {\n apply(tr);\n editor.view.dispatch(tr.scrollIntoView());\n } finally {\n hide();\n editor.view.focus();\n }\n };\n\n const runDelete = (): void => {\n if (currentBlockPos === null) return;\n const pos = currentBlockPos;\n runAndClose((tr) => { deleteBlock(tr, pos); });\n };\n\n const runDuplicate = (): void => {\n if (currentBlockPos === null) return;\n const pos = currentBlockPos;\n // When UniqueID is loaded, regenerate the id on the copy to avoid\n // colliding with the source; all other attrs are preserved by spreading.\n const transformAttrs = uniqueIDAttrName && uniqueIDGenerate\n ? (attrs: Attrs): Attrs => ({ ...attrs, [uniqueIDAttrName]: uniqueIDGenerate() })\n : undefined;\n runAndClose((tr) => { duplicateBlock(tr, pos, transformAttrs); });\n };\n\n const runCopyLink = (blockId: string): void => {\n const url = onCopyLink(blockId, editor);\n void writeToClipboard(url).then((ok: boolean) => {\n // `success` fires only on a successful write, `error` otherwise. Detail\n // carries the URL and id so the host can format its own message.\n const name = ok ? 'dm:copy-link-success' : 'dm:copy-link-error';\n editorEl?.dispatchEvent(new CustomEvent(name, {\n bubbles: false,\n detail: { url, blockId },\n }));\n });\n hide();\n editor.view.focus();\n };\n\n const runTurnInto = (target: TurnIntoTarget): void => {\n if (currentBlockPos === null) return;\n const blockPos = currentBlockPos;\n const sourceNode = editor.view.state.doc.nodeAt(blockPos);\n if (!sourceNode) return;\n const sourceIsTextblock = sourceNode.type.isTextblock;\n\n // For a wrapper source (listItem / taskItem / blockquote), descend to its\n // inner first textblock so the wrapper command gets a valid textblock source.\n const pos = sourceIsTextblock ? blockPos : blockPos + 1;\n\n // Wrapper targets route through the helper / editor command, which\n // dispatches its own transaction (with scrollIntoView), so we just\n // close the menu and restore focus.\n if (target.command) {\n turnIntoWrapper(editor, pos, target.command);\n hide();\n editor.view.focus();\n return;\n }\n const targetType = editor.view.state.schema.nodes[target.nodeType];\n if (!targetType) return;\n\n // Textblock source: position-precise setBlockType (preserves bg/text/id).\n if (sourceIsTextblock) {\n runAndClose((tr) => { turnIntoBlock(tr, pos, targetType, target.attrs); });\n return;\n }\n\n // Wrapper source (list item) + textblock target: a raw setBlockType is a\n // no-op inside a list item (its label must stay a paragraph), so lift the\n // item out of its list first (Notion turn-into: splits the run, unindents),\n // then set the block type. For the Paragraph target the lift IS the\n // conversion, so the setBlockType step is skipped.\n runAndClose((tr) => {\n const labelInner = Math.min(blockPos + 2, tr.doc.content.size);\n tr.setSelection(TextSelection.create(tr.doc, labelInner));\n const liftState = EditorState.create({ doc: tr.doc, selection: tr.selection });\n if (!liftCurrentListItem(liftState, tr)) return;\n if (targetType.name !== 'paragraph') {\n tr.setBlockType(\n tr.selection.from,\n tr.selection.to,\n targetType,\n (node) => ({ ...node.attrs, ...(target.attrs ?? {}) }),\n );\n }\n });\n };\n\n /**\n * Sets `bgColor` / `textColor` on the targeted block via `setNodeMarkup`,\n * bypassing the BlockColor command's ancestor walk (we already know the\n * block). Inline color marks of the same kind are stripped so the new block\n * tint wins (\"last action wins\"); see `stripInlineColorConflicts`.\n */\n const runSetColor = (attr: 'bgColor' | 'textColor', color: string | null): void => {\n if (currentBlockPos === null) return;\n const pos = currentBlockPos;\n runAndClose((tr) => {\n const n = tr.doc.nodeAt(pos);\n if (!n) return;\n tr.setNodeMarkup(pos, undefined, { ...n.attrs, [attr]: color });\n stripInlineColorConflicts(\n tr,\n editor.view.state,\n pos,\n pos + n.nodeSize,\n attr === 'textColor' ? 'text' : 'bg',\n );\n });\n };\n\n /**\n * Re-renders menu items for the target block. Hides \"Turn into\" targets that\n * match the current block (no-op conversions) and the whole section when the\n * source is neither a textblock nor a textblock-first wrapper.\n */\n const renderItems = (blockPos: number): void => {\n root.innerHTML = '';\n menuItemButtons = [];\n\n const node = editor.view.state.doc.nodeAt(blockPos);\n if (!node) return;\n\n // Primary actions section.\n const primaryGroup = document.createElement('div');\n primaryGroup.className = 'dm-block-context-menu-group';\n primaryGroup.setAttribute('role', 'group');\n\n primaryGroup.appendChild(\n makeItem('Delete', 'trash', runDelete),\n );\n if (node.type.name !== 'horizontalRule') {\n primaryGroup.appendChild(\n makeItem('Duplicate', 'copy', runDuplicate),\n );\n }\n // Copy link: only when enabled, UniqueID is loaded, and the block has an\n // id. Blocks without an id (legacy content) skip it rather than copy an empty hash.\n if (copyLinkEnabled && uniqueIDAttrName) {\n const id = (node.attrs as Record<string, unknown>)[uniqueIDAttrName];\n if (typeof id === 'string' && id.length > 0) {\n primaryGroup.appendChild(\n makeItem('Copy link', 'link', () => { runCopyLink(id); }),\n );\n }\n }\n root.appendChild(primaryGroup);\n\n // Colors section: shown only when BlockColor is loaded and the block type\n // is in its `types` list. Renders bg + text swatch rows, each led by a \"clear\" swatch.\n if (blockColorEnabled && blockColorTypes?.includes(node.type.name)) {\n const label = document.createElement('div');\n label.className = 'dm-block-context-menu-group-label';\n label.textContent = 'Colors';\n root.appendChild(label);\n\n const currentBg = (node.attrs as Record<string, unknown>)['bgColor'] as string | null;\n const currentText = (node.attrs as Record<string, unknown>)['textColor'] as string | null;\n\n root.appendChild(\n buildSwatchRow(\n 'Text color',\n 'text',\n blockTextPalette,\n currentText,\n (color) => { runSetColor('textColor', color); },\n ),\n );\n root.appendChild(\n buildSwatchRow(\n 'Background',\n 'bg',\n blockBgPalette,\n currentBg,\n (color) => { runSetColor('bgColor', color); },\n ),\n );\n }\n\n // Turn into section. Two source modes:\n // A. Textblock source (paragraph, heading, codeBlock): textblock AND\n // wrapper targets eligible.\n // B. Wrapper source (listItem/taskItem/blockquote whose first child is a\n // textblock): wrapper targets AND textblock targets eligible (a list\n // item is lifted out then converted; see runTurnInto), descending to\n // the inner textblock for the ancestor walk.\n // Atoms (HR) and wrapper-of-wrapper (e.g. bulletList) hide it entirely, like Notion.\n const sourceIsTextblock = node.type.isTextblock;\n const sourceIsWrapper = !sourceIsTextblock && node.firstChild?.isTextblock === true;\n // A list-item source can also offer textblock targets (Heading, Code, ...):\n // it gets lifted out then converted (runTurnInto). A blockquote wrapper can't,\n // so textblock targets stay hidden there.\n const sourceIsListItem = node.type.name === 'listItem' || node.type.name === 'taskItem';\n if (turnIntoEnabled && (sourceIsTextblock || sourceIsWrapper)) {\n // For wrapper sources, walk from the inner textblock (blockPos + 1, past\n // the wrapper opening token) so it picks up listItem / taskList / blockquote.\n const ancestorPos = sourceIsTextblock ? blockPos : blockPos + 1;\n const $pos = editor.view.state.doc.resolve(ancestorPos);\n const ancestorTypeNames = new Set<string>();\n for (let d = 0; d <= $pos.depth; d++) {\n ancestorTypeNames.add($pos.node(d).type.name);\n }\n\n // The list kind directly wrapping the block's LABEL (the nearest list item\n // whose label slot the block sits in). A LIST target matching this is\n // hidden (\"you're already a bullet\"); a different kind stays available and\n // converts just this item / innermost sublist. Mirrors the slash menu, so\n // a bullet nested in an ordered list still offers \"Ordered list\".\n let labelWrapperType: string | null = null;\n for (let d = $pos.depth; d >= 1; d--) {\n const t = $pos.node(d).type.name;\n if (t === 'listItem' || t === 'taskItem') {\n if ($pos.index(d) === 0) labelWrapperType = $pos.node(d - 1).type.name;\n break;\n }\n }\n\n const eligible = turnIntoTargets.filter((target) => {\n const type = editor.view.state.schema.nodes[target.nodeType];\n if (!type) return false;\n\n if (target.command) {\n // A LIST target is hidden only when it is the innermost label wrapper\n // (converting to it would just lift the item out). Non-list wrapper\n // targets (Quote) keep the ancestor check: hidden only when already\n // inside that wrapper.\n if (LIST_WRAPPER_TYPES.has(target.nodeType)) {\n return target.nodeType !== labelWrapperType;\n }\n return !ancestorTypeNames.has(target.nodeType);\n }\n\n // Textblock target: eligible for a textblock source or a list-item\n // source (which is lifted out then converted in runTurnInto). A\n // blockquote wrapper source can't be, so it's excluded.\n if (!sourceIsTextblock && !sourceIsListItem) return false;\n if (!type.isTextblock) return false;\n // Skip targets identical to the current block (same type AND attrs,\n // e.g. hide \"Heading 1\" when already on H1). A wrapper source's type\n // (listItem) never equals a textblock target, so all are offered.\n if (type.name !== node.type.name) return true;\n const targetAttrs = target.attrs;\n if (!targetAttrs) return false;\n const nodeAttrs = node.attrs as Record<string, unknown>;\n for (const k of Object.keys(targetAttrs)) {\n if (nodeAttrs[k] !== (targetAttrs as Record<string, unknown>)[k]) return true;\n }\n return false;\n });\n\n if (eligible.length > 0) {\n const label = document.createElement('div');\n label.className = 'dm-block-context-menu-group-label';\n label.textContent = 'Turn into';\n root.appendChild(label);\n\n const group = document.createElement('div');\n group.className = 'dm-block-context-menu-group';\n group.setAttribute('role', 'group');\n group.setAttribute('aria-label', 'Turn into');\n\n for (const target of eligible) {\n group.appendChild(\n makeItem(target.label, target.icon, () => { runTurnInto(target); }),\n );\n }\n root.appendChild(group);\n }\n }\n };\n\n /**\n * Builds the chrome shared by every menu button (item + swatch):\n * role=menuitem, roving-tabindex registration, mousedown preventDefault\n * (keeps editor focus), click handler.\n */\n const createMenuButton = (config: {\n className: string;\n ariaLabel: string;\n onClick: () => void;\n attributes?: Record<string, string>;\n }): HTMLButtonElement => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = config.className;\n btn.setAttribute('role', 'menuitem');\n btn.setAttribute('aria-label', config.ariaLabel);\n if (config.attributes) {\n for (const [k, v] of Object.entries(config.attributes)) {\n btn.setAttribute(k, v);\n }\n }\n btn.tabIndex = menuItemButtons.length === 0 ? 0 : -1;\n btn.addEventListener('mousedown', (e: MouseEvent) => { e.preventDefault(); });\n btn.addEventListener('click', (e: MouseEvent) => {\n e.preventDefault();\n config.onClick();\n });\n menuItemButtons.push(btn);\n return btn;\n };\n\n /** Builds a menuitem button (icon + label) and registers it for nav. */\n const makeItem = (\n label: string,\n iconKey: string,\n onClick: () => void,\n ): HTMLButtonElement => {\n const btn = createMenuButton({\n className: 'dm-block-context-menu-item',\n ariaLabel: label,\n onClick,\n });\n\n // Icon SVG is trusted (our phosphor set), but `label` may come from\n // user-supplied `turnIntoTargets`, so use textContent for it.\n const iconHTML = defaultIcons[iconKey] ?? '';\n const iconSpan = document.createElement('span');\n iconSpan.className = 'dm-block-context-menu-item-icon';\n iconSpan.setAttribute('aria-hidden', 'true');\n iconSpan.innerHTML = iconHTML;\n\n const labelSpan = document.createElement('span');\n labelSpan.className = 'dm-block-context-menu-item-label';\n labelSpan.textContent = label;\n\n btn.appendChild(iconSpan);\n btn.appendChild(labelSpan);\n return btn;\n };\n\n /**\n * Builds one color swatch (`null` color = \"clear\", unsets the attribute).\n * Swatches join the roving-tabindex nav alongside menu items.\n */\n const makeSwatch = (\n variant: 'bg' | 'text',\n color: string | null,\n current: string | null,\n onClick: (c: string | null) => void,\n ): HTMLButtonElement => {\n const ariaLabel = color === null\n ? (variant === 'bg' ? 'No background' : 'Default text color')\n : `${variant === 'bg' ? 'Background' : 'Text color'}: ${color}`;\n const isPressed = (current === color || (color === null && !current));\n return createMenuButton({\n className: `dm-block-color-swatch dm-block-color-swatch--${variant}`,\n ariaLabel,\n onClick: () => { onClick(color); },\n attributes: {\n 'data-color': color ?? 'null',\n 'aria-pressed': isPressed ? 'true' : 'false',\n },\n });\n };\n\n /** Builds a labelled swatch row (text or background), led by a \"clear\" swatch. */\n const buildSwatchRow = (\n rowLabel: string,\n variant: 'bg' | 'text',\n palette: string[],\n current: string | null,\n onClick: (color: string | null) => void,\n ): HTMLElement => {\n const row = document.createElement('div');\n row.className = 'dm-block-color-row';\n row.setAttribute('role', 'group');\n row.setAttribute('aria-label', rowLabel);\n\n const visuallyHidden = document.createElement('span');\n visuallyHidden.className = 'dm-block-color-row-label';\n visuallyHidden.textContent = rowLabel;\n row.appendChild(visuallyHidden);\n\n row.appendChild(makeSwatch(variant, null, current, onClick));\n for (const c of palette) {\n row.appendChild(makeSwatch(variant, c, current, onClick));\n }\n return row;\n };\n\n /**\n * Opens the menu anchored to `anchorElement`, targeting `blockPos`.\n *\n * `detail.blockPos` is whatever BlockHandle resolved under the cursor,\n * including nested list items (with `BlockHandle.nested`). Don't re-resolve\n * to the top-level block here, else \"Delete\" on one list item would nuke the\n * whole list.\n */\n const open = (detail: BlockContextMenuOpenDetail): void => {\n if (!editorEl) return;\n\n const node = editor.view.state.doc.nodeAt(detail.blockPos);\n if (!node) return;\n\n currentBlockPos = detail.blockPos;\n renderItems(detail.blockPos);\n if (menuItemButtons.length === 0) return;\n\n // Set the signal BEFORE dispatching dismiss so BlockHandle's listener can\n // tell \"menu opening\" from \"another overlay dismissing me\" and keep the\n // drag handle anchored.\n editorEl.setAttribute('data-block-context-menu-open', '');\n editorEl.dispatchEvent(new Event('dm:dismiss-overlays', { bubbles: false }));\n root.setAttribute('data-show', '');\n lockScroll();\n const openTr = editor.view.state.tr.setMeta(pluginKey, { activeBlockPos: detail.blockPos });\n openTr.setMeta('addToHistory', false);\n editor.view.dispatch(openTr);\n\n cleanupFloating?.();\n // Virtual reference: caches the last valid rect for when the anchor\n // disconnects. Bubble menus rebuild their DOM via `replaceChildren()` on\n // every transaction, orphaning the anchor; without caching, autoUpdate\n // recomputes against a zero rect and the menu flies to the corner.\n let anchorEl: HTMLElement = detail.anchorElement;\n const bubbleMenuRef = anchorEl.closest<HTMLElement>('.dm-bubble-menu');\n const matchingSelector = matchingSelectorFor(anchorEl);\n let lastRect = anchorEl.getBoundingClientRect();\n const virtualRef: { getBoundingClientRect: () => DOMRect } = {\n getBoundingClientRect: () => {\n if (anchorEl.isConnected) {\n lastRect = anchorEl.getBoundingClientRect();\n return lastRect;\n }\n // Anchor disconnected: find an equivalent in the same bubble menu so\n // the menu tracks live DOM instead of pinning to the stale rect.\n if (matchingSelector && bubbleMenuRef?.isConnected) {\n const fresh = bubbleMenuRef.querySelector<HTMLElement>(matchingSelector);\n if (fresh) {\n anchorEl = fresh;\n lastRect = fresh.getBoundingClientRect();\n return lastRect;\n }\n }\n return lastRect;\n },\n };\n cleanupFloating = positionFloatingOnce(virtualRef, root, {\n placement: 'right-start',\n offsetValue: 4,\n });\n\n // Focus the first item (keyboard nav). Wait a frame for layout so focus\n // sees the visible element; `hide()` can cancel the rAF if we close first.\n focusedIndex = 0;\n initialFocusRaf = requestAnimationFrame(() => {\n initialFocusRaf = null;\n menuItemButtons[0]?.focus();\n });\n };\n\n // Event handlers.\n const onOpen = (event: Event): void => {\n // Widen detail to `T | undefined` to keep the runtime guard against a\n // plain Event dispatched without detail.\n const detail = (event as CustomEvent<BlockContextMenuOpenDetail | undefined>).detail;\n if (!detail) return;\n open(detail);\n };\n\n const onDismiss = (): void => {\n if (!isOpen()) return;\n hide();\n };\n\n const onClickOutside = (event: Event): void => {\n if (!isOpen()) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (root.contains(target)) return;\n hide();\n };\n\n const onKeyDown = (event: KeyboardEvent): void => {\n if (!isOpen()) return;\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusItem((focusedIndex + 1) % menuItemButtons.length);\n return;\n case 'ArrowUp':\n event.preventDefault();\n focusItem((focusedIndex - 1 + menuItemButtons.length) % menuItemButtons.length);\n return;\n case 'Home':\n event.preventDefault();\n focusItem(0);\n return;\n case 'End':\n event.preventDefault();\n focusItem(menuItemButtons.length - 1);\n return;\n case 'Escape':\n event.preventDefault();\n event.stopPropagation();\n hide();\n editor.view.focus();\n return;\n default:\n return;\n }\n };\n\n return new Plugin<BlockContextMenuPluginState>({\n key: pluginKey,\n state: {\n init: () => ({ activeBlockPos: null }),\n apply(tr, value) {\n const meta = tr.getMeta(pluginKey) as { activeBlockPos?: number | null } | undefined;\n if (meta && 'activeBlockPos' in meta) {\n return { activeBlockPos: meta.activeBlockPos ?? null };\n }\n // Remap across doc changes so the highlight tracks structural edits.\n if (value.activeBlockPos !== null && tr.docChanged) {\n const mapped = tr.mapping.mapResult(value.activeBlockPos, 1);\n return { activeBlockPos: mapped.deleted ? null : mapped.pos };\n }\n return value;\n },\n },\n props: {\n decorations(state) {\n const plugin = pluginKey.getState(state);\n const activePos = plugin?.activeBlockPos ?? null;\n if (activePos === null) return null;\n const node = state.doc.nodeAt(activePos);\n if (!node) return null;\n return DecorationSet.create(state.doc, [\n Decoration.node(activePos, activePos + node.nodeSize, { class: 'dm-block-context-active' }),\n ]);\n },\n },\n\n view: (editorView) => {\n editorEl = editorView.dom.closest('.dm-editor');\n if (!editorEl) return { destroy: () => { /* noop */ } };\n\n editorEl.appendChild(root);\n hide();\n\n editorEl.addEventListener('dm:block-context-menu-open', onOpen);\n editorEl.addEventListener('dm:dismiss-overlays', onDismiss);\n document.addEventListener('mousedown', onClickOutside, true);\n root.addEventListener('keydown', onKeyDown);\n\n return {\n destroy: () => {\n hide();\n editorEl?.removeEventListener('dm:block-context-menu-open', onOpen);\n editorEl?.removeEventListener('dm:dismiss-overlays', onDismiss);\n document.removeEventListener('mousedown', onClickOutside, true);\n root.removeEventListener('keydown', onKeyDown);\n root.remove();\n editorEl = null;\n },\n };\n },\n });\n}\n\nexport const BlockContextMenu = Extension.create<BlockContextMenuOptions>({\n name: 'blockContextMenu',\n\n addOptions() {\n return {\n turnIntoEnabled: true,\n turnIntoTargets: DEFAULT_TURN_INTO,\n copyLinkEnabled: true,\n onCopyLink: defaultCopyLinkUrl,\n blockColorEnabled: true,\n };\n },\n\n addProseMirrorPlugins() {\n const editor = this.editor as Editor | null;\n if (!editor) return [];\n // Re-apply defaults to narrow the optional public option types back to\n // non-optional for the plugin factory.\n const opts = this.options;\n return [\n createBlockContextMenuPlugin({\n pluginKey: blockContextMenuPluginKey,\n editor,\n turnIntoEnabled: opts.turnIntoEnabled ?? true,\n turnIntoTargets: opts.turnIntoTargets ?? DEFAULT_TURN_INTO,\n copyLinkEnabled: opts.copyLinkEnabled ?? true,\n onCopyLink: opts.onCopyLink ?? defaultCopyLinkUrl,\n blockColorEnabled: opts.blockColorEnabled ?? true,\n }),\n ];\n },\n});\n","/**\n * Default DOM renderer factory for SlashCommand. Returns suggestion callbacks\n * that build and manage a grouped popup anchored at the cursor, mirroring the\n * Mention/Emoji renderer pattern.\n *\n * The popup reuses FloatingMenu's accessibility vocabulary: `role=\"menu\"`\n * container, `role=\"group\"` sections, `role=\"menuitem\"` buttons with\n * icon + label + shortcut layout. The `dm-slash-command-menu` root scopes SCSS.\n */\nimport {\n defaultIcons,\n groupFloatingMenuItems,\n positionFloatingOnce,\n} from '@domternal/core';\nimport type { FloatingMenuItem } from '@domternal/core';\nimport type { SlashCommandProps, SlashCommandRenderer } from './SlashCommand.js';\n\n// Unique id suffixes so `aria-activedescendant` on the menu root can announce\n// the selection to screen readers as the user arrow-keys through items.\nlet idCounter = 0;\n\nexport function createSlashSuggestionRenderer(): SlashCommandRenderer {\n let root: HTMLDivElement | null = null;\n let cleanupFloating: (() => void) | null = null;\n // Flat list of rendered menuitem buttons, parallel to filtered item list.\n let itemButtons: HTMLButtonElement[] = [];\n let flatItems: FloatingMenuItem[] = [];\n let selectedIndex = 0;\n let currentCommand: SlashCommandProps['command'] | null = null;\n // Set during onExit so a pending queued event (e.g. trailing mousedown+click\n // mid-teardown) can bail instead of dispatching into a destroyed editor.\n let destroyed = false;\n const rendererId = `dm-slash-${String(++idCounter)}`;\n\n const renderPopup = (props: SlashCommandProps): void => {\n if (!root) return;\n root.innerHTML = '';\n itemButtons = [];\n flatItems = [];\n\n if (props.items.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'dm-slash-command-empty';\n // status + aria-live=polite announces the filter result without stealing focus.\n empty.setAttribute('role', 'status');\n empty.setAttribute('aria-live', 'polite');\n empty.textContent = 'No matches';\n root.appendChild(empty);\n return;\n }\n\n const groups = groupFloatingMenuItems(props.items);\n for (const group of groups) {\n if (group.name) {\n const label = document.createElement('div');\n label.className = 'dm-slash-command-group-label';\n label.textContent = group.name;\n root.appendChild(label);\n }\n const groupEl = document.createElement('div');\n groupEl.className = 'dm-slash-command-group';\n groupEl.setAttribute('role', 'group');\n if (group.name) groupEl.setAttribute('aria-label', group.name);\n\n for (const item of group.items) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'dm-slash-command-item';\n btn.setAttribute('role', 'menuitem');\n btn.setAttribute('aria-label', item.label);\n btn.tabIndex = -1;\n // Stable per-button id for the root's `aria-activedescendant`.\n btn.id = `${rendererId}-item-${String(flatItems.length)}`;\n\n // Only the icon SVG (from our trusted phosphor set) is interpolated as\n // HTML. label/description/shortcut use textContent since FloatingMenuItem\n // fields may come from arbitrary extension authors (XSS).\n const iconHTML = item.icon ? (defaultIcons[item.icon] ?? '') : '';\n if (iconHTML) {\n const iconSpan = document.createElement('span');\n iconSpan.className = 'dm-slash-command-item-icon';\n iconSpan.setAttribute('aria-hidden', 'true');\n iconSpan.innerHTML = iconHTML;\n btn.appendChild(iconSpan);\n }\n\n const textSpan = document.createElement('span');\n textSpan.className = 'dm-slash-command-item-text';\n\n const labelSpan = document.createElement('span');\n labelSpan.className = 'dm-slash-command-item-label';\n labelSpan.textContent = item.label;\n textSpan.appendChild(labelSpan);\n\n if (item.description) {\n const descSpan = document.createElement('span');\n descSpan.className = 'dm-slash-command-item-description';\n descSpan.textContent = item.description;\n textSpan.appendChild(descSpan);\n }\n\n btn.appendChild(textSpan);\n\n if (item.shortcut) {\n const shortcutSpan = document.createElement('span');\n shortcutSpan.className = 'dm-slash-command-item-shortcut';\n shortcutSpan.setAttribute('aria-hidden', 'true');\n shortcutSpan.textContent = item.shortcut;\n btn.appendChild(shortcutSpan);\n }\n\n const indexForItem = flatItems.length;\n btn.addEventListener('mousedown', (e: MouseEvent) => { e.preventDefault(); });\n btn.addEventListener('mouseenter', () => { selectItem(indexForItem); });\n btn.addEventListener('click', (e: MouseEvent) => {\n e.preventDefault();\n // A mousedown-to-click pair can span `onExit` if the popup was\n // dismissed by an outside event while the button was held.\n if (destroyed) return;\n currentCommand?.(item);\n });\n\n itemButtons.push(btn);\n flatItems.push(item);\n groupEl.appendChild(btn);\n }\n root.appendChild(groupEl);\n }\n\n if (selectedIndex >= flatItems.length) selectedIndex = 0;\n highlight(selectedIndex);\n };\n\n const highlight = (index: number): void => {\n for (const [i, btn] of itemButtons.entries()) {\n if (i === index) {\n btn.setAttribute('data-selected', '');\n } else {\n btn.removeAttribute('data-selected');\n }\n }\n const selected = itemButtons[index];\n // Scroll within the popup only, never via `scrollIntoView`: that walks\n // ancestors and would yank the page during `renderPopup`, which runs before\n // `positionFloatingOnce` while the popup is still at its natural flow\n // position at the bottom of `.dm-editor`.\n if (root && selected) {\n const btnTop = selected.offsetTop;\n const btnBottom = btnTop + selected.offsetHeight;\n const viewTop = root.scrollTop;\n const viewBottom = viewTop + root.clientHeight;\n if (btnTop < viewTop) root.scrollTop = btnTop;\n else if (btnBottom > viewBottom) root.scrollTop = btnBottom - root.clientHeight;\n root.setAttribute('aria-activedescendant', selected.id);\n } else {\n root?.removeAttribute('aria-activedescendant');\n }\n };\n\n const selectItem = (index: number): void => {\n if (index < 0 || index >= itemButtons.length) return;\n selectedIndex = index;\n highlight(index);\n };\n\n const reposition = (props: SlashCommandProps): void => {\n if (!root) return;\n cleanupFloating?.();\n // Callable virtualRef so floating-ui's autoUpdate reads fresh cursor coords\n // every tick. Capturing a single rect would freeze the anchor and drift on\n // scroll. Mirrors the emoji suggestion renderer.\n const virtualRef = {\n getBoundingClientRect: (): DOMRect => props.clientRect() ?? new DOMRect(),\n };\n cleanupFloating = positionFloatingOnce(\n virtualRef,\n root,\n { placement: 'bottom-start', offsetValue: 4 },\n );\n };\n\n return {\n onStart(props): void {\n currentCommand = props.command;\n selectedIndex = 0;\n destroyed = false;\n\n root = document.createElement('div');\n root.className = 'dm-slash-command-menu';\n root.setAttribute('role', 'menu');\n root.setAttribute('aria-label', 'Insert block');\n root.setAttribute('data-dm-editor-ui', '');\n\n const editorEl = props.element.closest('.dm-editor');\n (editorEl ?? document.body).appendChild(root);\n root.setAttribute('data-show', '');\n\n renderPopup(props);\n reposition(props);\n },\n\n onUpdate(props): void {\n currentCommand = props.command;\n if (!root) return;\n renderPopup(props);\n reposition(props);\n },\n\n onExit(): void {\n destroyed = true;\n cleanupFloating?.();\n cleanupFloating = null;\n root?.remove();\n root = null;\n itemButtons = [];\n flatItems = [];\n selectedIndex = 0;\n currentCommand = null;\n },\n\n onKeyDown(event): boolean {\n if (!root || flatItems.length === 0) return false;\n\n switch (event.key) {\n case 'ArrowDown':\n selectItem((selectedIndex + 1) % flatItems.length);\n return true;\n case 'ArrowUp':\n selectItem((selectedIndex - 1 + flatItems.length) % flatItems.length);\n return true;\n case 'Home':\n selectItem(0);\n return true;\n case 'End':\n selectItem(flatItems.length - 1);\n return true;\n case 'Enter':\n case 'Tab': {\n const item = flatItems[selectedIndex];\n if (item && currentCommand) currentCommand(item);\n return true;\n }\n default:\n return false;\n }\n },\n };\n}\n","/**\n * `/` trigger that opens a filtered popup of insertable blocks. Items are\n * shared with FloatingMenu and BlockHandle via `addFloatingMenuItems()`.\n * On select, the `/query` range is deleted and the item's command runs at\n * the now-empty cursor (so \"Heading 1\" transforms the block, \"Image\" opens\n * its popover, etc.).\n */\nimport {\n Extension,\n FloatingMenuController,\n} from '@domternal/core';\nimport type {\n Editor,\n FloatingMenuItem,\n FloatingMenuItemsOverride,\n} from '@domternal/core';\nimport { Plugin, PluginKey } from '@domternal/pm/state';\nimport type { EditorState, Transaction } from '@domternal/pm/state';\nimport type { EditorView } from '@domternal/pm/view';\nimport { Decoration, DecorationSet } from '@domternal/pm/view';\nimport { ReplaceStep } from '@domternal/pm/transform';\nimport { createSlashSuggestionRenderer } from './createSlashSuggestionRenderer.js';\n\nexport const slashCommandPluginKey = new PluginKey<SlashCommandPluginState>('slashCommand');\n\n// Object Replacement Character (U+FFFC). ProseMirror uses it as the placeholder\n// for leaf nodes when flattening a range to a string.\nconst PM_LEAF_PLACEHOLDER = '';\n\n// ─── Public renderer contract ─────────────────────────────────────────────\n\nexport interface SlashCommandProps {\n /** The editor instance (passed so custom renderers can read state). */\n editor: Editor;\n /** Current query string (text after the `/`). */\n query: string;\n /** Document range of the `/` + query (for replacement). */\n range: { from: number; to: number };\n /** Filtered and ranked items matching the query. */\n items: FloatingMenuItem[];\n /** Execute the selected item and close the popup. */\n command: (item: FloatingMenuItem) => void;\n /** Returns the client rect of the cursor for positioning the popup. */\n clientRect: () => DOMRect | null;\n /** The editor's ProseMirror DOM node (for portal parents etc.). */\n element: HTMLElement;\n}\n\nexport interface SlashCommandRenderer {\n onStart: (props: SlashCommandProps) => void;\n onUpdate: (props: SlashCommandProps) => void;\n onExit: () => void;\n /** Return `true` to consume the key event and prevent default handling. */\n onKeyDown: (event: KeyboardEvent) => boolean;\n}\n\n// ─── Options ──────────────────────────────────────────────────────────────\n\nexport interface SlashCommandOptions {\n /**\n * The trigger character. @default '/'\n */\n char?: string;\n /**\n * Items override. When omitted, items from `editor.floatingMenuItems`\n * (collected via `addFloatingMenuItems()`) are used. An array replaces\n * defaults; a function transforms them.\n */\n items?: FloatingMenuItemsOverride;\n /**\n * Factory returning render callbacks for the popup. Default uses\n * `createSlashSuggestionRenderer()`.\n */\n render?: () => SlashCommandRenderer;\n /**\n * Node types where slash should NOT activate (e.g. `codeBlock`).\n * @default ['codeBlock']\n */\n invalidNodes?: string[];\n}\n\nexport interface CreateSlashCommandPluginOptions {\n pluginKey: PluginKey<SlashCommandPluginState>;\n editor: Editor;\n char: string;\n items?: FloatingMenuItemsOverride;\n render: () => SlashCommandRenderer;\n invalidNodes: string[];\n}\n\n// ─── Internal state ───────────────────────────────────────────────────────\n\nexport interface SlashCommandPluginState {\n active: boolean;\n query: string;\n range: { from: number; to: number } | null;\n}\n\nconst INITIAL_STATE: SlashCommandPluginState = {\n active: false,\n query: '',\n range: null,\n};\n\n/**\n * \"Did the user just type the trigger char?\" heuristic that gates popup\n * activation. True only for a single ReplaceStep inserting exactly the trigger\n * char (single-char slice, no depth). Rejects paste / programmatic insert\n * (slice.size > 1), selection-only changes (no steps), and undo/redo.\n *\n * Tying activation to the typing event, not the static presence of `/`,\n * matches Notion: a dismissed `/` becomes plain text and won't reopen the\n * popup when the user later clicks next to it.\n */\nfunction justTypedTrigger(tr: Transaction, char: string): boolean {\n if (tr.steps.length !== 1) return false;\n const step = tr.steps[0];\n if (!(step instanceof ReplaceStep)) return false;\n const slice = step.slice;\n if (slice.size !== 1 || slice.openStart !== 0 || slice.openEnd !== 0) return false;\n const node = slice.content.firstChild;\n return !!(node && node.isText && node.text === char);\n}\n\n/** Resolves the current `/query` at the cursor, or null if not on a qualifying line. */\nfunction findSlashQuery(\n state: EditorState,\n triggerChar: string,\n invalidNodes: string[],\n): { query: string; range: { from: number; to: number } } | null {\n const { selection } = state;\n if (!selection.empty) return null;\n\n const { $from } = selection;\n // Disallow in code blocks and any explicitly blocked node types.\n if ($from.parent.type.spec.code) return null;\n if (invalidNodes.includes($from.parent.type.name)) return null;\n\n const textBefore = $from.parent.textBetween(\n 0,\n $from.parentOffset,\n undefined,\n PM_LEAF_PLACEHOLDER,\n );\n const triggerIndex = textBefore.lastIndexOf(triggerChar);\n if (triggerIndex === -1) return null;\n\n // Trigger must be at textblock start OR preceded by whitespace.\n if (triggerIndex > 0 && !/\\s/.test(textBefore[triggerIndex - 1] ?? '')) return null;\n\n const queryText = textBefore.slice(triggerIndex + triggerChar.length);\n // Block queries that contain newlines or tabs (they'd break display).\n if (/[\\n\\t]/.test(queryText)) return null;\n\n const from = $from.start() + triggerIndex;\n const to = $from.pos;\n return { query: queryText, range: { from, to } };\n}\n\n/**\n * Removes items whose `hideWhenInside` matches the cursor's wrapping list type,\n * but ONLY when the cursor is in the label paragraph (first-child slot) of a\n * list item: picking the same list type there would lift the user out of the\n * list (`liftListItem` semantics), which is surprising.\n *\n * In the children zone (non-first paragraph) it's kept on purpose: picking the\n * same list type creates a nested sublist, which is useful and Notion-like.\n */\nexport function filterByCursorAncestors(\n items: FloatingMenuItem[],\n editor: Editor,\n): FloatingMenuItem[] {\n const { $from } = editor.view.state.selection;\n\n // Find the nearest list-item ancestor; if the cursor is in its label slot,\n // record the wrapping list's type name.\n let wrappingListType: string | null = null;\n for (let d = $from.depth; d >= 1; d--) {\n const t = $from.node(d).type.name;\n if (t === 'listItem' || t === 'taskItem') {\n if ($from.index(d) === 0 && d >= 1) {\n wrappingListType = $from.node(d - 1).type.name;\n }\n break;\n }\n }\n\n return items.filter((item) => {\n if (!item.hideWhenInside || item.hideWhenInside.length === 0) return true;\n if (!wrappingListType) return true;\n return !item.hideWhenInside.includes(wrappingListType);\n });\n}\n\n/**\n * Filters and ranks FloatingMenuItems against a query. Priority:\n * 1. Exact label prefix (case-insensitive)\n * 2. Label substring match\n * 3. Keyword match (preserving original keyword index for stable ranking)\n * Returns items in rank order, stable within the same rank.\n */\nexport function filterSlashItems(items: FloatingMenuItem[], query: string): FloatingMenuItem[] {\n if (query.length === 0) return items;\n const q = query.toLowerCase();\n\n const ranked: { item: FloatingMenuItem; score: number }[] = [];\n for (const item of items) {\n const label = item.label.toLowerCase();\n if (label.startsWith(q)) {\n ranked.push({ item, score: 0 });\n continue;\n }\n if (label.includes(q)) {\n ranked.push({ item, score: 1 });\n continue;\n }\n const keywords = item.keywords ?? [];\n const kwIndex = keywords.findIndex((k) => k.toLowerCase().includes(q));\n if (kwIndex !== -1) {\n ranked.push({ item, score: 2 + kwIndex * 0.01 });\n }\n }\n ranked.sort((a, b) => a.score - b.score);\n return ranked.map((r) => r.item);\n}\n\n// ─── Plugin factory ───────────────────────────────────────────────────────\n\nexport function createSlashCommandPlugin(\n options: CreateSlashCommandPluginOptions,\n): Plugin<SlashCommandPluginState> {\n const { pluginKey, editor, char, items: itemsOverride, render, invalidNodes } = options;\n let renderer: SlashCommandRenderer | null = null;\n\n return new Plugin<SlashCommandPluginState>({\n key: pluginKey,\n\n state: {\n init: (): SlashCommandPluginState => ({ ...INITIAL_STATE }),\n apply(tr: Transaction, prev, _oldState, newState): SlashCommandPluginState {\n if (tr.getMeta(pluginKey) === 'dismiss') return { ...INITIAL_STATE };\n\n // Neither doc nor selection changed: popup stays as-is.\n if (!tr.docChanged && !tr.selectionSet) return prev;\n\n // Branch 1: popup already active.\n // The query is the text between the trigger (`range.from`) and the\n // typed-end (`range.to`). `range.to` tracks WHAT THE USER TYPED, not\n // the cursor, so arrowing past existing text doesn't swallow chars\n // into the query.\n if (prev.active && prev.range) {\n let { from, to } = prev.range;\n\n if (tr.docChanged) {\n // Default bias (right): an insertion at the trigger position\n // pushes `/` forward and `from` follows; same for `to` so a char\n // typed at the query end extends the range.\n const fromResult = tr.mapping.mapResult(from);\n const toResult = tr.mapping.mapResult(to);\n if (fromResult.deleted) return { ...INITIAL_STATE };\n from = fromResult.pos;\n to = toResult.pos;\n\n // If the trigger char was replaced (autocomplete inserting at\n // `from`, paste over it), the session is gone.\n if (\n newState.doc.textBetween(from, from + 1, undefined, PM_LEAF_PLACEHOLDER) !== char\n ) {\n return { ...INITIAL_STATE };\n }\n }\n\n // Range selections make no sense for a single-cursor popup.\n if (!newState.selection.empty) return { ...INITIAL_STATE };\n const cursor = newState.selection.from;\n\n // Cursor must stay at or after the first query char (just past `/`).\n if (cursor < from + 1) return { ...INITIAL_STATE };\n\n if (cursor > to) {\n // Past the typed end is only legal as a side-effect of typing more\n // chars; a pure selection move past `to` means the user left the session.\n if (!tr.docChanged) return { ...INITIAL_STATE };\n to = cursor;\n }\n\n // Defensive: a collab edit may have turned the block into a code\n // block / invalidNodes type, where the session shouldn't survive.\n const $cursor = newState.doc.resolve(cursor);\n if ($cursor.parent.type.spec.code) return { ...INITIAL_STATE };\n if (invalidNodes.includes($cursor.parent.type.name)) {\n return { ...INITIAL_STATE };\n }\n\n const query = newState.doc.textBetween(\n from + 1,\n to,\n undefined,\n PM_LEAF_PLACEHOLDER,\n );\n if (/[\\n\\t]/.test(query)) return { ...INITIAL_STATE };\n\n return { active: true, query, range: { from, to } };\n }\n\n // Branch 2: popup inactive. Activation is gated to a real typing event\n // of the trigger char. Selection-only changes and bulk doc changes\n // (paste, programmatic insert) must NOT open the popup even when the\n // cursor lands right after an existing `/` (see justTypedTrigger).\n if (!tr.docChanged) return prev;\n if (!justTypedTrigger(tr, char)) return prev;\n\n const result = findSlashQuery(newState, char, invalidNodes);\n if (result) return { active: true, query: result.query, range: result.range };\n return prev;\n },\n },\n\n view(editorView) {\n // Cooperative dismissal: overlays broadcast `dm:dismiss-overlays` when\n // they open, so two floating menus never coexist. Suppress the handler\n // while WE dispatch, else the synchronous event would self-dismiss the\n // popup before `update` reaches `renderer.onStart`.\n const editorEl = editorView.dom.closest<HTMLElement>('.dm-editor');\n let suppressDismissHandler = false;\n const dismissHandler = (): void => {\n if (suppressDismissHandler) return;\n const state = pluginKey.getState(editor.view.state);\n if (state?.active) dismissSlashCommand(editor.view);\n };\n editorEl?.addEventListener('dm:dismiss-overlays', dismissHandler);\n\n // Fire the open-time dismiss only on the false->true transition.\n let wasActive = false;\n\n return {\n update(view: EditorView) {\n const state = pluginKey.getState(view.state);\n if (!state) return;\n\n // On activation, broadcast dismiss to close other overlays;\n // `suppressDismissHandler` keeps our own listener from self-dismissing.\n //\n // Flip `wasActive = true` BEFORE dispatching: the synchronous\n // dispatch re-enters this `update` (e.g. BlockHandle's\n // `onDismissOverlays` dispatches its own transaction). If `wasActive`\n // were still false the re-entry would fire a second\n // `dm:dismiss-overlays` whose nested `finally` clears\n // `suppressDismissHandler`, letting our listener tear down the popup\n // we just created (and a null `clientRect()` then paints it unpositioned).\n const becameActive = state.active && !wasActive;\n wasActive = state.active;\n if (becameActive) {\n suppressDismissHandler = true;\n try {\n editorEl?.dispatchEvent(new Event('dm:dismiss-overlays', { bubbles: false }));\n } finally {\n suppressDismissHandler = false;\n }\n }\n\n if (state.active && state.range) {\n const items = FloatingMenuController.resolveItems(editor, itemsOverride);\n const contextual = filterByCursorAncestors(items, editor);\n const filtered = filterSlashItems(contextual, state.query);\n\n const command = (item: FloatingMenuItem): void => {\n const current = pluginKey.getState(view.state);\n if (!current?.range) return;\n\n // Delete the `/query` range first so the item's command runs on\n // a clean cursor. Close popup state in the same tr to avoid a flash.\n const tr = view.state.tr;\n tr.delete(current.range.from, current.range.to);\n tr.setMeta(pluginKey, 'dismiss');\n view.dispatch(tr);\n\n // Execute on a fresh transaction (reads latest state). No focus()\n // call: items that open a popover need it to claim focus, and\n // simple inserts already leave focus in the editor.\n FloatingMenuController.executeItem(editor, item);\n };\n\n const clientRect = (): DOMRect | null => {\n const current = pluginKey.getState(view.state);\n if (!current?.range) return null;\n try {\n const coords = view.coordsAtPos(current.range.from);\n return new DOMRect(\n coords.left,\n coords.top,\n 0,\n coords.bottom - coords.top,\n );\n } catch {\n return null;\n }\n };\n\n const props: SlashCommandProps = {\n editor,\n query: state.query,\n range: state.range,\n items: filtered,\n command,\n clientRect,\n element: view.dom,\n };\n\n if (!renderer) {\n renderer = render();\n renderer.onStart(props);\n } else {\n renderer.onUpdate(props);\n }\n } else if (renderer) {\n renderer.onExit();\n renderer = null;\n }\n },\n\n destroy() {\n editorEl?.removeEventListener('dm:dismiss-overlays', dismissHandler);\n if (renderer) {\n try {\n renderer.onExit();\n } finally {\n renderer = null;\n }\n }\n },\n };\n },\n\n props: {\n // handleDOMEvents.keydown (not handleKeyDown) so we intercept keys before\n // other keymap plugins claim them (same trick as Mention).\n handleDOMEvents: {\n keydown(view, event): boolean {\n const state = pluginKey.getState(view.state);\n if (!state?.active) return false;\n\n if (event.key === 'Escape') {\n event.preventDefault();\n const tr = view.state.tr;\n tr.setMeta(pluginKey, 'dismiss');\n view.dispatch(tr);\n return true;\n }\n\n if (renderer) {\n const handled = renderer.onKeyDown(event);\n if (handled) event.preventDefault();\n return handled;\n }\n return false;\n },\n },\n\n decorations(state): DecorationSet {\n const pluginState = pluginKey.getState(state);\n if (!pluginState?.active || !pluginState.range) return DecorationSet.empty;\n return DecorationSet.create(state.doc, [\n Decoration.inline(pluginState.range.from, pluginState.range.to, {\n class: 'dm-slash-command-query',\n nodeName: 'span',\n }),\n ]);\n },\n },\n });\n}\n\nexport const SlashCommand = Extension.create<SlashCommandOptions>({\n name: 'slashCommand',\n\n addOptions() {\n return {\n char: '/',\n invalidNodes: ['codeBlock'],\n };\n },\n\n addProseMirrorPlugins() {\n const editor = this.editor as Editor | null;\n if (!editor) return [];\n return [\n createSlashCommandPlugin({\n pluginKey: slashCommandPluginKey,\n editor,\n char: this.options.char ?? '/',\n ...(this.options.items !== undefined && { items: this.options.items }),\n render: this.options.render ?? createSlashSuggestionRenderer,\n invalidNodes: this.options.invalidNodes ?? ['codeBlock'],\n }),\n ];\n },\n});\n\n/** Programmatically dismisses the slash suggestion. */\nexport function dismissSlashCommand(view: EditorView): void {\n view.dispatch(view.state.tr.setMeta(slashCommandPluginKey, 'dismiss'));\n}\n","/**\n * Pasting block-level content at an INLINE position normally goes through PM's\n * content fitter, which strips the block wrapper and pastes only inline text.\n * SmartPaste catches the relevant cases and routes each to the right strategy:\n *\n * 1. List slice into a list ancestor: same-kind items merge as siblings; a\n * different-kind list keeps its kind and splits the host list around it.\n * 2. Trailing hardBreak (Shift+Enter): trim the hardBreak, insert as sibling.\n * 3. Truly empty parent paragraph (`parentSize === 0`): replace the parent.\n * 4-6. Caret at start / end / middle: insert as sibling or split-and-insert.\n * 7. Range selection: delete first, then run through 2-6.\n *\n * Skipped (PM default applies) when: cursor isn't in a textblock; the slice's\n * top-level blocks are ALL plain paragraphs; or the slice is a SINGLE top-level\n * block of the SAME TYPE as the destination (heading-into-heading, etc.) where\n * PM's inline merge is what the user wants.\n *\n * Do NOT bail on `openStart > 0`: PM's clipboard parser routinely sets\n * `openStart=1` even for closed-looking input like `<h1>x</h1>`. Top-level\n * children of the slice are what matter.\n */\n\nimport { Extension } from '@domternal/core';\nimport { Plugin, TextSelection, Selection } from '@domternal/pm/state';\nimport { Fragment } from '@domternal/pm/model';\nimport type { Slice, Node as PMNode, ResolvedPos, NodeType } from '@domternal/pm/model';\nimport type { EditorView } from '@domternal/pm/view';\nimport type { Transaction } from '@domternal/pm/state';\nimport { insertBlockSplittingList } from './helpers/moveBlock.js';\n\nconst LIST_TYPES = new Set(['bulletList', 'orderedList', 'taskList']);\nconst LIST_ITEM_TYPES = new Set(['listItem', 'taskItem']);\n\nexport interface SmartPasteOptions {\n /**\n * Disable the plugin without removing the extension (falls back to PM's\n * default paste handling).\n * @default true\n */\n enabled?: boolean;\n}\n\nexport const SmartPaste = Extension.create<SmartPasteOptions>({\n name: 'smartPaste',\n\n addOptions() {\n return {\n enabled: true,\n };\n },\n\n addProseMirrorPlugins() {\n if (this.options.enabled === false) return [];\n return [\n new Plugin({\n props: {\n handlePaste: (view, _event, slice) => handleSmartPaste(view, slice),\n },\n }),\n ];\n },\n});\n\n/** Returns `true` when this plugin handled the paste (PM skips its default). */\nfunction handleSmartPaste(view: EditorView, slice: Slice): boolean {\n const { state } = view;\n const { selection } = state;\n const $from = selection.$from;\n\n // Cursor must be inline (inside a textblock); else PM's default is correct.\n if (!$from.parent.isTextblock) return false;\n\n // No non-paragraph block at top level: PM merges plain inline content cleanly.\n if (!sliceHasNonParagraphBlock(slice)) return false;\n\n // Single block of the SAME TYPE as the destination (e.g. <h1> into <h1>):\n // splitting the parent to \"preserve\" the wrapper would shred the heading\n // into three pieces. PM's default inline merge is what the user wants.\n if (sliceIsSingleSameTypeAsParent(slice, $from.parent.type.name)) return false;\n\n // Strategy 1: list-slice into list ancestor, merge as siblings.\n if (tryPasteListSliceIntoList(view, slice)) return true;\n\n // Strategies 2-7: collapse range, then route by parent state + offset.\n const tr = state.tr;\n if (!selection.empty) tr.deleteSelection();\n\n const $pos = tr.selection.$from;\n const parent = $pos.parent;\n const parentStart = $pos.before($pos.depth);\n const parentEnd = $pos.after($pos.depth);\n const offset = $pos.parentOffset;\n const parentSize = parent.content.size;\n\n // Caret sits in the LABEL paragraph (child 0) of a list/task item. The label\n // is the schema-required first child of `paragraph block*`, so inserting before\n // it (offset 0) would wedge the block INSIDE the item.\n const isListItemLabel = $pos.depth >= 2\n && LIST_ITEM_TYPES.has($pos.node($pos.depth - 1).type.name)\n && $pos.index($pos.depth - 1) === 0;\n\n if (hasTrailingHardBreakAtCursor(parent, offset, parentSize)) {\n // Shift+Enter: trim the trailing hardBreak, insert the slice as a SIBLING\n // after the parent. Text before the break is preserved (\"Existing<br>|\"\n // keeps \"Existing\" as a paragraph, heading lands next). Empty case\n // \"<p><br></p>\" becomes \"<p></p>\" + slice.\n const hbStart = parentEnd - 2; // hardBreak occupies 1 position before parent close\n const hbEnd = parentEnd - 1;\n tr.delete(hbStart, hbEnd);\n const adjustedParentEnd = parentEnd - 1;\n tr.insert(adjustedParentEnd, slice.content);\n setCaretAtEndOfInserted(tr, adjustedParentEnd, slice.content);\n } else if (parentSize === 0) {\n // Truly-empty parent: replace it with the slice so we don't leave a stray\n // empty paragraph beside the inserted block.\n //\n // Carve-out: when the empty paragraph is the LABEL slot of a\n // listItem/taskItem, replacing it would be schema-invalid or make PM's\n // content fitter inject a fresh empty paragraph. Insert AFTER the label\n // instead, so the content attaches as a nested child below the (still\n // empty) label.\n if (isListItemLabel) {\n tr.insert(parentEnd, slice.content);\n setCaretAtEndOfInserted(tr, parentEnd, slice.content);\n } else {\n tr.replaceWith(parentStart, parentEnd, slice.content);\n setCaretAtEndOfInserted(tr, parentStart, slice.content);\n }\n } else if (offset === 0) {\n if (isListItemLabel) {\n // Caret at the START of a list-item label: a non-list block keeps its type\n // and SPLITS the host list around the item (it lands at list level), rather\n // than being wedged inside the item, where PM's fitter would fabricate an\n // empty label and demote the item's own text into the children zone.\n // Matches the cross-kind drag rules (`moveBlock`).\n const $gap = tr.doc.resolve($pos.before($pos.depth - 1));\n const insertedAt = insertBlockSplittingList(tr, $gap, slice.content);\n setCaretAtEndOfInserted(tr, insertedAt, slice.content);\n } else {\n tr.insert(parentStart, slice.content);\n setCaretAtEndOfInserted(tr, parentStart, slice.content);\n }\n } else if (offset === parentSize) {\n tr.insert(parentEnd, slice.content);\n setCaretAtEndOfInserted(tr, parentEnd, slice.content);\n } else {\n // Caret in the middle: split the textblock, insert at the boundary between\n // the two halves. After split the cursor's pos sits at the END of the first\n // half (before its close marker); the boundary is one past that, cursorPos+1.\n const cursorPos = $pos.pos;\n tr.split(cursorPos);\n const insertAt = cursorPos + 1;\n tr.insert(insertAt, slice.content);\n setCaretAtEndOfInserted(tr, insertAt, slice.content);\n }\n\n view.dispatch(tr.scrollIntoView());\n return true;\n}\n\n/** True if any top-level slice child is a block other than `paragraph`. */\nfunction sliceHasNonParagraphBlock(slice: Slice): boolean {\n let result = false;\n slice.content.forEach((child) => {\n if (child.isBlock && child.type.name !== 'paragraph') result = true;\n });\n return result;\n}\n\n/**\n * True when the slice is exactly one top-level block whose type matches the\n * destination parent (heading-into-heading, etc.). Here PM's default strips the\n * matching wrapper and inline-merges, which is better than splitting the parent.\n */\nfunction sliceIsSingleSameTypeAsParent(slice: Slice, parentTypeName: string): boolean {\n if (slice.content.childCount !== 1) return false;\n return slice.content.firstChild?.type.name === parentTypeName;\n}\n\n/** Cursor at the very end of the parent AND parent's last child is a hardBreak (Shift+Enter trigger). */\nfunction hasTrailingHardBreakAtCursor(parent: PMNode, offset: number, parentSize: number): boolean {\n if (offset !== parentSize) return false;\n return parent.lastChild?.type.name === 'hardBreak';\n}\n\n/**\n * When the slice top-level is a single list AND the caret has a list ancestor:\n * - SAME list kind: adapt the items (a no-op for the same item type) and merge\n * them as siblings of the current item, preserving the surrounding list.\n * - DIFFERENT kind (e.g. to-dos pasted into a bullet list): the pasted list\n * keeps its OWN kind, checked state, and ordered `start`, splitting the host\n * list around it. This mirrors the cross-kind drag rules (`moveBlock`) and\n * prevents the silent checked-state loss a blind adapt-and-merge caused.\n * Returns false (caller falls through) when this case doesn't apply.\n */\nfunction tryPasteListSliceIntoList(view: EditorView, slice: Slice): boolean {\n const { state } = view;\n const { selection } = state;\n\n // Slice must be exactly one top-level list node.\n if (slice.content.childCount !== 1) return false;\n const sliceTop = slice.content.firstChild;\n if (!sliceTop || !LIST_TYPES.has(sliceTop.type.name)) return false;\n\n // Find nearest list-wrapper ancestor of the caret.\n const $from = selection.$from;\n let listDepth = -1;\n for (let d = $from.depth; d > 0; d--) {\n if (LIST_TYPES.has($from.node(d).type.name)) { listDepth = d; break; }\n }\n if (listDepth === -1) return false;\n\n // The corresponding listItem (one level inside the list).\n const listItemDepth = listDepth + 1;\n if ($from.depth < listItemDepth) return false;\n\n const listParent = $from.node(listDepth);\n const sameKind = sliceTop.type === listParent.type;\n\n const tr = state.tr;\n if (!selection.empty) tr.deleteSelection();\n\n // Re-resolve after potential range delete. Bail if the list ancestor was\n // lost (selection straddled out), letting the fallback paths run.\n const $pos = tr.selection.$from;\n if ($pos.depth < listItemDepth) return false;\n if (!LIST_TYPES.has($pos.node(listDepth).type.name)) return false;\n\n const parent = $pos.parent;\n const parentEnd = $pos.after($pos.depth);\n const offset = $pos.parentOffset;\n const parentSize = parent.content.size;\n const liStart = $pos.before(listItemDepth);\n const liEnd = $pos.after(listItemDepth);\n const itemHasOnlyOneChild = $pos.node(listItemDepth).childCount === 1;\n\n if (sameKind) {\n // Same wrapper kind: the items already match the host's item type, so insert\n // them as-is and merge them as siblings of the current item.\n const adapted = sliceTop.content;\n if (adapted.childCount === 0) return false;\n\n let insertAt: number;\n if (hasTrailingHardBreakAtCursor(parent, offset, parentSize)) {\n // Shift+Enter inside a listItem: trim the trailing hardBreak, insert the\n // adapted items as siblings AFTER the current listItem (empty row stays).\n const hbStart = parentEnd - 2;\n const hbEnd = parentEnd - 1;\n tr.delete(hbStart, hbEnd);\n const adjustedLiEnd = liEnd - 1;\n tr.insert(adjustedLiEnd, adapted);\n insertAt = adjustedLiEnd;\n } else if (parentSize === 0 && itemHasOnlyOneChild) {\n // Truly-empty listItem: replace it so we don't leave a stray empty item.\n tr.replaceWith(liStart, liEnd, adapted);\n insertAt = liStart;\n } else if (offset === 0) {\n tr.insert(liStart, adapted);\n insertAt = liStart;\n } else if (offset === parentSize) {\n tr.insert(liEnd, adapted);\n insertAt = liEnd;\n } else {\n // Caret in middle: split the listItem, insert items between the halves.\n // `tr.split(pos, depth)` doubles close+open at each level; for depth=2\n // (textblock + listItem) the boundary is pos + 2 (after both close tokens).\n // A checked to-do split mid-label spawns an UNCHECKED tail (Notion; matches\n // the Enter handler), so a split half is never silently pre-checked.\n const cursorPos = $pos.pos;\n tr.split(cursorPos, 2, typesAfterUncheckedTail($pos, listItemDepth));\n insertAt = cursorPos + 2;\n tr.insert(insertAt, adapted);\n }\n\n setCaretAtEndOfInserted(tr, insertAt, adapted);\n view.dispatch(tr.scrollIntoView());\n return true;\n }\n\n // Different list kind: keep the pasted list as its own wrapper and split the\n // host list around it, so kind / checked / `start` all survive.\n const content = Fragment.from(sliceTop);\n let insertedAt: number;\n if (hasTrailingHardBreakAtCursor(parent, offset, parentSize)) {\n const hbStart = parentEnd - 2;\n const hbEnd = parentEnd - 1;\n tr.delete(hbStart, hbEnd);\n insertedAt = insertBlockSplittingList(tr, tr.doc.resolve(liEnd - 1), content);\n } else if (parentSize === 0 && itemHasOnlyOneChild) {\n // Empty item: drop it so the pasted list takes its place.\n const wrapperNode = $pos.node(listDepth);\n if (wrapperNode.childCount === 1) {\n // Host list is just this empty item: replace the whole wrapper.\n const wrapperStart = $pos.before(listDepth);\n const wrapperEnd = $pos.after(listDepth);\n tr.replaceWith(wrapperStart, wrapperEnd, sliceTop);\n insertedAt = wrapperStart;\n } else {\n tr.delete(liStart, liEnd);\n insertedAt = insertBlockSplittingList(tr, tr.doc.resolve(liStart), content);\n }\n } else if (offset === 0) {\n insertedAt = insertBlockSplittingList(tr, tr.doc.resolve(liStart), content);\n } else if (offset === parentSize) {\n insertedAt = insertBlockSplittingList(tr, tr.doc.resolve(liEnd), content);\n } else {\n const cursorPos = $pos.pos;\n tr.split(cursorPos, 2, typesAfterUncheckedTail($pos, listItemDepth));\n insertedAt = insertBlockSplittingList(tr, tr.doc.resolve(cursorPos + 2), content);\n }\n\n setCaretAtEndOfInserted(tr, insertedAt, content);\n view.dispatch(tr.scrollIntoView());\n return true;\n}\n\n/**\n * `typesAfter` for `tr.split(pos, 2)` inside a list item: rebuild the textblock\n * and item types for the tail half, forcing a `taskItem` tail to `checked: false`\n * so splitting a checked to-do never pre-checks the new item (Notion semantics).\n * Returns `undefined` (PM's default attr-copying split) for non-task items.\n */\nfunction typesAfterUncheckedTail(\n $pos: ResolvedPos,\n listItemDepth: number,\n): { type: NodeType; attrs?: Record<string, unknown> }[] | undefined {\n const item = $pos.node(listItemDepth);\n if (item.type.name !== 'taskItem') return undefined;\n return [\n { type: item.type, attrs: { ...item.attrs, checked: false } },\n { type: $pos.parent.type },\n ];\n}\n\n/**\n * Place the cursor at the END of the last inserted block. Text-bearing blocks\n * land at the end of the deepest textblock; atom blocks (hr, image) use\n * Selection.near for the closest valid selection.\n *\n * The fragment occupies `[insertAt, insertAt + content.size)`; subtracting 1\n * lands just before the outermost close-token, i.e. the end of its content.\n */\nfunction setCaretAtEndOfInserted(tr: Transaction, insertAt: number, content: Fragment): void {\n if (content.childCount === 0) return;\n const target = Math.max(0, Math.min(tr.doc.content.size, insertAt + content.size - 1));\n const $target = tr.doc.resolve(target);\n if ($target.parent.isTextblock) {\n tr.setSelection(TextSelection.create(tr.doc, target));\n } else {\n tr.setSelection(Selection.near($target, -1));\n }\n}\n"]}
|