UNPKG

@huridocs/react-text-selection-handler

Version:

React pdf handler allows to render a PDF and handle text selection and highlights.

47 lines (41 loc) 1.53 kB
export const rangeToTextRects = (range: Range) => { const textNodeIterator = document.createNodeIterator( range.commonAncestorContainer, NodeFilter.SHOW_TEXT ); const selection: Selection | null = window.getSelection(); if (selection === null) return []; const extended = selection.focusNode?.childNodes?.length || 0 > 1; const position = selection.anchorNode?.compareDocumentPosition(selection.focusNode!) === 4 ? 'FOLLOWING' : 'PRECEDING'; const extentNode = extended || position === 'PRECEDING' ? selection.anchorNode : selection.focusNode; const nodes = []; while (textNodeIterator.nextNode()) { const isValidNode = !( nodes.length === 0 && textNodeIterator.referenceNode !== range.startContainer ); if (isValidNode) { nodes.push(textNodeIterator.referenceNode); } if ( extentNode === textNodeIterator.referenceNode || extentNode === textNodeIterator.referenceNode.parentElement ) break; } return nodes.reduce<DOMRect[]>((rects, n, index) => { const myRange = document.createRange(); myRange.selectNode(n); if (index === 0) { myRange.setStart(n, range.startOffset); } if (index === nodes.length - 1) { // @ts-expect-error - TS cannot now if Node is a text node, but this in handling text selections, so it's safe to assume it's a text node myRange.setEnd(n, !extended ? range.endOffset : n.length); } return [...rects, ...Array.from(myRange.getClientRects())]; }, []); };