From 65a17a0bb72571803bc53abb8712c16c8c11721d Mon Sep 17 00:00:00 2001 From: "Arthur @Refzlund" Date: Thu, 3 Jul 2025 09:50:13 +0200 Subject: [PATCH 1/3] issue story --- svelte-object/src/SvelteArray.svelte | 34 +++++++------ svelte-object/src/SvelteObject.svelte | 42 ++++++++-------- svelte-object/src/SvelteValue.svelte | 2 +- .../overriding-states/Issue.stories.svelte | 48 +++++++++++++++++++ .../issues/overriding-states/README.mdx | 1 + svelte-object/stories/tw.css | 1 + 6 files changed, 87 insertions(+), 41 deletions(-) create mode 100644 svelte-object/stories/issues/overriding-states/Issue.stories.svelte create mode 100644 svelte-object/stories/issues/overriding-states/README.mdx create mode 100644 svelte-object/stories/tw.css diff --git a/svelte-object/src/SvelteArray.svelte b/svelte-object/src/SvelteArray.svelte index 1b6912f..98cdbed 100644 --- a/svelte-object/src/SvelteArray.svelte +++ b/svelte-object/src/SvelteArray.svelte @@ -1,23 +1,26 @@ - + + diff --git a/svelte-object/src/SvelteValue.svelte b/svelte-object/src/SvelteValue.svelte index 61b1331..e3370db 100644 --- a/svelte-object/src/SvelteValue.svelte +++ b/svelte-object/src/SvelteValue.svelte @@ -23,7 +23,7 @@ onValidate }: Props & { onValidate?: (validationEvent: ValidationEvent) => void - children?: Snippet<[{ + children?: Snippet<[props: { value: Props['value'] blurValidation: (element: HTMLElement) => { destroy: () => void } submitOnEnter: (element: HTMLElement) => { destroy: () => void } diff --git a/svelte-object/stories/issues/overriding-states/Issue.stories.svelte b/svelte-object/stories/issues/overriding-states/Issue.stories.svelte new file mode 100644 index 0000000..183edef --- /dev/null +++ b/svelte-object/stories/issues/overriding-states/Issue.stories.svelte @@ -0,0 +1,48 @@ + + + + {#snippet template()} +
+ + {#snippet children(object)} + + {#snippet children(value)} + + {/snippet} + + + {#snippet children(array)} + {#each array.value as item, i (i)} + + {/each} + + {/snippet} + +
{JSON.stringify(object.value, null, '\t')}
+ {/snippet} + +
+
+ + {/snippet} +
\ No newline at end of file diff --git a/svelte-object/stories/issues/overriding-states/README.mdx b/svelte-object/stories/issues/overriding-states/README.mdx new file mode 100644 index 0000000..61d5446 --- /dev/null +++ b/svelte-object/stories/issues/overriding-states/README.mdx @@ -0,0 +1 @@ +When overriding the top-object value reactants such as lower-level arrays and objects stop working. \ No newline at end of file diff --git a/svelte-object/stories/tw.css b/svelte-object/stories/tw.css new file mode 100644 index 0000000..f173aa4 --- /dev/null +++ b/svelte-object/stories/tw.css @@ -0,0 +1 @@ +@import 'tailwindcss'; \ No newline at end of file From 5f4b76fdb4967a72c5beb8f6535a0c6c619e26cf Mon Sep 17 00:00:00 2001 From: "Arthur @Refzlund" Date: Thu, 3 Jul 2025 10:11:41 +0200 Subject: [PATCH 2/3] Use prescriptors --- svelte-object/src/SvelteObject.svelte | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/svelte-object/src/SvelteObject.svelte b/svelte-object/src/SvelteObject.svelte index 08b4cb0..fac294b 100644 --- a/svelte-object/src/SvelteObject.svelte +++ b/svelte-object/src/SvelteObject.svelte @@ -105,6 +105,16 @@ parent.setValue(name, value) }, + addPrescriptors( + name: PropertyKey, + getter: () => unknown, + setter: (value: unknown) => void, + ) { + + }, + + prescriptors: Record unknown, set: (value: unknown) => void }> = {}, + addValidator(fn: typeof validate) { validators.push(fn) }, From e8b7007b799720d3d0a4c205f7b2407091ffc029 Mon Sep 17 00:00:00 2001 From: "Arthur @Refzlund" Date: Thu, 3 Jul 2025 13:36:56 +0200 Subject: [PATCH 3/3] fix --- .changeset/tall-frogs-sleep.md | 5 +++ svelte-object/src/SvelteObject.svelte | 62 ++++++++++++++++----------- svelte-object/src/SvelteValue.svelte | 13 +----- 3 files changed, 42 insertions(+), 38 deletions(-) create mode 100644 .changeset/tall-frogs-sleep.md diff --git a/.changeset/tall-frogs-sleep.md b/.changeset/tall-frogs-sleep.md new file mode 100644 index 0000000..5cc2bab --- /dev/null +++ b/.changeset/tall-frogs-sleep.md @@ -0,0 +1,5 @@ +--- +"svelte-object": patch +--- + +fix: overriding parent values breaks reactivity diff --git a/svelte-object/src/SvelteObject.svelte b/svelte-object/src/SvelteObject.svelte index fac294b..2d5fed2 100644 --- a/svelte-object/src/SvelteObject.svelte +++ b/svelte-object/src/SvelteObject.svelte @@ -19,9 +19,15 @@ onSubmit?: (value: T) => void } + type Prescriptor = { name: PropertyKey, get: () => unknown, set: (value: unknown) => void } + type SvelteObjectGeneric = Record | unknown[] type SvelteObjectContext = { - setValue(key: string | number, newValue: unknown): void + addPrescriptor: ( + name: Prescriptor['name'], + getter: Prescriptor['get'], + setter: Prescriptor['set'] + ) => void addValidator(fn: (trigger?: ValidationType) => boolean): void removeValidator(fn: (trigger?: ValidationType) => boolean): void submit: () => void @@ -96,25 +102,41 @@ let validators = [] as (typeof validate)[] - const self = { - setValue(key: string | number, newValue: unknown) { - if(key === undefined || key === null || key === '') - return - value![key as keyof T] = newValue as T[keyof T] - if(parent && name !== '') - parent.setValue(name, value) - }, + const prescriptors: Prescriptor[] = $state([]) - addPrescriptors( + $effect.pre(() => { + for(const prescriptor of prescriptors) { + $effect.pre(() => { + prescriptor.set(value?.[prescriptor.name]) + }) + $effect.pre(() => { + const itemValue = prescriptor.get() + value ??= {} as T + prescriptor.name + untrack(() => { + value ??= {} as T + value[prescriptor.name] = itemValue + }) + }) + } + }) + + const self = { + addPrescriptor( name: PropertyKey, getter: () => unknown, setter: (value: unknown) => void, ) { + const prescriptor = { name, get: getter, set: setter } - }, - - prescriptors: Record unknown, set: (value: unknown) => void }> = {}, + value ??= {} as T + value[prescriptor.name] = getter() + prescriptors.push(prescriptor) + return () => { + prescriptors.splice(prescriptors.indexOf(prescriptor), 1) + } + }, addValidator(fn: typeof validate) { validators.push(fn) }, @@ -143,12 +165,7 @@ } if(parent && (name !== undefined && name !== null) && name !== '') { - if(parent?.value?.[name]) { - value = parent?.value[name] as T - } - else { - parent.value![name] = value - } + parent.addPrescriptor(name, () => value, v => value = v as T) } let checkingIsModified = false @@ -163,13 +180,6 @@ }, 125) } - const setValue = (v: T) => Object.assign(value!, v) - $effect.pre(() => { - if(parent?.value) { - setValue(parent.value[name] as T) - } - }) - $effect(() => { $state.snapshot(value) $state.snapshot(origin) diff --git a/svelte-object/src/SvelteValue.svelte b/svelte-object/src/SvelteValue.svelte index e3370db..1670799 100644 --- a/svelte-object/src/SvelteValue.svelte +++ b/svelte-object/src/SvelteValue.svelte @@ -122,20 +122,10 @@ object?.addValidator(validate) onDestroy(() => object?.removeValidator(validate)) - const setValue = (v: T) => value = v - if(object && (name !== undefined && name !== null) && name !== '') { - const val = object.value![name!] - if(val !== undefined) - setValue(val) + object.addPrescriptor(name, () => value, v => value = v as T) } - $effect(() => { - if(object?.value && name !== '') { - setValue(object.value[name!]) - } - }) - $effect.pre(() => { value @@ -146,7 +136,6 @@ warning = undefined validate('change') }) - untrack(() => object?.setValue(name, value)) })