"use client"; import { useMemo } from "react"; import { ActionIcon, Code, CopyButton, Group, Text, Tree, getTreeExpandedState, useTree } from "@mantine/core"; import type { RenderTreeNodePayload, TreeNodeData } from "@mantine/core"; import { IconCheck, IconChevronDown, IconChevronRight, IconCopy, IconPlus } from "@tabler/icons-react"; export interface ResponseTreeLabels { copyPath: string; pathCopied: string; insertPath: string; } export interface ResponseTreeProps { value: unknown; labels: ResponseTreeLabels; onInsertDataPath?: (path: string) => void; } interface ResponseTreeData extends TreeNodeData { path: string; displayValue: string; } export function ResponseTree({ value, labels, onInsertDataPath }: ResponseTreeProps) { const data = useMemo(() => [createResponseTreeNode(value, "data", "data")], [value]); const tree = useTree({ initialExpandedState: getTreeExpandedState(data, ["data"]) }); return ( } /> ); } function ResponseTreeNode({ node, expanded, hasChildren, elementProps, labels, onInsertDataPath, }: RenderTreeNodePayload & { labels: ResponseTreeLabels; onInsertDataPath?: (path: string) => void }) { const responseNode = node as ResponseTreeData; return (
{hasChildren && (expanded ? : )}
{responseNode.label} {responseNode.displayValue} {({ copied, copy }) => ( { event.stopPropagation(); copy(); }} > {copied ? : } )} {onInsertDataPath && ( { event.stopPropagation(); onInsertDataPath(responseNode.path); }} > )}
); } export function createResponseTreeNode(value: unknown, path: string, label: string): ResponseTreeData { const collection = value !== null && typeof value === "object"; const entries = collection ? Object.entries(value as Record) : []; return { value: path, label, path, displayValue: collection ? Array.isArray(value) ? `[${entries.length}]` : `{${entries.length}}` : formatValue(value), children: entries.map(([key, child]) => createResponseTreeNode(child, appendDataPath(path, key, Array.isArray(value)), key), ), }; } export function appendDataPath(parent: string, key: string, isArray: boolean): string { if (isArray) return `${parent}[${key}]`; return /^[A-Za-z_$][\w$]*$/u.test(key) ? `${parent}.${key}` : `${parent}[${JSON.stringify(key)}]`; } function formatValue(value: unknown): string { if (typeof value === "string") return JSON.stringify(value); if (value === undefined) return "undefined"; return String(value); }