Spaces:
Runtime error
Runtime error
<script lang="ts"> | |
import { onDestroy } from "svelte"; | |
import { JSON as JSONIcon } from "@gradio/icons"; | |
import { Empty } from "@gradio/atoms"; | |
import JSONNode from "./JSONNode.svelte"; | |
import { Copy, Check } from "@gradio/icons"; | |
export let value: any = {}; | |
export let open = false; | |
export let theme_mode: "system" | "light" | "dark" = "system"; | |
export let show_indices = false; | |
let copied = false; | |
let timer: NodeJS.Timeout; | |
function copy_feedback(): void { | |
copied = true; | |
if (timer) clearTimeout(timer); | |
timer = setTimeout(() => { | |
copied = false; | |
}, 1000); | |
} | |
async function handle_copy(): Promise<void> { | |
if ("clipboard" in navigator) { | |
await navigator.clipboard.writeText(JSON.stringify(value, null, 2)); | |
copy_feedback(); | |
} | |
} | |
function is_empty(obj: object): boolean { | |
return ( | |
obj && | |
Object.keys(obj).length === 0 && | |
Object.getPrototypeOf(obj) === Object.prototype && | |
JSON.stringify(obj) === JSON.stringify({}) | |
); | |
} | |
onDestroy(() => { | |
if (timer) clearTimeout(timer); | |
}); | |
</script> | |
{#if value && value !== '""' && !is_empty(value)} | |
<button | |
on:click={handle_copy} | |
title="copy" | |
class={copied ? "copied" : "copy-text"} | |
aria-roledescription={copied ? "Copied value" : "Copy value"} | |
aria-label={copied ? "Copied" : "Copy"} | |
> | |
{#if copied} | |
<Check /> | |
{:else} | |
<Copy /> | |
{/if} | |
</button> | |
<div class="json-holder"> | |
<JSONNode | |
{value} | |
depth={0} | |
is_root={true} | |
{open} | |
{theme_mode} | |
{show_indices} | |
/> | |
</div> | |
{:else} | |
<div class="empty-wrapper"> | |
<Empty> | |
<JSONIcon /> | |
</Empty> | |
</div> | |
{/if} | |
<style> | |
:global(.copied svg) { | |
animation: fade ease 300ms; | |
animation-fill-mode: forwards; | |
} | |
@keyframes fade { | |
0% { | |
opacity: 0; | |
} | |
100% { | |
opacity: 1; | |
} | |
} | |
.json-holder { | |
padding: var(--size-2); | |
overflow-y: scroll; | |
} | |
.empty-wrapper { | |
min-height: calc(var(--size-32) - 20px); | |
height: 100%; | |
} | |
button { | |
display: flex; | |
position: absolute; | |
top: var(--block-label-margin); | |
right: var(--block-label-margin); | |
align-items: center; | |
box-shadow: var(--shadow-drop); | |
border: 1px solid var(--border-color-primary); | |
border-top: none; | |
border-right: none; | |
border-radius: var(--block-label-right-radius); | |
background: var(--block-label-background-fill); | |
padding: 5px; | |
width: 22px; | |
height: 22px; | |
overflow: hidden; | |
color: var(--block-label-text-color); | |
font: var(--font); | |
font-size: var(--button-small-text-size); | |
} | |
</style> | |