{
  "version": 3,
  "sources": ["../../../src/components/collaborators-overlay/cursor-dom-utils.ts"],
  "sourcesContent": ["// @ts-expect-error - No type declarations available for @wordpress/block-editor\n// prettier-ignore\nimport { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';\nimport { unlock } from '../../lock-unlock';\n\nconst { isElementVisible } = unlock( blockEditorPrivateApis );\n\nexport interface SelectionRect {\n\tx: number;\n\ty: number;\n\twidth: number;\n\theight: number;\n}\n\nexport interface CursorCoords {\n\tx: number;\n\ty: number;\n\theight: number;\n}\n\n/**\n * Walk up from a hidden element (e.g. text inside a collapsed core/details\n * or an inactive core/accordion panel) to the nearest [data-block] ancestor\n * that's actually visible — always the collapsed container's own wrapper,\n * since only its *inner* content collapses, never the wrapper itself.\n *\n * Used to give collaborators a visible presence indicator (avatar/outline)\n * on the container when their cursor/selection is inside hidden content, in\n * place of a cursor that would otherwise have nowhere valid to render.\n *\n * @param element - The hidden element to walk up from.\n * @return The nearest visible [data-block] ancestor, or null if none found.\n */\nexport const getNearestVisibleBlockAncestor = (\n\telement: HTMLElement\n): HTMLElement | null => {\n\tlet current = element.closest< HTMLElement >( '[data-block]' );\n\n\twhile ( current ) {\n\t\tif ( isElementVisible( current ) ) {\n\t\t\treturn current;\n\t\t}\n\t\tcurrent =\n\t\t\tcurrent.parentElement?.closest< HTMLElement >( '[data-block]' ) ??\n\t\t\tnull;\n\t}\n\n\treturn null;\n};\n\nconst MAX_NODE_OFFSET_COUNT = 500;\n\n/**\n * Given a selection, returns the coordinates of the cursor in the block.\n *\n * @param absolutePositionIndex - The absolute position index\n * @param blockElement          - The block element (or null if deleted)\n * @param editorDocument        - The editor document\n * @param overlayRect           - Pre-computed bounding rect of the overlay element\n * @return The position of the cursor\n */\nexport const getCursorPosition = (\n\tabsolutePositionIndex: number | null,\n\tblockElement: HTMLElement | null,\n\teditorDocument: Document,\n\toverlayRect: DOMRect\n): CursorCoords | null => {\n\tif ( absolutePositionIndex === null || ! blockElement ) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\tgetOffsetPositionInBlock(\n\t\t\tblockElement,\n\t\t\tabsolutePositionIndex,\n\t\t\teditorDocument,\n\t\t\toverlayRect\n\t\t) ?? null\n\t);\n};\n\n/**\n * Given a block element and a character offset, returns the coordinates for drawing a visual cursor in the block.\n *\n * @param blockElement   - The block element\n * @param charOffset     - The character offset\n * @param editorDocument - The editor document\n * @param overlayRect    - Pre-computed bounding rect of the overlay element\n * @return The position of the cursor\n */\nconst getOffsetPositionInBlock = (\n\tblockElement: HTMLElement,\n\tcharOffset: number,\n\teditorDocument: Document,\n\toverlayRect: DOMRect\n) => {\n\t// The target may be hidden inside collapsed content (e.g. a closed\n\t// core/details or an inactive core/accordion panel). Its range then has\n\t// no layout box, so don't draw a cursor at a fallback position — suppress\n\t// it entirely rather than misplacing it at the collapsed wrapper.\n\tif ( ! isElementVisible( blockElement ) ) {\n\t\treturn null;\n\t}\n\n\tconst { node, offset } = findInnerBlockOffset(\n\t\tblockElement,\n\t\tcharOffset,\n\t\teditorDocument\n\t);\n\n\tconst cursorRange = editorDocument.createRange();\n\n\ttry {\n\t\tcursorRange.setStart( node, offset );\n\t} catch {\n\t\treturn null;\n\t}\n\n\t// Ensure the range only represents single point in the DOM.\n\tcursorRange.collapse( true );\n\n\tconst cursorRect = cursorRange.getBoundingClientRect();\n\tconst blockRect = blockElement.getBoundingClientRect();\n\n\tlet cursorX = 0;\n\tlet cursorY = 0;\n\n\tif (\n\t\tcursorRect.x === 0 &&\n\t\tcursorRect.y === 0 &&\n\t\tcursorRect.width === 0 &&\n\t\tcursorRect.height === 0\n\t) {\n\t\t// This can happen for empty blocks.\n\t\tcursorX = blockRect.left - overlayRect.left;\n\t\tcursorY = blockRect.top - overlayRect.top;\n\t} else {\n\t\tcursorX = cursorRect.left - overlayRect.left;\n\t\tcursorY = cursorRect.top - overlayRect.top;\n\t}\n\n\tlet cursorHeight = cursorRect.height;\n\tif ( cursorHeight === 0 ) {\n\t\tconst view = editorDocument.defaultView ?? window;\n\t\tcursorHeight =\n\t\t\tparseInt( view.getComputedStyle( blockElement ).lineHeight, 10 ) ||\n\t\t\tblockRect.height;\n\t}\n\n\treturn {\n\t\tx: cursorX,\n\t\ty: cursorY,\n\t\theight: cursorHeight,\n\t};\n};\n\n/**\n * Computes selection highlight rectangles for a text range within a single block.\n *\n * @param blockElement   - The block element\n * @param startOffset    - Start character offset within the block\n * @param endOffset      - End character offset within the block\n * @param editorDocument - The editor document\n * @param overlayRect    - Pre-computed bounding rect of the overlay element\n * @return Array of selection rectangles relative to the overlay, or null on failure\n */\nexport const getSelectionRects = (\n\tblockElement: HTMLElement,\n\tstartOffset: number,\n\tendOffset: number,\n\teditorDocument: Document,\n\toverlayRect: DOMRect\n): SelectionRect[] | null => {\n\t// Same rationale as getOffsetPositionInBlock: a hidden target has no\n\t// layout box to derive rects from, so skip it rather than draw a\n\t// misplaced or empty selection.\n\tif ( ! isElementVisible( blockElement ) ) {\n\t\treturn null;\n\t}\n\n\t// Normalize direction.\n\tlet normalizedStart = startOffset;\n\tlet normalizedEnd = endOffset;\n\tif ( normalizedStart > normalizedEnd ) {\n\t\t[ normalizedStart, normalizedEnd ] = [ normalizedEnd, normalizedStart ];\n\t}\n\n\tconst startPos = findInnerBlockOffset(\n\t\tblockElement,\n\t\tnormalizedStart,\n\t\teditorDocument\n\t);\n\tconst endPos = findInnerBlockOffset(\n\t\tblockElement,\n\t\tnormalizedEnd,\n\t\teditorDocument\n\t);\n\n\tconst range = editorDocument.createRange();\n\ttry {\n\t\trange.setStart( startPos.node, startPos.offset );\n\t\trange.setEnd( endPos.node, endPos.offset );\n\t} catch {\n\t\treturn null;\n\t}\n\n\tconst clientRects = range.getClientRects();\n\tconst rects: SelectionRect[] = [];\n\n\tfor ( const rect of clientRects ) {\n\t\tif ( rect.width === 0 && rect.height === 0 ) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst x = rect.left - overlayRect.left;\n\t\tconst y = rect.top - overlayRect.top;\n\n\t\t// Range.getClientRects() can return duplicate rects at inline\n\t\t// formatting boundaries (e.g. <em>, <strong>). Skip exact matches.\n\t\tconst isDuplicate = rects.some(\n\t\t\t( r ) =>\n\t\t\t\tr.x === x &&\n\t\t\t\tr.y === y &&\n\t\t\t\tr.width === rect.width &&\n\t\t\t\tr.height === rect.height\n\t\t);\n\t\tif ( isDuplicate ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\trects.push( {\n\t\t\tx,\n\t\t\ty,\n\t\t\twidth: rect.width,\n\t\t\theight: rect.height,\n\t\t} );\n\t}\n\n\treturn rects.length > 0 ? rects : null;\n};\n\n/**\n * Return the nearest [data-block] ancestor of el, or el itself if it has none.\n *\n * Used to promote inner blocks (e.g. list-items) to their parent container\n * (e.g. the list block) so the whole container is treated as one visual unit\n * rather than each child block being highlighted individually.\n *\n * @param el - The block element to promote.\n * @return The nearest [data-block] ancestor, or el itself.\n */\nexport const blockContainerOf = ( el: HTMLElement ): HTMLElement => {\n\tconst parent = el.parentElement;\n\treturn parent?.hasAttribute( 'data-block' ) ? parent : el;\n};\n\n/**\n * Finds all block elements between two blocks in DOM order (exclusive of\n * start and end). Descendant blocks are filtered out — if a parent block is\n * already in the result, its children are skipped. This prevents\n * double-highlighting nested structures (e.g. selecting across a list returns\n * the list block, not the individual list items inside it).\n *\n * NOTE: startBlockId and endBlockId may be in either order — the function\n * normalises to DOM order internally.\n *\n * @param startBlockId   - The clientId of one end block\n * @param endBlockId     - The clientId of the other end block\n * @param editorDocument - The editor document\n * @return Intermediate block HTMLElements in document order, descendants excluded\n */\nconst getBlocksBetween = (\n\tstartBlockId: string,\n\tendBlockId: string,\n\teditorDocument: Document\n): HTMLElement[] => {\n\tconst allBlocks =\n\t\teditorDocument.querySelectorAll< HTMLElement >( '[data-block]' );\n\n\tlet startIndex = -1;\n\tlet endIndex = -1;\n\n\tfor ( let i = 0; i < allBlocks.length; i++ ) {\n\t\tconst blockId = allBlocks[ i ].getAttribute( 'data-block' );\n\t\tif ( blockId === startBlockId ) {\n\t\t\tstartIndex = i;\n\t\t}\n\t\tif ( blockId === endBlockId ) {\n\t\t\tendIndex = i;\n\t\t}\n\t}\n\n\tif ( startIndex === -1 || endIndex === -1 ) {\n\t\treturn [];\n\t}\n\n\t// Normalize order.\n\tif ( startIndex > endIndex ) {\n\t\t[ startIndex, endIndex ] = [ endIndex, startIndex ];\n\t}\n\n\tconst result: HTMLElement[] = [];\n\tfor ( let i = startIndex + 1; i < endIndex; i++ ) {\n\t\tconst block = allBlocks[ i ];\n\t\t// Skip descendants of blocks already in the result to prevent\n\t\t// double-highlights on nested blocks (e.g. list items inside a list).\n\t\tif ( ! result.some( ( r ) => r.contains( block ) ) ) {\n\t\t\tresult.push( block );\n\t\t}\n\t}\n\treturn result;\n};\n\n/**\n * Result returned by getOrderedBlockRange.\n */\nexport interface BlockRangeResult {\n\t/** DOM-order first element, promoted to its nearest [data-block] ancestor. */\n\tfirstEl: HTMLElement;\n\t/** data-block value of firstEl. */\n\tfirstId: string;\n\t/** DOM-order last element, promoted to its nearest [data-block] ancestor. */\n\tlastEl: HTMLElement;\n\t/** data-block value of lastEl. */\n\tlastId: string;\n\t/** Block elements strictly between first and last, descendants of either excluded. */\n\tmiddleEls: HTMLElement[];\n\t/** True when firstEl and lastEl resolve to the same container after promotion. */\n\tsameContainer: boolean;\n}\n\n/**\n * Resolve two block clientIds to a DOM-ordered, promotion-aware block range.\n *\n * Handles: querySelector for both blocks (returns null if either is missing),\n * DOM-order normalisation, promotion via blockContainerOf, and retrieval of\n * intermediate blocks with descendants of the endpoints excluded.\n *\n * When the input IDs are already at container level (e.g. already promoted by\n * the caller), blockContainerOf is a no-op and the result is identical to a\n * plain query + normalise.\n *\n * @param startId - clientId of one block endpoint (may be in either DOM order).\n * @param endId   - clientId of the other block endpoint.\n * @param doc     - The editor document.\n * @return Ordered, promoted range, or null if either element is not in the DOM.\n */\nexport const getOrderedBlockRange = (\n\tstartId: string,\n\tendId: string,\n\tdoc: Document\n): BlockRangeResult | null => {\n\tconst startEl = doc.querySelector< HTMLElement >(\n\t\t`[data-block=\"${ startId }\"]`\n\t);\n\tconst endEl = doc.querySelector< HTMLElement >(\n\t\t`[data-block=\"${ endId }\"]`\n\t);\n\tif ( ! startEl || ! endEl ) {\n\t\treturn null;\n\t}\n\n\t// Normalise to DOM order.\n\tconst rawFirstEl = isNodeBefore( endEl, startEl ) ? endEl : startEl;\n\tconst rawLastEl = isNodeBefore( endEl, startEl ) ? startEl : endEl;\n\n\t// Promote inner-block elements (e.g. list-items) to their nearest\n\t// [data-block] ancestor so both callers operate on container-level blocks.\n\tconst firstEl = blockContainerOf( rawFirstEl );\n\tconst lastEl = blockContainerOf( rawLastEl );\n\tconst firstId = firstEl.getAttribute( 'data-block' )!;\n\tconst lastId = lastEl.getAttribute( 'data-block' )!;\n\n\tconst sameContainer = firstId === lastId;\n\tconst middleEls = sameContainer\n\t\t? []\n\t\t: getBlocksBetween( firstId, lastId, doc ).filter(\n\t\t\t\t( el ) => ! firstEl.contains( el ) && ! lastEl.contains( el )\n\t\t  );\n\n\treturn { firstEl, firstId, lastEl, lastId, middleEls, sameContainer };\n};\n\n/**\n * Given a block element and a character offset, returns an exact inner node and offset for use in a range.\n *\n * @param blockElement   - The block element\n * @param offset         - The character offset\n * @param editorDocument - The editor document\n * @return The node and offset of the character at the offset\n */\nexport const findInnerBlockOffset = (\n\tblockElement: HTMLElement,\n\toffset: number,\n\teditorDocument: Document\n) => {\n\tconst treeWalker = editorDocument.createTreeWalker(\n\t\tblockElement,\n\t\tNodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT // eslint-disable-line no-bitwise\n\t);\n\n\tlet currentOffset = 0;\n\tlet lastTextNode: Node | null = null;\n\n\tlet node: Node | null = null;\n\tlet nodeCount = 1;\n\n\twhile ( ( node = treeWalker.nextNode() ) ) {\n\t\tnodeCount++;\n\n\t\tif ( nodeCount > MAX_NODE_OFFSET_COUNT ) {\n\t\t\t// If we've walked too many nodes, return the last text node or the beginning of the block.\n\t\t\tif ( lastTextNode ) {\n\t\t\t\treturn { node: lastTextNode, offset: 0 };\n\t\t\t}\n\t\t\treturn { node: blockElement, offset: 0 };\n\t\t}\n\n\t\tconst nodeLength = node.nodeValue?.length ?? 0;\n\n\t\tif ( node.nodeType === Node.ELEMENT_NODE ) {\n\t\t\tif ( node.nodeName === 'BR' ) {\n\t\t\t\t// Treat <br> as a single \"\\n\" character.\n\n\t\t\t\tif ( currentOffset + 1 >= offset ) {\n\t\t\t\t\t// If the <br> occurs right on the target offset, return the next text node.\n\t\t\t\t\tconst nodeAfterBr = treeWalker.nextNode();\n\n\t\t\t\t\tif ( nodeAfterBr?.nodeType === Node.TEXT_NODE ) {\n\t\t\t\t\t\treturn { node: nodeAfterBr, offset: 0 };\n\t\t\t\t\t} else if ( lastTextNode ) {\n\t\t\t\t\t\t// If there's no text node after the <br>, return the end offset of the last text node.\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tnode: lastTextNode,\n\t\t\t\t\t\t\toffset: lastTextNode.nodeValue?.length ?? 0,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\t// Just in case, if there's no last text node, return the beginning of the block.\n\t\t\t\t\treturn { node: blockElement, offset: 0 };\n\t\t\t\t}\n\n\t\t\t\t// The <br> is before the target offset. Count it as a single character.\n\t\t\t\tcurrentOffset += 1;\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\t// Skip other element types.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif ( nodeLength === 0 ) {\n\t\t\t// Skip empty nodes.\n\t\t\tcontinue;\n\t\t}\n\n\t\tif ( currentOffset + nodeLength >= offset ) {\n\t\t\t// This node exceeds the target offset. Return the node and the position of the offset within it.\n\t\t\treturn { node, offset: offset - currentOffset };\n\t\t}\n\n\t\tcurrentOffset += nodeLength;\n\n\t\tif ( node.nodeType === Node.TEXT_NODE ) {\n\t\t\tlastTextNode = node;\n\t\t}\n\t}\n\n\tif ( lastTextNode && lastTextNode.nodeValue?.length ) {\n\t\t// We didn't reach the target offset. Return the last text node's last character.\n\t\treturn { node: lastTextNode, offset: lastTextNode.nodeValue.length };\n\t}\n\n\t// We didn't find any text nodes. Return the beginning of the block.\n\treturn { node: blockElement, offset: 0 };\n};\n\n/**\n * Check if node `a` precedes node `b` in document order.\n *\n * @param a - First node.\n * @param b - Second node.\n * @return True if `a` comes before `b`.\n */\nconst isNodeBefore = ( a: Node, b: Node ): boolean =>\n\t// eslint-disable-next-line no-bitwise\n\t!! ( a.compareDocumentPosition( b ) & Node.DOCUMENT_POSITION_FOLLOWING );\n"],
  "mappings": "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",
  "names": []
}
