Allowed ability to copy json object

This commit is contained in:
Emir Karabeg
2025-01-31 17:39:36 -08:00
parent f188ebb04b
commit 9f7c6fc16d

View File

@@ -35,31 +35,67 @@ const TruncatedValue = ({ value }: { value: string }) => {
) )
} }
const copyToClipboard = (data: any) => {
const stringified = JSON.stringify(data, null, 2)
navigator.clipboard.writeText(stringified)
}
export const JSONView = ({ export const JSONView = ({
data, data,
level = 0, level = 0,
initiallyExpanded = false, initiallyExpanded = false,
}: JSONViewProps) => { }: JSONViewProps) => {
const [isCollapsed, setIsCollapsed] = useState(!initiallyExpanded) const [isCollapsed, setIsCollapsed] = useState(!initiallyExpanded)
const [contextMenuPosition, setContextMenuPosition] = useState<{
x: number
y: number
} | null>(null)
useEffect(() => { useEffect(() => {
setIsCollapsed(!initiallyExpanded) setIsCollapsed(!initiallyExpanded)
}, [initiallyExpanded]) }, [initiallyExpanded])
const handleContextMenu = (e: React.MouseEvent) => {
e.preventDefault()
setContextMenuPosition({ x: e.clientX, y: e.clientY })
}
useEffect(() => {
const handleClickOutside = () => setContextMenuPosition(null)
if (contextMenuPosition) {
document.addEventListener('click', handleClickOutside)
return () => document.removeEventListener('click', handleClickOutside)
}
}, [contextMenuPosition])
if (data === null) return <span className="text-muted-foreground">null</span> if (data === null) return <span className="text-muted-foreground">null</span>
if (typeof data !== 'object') { if (typeof data !== 'object') {
const stringValue = JSON.stringify(data) const stringValue = JSON.stringify(data)
return ( return (
<span <span
onContextMenu={handleContextMenu}
className={`${ className={`${
typeof data === 'string' ? 'text-success' : 'text-info' typeof data === 'string' ? 'text-success' : 'text-info'
} break-all`} } break-all relative`}
> >
{typeof data === 'string' ? ( {typeof data === 'string' ? (
<TruncatedValue value={stringValue} /> <TruncatedValue value={stringValue} />
) : ( ) : (
stringValue stringValue
)} )}
{contextMenuPosition && (
<div
className="fixed z-50 bg-popover border rounded-md shadow-md py-1 min-w-[160px]"
style={{ left: contextMenuPosition.x, top: contextMenuPosition.y }}
>
<button
className="w-full px-3 py-1.5 text-sm text-left hover:bg-accent"
onClick={() => copyToClipboard(data)}
>
Copy value
</button>
</div>
)}
</span> </span>
) )
} }
@@ -75,7 +111,7 @@ export const JSONView = ({
} }
return ( return (
<div className="relative"> <div className="relative" onContextMenu={handleContextMenu}>
<span <span
className="cursor-pointer select-none inline-flex items-center text-muted-foreground" className="cursor-pointer select-none inline-flex items-center text-muted-foreground"
onClick={(e) => { onClick={(e) => {
@@ -89,6 +125,19 @@ export const JSONView = ({
<span>{isArray ? '[' : '{'}</span> <span>{isArray ? '[' : '{'}</span>
{isCollapsed ? '...' : ''} {isCollapsed ? '...' : ''}
</span> </span>
{contextMenuPosition && (
<div
className="fixed z-50 bg-popover border rounded-md shadow-md py-1 min-w-[160px]"
style={{ left: contextMenuPosition.x, top: contextMenuPosition.y }}
>
<button
className="w-full px-3 py-1.5 text-sm text-left hover:bg-accent"
onClick={() => copyToClipboard(data)}
>
Copy object
</button>
</div>
)}
{!isCollapsed && ( {!isCollapsed && (
<div className="ml-4 break-words"> <div className="ml-4 break-words">
{isArray {isArray