(null);
const lines = useMemo(() => (JSON.stringify(value, null, 2) ?? "null").split("\n"), [value]);
// IDs are globally unique for fields and unique within pages. Match the object containing its id.
const rangeFor = (id: string | undefined, page = false): [number, number] => {
if (!id) return [-1, -1];
const idLine = lines.findIndex(line => line.trim() === `"id": ${JSON.stringify(id)},` && (!page || line.startsWith(' "id"')));
if (idLine < 0) return [-1, -1];
const indent = lines[idLine].length - lines[idLine].trimStart().length - 2;
const start = idLine - 1;
const end = lines.findIndex((line, i) => i > idLine && (line === " ".repeat(indent) + "}" || line === " ".repeat(indent) + "},"));
return [start, end];
};
const [start, end] = rangeFor(activeNode, true);
const [questionStart, questionEnd] = rangeFor(activeQuestion);
const scrollTarget = questionStart >= 0 ? questionStart : start;
useEffect(() => {
const container = containerRef.current;
const active = activeRef.current;
if (isOpen && container && active) {
container.scrollTop += active.getBoundingClientRect().top - container.getBoundingClientRect().top - 16;
}
}, [activeNode, activeQuestion, isOpen, lines]);
return (
{lines.map((line, index) => (
= 0 && index >= start && index <= end ? " json-active-node" : ""}${questionStart >= 0 && index >= questionStart && index <= questionEnd ? " json-active-question" : ""}`}
aria-current={index === scrollTarget ? "location" : undefined}
>{highlightJson(line)}{"\n"}
))}
);
}