diff --git a/src/client/core.js b/src/client/core.js index 0f203ac..3848557 100644 --- a/src/client/core.js +++ b/src/client/core.js @@ -7,12 +7,25 @@ import { serialize } from './utils.js'; window['#SvelteDevTools'] = { /** * @param {string} id - * @param {string} key + * @param {string[]} keys * @param {any} value */ - inject(id, key, value) { + inject(id, keys, value) { const { detail: component } = v4.map.get(id) || {}; - component && component.$inject_state({ [key]: value }); + if (component) { + const [prop, ...rest] = keys; + const original = component.$capture_state()[prop]; + if (typeof original === 'object') { + let ref = original; + for (let i = 0; i < rest.length - 1; i += 1) { + ref = ref[rest[i]]; + } + ref[rest[rest.length - 1]] = value; + component.$inject_state({ [prop]: original }); + } else { + component.$inject_state({ [prop]: value }); + } + } }, }; diff --git a/src/client/utils.js b/src/client/utils.js index c3eb134..67a3428 100644 --- a/src/client/utils.js +++ b/src/client/utils.js @@ -68,7 +68,7 @@ export function serialize(node) { const listeners = node.detail.__listeners || []; res.detail = { - attributes: attributes.map(({ name: key, value }) => ({ key, value })), + attributes: attributes.map(({ name: key, value }) => ({ key, value, readonly: true })), listeners: listeners.map((o) => ({ ...o, handler: o.handler.toString() })), }; break; @@ -86,7 +86,7 @@ export function serialize(node) { const { ctx, source } = node.detail; const cloned = Object.entries(clone(ctx)); res.detail = { - ctx: cloned.map(([key, value]) => ({ key, value })), + ctx: cloned.map(([key, value]) => ({ key, value, readonly: true })), source: source.slice(source.indexOf('{'), source.indexOf('}') + 1), }; break; diff --git a/src/lib/panel/Editable.svelte b/src/lib/panel/Editable.svelte index be8865a..8a4c8c8 100644 --- a/src/lib/panel/Editable.svelte +++ b/src/lib/panel/Editable.svelte @@ -1,38 +1,66 @@ {#if editing} { - editing = false; // @ts-expect-error - target and value exists - const updated = target.value; - onchange((value = JSON.parse(updated))); + update(target.value); }} onkeydown={({ key, target }) => { if (key !== 'Enter') return; - editing = false; // @ts-expect-error - target and value exists - const updated = target.value; - onchange((value = JSON.parse(updated))); + update(target.value); }} /> {:else} (editing = !readonly)}> - {JSON.stringify(value)} + {type === 'string' ? `"${value}"` : `${value}`} {/if} diff --git a/src/lib/panel/Expandable.svelte b/src/lib/panel/Expandable.svelte deleted file mode 100644 index 8d27af1..0000000 --- a/src/lib/panel/Expandable.svelte +++ /dev/null @@ -1,149 +0,0 @@ - - - - -
  • { - event.stopPropagation(); - expanded = !expanded; - }} -> - {key}: -   - - {#if type === 'string'} - - {:else if value == null || value !== value} - - {:else if type === 'number' || type === 'boolean'} - - {:else if Array.isArray(value)} - Array [{value.length || ''}] - - {#if value.length && expanded} -
      - {#each value as v, key} - onchange(stringify(value, key, updated))} - /> - {/each} -
    - {/if} - {:else if type === 'object'} - {#if value.__is === 'function'} - function {value.name || ''}() - {#if expanded}
    {value.source}
    {/if} - {:else if value.__is === 'symbol'} - {value.name || 'Symbol()'} - {:else if Object.keys(value).length} - Object {…} - {#if expanded} -
      - {#each Object.entries(value) as [key, v] (key)} - onchange(stringify(value, key, updated))} - /> - {/each} -
    - {/if} - {:else} - Object { } - {/if} - {/if} -
  • - - diff --git a/src/lib/panel/PropertyList.svelte b/src/lib/panel/PropertyList.svelte index 98ec3c3..e05f678 100644 --- a/src/lib/panel/PropertyList.svelte +++ b/src/lib/panel/PropertyList.svelte @@ -1,37 +1,102 @@ {#if entries.length} {:else} @@ -40,9 +105,38 @@ diff --git a/src/lib/panel/core.svelte.ts b/src/lib/panel/core.svelte.ts new file mode 100644 index 0000000..3865e1a --- /dev/null +++ b/src/lib/panel/core.svelte.ts @@ -0,0 +1,17 @@ +import { app } from '$lib/state.svelte'; + +export const errors = $state<{ [keys: string]: string | false }>({}); + +export function inject(keys: string[], value: any) { + const uuid = app.selected?.id; + if (!uuid) return; + + const accessors = `[${keys.map((k) => `'${k}'`).join(', ')}]`; + chrome.devtools.inspectedWindow.eval( + `window['#SvelteDevTools'].inject('${uuid}', ${accessors}, ${value})`, + (_, error) => { + const id = `${uuid}+${keys.join('.')}`; + errors[id] = error?.isException && error.value.slice(0, error.value.indexOf('\n')); + }, + ); +} diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index c095369..19ceea2 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -146,28 +146,28 @@ {#if app.selected?.type === 'component'}

    Props

    - +

    Events

    - +

    State

    - + {:else if app.selected?.type === 'block' || app.selected?.type === 'iteration'}

    State

    - + {:else if app.selected?.type === 'element'}

    Attributes

    - +

    Events

    - + {/if} {:else}