// SelectionApp.tsx import React, { useState, useRef } from "react"; interface Span { span_text: string; start: number; end: number; } const SelectionApp: React.FC = () => { const [spans, setSpans] = useState([]); const [keySpan, setKeySpan] = useState("span_text"); const [keyStart, setKeyStart] = useState("start"); const [keyEnd, setKeyEnd] = useState("end"); const [lastText, setLastText] = useState(""); const inputRef = useRef(null); const getNormalizedText = (container: HTMLElement): string => { let html = container.innerHTML; html = html.replace(/

<\/div>/gi, '\n'); html = html.replace(/
/gi, '\n').replace(/<\/div>/gi, ''); html = html.replace(//gi, '\n'); html = html.replace(/ /g, ' '); html = html.replace(/<[^>]+>/g, ''); return html; }; const getSelectionIndices = () => { if (!inputRef.current) return; const container = inputRef.current; const selection = window.getSelection(); if (!selection || !selection.rangeCount) return; const range = selection.getRangeAt(0); if (!container.contains(range.startContainer) || !container.contains(range.endContainer)) return; const selectedText = selection.toString(); if (!selectedText) return; const preRange = range.cloneRange(); preRange.selectNodeContents(container); preRange.setEnd(range.startContainer, range.startOffset); const tempDiv = document.createElement("div"); tempDiv.appendChild(preRange.cloneContents()); const preText = getNormalizedText(tempDiv); const start = preText.length; const end = start + selectedText.length; const newSpan: Span = { span_text: selectedText, start, end }; setSpans((prev) => [newSpan, ...prev].slice(0, 5)); }; const renderSpans = () => { return spans.map((s) => ({ [keySpan]: s.span_text, [keyStart]: s.start, [keyEnd]: s.end, })); }; const handleInput = (e: React.FormEvent) => { const currentText = getNormalizedText(e.currentTarget); if (currentText !== lastText) { setSpans([]); setLastText(currentText); } }; return (

Highlight text to get indices

{/* Settings Panel */}
Settings (rename keys):

{/* Editable Div */}
Paste or type your text here...
{/* Display JSON */}
        {spans.length ? JSON.stringify(renderSpans(), null, 2) : ""}
      
); }; export default SelectionApp;