|
1 | 1 | <script>
|
| 2 | +/** @type {*} */ |
2 | 3 | export let json
|
3 | 4 | export let depth = Infinity
|
4 |
| -export let _lvl = 0 |
| 5 | +export let _cur = 0 |
5 | 6 | export let _last = true
|
6 | 7 |
|
7 |
| -const collapsedSymbol = '...' |
8 |
| -const getType = (i) => { |
| 8 | +/** @type {*[]} */ |
| 9 | +let items |
| 10 | +let isArray = false |
| 11 | +let brackets = ['', ''] |
| 12 | +let collapsed = false |
| 13 | +
|
| 14 | +/** |
| 15 | + * @param {*} i |
| 16 | + * @returns {string} |
| 17 | + */ |
| 18 | +function getType(i) { |
9 | 19 | if (i === null) return 'null'
|
10 | 20 | return typeof i
|
11 | 21 | }
|
12 | 22 |
|
13 |
| -let items |
14 |
| -let isArray |
15 |
| -let openBracket |
16 |
| -let closeBracket |
17 |
| -$: { |
18 |
| - items = getType(json) === 'object' ? Object.keys(json) : [] |
19 |
| - isArray = Array.isArray(json) |
20 |
| - openBracket = isArray ? '[' : '{' |
21 |
| - closeBracket = isArray ? ']' : '}' |
| 23 | +/** |
| 24 | + * @param {*} i |
| 25 | + * @returns {string} |
| 26 | + */ |
| 27 | +function format(i) { |
| 28 | + const t = getType(i) |
| 29 | + if (t === 'string') return `"${i}"` |
| 30 | + if (t === 'function') return 'f () {...}' |
| 31 | + if (t === 'symbol') return i.toString() |
| 32 | + return i |
22 | 33 | }
|
23 | 34 |
|
24 |
| -let collapsed |
25 |
| -$: collapsed = depth < _lvl |
| 35 | +function clicked() { |
| 36 | + collapsed = !collapsed |
| 37 | +} |
26 | 38 |
|
27 |
| -const format = (i) => { |
28 |
| - switch (getType(i)) { |
29 |
| - case 'string': |
30 |
| - return `"${i}"` |
31 |
| - case 'function': |
32 |
| - return 'f () {...}' |
33 |
| - case 'symbol': |
34 |
| - return i.toString() |
35 |
| - default: |
36 |
| - return i |
37 |
| - } |
| 39 | +/** |
| 40 | + * @param {Event} e |
| 41 | + */ |
| 42 | +function pressed(e) { |
| 43 | + if (e instanceof KeyboardEvent && ['Enter', ' '].includes(e.key)) clicked() |
38 | 44 | }
|
39 |
| -const clicked = () => { |
40 |
| - collapsed = !collapsed |
| 45 | +
|
| 46 | +$: { |
| 47 | + items = getType(json) === 'object' ? Object.keys(json) : [] |
| 48 | + isArray = Array.isArray(json) |
| 49 | + brackets = isArray ? ['[', ']'] : ['{', '}'] |
41 | 50 | }
|
| 51 | +
|
| 52 | +$: collapsed = depth < _cur |
42 | 53 | </script>
|
43 | 54 |
|
44 | 55 | {#if !items.length}
|
45 |
| - <span class="bracket" tabindex="0">{openBracket}{closeBracket}</span>{#if !_last}<span |
46 |
| - class="comma">,</span |
| 56 | + <span class="_jsonBkt empty">{brackets[0]}{brackets[1]}</span>{#if !_last}<span class="_jsonSep" |
| 57 | + >,</span |
47 | 58 | >{/if}
|
| 59 | +{:else if collapsed} |
| 60 | + <span class="_jsonBkt" role="button" tabindex="0" on:click={clicked} on:keydown={pressed} |
| 61 | + >{brackets[0]}...{brackets[1]}</span |
| 62 | + >{#if !_last && collapsed}<span class="_jsonSep">,</span>{/if} |
48 | 63 | {:else}
|
49 |
| - <span class:hidden={collapsed}> |
50 |
| - <span class="bracket" on:click={clicked} tabindex="0">{openBracket}</span> |
51 |
| - <ul> |
52 |
| - {#each items as i, idx} |
53 |
| - <li> |
54 |
| - {#if !isArray} |
55 |
| - <span class="key">"{i}":</span> |
56 |
| - {/if} |
57 |
| - {#if getType(json[i]) === 'object'} |
58 |
| - <svelte:self json={json[i]} {depth} _lvl={_lvl + 1} _last={idx === items.length - 1} /> |
59 |
| - {:else} |
60 |
| - <span class="val {getType(json[i])}" |
61 |
| - >{format(json[i])}{#if idx < items.length - 1}<span class="comma">,</span>{/if}</span |
62 |
| - > |
63 |
| - {/if} |
64 |
| - </li> |
65 |
| - {/each} |
66 |
| - </ul> |
67 |
| - <span class="bracket" on:click={clicked} tabindex="0">{closeBracket}</span>{#if !_last}<span |
68 |
| - class="comma">,</span |
69 |
| - >{/if} |
70 |
| - </span> |
71 |
| - <span class="bracket" class:hidden={!collapsed} on:click={clicked} tabindex="0" |
72 |
| - >{openBracket}{collapsedSymbol}{closeBracket}</span |
73 |
| - >{#if !_last && collapsed}<span class="comma">,</span>{/if} |
| 64 | + <span class="_jsonBkt" role="button" tabindex="0" on:click={clicked} on:keydown={pressed} |
| 65 | + >{brackets[0]}</span |
| 66 | + > |
| 67 | + <ul class="_jsonList"> |
| 68 | + {#each items as i, idx} |
| 69 | + <li> |
| 70 | + {#if !isArray} |
| 71 | + <span class="_jsonKey">"{i}"</span><span class="_jsonSep">:</span> |
| 72 | + {/if} |
| 73 | + {#if getType(json[i]) === 'object'} |
| 74 | + <svelte:self json={json[i]} {depth} _cur={_cur + 1} _last={idx === items.length - 1} /> |
| 75 | + {:else} |
| 76 | + <span class="_jsonVal {getType(json[i])}">{format(json[i])}</span |
| 77 | + >{#if idx < items.length - 1}<span class="_jsonSep">,</span>{/if} |
| 78 | + {/if} |
| 79 | + </li> |
| 80 | + {/each} |
| 81 | + </ul> |
| 82 | + <span class="_jsonBkt" role="button" tabindex="0" on:click={clicked} on:keydown={pressed} |
| 83 | + >{brackets[1]}</span |
| 84 | + >{#if !_last}<span class="_jsonSep">,</span>{/if} |
74 | 85 | {/if}
|
75 | 86 |
|
76 | 87 | <style>
|
77 |
| -ul { |
| 88 | +._jsonList { |
78 | 89 | list-style: none;
|
79 | 90 | margin: 0;
|
80 | 91 | padding: 0;
|
81 |
| - padding-left: var(--nodePaddingLeft, 1rem); |
82 |
| - border-left: var(--nodeBorderLeft, 1px dotted #9ca3af); |
83 |
| - color: var(--nodeColor, #374151); |
| 92 | + padding-left: var(--jsonPaddingLeft, 1rem); |
| 93 | + border-left: var(--jsonBorderLeft, 1px dotted); |
84 | 94 | }
|
85 |
| -.hidden { |
86 |
| - display: none; |
| 95 | +._jsonBkt { |
| 96 | + color: var(--jsonBracketColor, currentcolor); |
87 | 97 | }
|
88 |
| -.bracket { |
| 98 | +._jsonBkt:not(.empty):hover { |
89 | 99 | cursor: pointer;
|
| 100 | + background: var(--jsonBracketHoverBackground, #e5e7eb); |
90 | 101 | }
|
91 |
| -.bracket:hover { |
92 |
| - background: var(--bracketHoverBackground, #d1d5db); |
| 102 | +._jsonSep { |
| 103 | + color: var(--jsonSeparatorColor, currentcolor); |
93 | 104 | }
|
94 |
| -.comma { |
95 |
| - color: var(--nodeColor, #374151); |
| 105 | +._jsonKey { |
| 106 | + color: var(--jsonKeyColor, currentcolor); |
96 | 107 | }
|
97 |
| -.val { |
98 |
| - color: var(--leafDefaultColor, #9ca3af); |
| 108 | +._jsonVal { |
| 109 | + color: var(--jsonValColor, #9ca3af); |
99 | 110 | }
|
100 |
| -.val.string { |
101 |
| - color: var(--leafStringColor, #059669); |
| 111 | +._jsonVal.string { |
| 112 | + color: var(--jsonValStringColor, #059669); |
102 | 113 | }
|
103 |
| -.val.number { |
104 |
| - color: var(--leafNumberColor, #d97706); |
| 114 | +._jsonVal.number { |
| 115 | + color: var(--jsonValNumberColor, #d97706); |
105 | 116 | }
|
106 |
| -.val.boolean { |
107 |
| - color: var(--leafBooleanColor, #2563eb); |
| 117 | +._jsonVal.boolean { |
| 118 | + color: var(--jsonValBooleanColor, #2563eb); |
108 | 119 | }
|
109 | 120 | </style>
|
0 commit comments