import { TbCopy } from "react-icons/tb"; import { JsonView } from "react-json-view-lite"; import { twMerge } from "tailwind-merge"; import { IconButton } from "../buttons/IconButton"; import ErrorBoundary from "ui/components/display/ErrorBoundary"; import { forwardRef, useImperativeHandle, useState } from "react"; import { formatNumber } from "bknd/utils"; export type JsonViewerProps = { json: object | null; title?: string; expand?: number; showSize?: boolean; showCopy?: boolean; copyIconProps?: any; className?: string; }; const style = { basicChildStyle: "pl-5 ml-1 border-l border-muted hover:border-primary/20", container: "ml-[-10px]", label: "text-primary/90 font-bold font-mono mr-2", stringValue: "text-emerald-600 dark:text-emerald-500 font-mono select-text text-wrap whitespace-wrap break-words", numberValue: "text-sky-500 dark:text-sky-400 font-mono select-text", nullValue: "text-zinc-400 font-mono", undefinedValue: "text-zinc-400 font-mono", otherValue: "text-zinc-400 font-mono", booleanValue: "text-orange-500 dark:text-orange-400 font-mono", punctuation: "text-zinc-400 font-bold font-mono m-0.5", collapsedContent: "text-zinc-400 font-mono after:content-['...']", collapseIcon: "text-zinc-400 font-mono font-bold text-lg after:content-['▾'] mr-1.5", expandIcon: "text-zinc-400 font-mono font-bold text-lg after:content-['▸'] mr-1.5", noQuotesForStringValues: false, } as any; export const JsonViewer = ({ json, title, expand = 0, showSize = false, showCopy = false, copyIconProps = {}, className, }: JsonViewerProps) => { const size = showSize ? (!json ? 0 : JSON.stringify(json).length) : undefined; const formattedSize = formatNumber.fileSize(size ?? 0); const showContext = size || title || showCopy; function onCopy() { navigator.clipboard?.writeText(JSON.stringify(json, null, 2)); } return (
{showContext && (
{(title || size !== undefined) && (
{title && {title}}{" "} {size !== undefined && ({formattedSize})}
)} {showCopy && (
)}
)} level < expand} style={style} />
); }; export type JsonViewerTabsProps = Omit & { selected?: string; tabs: { [key: string]: JsonViewerProps & { enabled?: boolean; }; }; }; export type JsonViewerTabsRef = { setSelected: (selected: string) => void; }; export const JsonViewerTabs = forwardRef( ({ tabs: _tabs, ...defaultProps }, ref) => { const tabs = Object.fromEntries( Object.entries(_tabs).filter(([_, v]) => v.enabled !== false), ); const [selected, setSelected] = useState(defaultProps.selected ?? Object.keys(tabs)[0]); useImperativeHandle(ref, () => ({ setSelected, })); return (
{Object.keys(tabs).map((key) => ( ))}
{/* @ts-ignore */}
); }, );