<!-- Source: https://jsonview.svelte.page/examples/playground -->

# Live Playground

> Edit JSON or JS expressions and see a live JsonView render. Swap expand strategies, toggle click-to-expand, all in the browser.

**Source:** [https://jsonview.svelte.page/examples/playground](https://jsonview.svelte.page/examples/playground)

**Markdown mirror:** [https://jsonview.svelte.page/examples/playground.md](https://jsonview.svelte.page/examples/playground.md)

---

This mirror preserves the prose, implementation notes, and runnable Svelte source behind the live example page.

## FIG-001: live playground.

Edit JSON in real time, switch expansion behavior, and preview the rendered tree without leaving the page.

**Metadata:** tag: `DEMO` | input: `json` | preview: `JsonView`

### Notes

- Edit raw JSON or a JS expression and the tree re-renders as you type, with inline parse errors when the input is invalid.
- Swap the expand strategy between `allExpanded` and `collapseAllNested`, and toggle `clickToExpandNode` live.
- The preview is the real packaged `JsonView` — what you see is exactly what ships in your app.

### Source

#### JsonPlayground.svelte

Source file: [src/lib/examples/playground/demos/JsonPlayground.svelte](https://github.com/humanspeak/svelte-json-view-lite/blob/main/docs/src/lib/examples/playground/demos/JsonPlayground.svelte)

```svelte
<script lang="ts">
    import { JsonView, allExpanded, collapseAllNested } from '@humanspeak/svelte-json-view-lite'
    import { docsDarkJsonViewStyles, docsDefaultJsonViewStyles } from '$lib/json-view-docs-style'
    import { mode } from 'mode-watcher'

    type ParseMode = 'json' | 'js'
    type ExpandMode = 'root' | 'all' | 'level'

    const defaultSource = `{
    "user": {
        "id": 42,
        "name": "Ada Lovelace",
        "tags": ["admin", "beta"],
        "joined": "2024-01-15T09:00:00.000Z"
    },
    "totals": { "requests": 1523, "errors": 0, "latencyMs": 12.4 },
    "active": true,
    "nextReview": null
}`

    const jsDefault = `({
    user: { id: 42, name: 'Ada Lovelace', joined: new Date('2024-01-15') },
    counter: 9007199254740991n,
    active: true,
    render: function() { },
    nextReview: null
})`

    const jsValue = {
        user: { id: 42, name: 'Ada Lovelace', joined: new Date('2024-01-15') },
        counter: 9007199254740991n,
        active: true,
        render: function () {},
        nextReview: null
    }

    let parseMode = $state<ParseMode>('json')
    let source = $state(defaultSource)
    let expandMode = $state<ExpandMode>('root')
    let expandLevel = $state(2)
    let clickToExpand = $state(true)

    type Parsed = { value: unknown; error: string | null }

    const parsed = $derived.by<Parsed>(() => {
        try {
            if (parseMode === 'json') {
                return { value: JSON.parse(source), error: null }
            }
            if (source.trim() === jsDefault.trim()) {
                return { value: jsValue, error: null }
            }
            return {
                value: jsValue,
                error: 'JS expression editing is disabled by the docs CSP. Switch to JSON for editable input.'
            }
        } catch (err) {
            return { value: null, error: err instanceof Error ? err.message : String(err) }
        }
    })

    const expand = $derived.by(() => {
        if (expandMode === 'all') return allExpanded
        if (expandMode === 'root') return collapseAllNested
        return (level: number) => level < expandLevel
    })

    const style = $derived(
        mode.current === 'light' ? docsDefaultJsonViewStyles : docsDarkJsonViewStyles
    )

    const swapMode = (next: ParseMode) => {
        if (next === parseMode) return
        parseMode = next
        source = next === 'js' ? jsDefault : defaultSource
    }
</script>

<div class="json-demo column">
    <div class="json-demo-controls">
        <div class="json-demo-control-group">
            <span>parse</span>
            <button class:active={parseMode === 'json'} onclick={() => swapMode('json')}
                >JSON</button
            >
            <button class:active={parseMode === 'js'} onclick={() => swapMode('js')}>JS</button>
        </div>

        <div class="json-demo-divider"></div>

        <div class="json-demo-control-group">
            <span>expand</span>
            <select bind:value={expandMode}>
                <option value="root">Root only</option>
                <option value="all">All</option>
                <option value="level">By level</option>
            </select>
            {#if expandMode === 'level'}
                <input type="number" min="0" max="10" bind:value={expandLevel} />
            {/if}
        </div>

        <div class="json-demo-divider"></div>

        <label class="json-demo-control">
            <input type="checkbox" bind:checked={clickToExpand} />
            click label to expand
        </label>
    </div>

    <div class="json-demo grid">
        <div class="json-demo-source">
            <textarea bind:value={source} spellcheck="false"></textarea>
            {#if parsed.error}
                <div class="json-demo-error">
                    {parsed.error}
                </div>
            {/if}
        </div>

        <div class="json-demo-body">
            {#if parsed.value !== null && typeof parsed.value === 'object'}
                <JsonView
                    data={parsed.value as object}
                    {style}
                    shouldExpandNode={expand}
                    clickToExpandNode={clickToExpand}
                />
            {:else if parsed.error === null}
                <pre>{JSON.stringify(parsed.value, null, 2)}</pre>
            {:else}
                <p>Fix the parse error to preview.</p>
            {/if}
        </div>
    </div>
</div>
```
