From 5511ee976266357e11420c57bd09cfcd401f7c21 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Nov 2025 15:46:08 +0000 Subject: [PATCH 1/4] Initial plan From 386a69ec732d3baf95133ab05257abe320c5933f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Nov 2025 16:02:18 +0000 Subject: [PATCH 2/4] Fix: Propagate IncludeTransient flag for folder items with onChange Co-authored-by: gsimone <1862172+gsimone@users.noreply.github.com> --- packages/leva/src/types/public.test.ts | 46 ++++++++++++++++++++++++++ packages/leva/src/types/public.ts | 4 ++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/packages/leva/src/types/public.test.ts b/packages/leva/src/types/public.test.ts index ca6e9777..25805806 100644 --- a/packages/leva/src/types/public.test.ts +++ b/packages/leva/src/types/public.test.ts @@ -137,6 +137,52 @@ expectType<{ }) ) +// folders with onChange should exclude transient items from return type but include them in get function +expectType<{ a1: number }>( + useControls({ + a: folder({ + a1: 1, + a2: { value: 'transient', onChange: () => {} }, + }), + }) +) + +// test that get function includes transient items in folders +expectType< + [ + { a1: number }, + (value: { a1?: number; a2?: string }) => void, + (path: T) => { a1: number; a2: string }[T] + ] +>( + useControls(() => ({ + a: folder({ + a1: 1, + a2: { value: 'transient', onChange: () => {} }, + }), + })) +) + +// nested folders with onChange +expectType< + [ + { a1: number }, + (value: { a1?: number; b1?: number; b2?: string }) => void, + (path: T) => { a1: number; b1: number; b2: string }[T] + ] +>( + useControls(() => ({ + a: folder({ + a1: 1, + a2: { value: 'transient', onChange: () => {} }, + b: folder({ + b1: { value: 10 }, + b2: { value: 'also transient', onChange: () => {} }, + }), + }), + })) +) + /** * custom plugins */ diff --git a/packages/leva/src/types/public.ts b/packages/leva/src/types/public.ts index 254b678d..d1aea419 100644 --- a/packages/leva/src/types/public.ts +++ b/packages/leva/src/types/public.ts @@ -241,7 +241,9 @@ type Join = EndLeaf extends Leaf2 type Tree = { // if it's a folder we run the type check on it's schema key - 0: Leaf extends { schema: infer Schema } ? { [Key in keyof Schema]: Join } : never + 0: Leaf extends { schema: infer Schema } + ? { [Key in keyof Schema]: Join> }[keyof Schema] + : never 1: never // if the leaf is an object, we run the type check on each of its keys 2: { From 004527b2f8cd6c17f1fcce56cbdf46c2009523a9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Nov 2025 16:08:23 +0000 Subject: [PATCH 3/4] Add clarifying comment for recursive Tree call in folders Co-authored-by: gsimone <1862172+gsimone@users.noreply.github.com> --- packages/leva/src/types/public.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/leva/src/types/public.ts b/packages/leva/src/types/public.ts index d1aea419..975dd28a 100644 --- a/packages/leva/src/types/public.ts +++ b/packages/leva/src/types/public.ts @@ -241,6 +241,8 @@ type Join = EndLeaf extends Leaf2 type Tree = { // if it's a folder we run the type check on it's schema key + // recursively process each item in the folder with Tree to propagate IncludeTransient flag, + // which ensures items with onChange inside folders are correctly handled for the get function 0: Leaf extends { schema: infer Schema } ? { [Key in keyof Schema]: Join> }[keyof Schema] : never From 43039dfcdab60d62a0a4b77ef10ca5a4205b3d42 Mon Sep 17 00:00:00 2001 From: Gianmarco Date: Sat, 8 Nov 2025 16:31:02 +0100 Subject: [PATCH 4/4] changeset --- .changeset/dirty-radios-laugh.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/dirty-radios-laugh.md diff --git a/.changeset/dirty-radios-laugh.md b/.changeset/dirty-radios-laugh.md new file mode 100644 index 00000000..931dfd08 --- /dev/null +++ b/.changeset/dirty-radios-laugh.md @@ -0,0 +1,5 @@ +--- +"leva": patch +--- + +fix: using get with items with onChange is now correctly typed