|
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