import type { Editor } from '@tiptap/core' import type { Node as PMNode } from '@tiptap/pm/model' export const BLOCK_DRAG_HANDLE_ID = 'notion-block-drag-handle' export const BLOCK_DRAG_HANDLE_WIDTH = 20 /** Même logique de résolution de bloc que tiptap-extension-global-drag-handle */ export function resolveBlockAtDragHandle(editor: Editor): { node: PMNode; pos: number } | null { const handle = document.getElementById(BLOCK_DRAG_HANDLE_ID) if (!handle || editor.isDestroyed) return null const rect = handle.getBoundingClientRect() const coords = editor.view.posAtCoords({ left: rect.right + 50 + BLOCK_DRAG_HANDLE_WIDTH, top: rect.top + rect.height / 2, }) if (coords?.pos == null) return null const $pos = editor.state.doc.resolve(coords.pos) const blockPos = $pos.depth > 0 ? $pos.before($pos.depth) : coords.pos const node = editor.state.doc.nodeAt(blockPos) if (!node) return null // Climb up to container blocks (columns, toggleBlock, calloutBlock) // so the drag handle operates on the whole container, not inner paragraphs const CONTAINER_TYPES = ['columns', 'toggleBlock', 'calloutBlock'] const $blockPos = editor.state.doc.resolve(blockPos) for (let depth = $blockPos.depth; depth > 0; depth--) { const ancestor = $blockPos.node(depth) if (CONTAINER_TYPES.includes(ancestor.type.name)) { const containerPos = $blockPos.before(depth) const containerNode = editor.state.doc.nodeAt(containerPos) if (containerNode) { return { node: containerNode, pos: containerPos } } } } return { node, pos: blockPos } }