@shivaedev/form 0.16.0 → 0.17.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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.17.1 - 2026-11-04
4
+
5
+ ### Changed
6
+
7
+ - Require Effect 4.0.7 and its matching companion packages. Install the 4.0.7 Effect stack together.
8
+
9
+ ## 0.17.0 - 2026-11-04
10
+
11
+ ### Added
12
+
13
+ - Forms expose typed nested field refs and edits, with a React hook for nested inputs and their path feedback.
14
+
15
+ ### Fixed
16
+
17
+ - A zero `debounce` runs advisory field checks without scheduling a timer.
18
+
3
19
  ## 0.16.0 - 2026-11-04
4
20
 
5
21
  ### Breaking
package/README.md CHANGED
@@ -247,7 +247,19 @@ const profile = form(Schema.Struct({ name: Schema.String }), {
247
247
 
248
248
  This check produces advisory feedback after the configured debounce and completion. A message is shown only while its checked input is still the current field value. Pending checks, older results and a defective check do not show an earlier value's message. Checks can read services from the supplied runtime. Keep authoritative validation in the schema or handler.
249
249
 
250
- For a nested value held in one top-level field, `errorAt(["answers", index, "text"])` reads Schema feedback and handler rejections for that answer box. A blur or change of the top-level `answers` field, or a submission, reveals its nested messages. The path selects the first message at or beneath that path; a sibling message does not appear there. `error("answers")` retains the top-level summary. Advisory checks remain top-level. Nested values are still edited as a whole top-level field.
250
+ For a nested value held in one top-level field, `errorAt(["answers", index, "text"])` reads Schema feedback and handler rejections for that answer box. A blur or change of the top-level `answers` field, or a submission, reveals its nested messages. The path selects the first message at or beneath that path; a sibling message does not appear there. `error("answers")` retains the top-level summary. Advisory checks remain top-level. Use typed nested paths to edit individual members.
251
+
252
+ `fieldAt(["energy", "low"])` returns an encoded-value ref for a nested member. `changeAt(["energy", "low"], "12")` edits that member immutably, preserves its siblings and touches the top-level group for feedback. The schema still decodes the complete struct on submission. Receive, save and revert keep their existing top-level baseline semantics; nested fields do not create separate sessions.
253
+
254
+ React inputs use `useFieldAt` with the same typed path:
255
+
256
+ ```ts
257
+ import { useFieldAt } from "@shivaedev/form/adapters/useFieldAt.ts";
258
+
259
+ const low = useFieldAt(foodForm, ["energy", "low"]);
260
+ ```
261
+
262
+ Like `useField`, this returns `value`, `onChange`, `onBlur` and `error`. Its `name` joins the path with dots, such as `energy.low`, and its feedback comes from `errorAt`. The encoded field type determines what `onChange` accepts.
251
263
 
252
264
  Whole-form Schema refinements are available through `errorAt([])` after submission. This root path selects only a whole-form message; field errors stay on their field paths. In React, render it with `useAtomValue(form.errorAt([]))`. A failed submission also keeps that message in `Invalid.formMessage`. Matching the refinement clears the feedback. Schema feedback is hidden while a new asynchronous decode is pending.
253
265
 
@@ -438,7 +450,7 @@ pnpm add @effect/atom-react react
438
450
  ```
439
451
 
440
452
  The React mounting example also uses the application's `react-dom`. React and `@effect/atom-react` are optional peers; the core modules do not import them. The package needs Node 24 or newer.
441
- - Field names are top-level schema keys. `useList` edits top-level arrays; nested items remain whole-item edits.
453
+ - String field names are top-level schema keys. `fieldAt`, `changeAt` and `useFieldAt` accept nested path tuples. `useList` edits top-level arrays.
442
454
  - Replace encoded values rather than mutating objects in place; use `change` for ordinary UI edits.
443
455
  - Keep the form and registry for their intended session, and clean up the registry when that session ends.
444
456
  - Decide in the application when to receive normalized rows and how to render general failures. Attach a draft owner when persisted input must end with the session.
@@ -0,0 +1,10 @@
1
+ import type { FieldPath, ValueAt } from "#fieldPath.ts";
2
+ import type { Encoded, Fields, Form, Name, Path } from "#shape.ts";
3
+ export declare function useFieldAt<TFields extends Fields, A, E, TRuntimeError, const TPath extends Path<Name<TFields>> & FieldPath<Encoded<TFields>>>(form: Form<TFields, A, E, TRuntimeError>, path: TPath): {
4
+ error: string | undefined;
5
+ name: string;
6
+ onBlur: () => void;
7
+ onChange: (next: ValueAt<Encoded<TFields>, TPath>) => void;
8
+ value: ValueAt<import("effect/Schema").Struct.View<TFields, "Encoded", import("effect/Schema").Struct.EncodedOptionalKeys<TFields>, import("effect/Schema").Struct.EncodedMutableKeys<TFields>>, TPath>;
9
+ };
10
+ //# sourceMappingURL=useFieldAt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFieldAt.d.ts","sourceRoot":"","sources":["../../src/adapters/useFieldAt.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEnE,wBAAgB,UAAU,CAAC,OAAO,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAC5I,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,EACxC,IAAI,EAAE,KAAK;;;;qBASO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC;;EAGlD"}
@@ -0,0 +1,14 @@
1
+ import { useAtomMount, useAtomRef, useAtomValue } from "@effect/atom-react";
2
+ export function useFieldAt(form, path) {
3
+ useAtomMount(form.dirty);
4
+ const value = useAtomRef(form.fieldAt(path));
5
+ const error = useAtomValue(form.errorAt(path));
6
+ return {
7
+ error,
8
+ name: path.join("."),
9
+ onBlur: () => form.blur(path[0]),
10
+ onChange: (next) => form.changeAt(path, next),
11
+ value,
12
+ };
13
+ }
14
+ //# sourceMappingURL=useFieldAt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFieldAt.js","sourceRoot":"","sources":["../../src/adapters/useFieldAt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAI5E,MAAM,UAAU,UAAU,CACzB,IAAwC,EACxC,IAAW;IAEX,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/C,OAAO;QACN,KAAK;QACL,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QACpB,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChC,QAAQ,EAAE,CAAC,IAAsC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;QAC/E,KAAK;KACL,CAAC;AACH,CAAC"}
@@ -1,4 +1,4 @@
1
- import { type Duration, Effect } from "effect";
1
+ import { Duration, Effect } from "effect";
2
2
  import * as Atom from "effect/reactivity/Atom";
3
3
  import type * as AtomRef from "effect/reactivity/AtomRef";
4
4
  import type { Encoded, Fields, Name, Services } from "./shape.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"checkFeedback.d.ts","sourceRoot":"","sources":["../src/checkFeedback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,EAAS,MAAM,QAAQ,CAAC;AAEtD,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAC/C,OAAO,KAAK,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAE1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAElE,wBAAgB,aAAa,CAAC,OAAO,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EACzD,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAClD,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EACpH,MAAM,EAAE,CAAC,IAAI,SAAS,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,EAC3F,QAAQ,EAAE,QAAQ,CAAC,KAAK,yDAsBxB"}
1
+ {"version":3,"file":"checkFeedback.d.ts","sourceRoot":"","sources":["../src/checkFeedback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAS,MAAM,QAAQ,CAAC;AAEjD,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAC/C,OAAO,KAAK,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAE1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAElE,wBAAgB,aAAa,CAAC,OAAO,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EACzD,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAClD,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EACpH,MAAM,EAAE,CAAC,IAAI,SAAS,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,EAC3F,QAAQ,EAAE,QAAQ,CAAC,KAAK,yDAsBxB"}
@@ -1,4 +1,4 @@
1
- import { Effect, Equal } from "effect";
1
+ import { Duration, Effect, Equal } from "effect";
2
2
  import * as AsyncResult from "effect/reactivity/AsyncResult";
3
3
  import * as Atom from "effect/reactivity/Atom";
4
4
  import { fromRef } from "./refs.js";
@@ -9,7 +9,7 @@ export function checkFeedback(runtime, checks, refFor, debounce) {
9
9
  return Atom.make(() => undefined);
10
10
  }
11
11
  const current = fromRef(refFor(name));
12
- const settled = Atom.debounce(current, debounce);
12
+ const settled = Duration.isZero(Duration.fromInputUnsafe(debounce)) ? current : Atom.debounce(current, debounce);
13
13
  const answered = runtime.atom((get) => {
14
14
  const input = get(settled);
15
15
  return Effect.map(check(input), (message) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"checkFeedback.js","sourceRoot":"","sources":["../src/checkFeedback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACtD,OAAO,KAAK,WAAW,MAAM,+BAA+B,CAAC;AAC7D,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,UAAU,aAAa,CAC5B,OAAkD,EAClD,MAAoH,EACpH,MAA2F,EAC3F,QAAwB;IAExB,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,IAAmB,EAAiC,EAAE;QACzE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAuB,EAAE,CAAC,SAAS,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACrC,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;YAC3B,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBAC7C,KAAK;gBACL,OAAO;aACP,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAsB,EAAE;YAChD,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;YAC3B,OAAO,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QACvI,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"checkFeedback.js","sourceRoot":"","sources":["../src/checkFeedback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,WAAW,MAAM,+BAA+B,CAAC;AAC7D,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,UAAU,aAAa,CAC5B,OAAkD,EAClD,MAAoH,EACpH,MAA2F,EAC3F,QAAwB;IAExB,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,IAAmB,EAAiC,EAAE;QACzE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAuB,EAAE,CAAC,SAAS,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACjH,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACrC,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;YAC3B,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBAC7C,KAAK;gBACL,OAAO;aACP,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAsB,EAAE;YAChD,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;YAC3B,OAAO,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QACvI,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type * as AtomRef from "effect/reactivity/AtomRef";
2
+ type Keys<T> = T extends readonly unknown[] ? number : Extract<keyof T, string | number>;
3
+ export type FieldPath<T> = T extends object ? {
4
+ [TKey in Keys<T>]: TKey extends keyof T ? readonly [TKey] | readonly [TKey, ...FieldPath<NonNullable<T[TKey]>>] : never;
5
+ }[Keys<T>] : never;
6
+ export type ValueAt<T, TPath> = TPath extends readonly [infer TKey extends keyof NonNullable<T>, ...infer TRest extends PropertyKey[]] ? ValueAt<NonNullable<T>[TKey], TRest> : T;
7
+ export declare function refAt<T, const TPath extends readonly PropertyKey[] & FieldPath<T>>(parent: AtomRef.AtomRef<T>, path: TPath): AtomRef.AtomRef<ValueAt<T, TPath>>;
8
+ export {};
9
+ //# sourceMappingURL=fieldPath.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldPath.d.ts","sourceRoot":"","sources":["../src/fieldPath.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAG1D,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,OAAO,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AACzF,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,GACxC;KAAG,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK;CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GACpI,KAAK,CAAC;AAET,MAAM,MAAM,OAAO,CAAC,CAAC,EAAE,KAAK,IAAI,KAAK,SAAS,SAAS,CAAC,MAAM,IAAI,SAAS,MAAM,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,KAAK,SAAS,WAAW,EAAE,CAAC,GACnI,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,GACpC,CAAC,CAAC;AAEL,wBAAgB,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,SAAS,SAAS,WAAW,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,EACjF,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAC1B,IAAI,EAAE,KAAK,GACT,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { propertyRef } from "./refs.js";
2
+ export function refAt(parent, path) {
3
+ let ref = parent;
4
+ for (const segment of path) {
5
+ ref = propertyRef(ref, segment);
6
+ }
7
+ return ref;
8
+ }
9
+ //# sourceMappingURL=fieldPath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldPath.js","sourceRoot":"","sources":["../src/fieldPath.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAexC,MAAM,UAAU,KAAK,CAAC,MAAgC,EAAE,IAA4B;IACnF,IAAI,GAAG,GAAG,MAAM,CAAC;IACjB,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;QAC5B,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,MAAM,EAAkC,MAAM,QAAQ,CAAC;AAUvF,OAAO,EAAE,KAAK,MAAM,EAA4C,KAAK,MAAM,EAAE,KAAK,IAAI,EAA4C,MAAM,YAAY,CAAC;AAcrJ,wBAAgB,IAAI,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,KAAK,EAAE,aAAa,GAAG,KAAK,EACpG,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAC9B,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,CAAC,GAC/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CA2G9C"}
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,MAAM,EAAkC,MAAM,QAAQ,CAAC;AAWvF,OAAO,EAAE,KAAK,MAAM,EAA4C,KAAK,MAAM,EAAE,KAAK,IAAI,EAA4C,MAAM,YAAY,CAAC;AAcrJ,wBAAgB,IAAI,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,KAAK,EAAE,aAAa,GAAG,KAAK,EACpG,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAC9B,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,CAAC,GAC/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CAgH9C"}
package/dist/form.js CHANGED
@@ -4,6 +4,7 @@ import * as Atom from "effect/reactivity/Atom";
4
4
  import { persistence } from "#adapters/persistence.ts";
5
5
  import { checkFeedback } from "./checkFeedback.js";
6
6
  import { draft } from "./draft.js";
7
+ import { refAt } from "./fieldPath.js";
7
8
  import { literalChoices, messageAt, schemaFeedback } from "./messages.js";
8
9
  import { pathMessageAt } from "./paths.js";
9
10
  import { fromRef, propertyRef } from "./refs.js";
@@ -76,6 +77,10 @@ export function form(schema, config) {
76
77
  refFor(name).set(value);
77
78
  status.touch(name);
78
79
  },
80
+ changeAt: (path, value) => {
81
+ refAt(values, path).set(value);
82
+ status.touch(path[0]);
83
+ },
79
84
  choices: (name) => {
80
85
  const member = schema.fields[name];
81
86
  const decodeChoice = SchemaParser.decodeUnknownSync(Schema.toEncoded(schema), { disableChecks: true });
@@ -92,6 +97,7 @@ export function form(schema, config) {
92
97
  return Atom.readable((get) => get(status.touched)[name] === true || get(status.submitted) ? (pathMessageAt(get(status.paths), path) ?? get(message)) : undefined);
93
98
  }),
94
99
  field: refFor,
100
+ fieldAt: (path) => refAt(values, path),
95
101
  receive: editing.receive,
96
102
  revert: editing.revert,
97
103
  submit,
package/dist/form.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"form.js","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"form.js","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"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"}
package/dist/refs.d.ts CHANGED
@@ -2,4 +2,5 @@ import * as Atom from "effect/reactivity/Atom";
2
2
  import * as AtomRef from "effect/reactivity/AtomRef";
3
3
  export declare function fromRef<TValue>(ref: AtomRef.ReadonlyRef<TValue>): Atom.Atom<TValue>;
4
4
  export declare function propertyRef<TValue, TKey extends keyof TValue>(parent: AtomRef.AtomRef<TValue>, name: TKey): AtomRef.AtomRef<TValue[TKey]>;
5
+ export declare function propertyRef(parent: AtomRef.AtomRef<unknown>, name: PropertyKey): AtomRef.AtomRef<unknown>;
5
6
  //# sourceMappingURL=refs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"refs.d.ts","sourceRoot":"","sources":["../src/refs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAC/C,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAErD,wBAAgB,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAKnF;AAGD,wBAAgB,WAAW,CAAC,MAAM,EAAE,IAAI,SAAS,MAAM,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAsBzI"}
1
+ {"version":3,"file":"refs.d.ts","sourceRoot":"","sources":["../src/refs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAC/C,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAErD,wBAAgB,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAKnF;AAGD,wBAAgB,WAAW,CAAC,MAAM,EAAE,IAAI,SAAS,MAAM,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3I,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC"}
package/dist/refs.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Equal, Hash } from "effect";
1
+ import { Equal, Hash, Predicate } from "effect";
2
2
  import * as Atom from "effect/reactivity/Atom";
3
3
  import * as AtomRef from "effect/reactivity/AtomRef";
4
4
  export function fromRef(ref) {
@@ -7,9 +7,8 @@ export function fromRef(ref) {
7
7
  return ref.value;
8
8
  });
9
9
  }
10
- // Native prop refs retain removed keys; form fields must observe their absence.
11
10
  export function propertyRef(parent, name) {
12
- const read = parent.map((value) => value[name]);
11
+ const read = parent.map((value) => (Predicate.isObjectOrArray(value) ? Reflect.get(value, name) : undefined));
13
12
  const ref = {
14
13
  [AtomRef.TypeId]: AtomRef.TypeId,
15
14
  [Equal.symbol]: (other) => Equal.equals(read, other),
@@ -18,7 +17,7 @@ export function propertyRef(parent, name) {
18
17
  map: (transform) => read.map(transform),
19
18
  prop: (key) => propertyRef(ref, key),
20
19
  set: (value) => {
21
- parent.update((current) => Array.isArray(current) ? Object.assign(current.slice(), current, { [name]: value }) : { ...current, [name]: value });
20
+ parent.update((current) => Object.assign(Array.isArray(current) ? current.slice() : {}, current, { [name]: value }));
22
21
  return ref;
23
22
  },
24
23
  subscribe: (listener) => read.subscribe(listener),
package/dist/refs.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"refs.js","sourceRoot":"","sources":["../src/refs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAC/C,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAErD,MAAM,UAAU,OAAO,CAAS,GAAgC;IAC/D,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,EAAE;QAC5B,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/D,OAAO,GAAG,CAAC,KAAK,CAAC;IAClB,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,WAAW,CAAoC,MAA+B,EAAE,IAAU;IACzG,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,MAAM,GAAG,GAAkC;QAC1C,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM;QAChC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC;QACpD,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QACpC,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,GAAG,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;QACvC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC;QACpC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;YACd,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CACzB,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CACnH,CAAC;YACF,OAAO,GAAG,CAAC;QACZ,CAAC;QACD,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;QACjD,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,IAAI,KAAK;YACR,OAAO,IAAI,CAAC,KAAK,CAAC;QACnB,CAAC;KACD,CAAC;IACF,OAAO,GAAG,CAAC;AACZ,CAAC"}
1
+ {"version":3,"file":"refs.js","sourceRoot":"","sources":["../src/refs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAC/C,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAErD,MAAM,UAAU,OAAO,CAAS,GAAgC;IAC/D,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,EAAE;QAC5B,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/D,OAAO,GAAG,CAAC,KAAK,CAAC;IAClB,CAAC,CAAC,CAAC;AACJ,CAAC;AAKD,MAAM,UAAU,WAAW,CAAC,MAAgC,EAAE,IAAiB;IAC9E,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAW,EAAE,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACvH,MAAM,GAAG,GAA6B;QACrC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM;QAChC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC;QACpD,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QACpC,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,GAAG,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;QACvC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC;QACpC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;YACd,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;YACrH,OAAO,GAAG,CAAC;QACZ,CAAC;QACD,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;QACjD,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,IAAI,KAAK;YACR,OAAO,IAAI,CAAC,KAAK,CAAC;QACnB,CAAC;KACD,CAAC;IACF,OAAO,GAAG,CAAC;AACZ,CAAC"}
package/dist/shape.d.ts CHANGED
@@ -3,6 +3,7 @@ import type * as Atom from "effect/reactivity/Atom";
3
3
  import type * as AtomRef from "effect/reactivity/AtomRef";
4
4
  import type { AtomRegistry } from "effect/reactivity/AtomRegistry";
5
5
  import type { Reactivity } from "effect/reactivity/Reactivity";
6
+ import type { FieldPath, ValueAt } from "./fieldPath.ts";
6
7
  import type { FieldMessages } from "./messages.ts";
7
8
  import type { PersistedDraftConfig } from "./persistence.ts";
8
9
  export type Fields = Schema.Struct.Fields;
@@ -60,11 +61,13 @@ export interface Snapshot<TFields extends Fields> {
60
61
  export interface Form<TFields extends Fields, A, E, TRuntimeError> {
61
62
  readonly blur: (name: Name<TFields>) => void;
62
63
  readonly change: <TKey extends Name<TFields>>(name: TKey, value: Encoded<TFields>[TKey]) => void;
64
+ readonly changeAt: <const TPath extends Path<Name<TFields>> & FieldPath<Encoded<TFields>>>(path: TPath, value: ValueAt<Encoded<TFields>, TPath>) => void;
63
65
  readonly choices: <TKey extends Name<TFields>>(name: TKey) => readonly Encoded<TFields>[TKey][] | undefined;
64
66
  readonly dirty: Atom.Atom<boolean>;
65
67
  readonly error: (name: Name<TFields>) => Atom.Atom<string | undefined>;
66
68
  readonly errorAt: (path: Path<Name<TFields>> | readonly []) => Atom.Atom<string | undefined>;
67
69
  readonly field: <TKey extends Name<TFields>>(name: TKey) => AtomRef.AtomRef<Encoded<TFields>[TKey]>;
70
+ readonly fieldAt: <const TPath extends Path<Name<TFields>> & FieldPath<Encoded<TFields>>>(path: TPath) => AtomRef.AtomRef<ValueAt<Encoded<TFields>, TPath>>;
68
71
  readonly receive: (values: Encoded<TFields>) => void;
69
72
  readonly revert: () => void;
70
73
  readonly submit: Atom.AtomResultFn<void, A, E | TRuntimeError | FieldFailure | Invalid>;
@@ -1 +1 @@
1
- {"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"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"}
package/dist/shape.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"shape.js","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAuD,MAAM,QAAQ,CAAC;AA0BnF,MAAM,OAAO,YAAa,SAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAI/D;CAAG;AAEL,MAAM,OAAO,OAAQ,SAAQ,IAAI,CAAC,WAAW,CAAC,SAAS,CAGrD;CAAG"}
1
+ {"version":3,"file":"shape.js","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAuD,MAAM,QAAQ,CAAC;AA2BnF,MAAM,OAAO,YAAa,SAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAI/D;CAAG;AAEL,MAAM,OAAO,OAAQ,SAAQ,IAAI,CAAC,WAAW,CAAC,SAAS,CAGrD;CAAG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/form",
3
- "version": "0.16.0",
3
+ "version": "0.17.1",
4
4
  "description": "Schema-derived Effect atom forms with optional React hooks",
5
5
  "keywords": [
6
6
  "effect"
@@ -43,24 +43,23 @@
43
43
  "README.md"
44
44
  ],
45
45
  "dependencies": {
46
- "@shivaedev/errors": "0.9.0"
46
+ "@shivaedev/errors": "0.9.1"
47
47
  },
48
48
  "devDependencies": {
49
- "@effect/atom-react": "4.0.6",
50
- "@effect/vitest": "4.0.6",
51
- "@shivaedev/quality": "0.60.0",
52
- "@shivaedev/test": "0.15.0",
53
- "@shivaedev/test-story": "0.38.0",
49
+ "@effect/atom-react": "4.0.7",
50
+ "@effect/vitest": "4.0.7",
51
+ "@shivaedev/quality": "0.61.1",
52
+ "@shivaedev/test-story": "0.39.1",
54
53
  "@types/node": "24.19.2",
55
54
  "@types/react": "19.3.0",
56
- "effect": "4.0.6",
55
+ "effect": "4.0.7",
57
56
  "react": "19.3.1",
58
57
  "typescript": "7.0.2",
59
58
  "vitest": "5.0.5"
60
59
  },
61
60
  "peerDependencies": {
62
- "@effect/atom-react": "4.0.6",
63
- "effect": "4.0.6",
61
+ "@effect/atom-react": "4.0.7",
62
+ "effect": "4.0.7",
64
63
  "react": "19.3.1"
65
64
  },
66
65
  "peerDependenciesMeta": {
@@ -0,0 +1,19 @@
1
+ import { useAtomMount, useAtomRef, useAtomValue } from "@effect/atom-react";
2
+ import type { FieldPath, ValueAt } from "#fieldPath.ts";
3
+ import type { Encoded, Fields, Form, Name, Path } from "#shape.ts";
4
+
5
+ export function useFieldAt<TFields extends Fields, A, E, TRuntimeError, const TPath extends Path<Name<TFields>> & FieldPath<Encoded<TFields>>>(
6
+ form: Form<TFields, A, E, TRuntimeError>,
7
+ path: TPath,
8
+ ) {
9
+ useAtomMount(form.dirty);
10
+ const value = useAtomRef(form.fieldAt(path));
11
+ const error = useAtomValue(form.errorAt(path));
12
+ return {
13
+ error,
14
+ name: path.join("."),
15
+ onBlur: () => form.blur(path[0]),
16
+ onChange: (next: ValueAt<Encoded<TFields>, TPath>) => form.changeAt(path, next),
17
+ value,
18
+ };
19
+ }
@@ -1,4 +1,4 @@
1
- import { type Duration, Effect, Equal } from "effect";
1
+ import { Duration, Effect, Equal } from "effect";
2
2
  import * as AsyncResult from "effect/reactivity/AsyncResult";
3
3
  import * as Atom from "effect/reactivity/Atom";
4
4
  import type * as AtomRef from "effect/reactivity/AtomRef";
@@ -17,7 +17,7 @@ export function checkFeedback<TFields extends Fields, R, E>(
17
17
  return Atom.make((): string | undefined => undefined);
18
18
  }
19
19
  const current = fromRef(refFor(name));
20
- const settled = Atom.debounce(current, debounce);
20
+ const settled = Duration.isZero(Duration.fromInputUnsafe(debounce)) ? current : Atom.debounce(current, debounce);
21
21
  const answered = runtime.atom((get) => {
22
22
  const input = get(settled);
23
23
  return Effect.map(check(input), (message) => ({
@@ -0,0 +1,23 @@
1
+ import type * as AtomRef from "effect/reactivity/AtomRef";
2
+ import { propertyRef } from "./refs.ts";
3
+
4
+ type Keys<T> = T extends readonly unknown[] ? number : Extract<keyof T, string | number>;
5
+ export type FieldPath<T> = T extends object
6
+ ? { [TKey in Keys<T>]: TKey extends keyof T ? readonly [TKey] | readonly [TKey, ...FieldPath<NonNullable<T[TKey]>>] : never }[Keys<T>]
7
+ : never;
8
+
9
+ export type ValueAt<T, TPath> = TPath extends readonly [infer TKey extends keyof NonNullable<T>, ...infer TRest extends PropertyKey[]]
10
+ ? ValueAt<NonNullable<T>[TKey], TRest>
11
+ : T;
12
+
13
+ export function refAt<T, const TPath extends readonly PropertyKey[] & FieldPath<T>>(
14
+ parent: AtomRef.AtomRef<T>,
15
+ path: TPath,
16
+ ): AtomRef.AtomRef<ValueAt<T, TPath>>;
17
+ export function refAt(parent: AtomRef.AtomRef<unknown>, path: readonly PropertyKey[]): AtomRef.AtomRef<unknown> {
18
+ let ref = parent;
19
+ for (const segment of path) {
20
+ ref = propertyRef(ref, segment);
21
+ }
22
+ return ref;
23
+ }
package/src/form.ts CHANGED
@@ -5,6 +5,7 @@ import type * as AtomRef from "effect/reactivity/AtomRef";
5
5
  import { persistence } from "#adapters/persistence.ts";
6
6
  import { checkFeedback } from "./checkFeedback.ts";
7
7
  import { draft } from "./draft.ts";
8
+ import { refAt } from "./fieldPath.ts";
8
9
  import { literalChoices, messageAt, schemaFeedback } from "./messages.ts";
9
10
  import { pathMessageAt } from "./paths.ts";
10
11
  import { fromRef, propertyRef } from "./refs.ts";
@@ -107,6 +108,10 @@ export function form<TFields extends Fields, TValue, TError, TServices = never,
107
108
  refFor(name).set(value);
108
109
  status.touch(name);
109
110
  },
111
+ changeAt: (path, value) => {
112
+ refAt(values, path).set(value);
113
+ status.touch(path[0]);
114
+ },
110
115
  choices: <TName extends Name<TFields>>(name: TName) => {
111
116
  const member = schema.fields[name];
112
117
  const decodeChoice = SchemaParser.decodeUnknownSync(Schema.toEncoded(schema), { disableChecks: true });
@@ -125,6 +130,7 @@ export function form<TFields extends Fields, TValue, TError, TServices = never,
125
130
  );
126
131
  }),
127
132
  field: refFor,
133
+ fieldAt: (path) => refAt(values, path),
128
134
  receive: editing.receive,
129
135
  revert: editing.revert,
130
136
  submit,
package/src/refs.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Equal, Hash } from "effect";
1
+ import { Equal, Hash, Predicate } from "effect";
2
2
  import * as Atom from "effect/reactivity/Atom";
3
3
  import * as AtomRef from "effect/reactivity/AtomRef";
4
4
 
@@ -10,9 +10,11 @@ export function fromRef<TValue>(ref: AtomRef.ReadonlyRef<TValue>): Atom.Atom<TVa
10
10
  }
11
11
 
12
12
  // Native prop refs retain removed keys; form fields must observe their absence.
13
- export function propertyRef<TValue, TKey extends keyof TValue>(parent: AtomRef.AtomRef<TValue>, name: TKey): AtomRef.AtomRef<TValue[TKey]> {
14
- const read = parent.map((value) => value[name]);
15
- const ref: AtomRef.AtomRef<TValue[TKey]> = {
13
+ export function propertyRef<TValue, TKey extends keyof TValue>(parent: AtomRef.AtomRef<TValue>, name: TKey): AtomRef.AtomRef<TValue[TKey]>;
14
+ export function propertyRef(parent: AtomRef.AtomRef<unknown>, name: PropertyKey): AtomRef.AtomRef<unknown>;
15
+ export function propertyRef(parent: AtomRef.AtomRef<unknown>, name: PropertyKey): AtomRef.AtomRef<unknown> {
16
+ const read = parent.map((value): unknown => (Predicate.isObjectOrArray(value) ? Reflect.get(value, name) : undefined));
17
+ const ref: AtomRef.AtomRef<unknown> = {
16
18
  [AtomRef.TypeId]: AtomRef.TypeId,
17
19
  [Equal.symbol]: (other) => Equal.equals(read, other),
18
20
  [Hash.symbol]: () => Hash.hash(read),
@@ -20,9 +22,7 @@ export function propertyRef<TValue, TKey extends keyof TValue>(parent: AtomRef.A
20
22
  map: (transform) => read.map(transform),
21
23
  prop: (key) => propertyRef(ref, key),
22
24
  set: (value) => {
23
- parent.update((current) =>
24
- Array.isArray(current) ? Object.assign(current.slice(), current, { [name]: value }) : { ...current, [name]: value },
25
- );
25
+ parent.update((current) => Object.assign(Array.isArray(current) ? current.slice() : {}, current, { [name]: value }));
26
26
  return ref;
27
27
  },
28
28
  subscribe: (listener) => read.subscribe(listener),
package/src/shape.ts CHANGED
@@ -3,6 +3,7 @@ import type * as Atom from "effect/reactivity/Atom";
3
3
  import type * as AtomRef from "effect/reactivity/AtomRef";
4
4
  import type { AtomRegistry } from "effect/reactivity/AtomRegistry";
5
5
  import type { Reactivity } from "effect/reactivity/Reactivity";
6
+ import type { FieldPath, ValueAt } from "./fieldPath.ts";
6
7
  import type { FieldMessages } from "./messages.ts";
7
8
  import type { PersistedDraftConfig } from "./persistence.ts";
8
9
 
@@ -68,11 +69,18 @@ export interface Snapshot<TFields extends Fields> {
68
69
  export interface Form<TFields extends Fields, A, E, TRuntimeError> {
69
70
  readonly blur: (name: Name<TFields>) => void;
70
71
  readonly change: <TKey extends Name<TFields>>(name: TKey, value: Encoded<TFields>[TKey]) => void;
72
+ readonly changeAt: <const TPath extends Path<Name<TFields>> & FieldPath<Encoded<TFields>>>(
73
+ path: TPath,
74
+ value: ValueAt<Encoded<TFields>, TPath>,
75
+ ) => void;
71
76
  readonly choices: <TKey extends Name<TFields>>(name: TKey) => readonly Encoded<TFields>[TKey][] | undefined;
72
77
  readonly dirty: Atom.Atom<boolean>;
73
78
  readonly error: (name: Name<TFields>) => Atom.Atom<string | undefined>;
74
79
  readonly errorAt: (path: Path<Name<TFields>> | readonly []) => Atom.Atom<string | undefined>;
75
80
  readonly field: <TKey extends Name<TFields>>(name: TKey) => AtomRef.AtomRef<Encoded<TFields>[TKey]>;
81
+ readonly fieldAt: <const TPath extends Path<Name<TFields>> & FieldPath<Encoded<TFields>>>(
82
+ path: TPath,
83
+ ) => AtomRef.AtomRef<ValueAt<Encoded<TFields>, TPath>>;
76
84
  readonly receive: (values: Encoded<TFields>) => void;
77
85
  readonly revert: () => void;
78
86
  readonly submit: Atom.AtomResultFn<void, A, E | TRuntimeError | FieldFailure | Invalid>;