@shivaedev/effect-form 0.0.0 → 0.1.0

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/LICENSE +21 -0
  3. package/README.md +50 -1
  4. package/dist/draft.d.ts +15 -0
  5. package/dist/draft.d.ts.map +1 -0
  6. package/dist/draft.js +57 -0
  7. package/dist/draft.js.map +1 -0
  8. package/dist/form.d.ts +4 -0
  9. package/dist/form.d.ts.map +1 -0
  10. package/dist/form.js +102 -0
  11. package/dist/form.js.map +1 -0
  12. package/dist/index.d.ts +6 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +4 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/messages.d.ts +8 -0
  17. package/dist/messages.d.ts.map +1 -0
  18. package/dist/messages.js +60 -0
  19. package/dist/messages.js.map +1 -0
  20. package/dist/optional.d.ts +3 -0
  21. package/dist/optional.d.ts.map +1 -0
  22. package/dist/optional.js +6 -0
  23. package/dist/optional.js.map +1 -0
  24. package/dist/react.d.ts +19 -0
  25. package/dist/react.d.ts.map +1 -0
  26. package/dist/react.js +18 -0
  27. package/dist/react.js.map +1 -0
  28. package/dist/refs.d.ts +5 -0
  29. package/dist/refs.d.ts.map +1 -0
  30. package/dist/refs.js +31 -0
  31. package/dist/refs.js.map +1 -0
  32. package/dist/shape.d.ts +59 -0
  33. package/dist/shape.d.ts.map +1 -0
  34. package/dist/shape.js +18 -0
  35. package/dist/shape.js.map +1 -0
  36. package/dist/status.d.ts +9 -0
  37. package/dist/status.d.ts.map +1 -0
  38. package/dist/status.js +38 -0
  39. package/dist/status.js.map +1 -0
  40. package/package.json +68 -4
  41. package/src/draft.ts +77 -0
  42. package/src/form.ts +145 -0
  43. package/src/index.ts +15 -0
  44. package/src/messages.ts +73 -0
  45. package/src/optional.ts +11 -0
  46. package/src/react.ts +37 -0
  47. package/src/refs.ts +33 -0
  48. package/src/shape.ts +81 -0
  49. package/src/status.ts +46 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 - 2026-09-26
4
+
5
+ ### Added
6
+
7
+ - Extract schema-derived form state, submission, field messages, draft
8
+ preservation, and optional React hooks from Antumbra.
9
+ - Merge received values per field: untouched fields adopt refreshed server
10
+ values while edited fields keep local input.
11
+ - Keep a refresh received during an in-flight save as the baseline instead of
12
+ replacing it with the older submitted values.
13
+ - Show an async check message only while the field still holds the value it was
14
+ computed for.
15
+ - Clear optional field values and notify subscribers when a received or reverted
16
+ baseline omits the field.
17
+ - Allow submit handlers to use the native atom runtime's scope, registry, and
18
+ reactivity services.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ShivaeDev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,52 @@
1
1
  # @shivaedev/effect-form
2
2
 
3
- This version only reserves the name. Releases are published from https://github.com/ShivaeDev/platform.
3
+ Schema-derived form state built on Effect atoms. The core has no React dependency; optional hooks are exported from `@shivaedev/effect-form/react`.
4
+
5
+ ```ts
6
+ import { Effect, Layer, Schema } from "effect";
7
+ import * as Atom from "effect/unstable/reactivity/Atom";
8
+ import { make } from "@shivaedev/effect-form";
9
+
10
+ const runtime = Atom.runtime(Layer.empty);
11
+ const profile = make(Schema.Struct({ name: Schema.NonEmptyString }), {
12
+ initialValues: { name: "" },
13
+ runtime,
14
+ onSubmit: (values, submitter) =>
15
+ values.name === "reserved"
16
+ ? submitter.fail("name", "Choose another name")
17
+ : Effect.succeed(values),
18
+ });
19
+ ```
20
+
21
+ Fields hold the schema's encoded values; submission snapshots and decodes them before calling the handler. The handler receives the decoded values and, as its third argument, the encoded snapshot that was submitted (edits made while an async schema decodes are not part of it). Its dependencies and schema decoding services must be provided by the supplied atom runtime. Its success and error types are preserved in `form.submit`.
22
+
23
+ Submit handlers can also use the native runtime's `Scope`, `AtomRegistry`, and `Reactivity` services. For example, wrap a successful RPC save in `Reactivity.mutation(keys)` to invalidate queries in the same atom runtime. Application services still need to be supplied by the configured runtime.
24
+
25
+ Use an AtomRegistry to mount/read atoms and call `registry.set(profile.submit, undefined)` to submit. In React, use the atom-react registry provider and the hooks:
26
+
27
+ ```tsx
28
+ import { useField, useSubmit } from "@shivaedev/effect-form/react";
29
+
30
+ function Profile() {
31
+ const name = useField(profile, "name");
32
+ const submit = useSubmit(profile);
33
+ return <form onSubmit={(event) => { event.preventDefault(); submit.run(); }}>
34
+ <input value={name.value} onBlur={name.onBlur}
35
+ onChange={(event) => name.onChange(event.target.value)} />
36
+ <span>{name.error}</span>
37
+ <button disabled={submit.submitting}>Save</button>
38
+ </form>;
39
+ }
40
+ ```
41
+
42
+ Create one stable form instance per editing session; do not recreate it during every render. Applications own general submission error rendering through `submit.result`.
43
+
44
+ - Field errors appear after a change, blur, or submission. Editing clears a server field rejection.
45
+ - Optional debounced `checks` provide advisory field messages. A message shows only while the field still holds the value it was computed for; pending, failed or outdated checks show nothing. They do not block submission; authoritative validation belongs in the schema or submit handler.
46
+ - `receive(values)` merges per field: a field that still equals its baseline adopts the received value (an optional key the refresh omits disappears), an edited field keeps its local value, and the received values become the baseline. `revert()` restores the latest received baseline.
47
+ - Successful submission accepts the submitted encoded values as the baseline. Edits made while saving stay dirty. If a refresh arrived while the save was in flight, it stays the baseline; fields still holding the submitted values count as saved and adopt the next received values.
48
+ - `emptyAsNull(schema)` maps an empty input string to nullable domain values.
49
+
50
+ This package handles top-level fields. Nested error paths map to their first field; it does not provide nested field arrays or a general nested form DSL. Draft comparisons use Effect equality per field; callers should replace values instead of mutating them in place.
51
+
52
+ Install `effect` with the package. For React hooks also install compatible `@effect/atom-react` and React 19. This initial release targets Effect `4.0.0-rc.112`.
@@ -0,0 +1,15 @@
1
+ import * as Atom from "effect/unstable/reactivity/Atom";
2
+ import * as AtomRef from "effect/unstable/reactivity/AtomRef";
3
+ type Entries = Readonly<Record<string, unknown>>;
4
+ export declare const draft: <Values extends Entries>(initial: Values) => {
5
+ dirty: Atom.Atom<boolean>;
6
+ receive: (incoming: Values) => void;
7
+ revert: () => void;
8
+ submission: () => {
9
+ accept: () => void;
10
+ values: Values;
11
+ };
12
+ values: AtomRef.AtomRef<Values>;
13
+ };
14
+ export {};
15
+ //# sourceMappingURL=draft.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft.d.ts","sourceRoot":"","sources":["../src/draft.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,iCAAiC,CAAC;AACxD,OAAO,KAAK,OAAO,MAAM,oCAAoC,CAAC;AAE9D,KAAK,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAkCjD,eAAO,MAAM,KAAK,GAAI,MAAM,SAAS,OAAO,EAAE,SAAS,MAAM;;wBAWvC,MAAM,KAAG,IAAI;kBAOrB,IAAI;;sBAUF,IAAI;;;;CAUnB,CAAC"}
package/dist/draft.js ADDED
@@ -0,0 +1,57 @@
1
+ import { Equal } from "effect";
2
+ import * as Atom from "effect/unstable/reactivity/Atom";
3
+ import * as AtomRef from "effect/unstable/reactivity/AtomRef";
4
+ const none = {};
5
+ const untouched = ({ baseline, current, settled }, name) => Equal.equals(current[name], baseline[name]) || (Object.hasOwn(settled, name) && Equal.equals(current[name], settled[name]));
6
+ const changed = (held) => Object.keys({ ...held.baseline, ...held.current }).some((name) => !untouched(held, name));
7
+ function merged(held, incoming) {
8
+ const result = {};
9
+ for (const name of Object.keys({ ...held.current, ...incoming })) {
10
+ const source = untouched(held, name) ? incoming : held.current;
11
+ if (Object.hasOwn(source, name)) {
12
+ result[name] = source[name];
13
+ }
14
+ }
15
+ return result;
16
+ }
17
+ const matching = (current, submitted) => Object.fromEntries(Object.keys({ ...current, ...submitted })
18
+ .filter((name) => Equal.equals(current[name], submitted[name]))
19
+ .map((name) => [name, submitted[name]]));
20
+ export const draft = (initial) => {
21
+ const state = AtomRef.make({
22
+ baseline: initial,
23
+ current: initial,
24
+ settled: none,
25
+ });
26
+ return {
27
+ dirty: Atom.readable((get) => {
28
+ get.addFinalizer(state.subscribe((value) => get.setSelf(changed(value))));
29
+ return changed(state.value);
30
+ }),
31
+ receive: (incoming) => {
32
+ state.update((held) => ({
33
+ baseline: incoming,
34
+ current: changed(held) ? merged(held, incoming) : incoming,
35
+ settled: none,
36
+ }));
37
+ },
38
+ revert: () => {
39
+ state.update((held) => ({
40
+ ...held,
41
+ current: held.baseline,
42
+ settled: none,
43
+ }));
44
+ },
45
+ submission: () => {
46
+ const { baseline, current: submitted } = state.value;
47
+ return {
48
+ accept: () => {
49
+ state.update((held) => held.baseline === baseline ? { ...held, baseline: submitted, settled: none } : { ...held, settled: matching(held.current, submitted) });
50
+ },
51
+ values: submitted,
52
+ };
53
+ },
54
+ values: state.prop("current"),
55
+ };
56
+ };
57
+ //# sourceMappingURL=draft.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft.js","sourceRoot":"","sources":["../src/draft.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC/B,OAAO,KAAK,IAAI,MAAM,iCAAiC,CAAC;AACxD,OAAO,KAAK,OAAO,MAAM,oCAAoC,CAAC;AAU9D,MAAM,IAAI,GAAY,EAAE,CAAC;AAEzB,MAAM,SAAS,GAAG,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAkB,EAAE,IAAY,EAAW,EAAE,CAC3F,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAE7H,MAAM,OAAO,GAAG,CAAC,IAAoB,EAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAG7I,SAAS,MAAM,CAAC,IAAoB,EAAE,QAAiB;IACtD,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC,EAAE,CAAC;QAClE,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QAC/D,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;YACjC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;IACF,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,QAAQ,GAAG,CAAC,OAAgB,EAAE,SAAkB,EAAW,EAAE,CAClE,MAAM,CAAC,WAAW,CACjB,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,SAAS,EAAE,CAAC;KACvC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;KAC9D,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CACxC,CAAC;AAEH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAyB,OAAe,EAAE,EAAE;IAChE,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAgB;QACzC,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,IAAI;KACb,CAAC,CAAC;IACH,OAAO;QACN,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,EAAE;YAC5B,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1E,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC,CAAC;QACF,OAAO,EAAE,CAAC,QAAgB,EAAQ,EAAE;YACnC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACvB,QAAQ,EAAE,QAAQ;gBAClB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ;gBAC1D,OAAO,EAAE,IAAI;aACb,CAAC,CAAC,CAAC;QACL,CAAC;QACD,MAAM,EAAE,GAAS,EAAE;YAClB,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACvB,GAAG,IAAI;gBACP,OAAO,EAAE,IAAI,CAAC,QAAQ;gBACtB,OAAO,EAAE,IAAI;aACb,CAAC,CAAC,CAAC;QACL,CAAC;QACD,UAAU,EAAE,GAAG,EAAE;YAChB,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC;YACrD,OAAO;gBACN,MAAM,EAAE,GAAS,EAAE;oBAClB,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CACrB,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CACtI,CAAC;gBACH,CAAC;gBACD,MAAM,EAAE,SAAS;aACjB,CAAC;QACH,CAAC;QACD,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;KAC7B,CAAC;AACH,CAAC,CAAC"}
package/dist/form.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { type Schema } from "effect";
2
+ import { type Config, type Fields, type Form } from "./shape.ts";
3
+ export declare const make: <F extends Fields, A, E, R, ER>(schema: Schema.Struct<F>, config: Config<F, A, E, R, ER>) => Form<F, A, E, ER>;
4
+ //# sourceMappingURL=form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,KAAK,MAAM,EAAgB,MAAM,QAAQ,CAAC;AAOlF,OAAO,EACN,KAAK,MAAM,EAMX,KAAK,MAAM,EACX,KAAK,IAAI,EAMT,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAG,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAwH9H,CAAC"}
package/dist/form.js ADDED
@@ -0,0 +1,102 @@
1
+ import { Effect, Equal, Option, Result, SchemaParser } from "effect";
2
+ import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
3
+ import * as Atom from "effect/unstable/reactivity/Atom";
4
+ import { draft } from "./draft.js";
5
+ import { literalChoices, messageAt, messagesByField, noMessages } from "./messages.js";
6
+ import { fromRef, propertyRef } from "./refs.js";
7
+ import { checkOf, choicesOf, FieldFailure, fieldOf, holder, Invalid, } from "./shape.js";
8
+ import { statusOf } from "./status.js";
9
+ export const make = (schema, config) => {
10
+ const { initialValues, onSubmit, runtime } = config;
11
+ const debounce = config.debounce ?? "300 millis";
12
+ const checks = new Map(Object.entries(config.checks ?? {}));
13
+ const decode = SchemaParser.decodeUnknownEffect(schema, { errors: "all" });
14
+ const editing = draft(initialValues);
15
+ const { values } = editing;
16
+ const status = statusOf();
17
+ const held = new Map();
18
+ const refFor = (name) => {
19
+ const known = held.get(name);
20
+ if (known !== undefined) {
21
+ return known;
22
+ }
23
+ const made = propertyRef(holder(values), name);
24
+ held.set(name, made);
25
+ return made;
26
+ };
27
+ const offered = new Map();
28
+ for (const [name, member] of Object.entries(schema.fields)) {
29
+ const choices = literalChoices(member.ast);
30
+ if (choices !== undefined) {
31
+ offered.set(name, choices);
32
+ }
33
+ }
34
+ const valuesAtom = fromRef(values);
35
+ const decoded = runtime.atom((get) => decode(get(valuesAtom)).pipe(Effect.match({
36
+ onFailure: (issue) => Result.fail(messagesByField(issue)),
37
+ onSuccess: (value) => Result.succeed(value),
38
+ })));
39
+ const schemaMessages = Atom.map(decoded, (result) => Option.match(AsyncResult.value(result), {
40
+ onNone: () => noMessages,
41
+ onSome: (either) => (Result.isFailure(either) ? either.failure : noMessages),
42
+ }));
43
+ const schemaError = Atom.family((name) => Atom.map(schemaMessages, (messages) => messageAt(messages, name)));
44
+ const checkError = Atom.family((name) => {
45
+ const check = checks.get(name);
46
+ if (check === undefined) {
47
+ return Atom.make(() => undefined);
48
+ }
49
+ const current = fromRef(refFor(name));
50
+ const settled = Atom.debounce(current, debounce);
51
+ const answered = runtime.atom((get) => {
52
+ const input = get(settled);
53
+ return Effect.map(checkOf(check)(input), (message) => ({
54
+ input,
55
+ message,
56
+ }));
57
+ });
58
+ return Atom.readable((get) => {
59
+ const result = get(answered);
60
+ const value = get(current);
61
+ return AsyncResult.isSuccess(result) && !result.waiting && Equal.equals(result.value.input, value) ? result.value.message : undefined;
62
+ });
63
+ });
64
+ const error = Atom.family((name) => Atom.readable((get) => {
65
+ if (get(status.touched)[name] !== true && !get(status.submitted)) {
66
+ return undefined;
67
+ }
68
+ return messageAt(get(status.failures), name) ?? get(schemaError(name)) ?? get(checkError(name));
69
+ }));
70
+ const noted = (submitted) => (cause) => Effect.sync(() => {
71
+ if (cause instanceof FieldFailure && Equal.equals(refFor(cause.path).value, new Map(Object.entries(submitted)).get(cause.path))) {
72
+ status.note(cause.path, cause.message);
73
+ }
74
+ });
75
+ const submitter = {
76
+ fail: (path, message) => Effect.fail(new FieldFailure({ message, path })),
77
+ };
78
+ const submit = runtime.fn()(() => Effect.gen(function* () {
79
+ status.attempt();
80
+ const submission = editing.submission();
81
+ const submitted = submission.values;
82
+ const value = yield* decode(submitted).pipe(Effect.mapError((issue) => new Invalid({ messages: messagesByField(issue) })));
83
+ return yield* onSubmit(value, submitter, submitted).pipe(Effect.tapError(noted(submitted)), Effect.tap(() => Effect.sync(submission.accept)));
84
+ }));
85
+ return {
86
+ blur: status.touch,
87
+ change: (name, value) => {
88
+ refFor(name).set(value);
89
+ status.touch(name);
90
+ },
91
+ choices: (name) => choicesOf(offered.get(name)),
92
+ dirty: editing.dirty,
93
+ error,
94
+ field: (name) => fieldOf(refFor(name)),
95
+ receive: editing.receive,
96
+ revert: editing.revert,
97
+ submit,
98
+ submitting: Atom.map(submit, AsyncResult.isWaiting),
99
+ values,
100
+ };
101
+ };
102
+ //# sourceMappingURL=form.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.js","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export { make } from "./form.ts";
2
+ export type { FieldMessages } from "./messages.ts";
3
+ export { emptyAsNull } from "./optional.ts";
4
+ export type { Checks, Config, Decoded, Encoded, Fields, Form, Name, Services, Submitter, } from "./shape.ts";
5
+ export { FieldFailure, Invalid } from "./shape.ts";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EACX,MAAM,EACN,MAAM,EACN,OAAO,EACP,OAAO,EACP,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,SAAS,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { make } from "./form.js";
2
+ export { emptyAsNull } from "./optional.js";
3
+ export { FieldFailure, Invalid } from "./shape.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAY5C,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { SchemaAST, SchemaIssue } from "effect";
2
+ export type FieldMessages = Readonly<Record<string, string>>;
3
+ export declare const noMessages: FieldMessages;
4
+ export declare const messagesByField: (issue: SchemaIssue.Issue) => FieldMessages;
5
+ export declare const withoutField: (messages: FieldMessages, name: string) => FieldMessages;
6
+ export declare const literalChoices: (input: SchemaAST.AST) => readonly SchemaAST.LiteralValue[] | undefined;
7
+ export declare const messageAt: (messages: FieldMessages, name: string) => string | undefined;
8
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAuB,MAAM,QAAQ,CAAC;AAErE,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE7D,eAAO,MAAM,UAAU,EAAE,aAAkB,CAAC;AAyB5C,eAAO,MAAM,eAAe,GAAI,OAAO,WAAW,CAAC,KAAK,KAAG,aAa1D,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,UAAU,aAAa,EAAE,MAAM,MAAM,KAAG,aAWpE,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,SAAS,CAAC,GAAG,KAAG,SAAS,SAAS,CAAC,YAAY,EAAE,GAAG,SAazF,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,UAAU,aAAa,EAAE,MAAM,MAAM,KAAG,MAAM,GAAG,SAAyE,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { SchemaAST, SchemaIssue } from "effect";
2
+ export const noMessages = {};
3
+ const REQUIRED = "Required";
4
+ const MINIMUM_LENGTH = "effect/schema/isMinLength";
5
+ const refusesEmpty = (check) => {
6
+ const representation = check.annotations?.representation;
7
+ if (representation === undefined || representation.id !== MINIMUM_LENGTH) {
8
+ return false;
9
+ }
10
+ const payload = representation.payload;
11
+ if (typeof payload !== "object" || payload === null || !("minLength" in payload)) {
12
+ return false;
13
+ }
14
+ return payload.minLength === 1;
15
+ };
16
+ const checkHook = (issue) => SchemaIssue.defaultCheckHook(issue) ?? (refusesEmpty(issue.filter) ? REQUIRED : undefined);
17
+ const formatIssue = SchemaIssue.makeFormatterStandardSchemaV1({ checkHook });
18
+ const segmentKey = (segment) => typeof segment === "object" ? String(segment.key) : String(segment);
19
+ export const messagesByField = (issue) => {
20
+ const messages = Object.create(null);
21
+ for (const entry of formatIssue(issue).issues) {
22
+ const head = entry.path?.[0];
23
+ if (head === undefined) {
24
+ continue;
25
+ }
26
+ const name = segmentKey(head);
27
+ if (!Object.hasOwn(messages, name)) {
28
+ messages[name] = entry.message;
29
+ }
30
+ }
31
+ return messages;
32
+ };
33
+ export const withoutField = (messages, name) => {
34
+ if (!Object.hasOwn(messages, name)) {
35
+ return messages;
36
+ }
37
+ const next = Object.create(null);
38
+ for (const [key, message] of Object.entries(messages)) {
39
+ if (key !== name) {
40
+ next[key] = message;
41
+ }
42
+ }
43
+ return next;
44
+ };
45
+ export const literalChoices = (input) => {
46
+ const ast = SchemaAST.toEncoded(input);
47
+ if (ast._tag !== "Union") {
48
+ return undefined;
49
+ }
50
+ const choices = [];
51
+ for (const member of ast.types) {
52
+ if (member._tag !== "Literal") {
53
+ return undefined;
54
+ }
55
+ choices.push(member.literal);
56
+ }
57
+ return choices;
58
+ };
59
+ export const messageAt = (messages, name) => (Object.hasOwn(messages, name) ? messages[name] : undefined);
60
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAuB,MAAM,QAAQ,CAAC;AAIrE,MAAM,CAAC,MAAM,UAAU,GAAkB,EAAE,CAAC;AAE5C,MAAM,QAAQ,GAAG,UAAU,CAAC;AAE5B,MAAM,cAAc,GAAG,2BAA2B,CAAC;AAEnD,MAAM,YAAY,GAAG,CAAC,KAAgC,EAAW,EAAE;IAClE,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,EAAE,cAAc,CAAC;IACzD,IAAI,cAAc,KAAK,SAAS,IAAI,cAAc,CAAC,EAAE,KAAK,cAAc,EAAE,CAAC;QAC1E,OAAO,KAAK,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC;IACvC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,WAAW,IAAI,OAAO,CAAC,EAAE,CAAC;QAClF,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,OAAO,CAAC,SAAS,KAAK,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF,MAAM,SAAS,GAA0B,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AAE/I,MAAM,WAAW,GAAG,WAAW,CAAC,6BAA6B,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;AAE7E,MAAM,UAAU,GAAG,CAAC,OAAkE,EAAU,EAAE,CACjG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAErE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAAwB,EAAiB,EAAE;IAC1E,MAAM,QAAQ,GAA2B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7D,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACxB,SAAS;QACV,CAAC;QACD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC;YACpC,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC;QAChC,CAAC;IACF,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,QAAuB,EAAE,IAAY,EAAiB,EAAE;IACpF,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC;QACpC,OAAO,QAAQ,CAAC;IACjB,CAAC;IACD,MAAM,IAAI,GAA2B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACzD,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvD,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YAClB,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;QACrB,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAoB,EAAiD,EAAE;IACrG,MAAM,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,OAAO,GAA6B,EAAE,CAAC;IAC7C,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,QAAuB,EAAE,IAAY,EAAsB,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Schema } from "effect";
2
+ export declare const emptyAsNull: <S extends Schema.Constraint & Schema.Top>(inner: S) => Schema.Codec<S["Type"] | null, S["Encoded"] | "", S["DecodingServices"], S["EncodingServices"]>;
3
+ //# sourceMappingURL=optional.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional.d.ts","sourceRoot":"","sources":["../src/optional.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAgB,MAAM,QAAQ,CAAC;AAE9C,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,GAAG,EACnE,OAAO,CAAC,KACN,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,kBAAkB,CAAC,CAM/F,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Schema, SchemaGetter } from "effect";
2
+ export const emptyAsNull = (inner) => Schema.Union([Schema.Literal(""), inner]).pipe(Schema.decodeTo(Schema.NullOr(Schema.toType(inner)), {
3
+ decode: SchemaGetter.transform((value) => (value === "" ? null : value)),
4
+ encode: SchemaGetter.transform((value) => (value === null ? "" : value)),
5
+ }));
6
+ //# sourceMappingURL=optional.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional.js","sourceRoot":"","sources":["../src/optional.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAE9C,MAAM,CAAC,MAAM,WAAW,GAAG,CAC1B,KAAQ,EAC0F,EAAE,CACpG,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAC7C,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE;IACpD,MAAM,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACxE,MAAM,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;CACxE,CAAC,CACF,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
2
+ import type { Encoded, FieldFailure, Fields, Form, Invalid, Name } from "./shape.ts";
3
+ export interface Field<F extends Fields, K extends Name<F>> {
4
+ readonly choices: readonly Encoded<F>[K][] | undefined;
5
+ readonly error: string | undefined;
6
+ readonly name: K;
7
+ readonly onBlur: () => void;
8
+ readonly onChange: (value: Encoded<F>[K]) => void;
9
+ readonly value: Encoded<F>[K];
10
+ }
11
+ export declare const useField: <F extends Fields, A, E, ER, K extends Name<F>>(form: Form<F, A, E, ER>, name: K) => Field<F, K>;
12
+ export interface Submit<A, E> {
13
+ readonly result: AsyncResult.AsyncResult<A, E>;
14
+ readonly run: () => void;
15
+ readonly submitting: boolean;
16
+ }
17
+ export declare const useSubmit: <F extends Fields, A, E, ER>(form: Form<F, A, E, ER>) => Submit<A, E | ER | FieldFailure | Invalid>;
18
+ export declare const useDirty: <F extends Fields, A, E, ER>(form: Form<F, A, E, ER>) => boolean;
19
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,WAAW,MAAM,wCAAwC,CAAC;AAE3E,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAErF,MAAM,WAAW,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC;IACzD,QAAQ,CAAC,OAAO,EAAE,SAAS,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC;IACvD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC9B;AAED,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,KAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAOpH,CAAC;AAEF,MAAM,WAAW,MAAM,CAAC,CAAC,EAAE,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/C,QAAQ,CAAC,GAAG,EAAE,MAAM,IAAI,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAG,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,YAAY,GAAG,OAAO,CAKxH,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAG,OAAmC,CAAC"}
package/dist/react.js ADDED
@@ -0,0 +1,18 @@
1
+ import { useAtomRef, useAtomSet, useAtomValue } from "@effect/atom-react";
2
+ import { useCallback, useMemo } from "react";
3
+ export const useField = (form, name) => {
4
+ const value = useAtomRef(form.field(name));
5
+ const error = useAtomValue(form.error(name));
6
+ const onChange = useCallback((next) => form.change(name, next), [form, name]);
7
+ const onBlur = useCallback(() => form.blur(name), [form, name]);
8
+ const choices = useMemo(() => form.choices(name), [form, name]);
9
+ return { choices, error, name, onBlur, onChange, value };
10
+ };
11
+ export const useSubmit = (form) => {
12
+ const result = useAtomValue(form.submit);
13
+ const set = useAtomSet(form.submit);
14
+ const run = useCallback(() => set(), [set]);
15
+ return { result, run, submitting: result.waiting };
16
+ };
17
+ export const useDirty = (form) => useAtomValue(form.dirty);
18
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE1E,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAY7C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAgD,IAAuB,EAAE,IAAO,EAAe,EAAE;IACxH,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,IAAmB,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7F,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAChE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC1D,CAAC,CAAC;AAQF,MAAM,CAAC,MAAM,SAAS,GAAG,CAA6B,IAAuB,EAA8C,EAAE;IAC5H,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;AACpD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAA6B,IAAuB,EAAW,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC"}
package/dist/refs.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import * as Atom from "effect/unstable/reactivity/Atom";
2
+ import * as AtomRef from "effect/unstable/reactivity/AtomRef";
3
+ export declare const fromRef: <A>(ref: AtomRef.ReadonlyRef<A>) => Atom.Atom<A>;
4
+ export declare const propertyRef: <A, K extends keyof A>(parent: AtomRef.AtomRef<A>, name: K) => AtomRef.AtomRef<A[K]>;
5
+ //# sourceMappingURL=refs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refs.d.ts","sourceRoot":"","sources":["../src/refs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,iCAAiC,CAAC;AACxD,OAAO,KAAK,OAAO,MAAM,oCAAoC,CAAC;AAE9D,eAAO,MAAM,OAAO,GAAI,CAAC,EAAE,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,KAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAIjE,CAAC;AAGJ,eAAO,MAAM,WAAW,GAAI,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,EAAE,QAAQ,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAqB3G,CAAC"}
package/dist/refs.js ADDED
@@ -0,0 +1,31 @@
1
+ import { Equal, Hash } from "effect";
2
+ import * as Atom from "effect/unstable/reactivity/Atom";
3
+ import * as AtomRef from "effect/unstable/reactivity/AtomRef";
4
+ export const fromRef = (ref) => Atom.readable((get) => {
5
+ get.addFinalizer(ref.subscribe((value) => get.setSelf(value)));
6
+ return ref.value;
7
+ });
8
+ // Native prop refs retain removed keys; form fields must observe their absence.
9
+ export const propertyRef = (parent, name) => {
10
+ const read = parent.map((value) => value[name]);
11
+ const write = parent.prop(name);
12
+ const ref = {
13
+ [AtomRef.TypeId]: AtomRef.TypeId,
14
+ [Equal.symbol]: (other) => Equal.equals(read, other),
15
+ [Hash.symbol]: () => Hash.hash(read),
16
+ key: read.key,
17
+ get value() {
18
+ return read.value;
19
+ },
20
+ subscribe: (listener) => read.subscribe(listener),
21
+ map: (transform) => read.map(transform),
22
+ prop: (key) => propertyRef(ref, key),
23
+ set: (value) => {
24
+ write.set(value);
25
+ return ref;
26
+ },
27
+ update: (transform) => ref.set(transform(read.value)),
28
+ };
29
+ return ref;
30
+ };
31
+ //# sourceMappingURL=refs.js.map
@@ -0,0 +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,iCAAiC,CAAC;AACxD,OAAO,KAAK,OAAO,MAAM,oCAAoC,CAAC;AAE9D,MAAM,CAAC,MAAM,OAAO,GAAG,CAAI,GAA2B,EAAgB,EAAE,CACvE,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,EAAE;IACrB,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC/D,OAAO,GAAG,CAAC,KAAK,CAAC;AAClB,CAAC,CAAC,CAAC;AAEJ,gFAAgF;AAChF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAuB,MAA0B,EAAE,IAAO,EAAyB,EAAE;IAC/G,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,GAAG,GAA0B;QAClC,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,IAAI,KAAK;YACR,OAAO,IAAI,CAAC,KAAK,CAAC;QACnB,CAAC;QACD,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;QACjD,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,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACjB,OAAO,GAAG,CAAC;QACZ,CAAC;QACD,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;KACrD,CAAC;IACF,OAAO,GAAG,CAAC;AACZ,CAAC,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { type Duration, type Effect, type Schema, type Scope } from "effect";
2
+ import type * as Atom from "effect/unstable/reactivity/Atom";
3
+ import type * as AtomRef from "effect/unstable/reactivity/AtomRef";
4
+ import type { AtomRegistry } from "effect/unstable/reactivity/AtomRegistry";
5
+ import type { Reactivity } from "effect/unstable/reactivity/Reactivity";
6
+ import type { FieldMessages } from "./messages.ts";
7
+ export type Fields = Schema.Struct.Fields;
8
+ export type Encoded<F extends Fields> = Schema.Struct.Encoded<F>;
9
+ export type Decoded<F extends Fields> = Schema.Struct.Type<F>;
10
+ export type Name<F extends Fields> = keyof Encoded<F> & string;
11
+ export type Services<F extends Fields, R> = R | Schema.Struct.DecodingServices<F>;
12
+ declare const FieldFailure_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
13
+ readonly _tag: "FieldFailure";
14
+ } & Readonly<A>;
15
+ export declare class FieldFailure extends FieldFailure_base<{
16
+ readonly message: string;
17
+ readonly path: string;
18
+ }> {
19
+ }
20
+ declare const Invalid_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
21
+ readonly _tag: "Invalid";
22
+ } & Readonly<A>;
23
+ export declare class Invalid extends Invalid_base<{
24
+ readonly messages: FieldMessages;
25
+ }> {
26
+ }
27
+ export interface Submitter<N extends string> {
28
+ readonly fail: (path: N, message: string) => Effect.Effect<never, FieldFailure>;
29
+ }
30
+ export type Checks<F extends Fields, R> = {
31
+ readonly [K in Name<F>]?: (value: Encoded<F>[K]) => Effect.Effect<string | undefined, never, R>;
32
+ };
33
+ export interface Config<F extends Fields, A, E, R, ER> {
34
+ readonly checks?: Checks<F, R>;
35
+ readonly debounce?: Duration.Input;
36
+ readonly initialValues: Encoded<F>;
37
+ readonly onSubmit: (values: Decoded<F>, submitter: Submitter<Name<F>>, submitted: Encoded<F>) => Effect.Effect<A, E, R | Scope.Scope | AtomRegistry | Reactivity>;
38
+ readonly runtime: Atom.AtomRuntime<Services<F, R>, ER>;
39
+ }
40
+ export interface Form<F extends Fields, A, E, ER> {
41
+ readonly blur: (name: Name<F>) => void;
42
+ readonly change: <K extends Name<F>>(name: K, value: Encoded<F>[K]) => void;
43
+ readonly choices: <K extends Name<F>>(name: K) => readonly Encoded<F>[K][] | undefined;
44
+ readonly dirty: Atom.Atom<boolean>;
45
+ readonly error: (name: Name<F>) => Atom.Atom<string | undefined>;
46
+ readonly field: <K extends Name<F>>(name: K) => AtomRef.AtomRef<Encoded<F>[K]>;
47
+ readonly receive: (values: Encoded<F>) => void;
48
+ readonly revert: () => void;
49
+ readonly submit: Atom.AtomResultFn<void, A, E | ER | FieldFailure | Invalid>;
50
+ readonly submitting: Atom.Atom<boolean>;
51
+ readonly values: AtomRef.AtomRef<Encoded<F>>;
52
+ }
53
+ export type Holder = AtomRef.AtomRef<Readonly<Record<string, unknown>>>;
54
+ export declare function holder(values: object): Holder;
55
+ export declare function fieldOf<Value>(ref: AtomRef.AtomRef<unknown>): AtomRef.AtomRef<Value>;
56
+ export declare function choicesOf<Value>(choices: readonly unknown[] | undefined): readonly Value[] | undefined;
57
+ export declare function checkOf<R>(check: unknown): (value: unknown) => Effect.Effect<string | undefined, never, R>;
58
+ export {};
59
+ //# sourceMappingURL=shape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"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"}
package/dist/shape.js ADDED
@@ -0,0 +1,18 @@
1
+ import { Data } from "effect";
2
+ export class FieldFailure extends Data.TaggedError("FieldFailure") {
3
+ }
4
+ export class Invalid extends Data.TaggedError("Invalid") {
5
+ }
6
+ export function holder(values) {
7
+ return values;
8
+ }
9
+ export function fieldOf(ref) {
10
+ return ref;
11
+ }
12
+ export function choicesOf(choices) {
13
+ return choices;
14
+ }
15
+ export function checkOf(check) {
16
+ return check;
17
+ }
18
+ //# sourceMappingURL=shape.js.map