vultus-core 0.5.3 → 0.5.4

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/README.md CHANGED
@@ -31,7 +31,8 @@ npm install vultus-core
31
31
  `initialValueOf`, `valueTypeOf`, `sanitizeStored`); the argument layer
32
32
  (the value types, `memoryStore`, `localStorageStore`, `ArgStoreProvider` /
33
33
  `useArgStore`, `useArg`, `useArgWriter`, `setArg` / `resetArg`, `argOf`,
34
- `useStoredField` / `useStoredFields`); `InternalLinkContext` /
34
+ `useStoredField` / `useStoredFields`); field groups (`useFieldGroup` and
35
+ its `FieldGroup` type); `InternalLinkContext` /
35
36
  `useInternalLink` / `InternalLinkComponent`, `MessageSinkContext` /
36
37
  `useMessageSink` / `MessageSink`, and `VultusComponentsContext` /
37
38
  `useVultusComponents` / `SpinnerScope` / `useSpinnerKey` /
@@ -466,6 +467,121 @@ function Category() {
466
467
  }
467
468
  ```
468
469
 
470
+ ## Field groups
471
+
472
+ A field's options sometimes depend on another field's value: a print dialog offers some paper
473
+ sizes only for one layout, a filter shows a sub-filter only when another is on. With hooks, an
474
+ option takes a value computed from the other field's controls. Definitions as data say it
475
+ through the field context: `useFieldGroup(definitions)` runs a list of definitions together, and
476
+ every option function of each one receives `ctx.values`, the group's values by field id.
477
+
478
+ ```tsx
479
+ const printOptions: FieldDefinition[] = [
480
+ { kind: 'oneOf', id: 'layout', choices: [{ value: 'rendered' }, { value: 'original' }] },
481
+ { kind: 'oneOf', id: 'paper', choices: (ctx) => (ctx.values.layout === 'rendered' ? A_SIZES : ALL_SIZES) },
482
+ { kind: 'numeric', id: 'copies', min: 1, visible: (ctx) => ctx.values.layout === 'original' },
483
+ ];
484
+
485
+ function PrintDialog() {
486
+ const group = useFieldGroup(printOptions);
487
+ return <>{group.fields.map((f) => <FieldWidget key={f.id} field={f} item />)}</>;
488
+ }
489
+ ```
490
+
491
+ It returns `fields`, each field's controls exactly as its kind's hook returns them, in definition
492
+ order; `byId`, the same controls by id; `values`, the shown values by id as of this render (a
493
+ plain object, which keeps its identity until a shown value changes, so an effect keyed on it runs
494
+ only then); `isDefault(id)` (an id not in the group throws), `changedCount` and `resetAll()`
495
+ ("more filters (3)", "clear all"). The controls are typed `FieldControls`, which every widget
496
+ takes; for a kind's own controls (a tree's `nodes`, numeric's `format`), cast by kind:
497
+ `group.byId.toc as OneOfTreeFieldControls<string>`.
498
+
499
+ **References.** Every option function of a group's definition receives `ctx.values` (`label`,
500
+ `description`, `placeholder`, `visible` / `hidden`, `enabled` / `disabled`, `choices`, a tree's
501
+ `nodes`, `min` / `max`, numeric's `format(n, ctx)`, ...), beside the keys of the app's own field
502
+ context (the nearest `FieldContextProvider`), which keep working. A function the controls keep
503
+ and call later (`format`, through `field.format(n)`) sees the group's values too. `initialValue`
504
+ cannot read them. In a plain `FieldDefinition` the context is untyped (`any`); an app wanting
505
+ `ctx.values` typed declares `values` in its context type (`FieldDefinition<Ctx>`,
506
+ `createFieldContext<Ctx>()`).
507
+
508
+ **The fallback rule.** A field's shown value is its kept value checked as a stored value is
509
+ (`sanitizeStored`), with its options evaluated in the group's context. A value that another
510
+ field's change made invalid (a paper size the layout no longer offers) shows the field's
511
+ fallback, and the other fields see that fallback. Nothing is rewritten: the kept value shows
512
+ again once it is valid again (the layout back). A hidden field keeps its value, and the others
513
+ still see it.
514
+
515
+ **Defaults follow the options.** A field's default is its `initialValue`, else its kind's
516
+ implicit initial value from its options as they are now (the first enabled choice of its current
517
+ `choices`, a tree's first choosable node, `min`, ...), so it moves with the fields those options
518
+ read. A field never set, or set to its current default, keeps nothing and shows its current
519
+ default as it moves. `isDefault(id)` is useStoredFields' rule: nothing kept, or the kept value or
520
+ the value shown equals the current default.
521
+
522
+ **Errors.** These fail loudly, naming the field and the option where there is one:
523
+
524
+ - an option reading an id not in the group: `Field 'paper': option 'choices': no field 'layot'
525
+ in the group (fields: layout, paper, copies)`;
526
+ - reading `ctx.values` outside a group, with a `FieldContextProvider` above: `... ctx.values is
527
+ only available inside a field group`; with none, a function declaring `ctx` gets the existing
528
+ `... is a function of the field context, but no FieldContextProvider is above it`;
529
+ - `initialValue` reading `ctx.values`: `... initialValue cannot read other fields' values`;
530
+ - fields whose values depend on each other (A's choices read B, and B's read A): `Fields 'a' ->
531
+ 'b' -> 'a' depend on each other's values`. Options that never affect a value (`visible`,
532
+ `enabled`, `label`, `unit`, `format`, ...) cannot form a cycle;
533
+ - two definitions with the same id; a mixed-boolean definition (it shows an aggregate of other
534
+ data, not a value of its own); an app field context that already has `values` (the group
535
+ would shadow it);
536
+ - a list of another shape than the first render's. The hooks run per field, so the ids and kinds
537
+ stay the same, in the same order: to swap lists, remount the component running the group with
538
+ a React `key`. The definitions' contents may change, and new objects of the same shape on
539
+ every render (inline literals) are fine.
540
+
541
+ **Storage**, for the whole group, is the runner's choice. By default the group keeps the values
542
+ in its own state, as a store keeps them: a field without a kept value shows its current default,
543
+ and a value set equal to it is not kept. A fallback is silent here, as it is the designed
544
+ behaviour, not bad input. `resetAll()` clears every kept value.
545
+
546
+ With `useFieldGroup(definitions, { stored: true })` the values live in the nearest `ArgStore`
547
+ (the URL through vultus-react-router's `<ReactRouterArgStore>`, or localStorage) under each
548
+ field's id, as `useStoredField` keeps a single field there, all read in one store subscription:
549
+
550
+ ```tsx
551
+ const filters: FieldDefinition[] = [
552
+ { kind: 'text', id: 'search' },
553
+ { kind: 'oneOfTree', id: 'toc', optional: true, nodes: CHAPTERS, widget: 'list', visible: (ctx) => ctx.values.search === '' },
554
+ ];
555
+
556
+ function Filters() {
557
+ const group = useFieldGroup(filters, { stored: true }); // ?search=...&toc=...
558
+ return <>{group.fields.map((f) => <FieldWidget key={f.id} field={f} />)}</>;
559
+ }
560
+ ```
561
+
562
+ An absent key reads as the field's current default, and a value equal to it is written as an
563
+ absent key (with `'replace'`). The default compared with is the one under the store's values at
564
+ the moment of the write (a store reads its own writes back at once), so, as in the group's own
565
+ state, `layout.setValue('original'); paper.setValue('a4')` in one handler keeps `a4` even where
566
+ `a4` was paper's default under the old layout. Each field's `hrefFor` links a value through the
567
+ store, as rendered (`undefined` where the store has no links). The fallback rule is the same,
568
+ and the stored value is never rewritten (the search above hides `toc`; `?toc=` stays). A stored
569
+ raw value that does not parse, or does not fit its field, warns once, in the render that first
570
+ reads it, as `useStoredField`'s does; one that does not parse reads as the current default. A
571
+ value that another field's change makes fall back later does not warn: that is how a group
572
+ behaves, not bad input. Nor does a raw value the group itself wrote:
573
+ `layout.setValue('rendered'); paper.setValue('letter')` in one handler (Letter offered under the
574
+ original layout) stores `letter`, which falls back at once; the warnings are for raw values from
575
+ elsewhere (the URL, another tab). `resetAll(method = 'replace')` removes every field's key in one store
576
+ write (one history entry). Switching between the two storages is a change of shape: it throws
577
+ (remount with a React `key`).
578
+
579
+ **Rendering.** vultus-antd's `<FieldWidget>` renders the controls (by the definition's `widget`
580
+ hint; `item` for a labelled form item), in order as above or by id
581
+ (`<FieldWidget field={group.byId.paper} />`). A request goes through the kind's own checks (a
582
+ paper size the layout does not offer is refused with a warning, as the kind's hook alone refuses
583
+ it). The group then keeps the value and re-renders, so every option is computed again.
584
+
469
585
  ## Components
470
586
 
471
587
  `VultusComponentsContext` (default `{}`) / `useVultusComponents()` is how an app lends its own
@@ -6,6 +6,22 @@ import { type JSX, type ReactNode } from 'react';
6
6
  export declare const NO_FIELD_CONTEXT: unique symbol;
7
7
  /** The field context as the hooks hold it: the guarded value, or the mark that there is none. */
8
8
  export type FieldCtx = object | typeof NO_FIELD_CONTEXT;
9
+ /**
10
+ * What the guard throws for a key no provider gave, so readingContext can tell it from the
11
+ * function's own errors. Exported for the field group (fieldGroupValues), whose own reads that
12
+ * fail (an id not in the group, `values` read from `initialValue`) get the field and option in
13
+ * front the same way; not part of the package's API.
14
+ */
15
+ export declare class MissingKeyError extends Error {
16
+ }
17
+ /**
18
+ * `raw` guarded against reading a key it lacks: such a read throws a MissingKeyError with
19
+ * `missing(key)` as its message, which readingContext puts the field and the option in front
20
+ * of. `has` says whether `raw` has the key; by default inherited members (`toString`) count,
21
+ * and `Object.hasOwn` makes them missing too. Probes and symbol keys read as usual. Exported for
22
+ * the field group's `values` (an id not in the group); not part of the package's API.
23
+ */
24
+ export declare function guardKeys(raw: object, missing: (key: string) => string, has?: (target: object, key: string) => boolean): object;
9
25
  /**
10
26
  * Runs `read`, a call of a definition's function with the field context. A key it reads that
11
27
  * no provider gave throws with `where` (`Field '<id>': option '<name>'`) in front of the
@@ -33,6 +49,26 @@ export declare function createFieldContext<Ctx extends object>(): {
33
49
  children?: ReactNode;
34
50
  }) => JSX.Element;
35
51
  };
36
- /** The field context the hooks resolve functions with: the guarded value, or NO_FIELD_CONTEXT. */
52
+ /**
53
+ * A field context with `base`'s keys (none for NO_FIELD_CONTEXT) and `extra`'s, guarded as a
54
+ * provider's value is: how a field group gives its fields' functions `values` beside the app's
55
+ * own keys. `extra`'s properties are copied as defined, so a getter among them runs when its
56
+ * key is read, not here. A key of `extra` that `base` already has throws, `where` in front,
57
+ * instead of shadowing the app's value; every key the copy takes is checked (non-enumerable
58
+ * and symbol keys too).
59
+ */
60
+ export declare function extendFieldContext(base: FieldCtx, extra: Record<string, unknown>, where: string): object;
61
+ /**
62
+ * Runs `run` with `ctx` as the field context: a hook it calls gets `ctx` from useFieldContext
63
+ * instead of the providers' value. It is for a hook that calls other hooks in its own render,
64
+ * each with its own context (a field group runs each field's kind hook with the group's); the
65
+ * components rendered below do not see it. `run` must be synchronous: the previous context
66
+ * comes back when it returns or throws. Calls nest.
67
+ */
68
+ export declare function withFieldContext<T>(ctx: FieldCtx, run: () => T): T;
69
+ /**
70
+ * The field context the hooks resolve functions with: the one withFieldContext gives while it
71
+ * runs, else the providers' guarded value, or NO_FIELD_CONTEXT.
72
+ */
37
73
  export declare function useFieldContext(): FieldCtx;
38
74
  //# sourceMappingURL=FieldContext.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FieldContext.d.ts","sourceRoot":"","sources":["../src/FieldContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAErF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,OAAO,MAAwC,CAAC;AAE/E,iGAAiG;AACjG,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,gBAAgB,CAAC;AA2CxD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAOjE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,eAShG;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,SAAS,MAAM,KAAK;IACxD,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;KAAE,KAAK,GAAG,CAAC,OAAO,CAAC;CACjF,CAEA;AAED,kGAAkG;AAClG,wBAAgB,eAAe,IAAI,QAAQ,CAE1C"}
1
+ {"version":3,"file":"FieldContext.d.ts","sourceRoot":"","sources":["../src/FieldContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAErF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,OAAO,MAAwC,CAAC;AAE/E,iGAAiG;AACjG,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,gBAAgB,CAAC;AAwBxD;;;;;GAKG;AACH,qBAAa,eAAgB,SAAQ,KAAK;CAAG;AAE7C;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,EAChC,GAAG,GAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAwC,GAC7E,MAAM,CAOR;AAcD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAOjE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,eAShG;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,SAAS,MAAM,KAAK;IACxD,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;KAAE,KAAK,GAAG,CAAC,OAAO,CAAC;CACjF,CAEA;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMxG;AAKD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAQlE;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,QAAQ,CAI1C"}
@@ -18,24 +18,41 @@ const PROBED_KEYS = new Set([
18
18
  function isProbe(key) {
19
19
  return PROBED_KEYS.has(key) || key.startsWith('@@');
20
20
  }
21
- /** What the guard throws for a key no provider gave, so readingContext can tell it from the function's own errors. */
22
- class MissingKeyError extends Error {
21
+ /**
22
+ * What the guard throws for a key no provider gave, so readingContext can tell it from the
23
+ * function's own errors. Exported for the field group (fieldGroupValues), whose own reads that
24
+ * fail (an id not in the group, `values` read from `initialValue`) get the field and option in
25
+ * front the same way; not part of the package's API.
26
+ */
27
+ export class MissingKeyError extends Error {
23
28
  }
24
29
  /**
25
- * The context value as the definitions' functions receive it: reading a key that no provider
26
- * gave throws, naming it and the keys present, so a forgotten value fails loudly instead of
27
- * passing `undefined` along. A key provided with the value `undefined` is fine.
30
+ * `raw` guarded against reading a key it lacks: such a read throws a MissingKeyError with
31
+ * `missing(key)` as its message, which readingContext puts the field and the option in front
32
+ * of. `has` says whether `raw` has the key; by default inherited members (`toString`) count,
33
+ * and `Object.hasOwn` makes them missing too. Probes and symbol keys read as usual. Exported for
34
+ * the field group's `values` (an id not in the group); not part of the package's API.
28
35
  */
29
- function guard(raw) {
36
+ export function guardKeys(raw, missing, has = (target, key) => key in target) {
30
37
  return new Proxy(raw, {
31
38
  get(target, key, receiver) {
32
- if (typeof key === 'string' && !isProbe(key) && !(key in target)) {
33
- throw new MissingKeyError(`Field context: '${key}' was never provided (provided: ${Object.keys(target).join(', ')})`);
34
- }
39
+ if (typeof key === 'string' && !isProbe(key) && !has(target, key))
40
+ throw new MissingKeyError(missing(key));
35
41
  return Reflect.get(target, key, receiver);
36
42
  },
37
43
  });
38
44
  }
45
+ /**
46
+ * The context value as the definitions' functions receive it: reading a key that no provider
47
+ * gave throws, naming it and the keys present, so a forgotten value fails loudly instead of
48
+ * passing `undefined` along. A key provided with the value `undefined` is fine. `values` is the
49
+ * key a field group adds (extendFieldContext), so reading it from any other context says so.
50
+ */
51
+ function guard(raw) {
52
+ return guardKeys(raw, (key) => (key === 'values'
53
+ ? 'ctx.values is only available inside a field group'
54
+ : `Field context: '${key}' was never provided (provided: ${Object.keys(raw).join(', ')})`));
55
+ }
39
56
  /**
40
57
  * Runs `read`, a call of a definition's function with the field context. A key it reads that
41
58
  * no provider gave throws with `where` (`Field '<id>': option '<name>'`) in front of the
@@ -75,8 +92,48 @@ export function FieldContextProvider({ value, children }) {
75
92
  export function createFieldContext() {
76
93
  return { Provider: FieldContextProvider };
77
94
  }
78
- /** The field context the hooks resolve functions with: the guarded value, or NO_FIELD_CONTEXT. */
95
+ /**
96
+ * A field context with `base`'s keys (none for NO_FIELD_CONTEXT) and `extra`'s, guarded as a
97
+ * provider's value is: how a field group gives its fields' functions `values` beside the app's
98
+ * own keys. `extra`'s properties are copied as defined, so a getter among them runs when its
99
+ * key is read, not here. A key of `extra` that `base` already has throws, `where` in front,
100
+ * instead of shadowing the app's value; every key the copy takes is checked (non-enumerable
101
+ * and symbol keys too).
102
+ */
103
+ export function extendFieldContext(base, extra, where) {
104
+ const raw = base === NO_FIELD_CONTEXT ? {} : { ...base };
105
+ for (const key of Reflect.ownKeys(extra)) {
106
+ if (Object.hasOwn(raw, key))
107
+ throw new Error(`${where}: the field context already has '${String(key)}'; a field group provides it`);
108
+ }
109
+ return guard(Object.defineProperties(raw, Object.getOwnPropertyDescriptors(extra)));
110
+ }
111
+ /** The context withFieldContext gives the hooks it is running, if any. */
112
+ let override;
113
+ /**
114
+ * Runs `run` with `ctx` as the field context: a hook it calls gets `ctx` from useFieldContext
115
+ * instead of the providers' value. It is for a hook that calls other hooks in its own render,
116
+ * each with its own context (a field group runs each field's kind hook with the group's); the
117
+ * components rendered below do not see it. `run` must be synchronous: the previous context
118
+ * comes back when it returns or throws. Calls nest.
119
+ */
120
+ export function withFieldContext(ctx, run) {
121
+ const previous = override;
122
+ override = ctx;
123
+ try {
124
+ return run();
125
+ }
126
+ finally {
127
+ override = previous;
128
+ }
129
+ }
130
+ /**
131
+ * The field context the hooks resolve functions with: the one withFieldContext gives while it
132
+ * runs, else the providers' guarded value, or NO_FIELD_CONTEXT.
133
+ */
79
134
  export function useFieldContext() {
80
- return useContext(FieldContext)?.guarded ?? NO_FIELD_CONTEXT;
135
+ // Called under an override too, so that the hooks' order never depends on one.
136
+ const provided = useContext(FieldContext);
137
+ return override ?? provided?.guarded ?? NO_FIELD_CONTEXT;
81
138
  }
82
139
  //# sourceMappingURL=FieldContext.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FieldContext.js","sourceRoot":"","sources":["../src/FieldContext.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAA4B,MAAM,OAAO,CAAC;AAErF;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAkB,MAAM,CAAC,uBAAuB,CAAC,CAAC;AAW/E,MAAM,YAAY,GAAG,aAAa,CAAuB,SAAS,CAAC,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,MAAM,EAAE,QAAQ,EAAE,iBAAiB,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,iBAAiB;CAC1G,CAAC,CAAC;AAEH,SAAS,OAAO,CAAC,GAAW;IAC1B,OAAO,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACtD,CAAC;AAED,sHAAsH;AACtH,MAAM,eAAgB,SAAQ,KAAK;CAAG;AAEtC;;;;GAIG;AACH,SAAS,KAAK,CAAC,GAAW;IACxB,OAAO,IAAI,KAAK,CAAC,GAAG,EAAE;QACpB,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ;YACvB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,EAAE,CAAC;gBACjE,MAAM,IAAI,eAAe,CAAC,mBAAmB,GAAG,mCAAmC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACxH,CAAC;YACD,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC5C,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAI,KAAa,EAAE,IAAa;IAC5D,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,eAAe;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACtG,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAA2C;IAC/F,MAAM,KAAK,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IACvC,4FAA4F;IAC5F,8FAA8F;IAC9F,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE;QAC5B,MAAM,GAAG,GAAG,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;QACxC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IACtC,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IACnB,OAAO,KAAC,YAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,QAAQ,YAAG,QAAQ,GAAyB,CAAC;AACpF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB;IAGhC,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,CAAC;AAC5C,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,eAAe;IAC7B,OAAO,UAAU,CAAC,YAAY,CAAC,EAAE,OAAO,IAAI,gBAAgB,CAAC;AAC/D,CAAC"}
1
+ {"version":3,"file":"FieldContext.js","sourceRoot":"","sources":["../src/FieldContext.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import { type FieldCtx } from './FieldContext.js';
2
+ import { type FieldDefinition } from './kinds.js';
3
+ /**
4
+ * One render's values of a field group (see useFieldGroup): each field's shown value and
5
+ * default, computed on demand by id from the kept values, with the definitions' options
6
+ * evaluated in the group's context, and each computed once.
7
+ */
8
+ export interface GroupValues {
9
+ /**
10
+ * The field context the group's option functions receive: the app's own keys (guarded as a
11
+ * provider's value is) and `values`, the fields' shown values by id.
12
+ */
13
+ ctx: object;
14
+ /**
15
+ * A field's shown value: its kept value, else its current default, made fit for its options
16
+ * as they are now (sanitizeStored); one that no longer fits shows the field's fallback. The
17
+ * kept value itself is never touched, so it shows again once it fits again.
18
+ */
19
+ valueOf(id: string): unknown;
20
+ /**
21
+ * A field's default: its `initialValue` (which cannot read `values`), else its kind's
22
+ * implicit initial value from its options as they are now (the first enabled choice, `min`,
23
+ * ...), so it moves with the fields those options read.
24
+ */
25
+ defaultOf(id: string): unknown;
26
+ /** The shown values by id, each computed when first read; `ctx.values` is the same object. */
27
+ values: Readonly<Record<string, unknown>>;
28
+ }
29
+ /** What createGroupValues computes the values from. */
30
+ export interface GroupValuesParams {
31
+ /** The group's fields, as data: unique ids, no mixed-boolean. */
32
+ definitions: readonly FieldDefinition[];
33
+ /** The app's field context (useFieldContext), which `values` is added to. */
34
+ appCtx: FieldCtx;
35
+ /** A field's kept value; `undefined` when none is kept, so the field shows its current default. */
36
+ kept(id: string): unknown | undefined;
37
+ /**
38
+ * Where a kept value's sanitizing warnings go, with the field's id: the caller decides whether
39
+ * to show them (and how often). A default made fit is the definer's, not kept input, so it
40
+ * never warns.
41
+ */
42
+ warn(id: string, message: string): void;
43
+ }
44
+ /**
45
+ * The values of a field group for one render, computed from its definitions and kept values.
46
+ *
47
+ * Every option function of the definitions receives `ctx`: the app's field context and
48
+ * `values`, the fields' shown values by id. A field's value is computed when an option (or the
49
+ * caller) first reads it, and kept for the rest of this snapshot; a new render makes a new one.
50
+ * The shown value is the kept value (else the current default) checked against the field's
51
+ * options as they are now, as a store's value is (sanitizeStored); one that no longer fits
52
+ * shows the fallback, which the other fields see too.
53
+ *
54
+ * Throws here for two definitions with the same id and for a mixed-boolean definition (naming
55
+ * the field), and for an app context that already has `values`. Throws when read, naming the
56
+ * field and the option, for an option reading an id not in the group and for `initialValue`
57
+ * reading `values`. Fields whose values depend on each other throw when read, naming the cycle
58
+ * (`Fields 'a' -> 'b' -> 'a' depend on each other's values`): a field's value and default are in
59
+ * progress while its options run, and reading one in progress is a cycle. Options that never
60
+ * affect a value (`visible`, `label`, `unit`, ...) are not run here, so they cannot form one.
61
+ */
62
+ export declare function createGroupValues({ definitions, appCtx, kept, warn }: GroupValuesParams): GroupValues;
63
+ //# sourceMappingURL=fieldGroupValues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldGroupValues.d.ts","sourceRoot":"","sources":["../src/fieldGroupValues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClG,OAAO,EAAkC,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAElF;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,8FAA8F;IAC9F,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC3C;AAED,uDAAuD;AACvD,MAAM,WAAW,iBAAiB;IAChC,iEAAiE;IACjE,WAAW,EAAE,SAAS,eAAe,EAAE,CAAC;IACxC,6EAA6E;IAC7E,MAAM,EAAE,QAAQ,CAAC;IACjB,mGAAmG;IACnG,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IACtC;;;;OAIG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AA8BD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,iBAAiB,GAAG,WAAW,CA4ErG"}
@@ -0,0 +1,119 @@
1
+ import { extendFieldContext, guardKeys, MissingKeyError } from './FieldContext.js';
2
+ import { initialValueOf, sanitizeStored } from './kinds.js';
3
+ const WHERE = 'Field group';
4
+ const INITIAL_VALUE_READS_VALUES = "initialValue cannot read other fields' values";
5
+ const NOT_IN_A_GROUP = 'a mixed-boolean field shows an aggregate of other data, not a value of its own, so it cannot be in a field group';
6
+ function silently(_message) { }
7
+ /**
8
+ * A definition as its values are computed from it. Its `initialValue` function receives
9
+ * `initialCtx`, whose `values` throws: a default cannot depend on other fields' values. A
10
+ * number's or range's display options (`step`, `unit`, `format`) are left out, because resolving
11
+ * its bounds (resolveNumeric) resolves them too, and an option that never affects the value
12
+ * (`unit: (ctx) => ctx.values.copies === 1 ? ...`) must not count as a dependency, nor form a
13
+ * cycle.
14
+ */
15
+ function forComputingValues(definition, initialCtx) {
16
+ const computing = { ...definition };
17
+ const { initialValue } = definition;
18
+ if (typeof initialValue === 'function') {
19
+ Object.assign(computing, { initialValue: () => initialValue(initialCtx) });
20
+ }
21
+ if (computing.kind === 'numeric' || computing.kind === 'range') {
22
+ delete computing.step;
23
+ delete computing.unit;
24
+ delete computing.format;
25
+ }
26
+ return computing;
27
+ }
28
+ /**
29
+ * The values of a field group for one render, computed from its definitions and kept values.
30
+ *
31
+ * Every option function of the definitions receives `ctx`: the app's field context and
32
+ * `values`, the fields' shown values by id. A field's value is computed when an option (or the
33
+ * caller) first reads it, and kept for the rest of this snapshot; a new render makes a new one.
34
+ * The shown value is the kept value (else the current default) checked against the field's
35
+ * options as they are now, as a store's value is (sanitizeStored); one that no longer fits
36
+ * shows the fallback, which the other fields see too.
37
+ *
38
+ * Throws here for two definitions with the same id and for a mixed-boolean definition (naming
39
+ * the field), and for an app context that already has `values`. Throws when read, naming the
40
+ * field and the option, for an option reading an id not in the group and for `initialValue`
41
+ * reading `values`. Fields whose values depend on each other throw when read, naming the cycle
42
+ * (`Fields 'a' -> 'b' -> 'a' depend on each other's values`): a field's value and default are in
43
+ * progress while its options run, and reading one in progress is a cycle. Options that never
44
+ * affect a value (`visible`, `label`, `unit`, ...) are not run here, so they cannot form one.
45
+ */
46
+ export function createGroupValues({ definitions, appCtx, kept, warn }) {
47
+ const ids = definitions.map((definition) => definition.id);
48
+ for (const definition of definitions) {
49
+ if (ids.indexOf(definition.id) !== ids.lastIndexOf(definition.id)) {
50
+ throw new Error(`Field '${definition.id}': another field in the group has the same id`);
51
+ }
52
+ if (definition.kind === 'mixed-boolean')
53
+ throw new Error(`Field '${definition.id}': ${NOT_IN_A_GROUP}`);
54
+ }
55
+ const noField = (id) => `no field '${id}' in the group (fields: ${ids.join(', ')})`;
56
+ const getters = {};
57
+ for (const id of ids)
58
+ Object.defineProperty(getters, id, { get: () => valueOf(id), enumerable: true });
59
+ // Own keys only: `values.toString` is a typo for an id, not Object's member. `constructor`
60
+ // reads as usual, as the probes do, because printers (vitest's) name an object by it.
61
+ const values = guardKeys(getters, noField, (target, key) => key === 'constructor' || Object.hasOwn(target, key));
62
+ const ctx = extendFieldContext(appCtx, { values }, WHERE);
63
+ // `values` not enumerable: a missing key's message lists the keys provided, and this one only throws.
64
+ const initialCtx = extendFieldContext(appCtx, Object.defineProperty({}, 'values', {
65
+ get() {
66
+ throw new MissingKeyError(INITIAL_VALUE_READS_VALUES);
67
+ },
68
+ }), WHERE);
69
+ const computingDefinitions = new Map(definitions.map((definition) => [definition.id, forComputingValues(definition, initialCtx)]));
70
+ const shown = new Map();
71
+ const defaults = new Map();
72
+ /** The fields whose value or default is being computed, outermost first. */
73
+ const inProgress = [];
74
+ function definitionOf(id) {
75
+ const definition = computingDefinitions.get(id);
76
+ if (definition === undefined)
77
+ throw new MissingKeyError(noField(id));
78
+ return definition;
79
+ }
80
+ /** Runs `compute` with `id` in progress; reading `id` again before it returns is a cycle. */
81
+ function computing(id, compute) {
82
+ const at = inProgress.indexOf(id);
83
+ if (at !== -1) {
84
+ const cycle = [...inProgress.slice(at), id].map((each) => `'${each}'`).join(' -> ');
85
+ throw new Error(`Fields ${cycle} depend on each other's values`);
86
+ }
87
+ inProgress.push(id);
88
+ try {
89
+ return compute();
90
+ }
91
+ finally {
92
+ inProgress.pop();
93
+ }
94
+ }
95
+ /** The default, computed as part of `id`'s own value or default (already in progress). */
96
+ function ownDefault(id) {
97
+ if (!defaults.has(id))
98
+ defaults.set(id, initialValueOf(definitionOf(id), ctx));
99
+ return defaults.get(id);
100
+ }
101
+ function defaultOf(id) {
102
+ definitionOf(id);
103
+ return defaults.has(id) ? defaults.get(id) : computing(id, () => ownDefault(id));
104
+ }
105
+ function valueOf(id) {
106
+ const definition = definitionOf(id);
107
+ if (!shown.has(id)) {
108
+ shown.set(id, computing(id, () => {
109
+ const value = kept(id);
110
+ return value === undefined
111
+ ? sanitizeStored(definition, ownDefault(id), ctx, silently)
112
+ : sanitizeStored(definition, value, ctx, (message) => warn(id, message));
113
+ }));
114
+ }
115
+ return shown.get(id);
116
+ }
117
+ return { ctx, valueOf, defaultOf, values };
118
+ }
119
+ //# sourceMappingURL=fieldGroupValues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldGroupValues.js","sourceRoot":"","sources":["../src/fieldGroupValues.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -28,6 +28,7 @@ export { localStorageStore } from './localStorageStore.js';
28
28
  export { ArgStoreProvider, useArgStore } from './ArgStoreContext.js';
29
29
  export { useArg, useArgWriter, setArg, resetArg, type ArgDefinition, type ArgControls, type ArgChange, } from './useArg.js';
30
30
  export { argOf, useStoredField, useStoredFields, type StoredField, type StoredFields, } from './useStoredField.js';
31
+ export { useFieldGroup, type FieldGroup } from './useFieldGroup.js';
31
32
  export { InternalLinkContext, useInternalLink, type InternalLinkComponent } from './LinkContext.js';
32
33
  export { MessageSinkContext, useMessageSink, type MessageSink } from './MessageSink.js';
33
34
  export { VultusComponentsContext, useVultusComponents, SpinnerScope, useSpinnerKey, type VultusComponents, type SpinnerProps, type SpinnerComponent, } from './Components.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -27,6 +27,7 @@ export { localStorageStore } from './localStorageStore.js';
27
27
  export { ArgStoreProvider, useArgStore } from './ArgStoreContext.js';
28
28
  export { useArg, useArgWriter, setArg, resetArg, } from './useArg.js';
29
29
  export { argOf, useStoredField, useStoredFields, } from './useStoredField.js';
30
+ export { useFieldGroup } from './useFieldGroup.js';
30
31
  export { InternalLinkContext, useInternalLink } from './LinkContext.js';
31
32
  export { MessageSinkContext, useMessageSink } from './MessageSink.js';
32
33
  export { VultusComponentsContext, useVultusComponents, SpinnerScope, useSpinnerKey, } from './Components.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,oBAAoB,EAAE,kBAAkB,EAAE,eAAe,EAAE,gBAAgB,GAC5E,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,GAGnE,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAA8C,MAAM,cAAc,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAiD,MAAM,mBAAmB,CAAC;AAClH,OAAO,EACL,iBAAiB,EAAE,aAAa,EAAE,qBAAqB,GAExD,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,aAAa,EAAE,iBAAiB,GACjC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,cAAc,EAAE,kBAAkB,GAEnC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,cAAc,EAA4C,MAAM,cAAc,CAAC;AAC/F,OAAO,EACL,eAAe,EAAE,mBAAmB,GAErC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,aAAa,EAAE,iBAAiB,GAEjC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,UAAU,EAC/E,aAAa,EAAE,eAAe,EAAE,QAAQ,GAEzC,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,kBAAkB,EAAE,sBAAsB,GAE3C,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,iBAAiB,EAAE,qBAAqB,GAEzC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,YAAY,EAAE,gBAAgB,GAE/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,GAC9D,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAwB,MAAM,YAAY,CAAC;AAC/F,OAAO,EAAE,WAAW,EAAoD,MAAM,eAAe,CAAC;AAC9F,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EACL,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,GAEvC,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,EAAE,cAAc,EAAE,eAAe,GACvC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAA8B,MAAM,kBAAkB,CAAC;AACpG,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAoB,MAAM,kBAAkB,CAAC;AACxF,OAAO,EACL,uBAAuB,EAAE,mBAAmB,EAAE,YAAY,EAAE,aAAa,GAE1E,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,oBAAoB,EAAE,kBAAkB,EAAE,eAAe,EAAE,gBAAgB,GAC5E,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,GAGnE,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAA8C,MAAM,cAAc,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAiD,MAAM,mBAAmB,CAAC;AAClH,OAAO,EACL,iBAAiB,EAAE,aAAa,EAAE,qBAAqB,GAExD,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,aAAa,EAAE,iBAAiB,GACjC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,cAAc,EAAE,kBAAkB,GAEnC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,cAAc,EAA4C,MAAM,cAAc,CAAC;AAC/F,OAAO,EACL,eAAe,EAAE,mBAAmB,GAErC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,aAAa,EAAE,iBAAiB,GAEjC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,UAAU,EAC/E,aAAa,EAAE,eAAe,EAAE,QAAQ,GAEzC,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,kBAAkB,EAAE,sBAAsB,GAE3C,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,iBAAiB,EAAE,qBAAqB,GAEzC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,YAAY,EAAE,gBAAgB,GAE/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,GAC9D,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAwB,MAAM,YAAY,CAAC;AAC/F,OAAO,EAAE,WAAW,EAAoD,MAAM,eAAe,CAAC;AAC9F,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EACL,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,GAEvC,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,EAAE,cAAc,EAAE,eAAe,GACvC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAmB,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAA8B,MAAM,kBAAkB,CAAC;AACpG,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAoB,MAAM,kBAAkB,CAAC;AACxF,OAAO,EACL,uBAAuB,EAAE,mBAAmB,EAAE,YAAY,EAAE,aAAa,GAE1E,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { FieldControls } from './field.js';
2
+ import type { FieldDefinition } from './kinds.js';
3
+ /**
4
+ * A definition in its outside form, as its kind's hook takes it: without `initialValue` (whoever
5
+ * keeps the value keeps its default too), with the value, its writer, and the link a value
6
+ * amounts to where whoever keeps it has one.
7
+ */
8
+ export type KindFieldOptions = OutsideForm<FieldDefinition>;
9
+ /** The outside form of a definition, member by member for a union (the conditional type distributes). */
10
+ type OutsideForm<D> = D extends FieldDefinition ? Omit<D, 'initialValue'> & {
11
+ value: unknown;
12
+ onChange(value: any): void;
13
+ hrefFor?(value: any): string | undefined;
14
+ } : never;
15
+ /**
16
+ * Runs the hook of `definition`'s kind with `options` and returns its controls, exactly as that
17
+ * hook returns them. The hook called depends on the kind, so a caller running several fields
18
+ * (useFieldGroup) keeps each field's kind the same across renders. A kind that is none of
19
+ * FieldKind's (plain data can carry anything) throws, naming the field.
20
+ */
21
+ export declare function useKindField(definition: FieldDefinition, options: KindFieldOptions): FieldControls<any, any>;
22
+ export {};
23
+ //# sourceMappingURL=kindHooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kindHooks.d.ts","sourceRoot":"","sources":["../src/kindHooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,YAAY,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAWlD;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC,eAAe,CAAC,CAAC;AAE5D,yGAAyG;AACzG,KAAK,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,eAAe,GAC3C,IAAI,CAAC,CAAC,EAAE,cAAc,CAAC,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI,CAAC;IAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,GAAG,SAAS,CAAA;CAAE,GAClH,KAAK,CAAC;AAkBV;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,eAAe,EAAE,OAAO,EAAE,gBAAgB,GAAG,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAK5G"}
@@ -0,0 +1,38 @@
1
+ import { useBoolField } from './useBoolField.js';
2
+ import { useManyOfField } from './useManyOfField.js';
3
+ import { useManyOfTreeField } from './useManyOfTreeField.js';
4
+ import { useMixedBoolField } from './useMixedBoolField.js';
5
+ import { useNumericField } from './useNumericField.js';
6
+ import { useOneOfField } from './useOneOfField.js';
7
+ import { useOneOfTreeField } from './useOneOfTreeField.js';
8
+ import { useRangeField } from './useRangeField.js';
9
+ import { useTextField } from './useTextField.js';
10
+ /**
11
+ * Each kind's hook. Its options are checked against the definition in kinds.ts
12
+ * (DefinitionsFitTheirHooks); the mapped type makes leaving a kind out a compile error.
13
+ */
14
+ const KIND_HOOKS = {
15
+ boolean: useBoolField,
16
+ 'mixed-boolean': useMixedBoolField,
17
+ oneOf: useOneOfField,
18
+ manyOf: useManyOfField,
19
+ numeric: useNumericField,
20
+ range: useRangeField,
21
+ manyOfTree: useManyOfTreeField,
22
+ oneOfTree: useOneOfTreeField,
23
+ text: useTextField,
24
+ };
25
+ /**
26
+ * Runs the hook of `definition`'s kind with `options` and returns its controls, exactly as that
27
+ * hook returns them. The hook called depends on the kind, so a caller running several fields
28
+ * (useFieldGroup) keeps each field's kind the same across renders. A kind that is none of
29
+ * FieldKind's (plain data can carry anything) throws, naming the field.
30
+ */
31
+ export function useKindField(definition, options) {
32
+ const { id, kind } = definition;
33
+ if (!Object.hasOwn(KIND_HOOKS, kind))
34
+ throw new Error(`Field '${id}': unknown kind '${String(kind)}'`);
35
+ const useHook = KIND_HOOKS[kind];
36
+ return useHook(options);
37
+ }
38
+ //# sourceMappingURL=kindHooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kindHooks.js","sourceRoot":"","sources":["../src/kindHooks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAcjD;;;GAGG;AACH,MAAM,UAAU,GAAoE;IAClF,OAAO,EAAE,YAAY;IACrB,eAAe,EAAE,iBAAiB;IAClC,KAAK,EAAE,aAAa;IACpB,MAAM,EAAE,cAAc;IACtB,OAAO,EAAE,eAAe;IACxB,KAAK,EAAE,aAAa;IACpB,UAAU,EAAE,kBAAkB;IAC9B,SAAS,EAAE,iBAAiB;IAC5B,IAAI,EAAE,YAAY;CACnB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,UAA2B,EAAE,OAAyB;IACjF,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC;IAChC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,UAAU,EAAE,oBAAoB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvG,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC"}