fragment-tools 0.1.20 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.js +2 -2
- package/package.json +5 -6
- package/src/cli/build.js +1 -1
- package/src/cli/plugins/check-dependencies.js +19 -17
- package/src/cli/run.js +1 -1
- package/src/cli/templates/three-fragment/index.js +6 -6
- package/src/cli/templates/three-orthographic/index.js +3 -3
- package/src/cli/templates/three-perspective/index.js +3 -3
- package/src/client/app/actions/resize.js +14 -0
- package/src/client/app/components/HintLoading.svelte +94 -0
- package/src/client/app/components/HintPaused.svelte +88 -0
- package/src/client/app/components/HintRecord.svelte +62 -0
- package/src/client/app/components/IconLocked.svelte +51 -0
- package/src/client/app/components/IconTriggers.svelte +48 -0
- package/src/client/app/components/Init.svelte +14 -27
- package/src/client/app/components/KeyBinding.svelte +3 -6
- package/src/client/app/helpers.js +4 -40
- package/src/client/app/hooks.js +41 -17
- package/src/client/app/inputs/MIDI.js +2 -1
- package/src/client/app/lib/canvas-recorder/CanvasRecorder.js +6 -1
- package/src/client/app/lib/gl/Renderer.js +1 -0
- package/src/client/app/lib/svelte-json-tree/ErrorNode.svelte +28 -0
- package/src/client/app/lib/svelte-json-tree/ErrorStack.svelte +31 -0
- package/src/client/app/lib/svelte-json-tree/Expandable.svelte +25 -0
- package/src/client/app/lib/svelte-json-tree/JSONArrayNode.svelte +38 -0
- package/src/client/app/lib/svelte-json-tree/JSONArrow.svelte +47 -0
- package/src/client/app/lib/svelte-json-tree/JSONFunctionNode.svelte +114 -0
- package/src/client/app/lib/svelte-json-tree/JSONIterableArrayNode.svelte +60 -0
- package/src/client/app/lib/svelte-json-tree/JSONIterableMapNode.svelte +87 -0
- package/src/client/app/lib/svelte-json-tree/JSONNested.svelte +94 -0
- package/src/client/app/lib/svelte-json-tree/JSONNode.svelte +91 -0
- package/src/client/app/lib/svelte-json-tree/JSONObjectNode.svelte +40 -0
- package/src/client/app/lib/svelte-json-tree/JSONStringNode.svelte +31 -0
- package/src/client/app/lib/svelte-json-tree/JSONValueNode.svelte +31 -0
- package/src/client/app/lib/svelte-json-tree/PreviewList.svelte +38 -0
- package/src/client/app/lib/svelte-json-tree/RegExpNode.svelte +42 -0
- package/src/client/app/lib/svelte-json-tree/Root.svelte +75 -0
- package/src/client/app/lib/svelte-json-tree/Summary.svelte +9 -0
- package/src/client/app/lib/svelte-json-tree/TypedArrayNode.svelte +56 -0
- package/src/client/app/lib/svelte-json-tree/index.js +1 -0
- package/src/client/app/lib/svelte-json-tree/utils.js +57 -0
- package/src/client/app/modules/Console/ConsoleLine.svelte +12 -11
- package/src/client/app/modules/Console.svelte +82 -17
- package/src/client/app/modules/Exports.svelte +48 -48
- package/src/client/app/modules/MidiPanel.svelte +12 -19
- package/src/client/app/modules/Monitor.svelte +147 -55
- package/src/client/app/modules/Params.svelte +127 -80
- package/src/client/app/renderers/2DRenderer.js +1 -0
- package/src/client/app/renderers/FragmentRenderer.js +1 -1
- package/src/client/app/renderers/P5GLRenderer.js +11 -5
- package/src/client/app/renderers/P5Renderer.js +7 -3
- package/src/client/app/renderers/THREERenderer.js +42 -79
- package/src/client/app/state/Sketch.svelte.js +538 -0
- package/src/client/app/state/errors.svelte.js +17 -0
- package/src/client/app/state/exports.svelte.js +152 -0
- package/src/client/app/state/layout.svelte.js +205 -0
- package/src/client/app/state/monitors.svelte.js +36 -0
- package/src/client/app/state/renderers.svelte.js +77 -0
- package/src/client/app/state/rendering.svelte.js +697 -0
- package/src/client/app/state/sketches.svelte.js +73 -0
- package/src/client/app/state/utils.svelte.js +65 -0
- package/src/client/app/ui/Build.svelte +53 -60
- package/src/client/app/ui/ErrorOverlay.svelte +2 -2
- package/src/client/app/ui/Field.svelte +63 -189
- package/src/client/app/ui/FieldGroup.svelte +4 -5
- package/src/client/app/ui/FieldSection.svelte +14 -9
- package/src/client/app/ui/FieldSpace.svelte +1 -1
- package/src/client/app/ui/FieldTrigger.svelte +86 -84
- package/src/client/app/ui/FieldTriggers.svelte +25 -24
- package/src/client/app/ui/FloatingParams.svelte +50 -12
- package/src/client/app/ui/Layout.svelte +24 -13
- package/src/client/app/ui/LayoutColumn.svelte +2 -2
- package/src/client/app/ui/LayoutComponent.svelte +86 -195
- package/src/client/app/ui/LayoutResizer.svelte +25 -37
- package/src/client/app/ui/LayoutRoot.svelte +3 -5
- package/src/client/app/ui/LayoutRow.svelte +2 -2
- package/src/client/app/ui/LayoutToolbar.svelte +17 -76
- package/src/client/app/ui/Module.svelte +31 -35
- package/src/client/app/ui/ModuleHeaderAction.svelte +23 -16
- package/src/client/app/ui/ModuleHeaderButton.svelte +3 -3
- package/src/client/app/ui/ModuleHeaderSelect.svelte +4 -12
- package/src/client/app/ui/ModuleRenderer.svelte +84 -22
- package/src/client/app/ui/ParamsOutput.svelte +61 -77
- package/src/client/app/ui/Preview.svelte +15 -4
- package/src/client/app/ui/SelectChevrons.svelte +1 -2
- package/src/client/app/ui/SketchRenderer.svelte +89 -701
- package/src/client/app/ui/SketchSelect.svelte +14 -49
- package/src/client/app/ui/fields/ButtonInput.svelte +14 -11
- package/src/client/app/ui/fields/CheckboxInput.svelte +5 -12
- package/src/client/app/ui/fields/ColorInput.svelte +46 -121
- package/src/client/app/ui/fields/FieldInputRow.svelte +5 -1
- package/src/client/app/ui/fields/ImageInput.svelte +14 -14
- package/src/client/app/ui/fields/Input.svelte +19 -25
- package/src/client/app/ui/fields/IntervalInput.svelte +22 -22
- package/src/client/app/ui/fields/NumberInput.svelte +32 -38
- package/src/client/app/ui/fields/ProgressInput.svelte +14 -13
- package/src/client/app/ui/fields/Select.svelte +34 -45
- package/src/client/app/ui/fields/TextInput.svelte +10 -6
- package/src/client/app/ui/fields/VectorInput.svelte +25 -30
- package/src/client/app/utils/canvas.utils.js +8 -8
- package/src/client/app/utils/color.utils.js +46 -13
- package/src/client/app/utils/fields.utils.js +1 -1
- package/src/client/app/utils/glsl.utils.js +1 -1
- package/src/client/app/utils/glslErrors.js +1 -1
- package/src/client/main.js +2 -2
|
@@ -1,42 +1,6 @@
|
|
|
1
|
-
import { props } from './stores/props';
|
|
2
|
-
|
|
3
|
-
const propHandler = {
|
|
4
|
-
set: function (target, key, value, receiver) {
|
|
5
|
-
Reflect.set(target, key, value, receiver);
|
|
6
|
-
|
|
7
|
-
if (key === 'value') {
|
|
8
|
-
props.update((currentProps) => currentProps);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return true;
|
|
12
|
-
},
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const propsHandler = {
|
|
16
|
-
get: (target, key) => {
|
|
17
|
-
if (typeof target[key] === 'object' && target[key] !== null) {
|
|
18
|
-
return new Proxy(target[key], propHandler);
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
set: (target, key, value) => {
|
|
22
|
-
console.log('new set', target, key, value);
|
|
23
|
-
|
|
24
|
-
target[key] = value;
|
|
25
|
-
|
|
26
|
-
props.update((currentProps) => currentProps);
|
|
27
|
-
|
|
28
|
-
return true;
|
|
29
|
-
},
|
|
30
|
-
deleteProperty: (target, prop) => {
|
|
31
|
-
if (prop in target) {
|
|
32
|
-
delete target[prop];
|
|
33
|
-
props.update((currentProps) => currentProps);
|
|
34
|
-
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
|
|
40
1
|
export function reactiveProps(props = {}) {
|
|
41
|
-
|
|
2
|
+
console.warn(
|
|
3
|
+
`reactiveProps has been deprecated. Props are now reactive by default.`,
|
|
4
|
+
);
|
|
5
|
+
return props;
|
|
42
6
|
}
|
package/src/client/app/hooks.js
CHANGED
|
@@ -1,20 +1,44 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
removeBeforeRecordFrom,
|
|
5
|
-
removeAfterRecordFrom,
|
|
6
|
-
} from './stores/exports';
|
|
1
|
+
import { rendering } from './state/rendering.svelte';
|
|
2
|
+
import { sketchesManager } from './state/sketches.svelte';
|
|
3
|
+
import { getContext } from './triggers/shared';
|
|
7
4
|
|
|
8
|
-
export {
|
|
9
|
-
onBeforeCapture
|
|
10
|
-
|
|
11
|
-
onBeforeRecord,
|
|
12
|
-
onAfterRecord,
|
|
13
|
-
} from './stores/exports';
|
|
5
|
+
export let onBeforeCapture = (listener, context = getContext()) => {
|
|
6
|
+
sketchesManager.sketches[context]?.onBeforeCapture(listener);
|
|
7
|
+
};
|
|
14
8
|
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
export let onAfterCapture = (listener, context = getContext()) => {
|
|
10
|
+
sketchesManager.sketches[context]?.onAfterCapture(listener);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export let onBeforeRecord = (listener, context = getContext()) => {
|
|
14
|
+
sketchesManager.sketches[context]?.onBeforeRecord(listener);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export let onAfterRecord = (listener, context = getContext()) => {
|
|
18
|
+
sketchesManager.sketches[context]?.onAfterRecord(listener);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Screenshot the sketch it is called from
|
|
23
|
+
* @param {object} options
|
|
24
|
+
* @param {string} [options.filename]
|
|
25
|
+
* @param {function} [options.pattern]
|
|
26
|
+
* @param {exportDir} [options.pattern ]
|
|
27
|
+
*/
|
|
28
|
+
export async function screenshot({ filename, pattern, exportDir } = {}) {
|
|
29
|
+
const context = getContext();
|
|
30
|
+
|
|
31
|
+
const renders = rendering.renders.filter(
|
|
32
|
+
(render) => render.sketch.key === context,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
if (renders.length > 0) {
|
|
36
|
+
for (let i = 0; i < renders.length; i++) {
|
|
37
|
+
await renders[i].screenshot({
|
|
38
|
+
filename,
|
|
39
|
+
pattern,
|
|
40
|
+
exportDir,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
20
44
|
}
|
|
@@ -8,7 +8,7 @@ const commands = {
|
|
|
8
8
|
|
|
9
9
|
const notes = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];
|
|
10
10
|
|
|
11
|
-
const LOCAL_STORAGE_KEY = 'midi.requested';
|
|
11
|
+
const LOCAL_STORAGE_KEY = 'fragment.midi.requested';
|
|
12
12
|
|
|
13
13
|
class MIDI extends Input {
|
|
14
14
|
constructor() {
|
|
@@ -125,6 +125,7 @@ class MIDI extends Input {
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
async request() {
|
|
128
|
+
console.log('MIDI :: request!');
|
|
128
129
|
try {
|
|
129
130
|
if (!this.requesting && !this.access) {
|
|
130
131
|
localStorage.setItem(LOCAL_STORAGE_KEY, true);
|
|
@@ -29,11 +29,14 @@ class CanvasRecorder {
|
|
|
29
29
|
: Infinity;
|
|
30
30
|
this.started = false;
|
|
31
31
|
this.stopped = false;
|
|
32
|
+
|
|
33
|
+
this.startTime = 0;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
async load() {}
|
|
35
37
|
|
|
36
38
|
async start() {
|
|
39
|
+
this.startTime = performance.now();
|
|
37
40
|
this.onStart();
|
|
38
41
|
|
|
39
42
|
await this.load();
|
|
@@ -96,7 +99,9 @@ class CanvasRecorder {
|
|
|
96
99
|
tick() {}
|
|
97
100
|
|
|
98
101
|
end() {
|
|
99
|
-
console.log(
|
|
102
|
+
console.log(
|
|
103
|
+
`CanvasRecorder - compiled ${this.frameCount + 1} frames in ${(performance.now() - this.startTime) / 1000}s`,
|
|
104
|
+
);
|
|
100
105
|
this.onComplete(this.result);
|
|
101
106
|
}
|
|
102
107
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import ErrorStack from './ErrorStack.svelte';
|
|
3
|
+
import JSONNested from './JSONNested.svelte';
|
|
4
|
+
import JSONNode from './JSONNode.svelte';
|
|
5
|
+
|
|
6
|
+
let { value } = $props();
|
|
7
|
+
|
|
8
|
+
let stack = $derived(value.stack.split('\n'));
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<JSONNested keys={['message', 'stack']}>
|
|
12
|
+
{#snippet summary()}
|
|
13
|
+
<span class="label">Error: {String(value.message)}</span>
|
|
14
|
+
{/snippet}
|
|
15
|
+
{#snippet preview()}
|
|
16
|
+
<span class="label">Error: {String(value.message)}</span>
|
|
17
|
+
{/snippet}
|
|
18
|
+
{#snippet itemKey(key)}
|
|
19
|
+
<span class="property">{key}</span>
|
|
20
|
+
{/snippet}
|
|
21
|
+
{#snippet itemValue(key)}
|
|
22
|
+
{#if key === 'stack'}
|
|
23
|
+
<ErrorStack {stack} />
|
|
24
|
+
{:else}
|
|
25
|
+
<JSONNode value={value[key]} />
|
|
26
|
+
{/if}
|
|
27
|
+
{/snippet}
|
|
28
|
+
</JSONNested>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import JsonNode from './JSONNode.svelte';
|
|
3
|
+
import { useState } from './utils.js';
|
|
4
|
+
|
|
5
|
+
let { stack } = $props();
|
|
6
|
+
|
|
7
|
+
const { expanded, expandable, toggleExpand } = useState();
|
|
8
|
+
//expandable = true;
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<!-- svelte-ignore a11y_click_events_have_key_events a11y-no-static-element-interactions -->
|
|
12
|
+
<span onclick={(e) => toggleExpand(e)} role="button">
|
|
13
|
+
{#if expanded}
|
|
14
|
+
{#each stack as line, index}
|
|
15
|
+
{@const appendNewLine = index < stack.length - 1}
|
|
16
|
+
<span class:indent={index > 0}
|
|
17
|
+
><JsonNode value={line + (appendNewLine ? '\\n' : '')} /><span
|
|
18
|
+
class="operator">{appendNewLine ? ' +' : ''}</span
|
|
19
|
+
></span
|
|
20
|
+
><br />
|
|
21
|
+
{/each}
|
|
22
|
+
{:else}
|
|
23
|
+
<span><JsonNode value={stack[0] + '…'} /></span>
|
|
24
|
+
{/if}
|
|
25
|
+
</span>
|
|
26
|
+
|
|
27
|
+
<style>
|
|
28
|
+
.indent {
|
|
29
|
+
padding-left: var(--li-identation);
|
|
30
|
+
}
|
|
31
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { useState } from './utils.js';
|
|
3
|
+
|
|
4
|
+
let { key, children } = $props();
|
|
5
|
+
|
|
6
|
+
// const expandable = $state(false);
|
|
7
|
+
// setContext('expandable', false);
|
|
8
|
+
// useState(({ keyPath, level }) => {
|
|
9
|
+
// if (key !== '[[Entries]]') {
|
|
10
|
+
// keyPath = [...keyPath, key];
|
|
11
|
+
// level = level + 1;
|
|
12
|
+
// }
|
|
13
|
+
// return {
|
|
14
|
+
// keyPath,
|
|
15
|
+
// level,
|
|
16
|
+
// expanded,
|
|
17
|
+
// expandable,
|
|
18
|
+
// toggle: () => {
|
|
19
|
+
// expanded = !expanded;
|
|
20
|
+
// },
|
|
21
|
+
// };
|
|
22
|
+
// });
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
{@render children?.()}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import JSONArrow from './JSONArrow.svelte';
|
|
3
|
+
import JSONNested from './JSONNested.svelte';
|
|
4
|
+
import JSONNode from './JSONNode.svelte';
|
|
5
|
+
import PreviewList from './PreviewList.svelte';
|
|
6
|
+
|
|
7
|
+
let { value } = $props();
|
|
8
|
+
|
|
9
|
+
let keys = $derived(Object.getOwnPropertyNames(value));
|
|
10
|
+
let previewList = $derived(value.slice(0, 5));
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<JSONNested {keys}>
|
|
14
|
+
{#snippet summary()}
|
|
15
|
+
<span class="label">Array({value.length})</span>
|
|
16
|
+
{/snippet}
|
|
17
|
+
|
|
18
|
+
{#snippet preview(root)}
|
|
19
|
+
<PreviewList
|
|
20
|
+
list={previewList}
|
|
21
|
+
hasMore={previewList.length < value.length}
|
|
22
|
+
label="({value.length}) "
|
|
23
|
+
prefix="["
|
|
24
|
+
postfix="]"
|
|
25
|
+
{root}
|
|
26
|
+
>
|
|
27
|
+
{#snippet item(node)}
|
|
28
|
+
<JSONNode value={node} />
|
|
29
|
+
{/snippet}
|
|
30
|
+
</PreviewList>
|
|
31
|
+
{/snippet}
|
|
32
|
+
{#snippet itemKey(key)}
|
|
33
|
+
<span class="property">{String(key)}</span>
|
|
34
|
+
{/snippet}
|
|
35
|
+
{#snippet itemValue(key)}
|
|
36
|
+
<JSONNode value={value[key]} />
|
|
37
|
+
{/snippet}
|
|
38
|
+
</JSONNested>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { useState } from './utils';
|
|
3
|
+
|
|
4
|
+
let {
|
|
5
|
+
expandable: _expandable,
|
|
6
|
+
expanded: _expanded,
|
|
7
|
+
toggleExpand,
|
|
8
|
+
} = useState();
|
|
9
|
+
let { expanded = _expanded, expandable = _expandable } = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
{#if expandable}
|
|
13
|
+
<!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
|
|
14
|
+
<span class="json-arrow" class:expanded>
|
|
15
|
+
<span class="char">{'\u25B6'}</span>
|
|
16
|
+
</span>
|
|
17
|
+
{/if}
|
|
18
|
+
|
|
19
|
+
<style>
|
|
20
|
+
.json-arrow {
|
|
21
|
+
display: inline-flex;
|
|
22
|
+
transition: 150ms;
|
|
23
|
+
line-height: 1.1em;
|
|
24
|
+
|
|
25
|
+
transform-origin: 2px 50%;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.json-arrow.expanded {
|
|
29
|
+
transform: rotateZ(90deg);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.char {
|
|
33
|
+
transform-origin: 25% 50%;
|
|
34
|
+
position: relative;
|
|
35
|
+
font-size: 0.75em;
|
|
36
|
+
margin-left: 0;
|
|
37
|
+
color: var(--arrow-color);
|
|
38
|
+
user-select: none;
|
|
39
|
+
font-family: 'Courier New', Courier, monospace;
|
|
40
|
+
display: block;
|
|
41
|
+
margin-top: 1px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* .expanded {
|
|
45
|
+
transform: rotateZ(90deg) translateX(-3px);
|
|
46
|
+
} */
|
|
47
|
+
</style>
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import JSONNested from './JSONNested.svelte';
|
|
3
|
+
import JSONNode from './JSONNode.svelte';
|
|
4
|
+
import JsonObjectNode from './JSONObjectNode.svelte';
|
|
5
|
+
|
|
6
|
+
let { value = () => {} } = $props();
|
|
7
|
+
|
|
8
|
+
let str = $derived(toString(value));
|
|
9
|
+
let ctx = $derived(parseFunction(str));
|
|
10
|
+
|
|
11
|
+
function parseFunction(str) {
|
|
12
|
+
const match = str.match(
|
|
13
|
+
/^(?:(async)\s+)?(?:function)?(\*)?\s*([^(]+)?(\([^)]*\))\s*(=>)?/,
|
|
14
|
+
);
|
|
15
|
+
const isAsync = match?.[1];
|
|
16
|
+
const isGenerator = match?.[2];
|
|
17
|
+
const fnName = match?.[3];
|
|
18
|
+
const args = match?.[4];
|
|
19
|
+
const isArrow = match?.[5];
|
|
20
|
+
const classMatch = str.match(/^class\s+([^\s]+)/);
|
|
21
|
+
const isClass = classMatch?.[1];
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
args,
|
|
25
|
+
isAsync,
|
|
26
|
+
isGenerator,
|
|
27
|
+
fnName,
|
|
28
|
+
isArrow,
|
|
29
|
+
isClass,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function getPreview1({ isGenerator, isAsync, isClass }) {
|
|
34
|
+
if (isClass) return `class ${isClass}`;
|
|
35
|
+
return (isAsync ? 'async ' : '') + 'ƒ' + (isGenerator ? '*' : '');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function getPreview2({ isAsync, isArrow, fnName, args }) {
|
|
39
|
+
return (
|
|
40
|
+
(isArrow && isAsync ? 'async' : '') +
|
|
41
|
+
' ' +
|
|
42
|
+
(fnName ?? '') +
|
|
43
|
+
args +
|
|
44
|
+
(isArrow ? ' => …' : '')
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const FUNCTION = '[[Function]]';
|
|
49
|
+
const PROTO = '[[Prototype]]';
|
|
50
|
+
|
|
51
|
+
function getValue(key) {
|
|
52
|
+
if (key === PROTO) return value.__proto__;
|
|
53
|
+
return value[key];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function filterKeys(key) {
|
|
57
|
+
if (key === FUNCTION) return true;
|
|
58
|
+
return getValue(key);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function toString(value = () => {}) {
|
|
62
|
+
try {
|
|
63
|
+
return value.toString();
|
|
64
|
+
} catch {
|
|
65
|
+
switch (value.constructor.name) {
|
|
66
|
+
case 'AsyncFunction':
|
|
67
|
+
return 'async function () {}';
|
|
68
|
+
case 'AsyncGeneratorFunction':
|
|
69
|
+
return 'async function * () {}';
|
|
70
|
+
case 'GeneratorFunction:':
|
|
71
|
+
return 'function * () {}';
|
|
72
|
+
default:
|
|
73
|
+
return 'function () {}';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let keys = $derived(
|
|
79
|
+
['length', 'name', 'prototype', FUNCTION, PROTO].filter(filterKeys),
|
|
80
|
+
);
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<JSONNested {keys}>
|
|
84
|
+
{#snippet summary()}
|
|
85
|
+
<span class="i">ƒ</span>
|
|
86
|
+
{/snippet}
|
|
87
|
+
{#snippet preview()}
|
|
88
|
+
{#if !ctx.isArrow}<span class="fn i">{getPreview1(ctx)}</span
|
|
89
|
+
>{/if}{#if !ctx.isClass}<span class="i">{getPreview2(ctx)}</span
|
|
90
|
+
>{/if}
|
|
91
|
+
{/snippet}
|
|
92
|
+
{#snippet itemKey(key)}
|
|
93
|
+
<span
|
|
94
|
+
class={key === FUNCTION || key === PROTO ? 'internal' : 'property'}
|
|
95
|
+
>{key}</span
|
|
96
|
+
>
|
|
97
|
+
{/snippet}
|
|
98
|
+
{#snippet itemValue(key)}
|
|
99
|
+
{#if key === FUNCTION}<span class="i">{str}</span
|
|
100
|
+
>{:else if key === 'prototype'}<JsonObjectNode
|
|
101
|
+
value={getValue(key)}
|
|
102
|
+
/>{:else}<JSONNode value={getValue(key)} />{/if}
|
|
103
|
+
{/snippet}
|
|
104
|
+
</JSONNested>
|
|
105
|
+
|
|
106
|
+
<style>
|
|
107
|
+
.i {
|
|
108
|
+
font-style: italic;
|
|
109
|
+
}
|
|
110
|
+
.fn,
|
|
111
|
+
.i {
|
|
112
|
+
color: var(--function-color);
|
|
113
|
+
}
|
|
114
|
+
</style>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import JSONNested from './JSONNested.svelte';
|
|
3
|
+
import JSONNode from './JSONNode.svelte';
|
|
4
|
+
import PreviewList from './PreviewList.svelte';
|
|
5
|
+
|
|
6
|
+
let { value, nodeType } = $props();
|
|
7
|
+
|
|
8
|
+
let [indexes, items] = $derived.by(() => {
|
|
9
|
+
let _indexes = [];
|
|
10
|
+
let _items = [];
|
|
11
|
+
let i = 0;
|
|
12
|
+
for (const entry of value) {
|
|
13
|
+
_indexes.push(i++);
|
|
14
|
+
_items.push(entry);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return [_indexes, _items];
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
let previewItems = $derived(items.slice(0, 5));
|
|
21
|
+
|
|
22
|
+
const ENTRIES = '[[Entries]]';
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<JSONNested keys={[ENTRIES, 'size']} shouldShowColon={(key) => key !== ENTRIES}>
|
|
26
|
+
{#snippet summary()}
|
|
27
|
+
<span class="label">{nodeType}({indexes.length})</span>
|
|
28
|
+
{/snippet}
|
|
29
|
+
{#snippet preview(root)}
|
|
30
|
+
<PreviewList
|
|
31
|
+
list={previewItems}
|
|
32
|
+
hasMore={previewItems.length < items.length}
|
|
33
|
+
label={`${nodeType}(${indexes.length}) `}
|
|
34
|
+
prefix={'{'}
|
|
35
|
+
postfix="}"
|
|
36
|
+
{root}
|
|
37
|
+
>
|
|
38
|
+
{#snippet item(value)}
|
|
39
|
+
<JSONNode {value} />
|
|
40
|
+
{/snippet}
|
|
41
|
+
</PreviewList>
|
|
42
|
+
{/snippet}
|
|
43
|
+
{#snippet itemKey(key)}
|
|
44
|
+
<span class={key === ENTRIES ? 'internal' : 'property'}>{key}</span>
|
|
45
|
+
{/snippet}
|
|
46
|
+
{#snippet itemValue(key)}
|
|
47
|
+
{#if key === ENTRIES}
|
|
48
|
+
<JSONNested keys={indexes} defaultExpanded>
|
|
49
|
+
{#snippet itemKey(index)}
|
|
50
|
+
<span class="property">{index}</span>
|
|
51
|
+
{/snippet}
|
|
52
|
+
{#snippet itemValue(index)}
|
|
53
|
+
<JSONNode value={items[index]} />
|
|
54
|
+
{/snippet}
|
|
55
|
+
</JSONNested>
|
|
56
|
+
{:else}
|
|
57
|
+
<JSONNode value={value[key]} />
|
|
58
|
+
{/if}
|
|
59
|
+
{/snippet}
|
|
60
|
+
</JSONNested>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { useState } from './utils.js';
|
|
3
|
+
import JSONNested from './JSONNested.svelte';
|
|
4
|
+
import JSONNode from './JSONNode.svelte';
|
|
5
|
+
import PreviewList from './PreviewList.svelte';
|
|
6
|
+
|
|
7
|
+
let { value } = $props();
|
|
8
|
+
useState();
|
|
9
|
+
|
|
10
|
+
let [indexes, keys, values] = $derived.by(() => {
|
|
11
|
+
let _indexes = [];
|
|
12
|
+
let _keys = [];
|
|
13
|
+
let _values = [];
|
|
14
|
+
let i = 0;
|
|
15
|
+
for (const entry of value) {
|
|
16
|
+
_indexes.push(i++);
|
|
17
|
+
_keys.push(entry[0]);
|
|
18
|
+
_values.push(entry[1]);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return [_indexes, _keys, _values];
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
let previewKeys = $derived(Array.from(value.keys()).slice(0, 5));
|
|
25
|
+
|
|
26
|
+
const ENTRIES = '[[Entries]]';
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<JSONNested keys={[ENTRIES, 'size']} shouldShowColon={(key) => key !== ENTRIES}>
|
|
30
|
+
{#snippet summary()}
|
|
31
|
+
<span color="label">Map({keys.length})</span>
|
|
32
|
+
{/snippet}
|
|
33
|
+
{#snippet preview(root)}
|
|
34
|
+
<PreviewList
|
|
35
|
+
list={previewKeys}
|
|
36
|
+
hasMore={previewKeys.length < value.size}
|
|
37
|
+
label={`Map(${keys.length}) `}
|
|
38
|
+
prefix={`{`}
|
|
39
|
+
postfix="}"
|
|
40
|
+
{root}
|
|
41
|
+
>
|
|
42
|
+
{#snippet item(key)}
|
|
43
|
+
<JSONNode value={key} /><span class="operator">{' => '}</span
|
|
44
|
+
><JSONNode value={value.get(key)} />
|
|
45
|
+
{/snippet}
|
|
46
|
+
</PreviewList>
|
|
47
|
+
{/snippet}
|
|
48
|
+
{#snippet itemKey(key)}
|
|
49
|
+
<span class={key === ENTRIES ? 'internal' : 'property'}>{key}</span>
|
|
50
|
+
{/snippet}
|
|
51
|
+
{#snippet itemValue(key)}
|
|
52
|
+
{#if key === ENTRIES}
|
|
53
|
+
<JSONNested
|
|
54
|
+
keys={indexes}
|
|
55
|
+
expandKey={(index) => keys[index]}
|
|
56
|
+
defaultExpanded
|
|
57
|
+
>
|
|
58
|
+
{#snippet itemKey(index)}
|
|
59
|
+
<span class="property">{index}</span>
|
|
60
|
+
{/snippet}
|
|
61
|
+
{#snippet itemValue(index)}
|
|
62
|
+
<JSONNested keys={['key', 'value']}>
|
|
63
|
+
{#snippet preview()}
|
|
64
|
+
<span class="operator">{'{ '}</span><JSONNode
|
|
65
|
+
value={keys[index]}
|
|
66
|
+
/><span class="operator">{' => '}</span><JSONNode
|
|
67
|
+
value={values[index]}
|
|
68
|
+
/><span class="operator">{' }'}</span>
|
|
69
|
+
{/snippet}
|
|
70
|
+
{#snippet itemKey(name)}
|
|
71
|
+
<span class="property">{name}</span>
|
|
72
|
+
{/snippet}
|
|
73
|
+
{#snippet itemValue(name)}
|
|
74
|
+
<JSONNode
|
|
75
|
+
value={name === 'key'
|
|
76
|
+
? keys[index]
|
|
77
|
+
: values[index]}
|
|
78
|
+
/>
|
|
79
|
+
{/snippet}
|
|
80
|
+
</JSONNested>
|
|
81
|
+
{/snippet}
|
|
82
|
+
</JSONNested>
|
|
83
|
+
{:else}
|
|
84
|
+
<JSONNode value={value[key]} />
|
|
85
|
+
{/if}
|
|
86
|
+
{/snippet}
|
|
87
|
+
</JSONNested>
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
3
|
+
import { getContext, onMount, setContext } from 'svelte';
|
|
4
|
+
import JSONArrow from './JSONArrow.svelte';
|
|
5
|
+
import { useState } from './utils.js';
|
|
6
|
+
import Summary from './Summary.svelte';
|
|
7
|
+
import Expandable from './Expandable.svelte';
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
keys,
|
|
11
|
+
shouldShowColon = undefined,
|
|
12
|
+
expandKey = (key) => key,
|
|
13
|
+
defaultExpanded = false,
|
|
14
|
+
summary,
|
|
15
|
+
preview,
|
|
16
|
+
itemKey,
|
|
17
|
+
itemValue,
|
|
18
|
+
} = $props();
|
|
19
|
+
|
|
20
|
+
let expanded = $state(defaultExpanded);
|
|
21
|
+
let expandable = $state(false);
|
|
22
|
+
let displayMode = getContext('displayMode');
|
|
23
|
+
let root = getContext('root');
|
|
24
|
+
let toggleExpand = (e) => {
|
|
25
|
+
e?.preventDefault();
|
|
26
|
+
e.stopPropagation();
|
|
27
|
+
|
|
28
|
+
expanded = !expanded;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
$effect(() => {
|
|
32
|
+
setContext('expandable', expandable);
|
|
33
|
+
setContext('expanded', expanded);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
setContext('root', false);
|
|
37
|
+
setContext('toggleExpand', toggleExpand);
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
{#if displayMode === 'summary'}
|
|
41
|
+
{@render summary?.()}
|
|
42
|
+
{:else}
|
|
43
|
+
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
|
|
44
|
+
<span class="root jsonnested" onclick={(e) => toggleExpand(e)}>
|
|
45
|
+
<!-- {#if root}
|
|
46
|
+
<JSONArrow {expanded} {expandable} />
|
|
47
|
+
{/if} -->
|
|
48
|
+
<Summary>
|
|
49
|
+
{@render preview?.(root)}
|
|
50
|
+
</Summary>
|
|
51
|
+
</span>
|
|
52
|
+
|
|
53
|
+
{#if expanded}
|
|
54
|
+
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-noninteractive-element-interactions -->
|
|
55
|
+
<ul
|
|
56
|
+
onclick={(e) => {
|
|
57
|
+
e.stopPropagation();
|
|
58
|
+
toggleExpand(e);
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
{#each keys as key, index}
|
|
62
|
+
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
|
63
|
+
<li class:indent={expanded}>
|
|
64
|
+
<Expandable key={expandKey(key)}>
|
|
65
|
+
<span class="label">
|
|
66
|
+
<!-- <JSONArrow /> -->
|
|
67
|
+
{@render itemKey?.(key)}
|
|
68
|
+
{#if !shouldShowColon || shouldShowColon(key)}
|
|
69
|
+
<span class="operator">{': '}</span>
|
|
70
|
+
{/if}
|
|
71
|
+
</span>
|
|
72
|
+
{@render itemValue?.(key)}
|
|
73
|
+
</Expandable>
|
|
74
|
+
</li>
|
|
75
|
+
{/each}
|
|
76
|
+
</ul>
|
|
77
|
+
{/if}
|
|
78
|
+
{/if}
|
|
79
|
+
|
|
80
|
+
<style>
|
|
81
|
+
.root {
|
|
82
|
+
display: inline-flex;
|
|
83
|
+
position: relative;
|
|
84
|
+
flex-wrap: wrap;
|
|
85
|
+
white-space: pre-wrap;
|
|
86
|
+
}
|
|
87
|
+
.indent {
|
|
88
|
+
padding-left: var(--li-identation);
|
|
89
|
+
}
|
|
90
|
+
.label {
|
|
91
|
+
position: relative;
|
|
92
|
+
display: inline-flex;
|
|
93
|
+
}
|
|
94
|
+
</style>
|