chore: move jsonviewer into ui package

This commit is contained in:
2026-05-03 16:11:40 +02:00
parent 3450d70047
commit 6ef5dc28ed
5 changed files with 71 additions and 30 deletions
@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { Graph } from '$lib/types'; import type { Graph } from '$lib/types';
import JsonNode from './JsonNode.svelte'; import { JsonViewer } from '@nodarium/ui';
const { graph }: { graph?: Graph } = $props(); const { graph }: { graph?: Graph } = $props();
@@ -16,7 +16,7 @@
<div class="overflow-auto p-2"> <div class="overflow-auto p-2">
{#if data} {#if data}
<JsonNode value={data} path="graph" /> <JsonViewer value={data} path="graph" />
{:else} {:else}
<span class="font-mono text-xs text-neutral-500">No graph loaded</span> <span class="font-mono text-xs text-neutral-500">No graph loaded</span>
{/if} {/if}
@@ -31,7 +31,7 @@
<script lang="ts"> <script lang="ts">
import { browser } from '$app/environment'; import { browser } from '$app/environment';
import JsonNode from './JsonNode.svelte'; import JsonViewer from './JsonViewer.svelte';
let { let {
value, value,
@@ -49,7 +49,7 @@
const open_bracket = $derived(isArr ? '[' : '{'); const open_bracket = $derived(isArr ? '[' : '{');
const close_bracket = $derived(isArr ? ']' : '}'); const close_bracket = $derived(isArr ? ']' : '}');
const items = $derived.by(() => { const items = $derived.by(() => {
if (Array.isArray(value)) { if (isArr) {
return (value as unknown[]).map((v, i) => [String(i), v] as [string, unknown]); return (value as unknown[]).map((v, i) => [String(i), v] as [string, unknown]);
} }
if (value !== null && typeof value === 'object') { if (value !== null && typeof value === 'object') {
@@ -59,6 +59,7 @@
} }
return [] as [string, unknown][]; return [] as [string, unknown][];
}); });
const showKeys = $derived(!isArr || typeof items[0]?.[1] === "object")
function toggle(next: boolean) { function toggle(next: boolean) {
open = next; open = next;
@@ -84,53 +85,53 @@
<span <span
class="font-mono text-xs leading-[1.6] rounded transition-[background-color] duration-500" class="font-mono text-xs leading-[1.6] rounded transition-[background-color] duration-500"
class:bg-white={flashing} class:bg-layer-3={flashing}
> >
{#if key !== undefined} {#if key !== undefined}
<span class="text-neutral-300">{key}</span><span class="text-neutral-600">: </span> <span class="text-text">{key}</span><span class="text-text/40">: </span>
{/if} {/if}
{#if isExpandable} {#if isExpandable}
{#if items.length === 0} {#if items.length === 0}
<span class="text-neutral-500">{open_bracket}{close_bracket}</span> <span class="text-text/50">{open_bracket}{close_bracket}</span>
{:else if open} {:else if open}
{#if depth > 0} {#if depth > 0}
<button class="w-3 text-neutral-500 hover:text-neutral-200" onclick={() => toggle(false)}> <button class="w-3 text-text/50 hover:text-text" onclick={() => toggle(false)}>
</button> </button>
{/if} {/if}
<span class="text-neutral-500">{open_bracket}</span> <span class="text-text/50">{open_bracket}</span>
<div class="pl-4 border-l border-neutral-700/60"> <div class="pl-4 border-l border-outline">
{#each items as [k, v], i (k)} {#each items as [k, v], i (k)}
<div> <div>
<JsonNode <JsonViewer
value={v} value={v}
key={k} key={showKeys ? k : undefined }
depth={depth + 1} depth={depth + 1}
path={path ? `${path}/${k}` : k} path={path ? `${path}/${k}` : k}
/>{#if i < items.length - 1}<span class="text-neutral-700">,</span>{/if} />{#if i < items.length - 1}<span class="text-text/20">,</span>{/if}
</div> </div>
{/each} {/each}
</div> </div>
<span class="text-neutral-500">{close_bracket}</span> <span class="text-text/50">{close_bracket}</span>
{:else} {:else}
<button <button
class="inline text-neutral-500 hover:text-neutral-200" class="inline text-text/50 hover:text-text"
onclick={() => toggle(true)} onclick={() => toggle(true)}
> >
<span class="w-3 inline-block"></span> <span class="w-3 inline-block"></span>
{open_bracket}<span class="text-neutral-600 mx-1">{items.length}</span>{close_bracket} {open_bracket}<span class="text-text/40 mx-1">{items.length}</span>{close_bracket}
</button> </button>
{/if} {/if}
{:else if value === null} {:else if value === null}
<span class="text-neutral-500!">null</span> <span class="text-emerald-500!">null</span>
{:else if typeof value === 'boolean'} {:else if typeof value === 'boolean'}
<span class="text-amber-400!">{value}</span> <span class="text-blue-500!">{value}</span>
{:else if typeof value === 'number'} {:else if typeof value === 'number'}
<span class="text-sky-400!">{value}</span> <span class="text-orange-400!">{value}</span>
{:else if typeof value === 'string'} {:else if typeof value === 'string'}
<span class="text-emerald-400!">"{value}"</span> <span class="text-emerald-500!">"{value}"</span>
{:else} {:else}
<span class="text-neutral-400">{String(value)}</span> <span class="text-text/70">{String(value)}</span>
{/if} {/if}
</span> </span>
+1
View File
@@ -7,6 +7,7 @@ export { default as InputShape } from './inputs/InputShape.svelte';
export { default as InputVec3 } from './inputs/InputVec3.svelte'; export { default as InputVec3 } from './inputs/InputVec3.svelte';
export { default as Details } from './Details.svelte'; export { default as Details } from './Details.svelte';
export { default as JsonViewer } from './JsonViewer.svelte';
export { default as ShortCut } from './ShortCut.svelte'; export { default as ShortCut } from './ShortCut.svelte';
import Input from './Input.svelte'; import Input from './Input.svelte';
+45
View File
@@ -8,6 +8,7 @@
InputSelect, InputSelect,
InputShape, InputShape,
InputVec3, InputVec3,
JsonViewer,
ShortCut ShortCut
} from '$lib'; } from '$lib';
import Section from './Section.svelte'; import Section from './Section.svelte';
@@ -25,6 +26,32 @@
let colorValue = $state<[number, number, number]>([59, 130, 246]); let colorValue = $state<[number, number, number]>([59, 130, 246]);
let mirrorShape = $state(true); let mirrorShape = $state(true);
let detailsOpen = $state(false); let detailsOpen = $state(false);
let jsonValue = $state({
id: 1,
nodes: [{ id: 0, type: 'max/test/node', position: [0, 0] }, {
id: 1,
type: 'max/test/other',
position: [100, 50]
}],
edges: [[0, 0, 1, 'input']],
groups: [],
settings: { seed: 42, enabled: true }
});
function randomlyUpdateJson() {
const rand = Math.floor(Math.random() * 5);
if (rand === 0) {
jsonValue.nodes[0].position[0] += 1;
} else if (rand === 1) {
jsonValue.nodes[0].position[1] += 1;
} else if (rand === 2) {
jsonValue.settings.seed += 1;
} else if (rand === 3) {
jsonValue.settings.enabled = !jsonValue.settings.enabled;
} else if (rand === 4) {
jsonValue.id += Math.floor(Math.random() * 10 - 5);
}
}
let points = $state([]); let points = $state([]);
let theme = $state('dark'); let theme = $state('dark');
@@ -56,6 +83,7 @@
</Section> </Section>
<Section title="Select" value={d}> <Section title="Select" value={d}>
<i>Select with simple values</i>
<InputSelect bind:value={selectValue} {options} /> <InputSelect bind:value={selectValue} {options} />
</Section> </Section>
@@ -86,6 +114,23 @@
</Details> </Details>
</Section> </Section>
<Section title="JsonViewer">
{#snippet header()}
<button
onclick={() => randomlyUpdateJson()}
class="-mt-1 bg-layer-2 p-1 px-2 rounded-sm cursor-pointer"
>
update
</button>
{/snippet}
<div class="w-64 bg-layer-1 p-2 rounded">
<JsonViewer
value={jsonValue}
path="demo"
/>
</div>
</Section>
<Section title="Shortcut"> <Section title="Shortcut">
<div class="flex gap-4"> <div class="flex gap-4">
<ShortCut ctrl key="S" /> <ShortCut ctrl key="S" />
-6
View File
@@ -4,12 +4,6 @@ settings:
autoInstallPeers: true autoInstallPeers: true
excludeLinksFromLockfile: false excludeLinksFromLockfile: false
catalogs:
default:
chokidar-cli:
specifier: github:open-cli-tools/chokidar-cli#semver:v4.0.0
version: 4.0.0
importers: importers:
.: .: