mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-09 15:07:55 -05:00
Allowed ability to copy json object
This commit is contained in:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user