vultus-core 0.5.3 → 0.5.5
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 +121 -3
- package/dist/FieldContext.d.ts +37 -1
- package/dist/FieldContext.d.ts.map +1 -1
- package/dist/FieldContext.js +68 -11
- package/dist/FieldContext.js.map +1 -1
- package/dist/fieldGroupValues.d.ts +63 -0
- package/dist/fieldGroupValues.d.ts.map +1 -0
- package/dist/fieldGroupValues.js +119 -0
- package/dist/fieldGroupValues.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/kindHooks.d.ts +23 -0
- package/dist/kindHooks.d.ts.map +1 -0
- package/dist/kindHooks.js +38 -0
- package/dist/kindHooks.js.map +1 -0
- package/dist/tree.d.ts +5 -2
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +3 -3
- package/dist/tree.js.map +1 -1
- package/dist/useArg.d.ts +6 -0
- package/dist/useArg.d.ts.map +1 -1
- package/dist/useArg.js +6 -2
- package/dist/useArg.js.map +1 -1
- package/dist/useFieldGroup.d.ts +80 -0
- package/dist/useFieldGroup.d.ts.map +1 -0
- package/dist/useFieldGroup.js +266 -0
- package/dist/useFieldGroup.js.map +1 -0
- package/dist/useStoredField.d.ts +8 -0
- package/dist/useStoredField.d.ts.map +1 -1
- package/dist/useStoredField.js +4 -2
- package/dist/useStoredField.js.map +1 -1
- package/package.json +1 -1
- package/src/FieldContext.tsx +73 -11
- package/src/fieldGroupValues.ts +169 -0
- package/src/index.ts +1 -0
- package/src/kindHooks.ts +52 -0
- package/src/tree.ts +8 -5
- package/src/useArg.ts +6 -2
- package/src/useFieldGroup.ts +346 -0
- package/src/useStoredField.ts +4 -2
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`); `
|
|
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` /
|
|
@@ -221,7 +222,8 @@ their own, with no cascading). The hook normalizes the value under
|
|
|
221
222
|
`selection` on every render — with `'topmost'`, a node and all its checked
|
|
222
223
|
children collapse to the node alone — and exposes `expandedKeys` (which
|
|
223
224
|
nodes a widget opens at first, controlled by `expand`: `'top'` (default),
|
|
224
|
-
`'none'`, `'selected'`, `'all'
|
|
225
|
+
`'none'`, `'selected'`, `'all'`, or a list of node values: those with children,
|
|
226
|
+
and the value's ancestors) and `toggle(value)` (refused, with a
|
|
225
227
|
warning, for an unknown or disabled node, as many-of's does).
|
|
226
228
|
`coveredNodes(nodes, value, selection)` expands a value to every node it
|
|
227
229
|
stands for — what a module matches an item's categories against.
|
|
@@ -290,7 +292,8 @@ be chosen, e.g. a value naming a folder or a node a context change disabled, sti
|
|
|
290
292
|
neighbours; undefined at the ends, and with no `current`, `previous` undefined and `next` the
|
|
291
293
|
first choosable node), `optional`, `choose` and `expandedKeys`
|
|
292
294
|
(from `expand`, default `'selected'` — the value's ancestors, so a table of contents opens where
|
|
293
|
-
the reader is; `'top'`, `'none'
|
|
295
|
+
the reader is; `'top'`, `'none'`, `'all'` and a list as the many-of tree's: a list opens a
|
|
296
|
+
book's printed shape, its chapters open and its sections folded, the reader's place shown). The field's current state is
|
|
294
297
|
the chosen node's description, unless `valueDescriptions` words it differently (as `oneOf`).
|
|
295
298
|
Implicit initial value: `initialValue`, else `''` when `optional`, else the first node that can be
|
|
296
299
|
chosen in tree pre-order, else `''` (no node can be chosen; as `oneOf`'s undefined choice).
|
|
@@ -466,6 +469,121 @@ function Category() {
|
|
|
466
469
|
}
|
|
467
470
|
```
|
|
468
471
|
|
|
472
|
+
## Field groups
|
|
473
|
+
|
|
474
|
+
A field's options sometimes depend on another field's value: a print dialog offers some paper
|
|
475
|
+
sizes only for one layout, a filter shows a sub-filter only when another is on. With hooks, an
|
|
476
|
+
option takes a value computed from the other field's controls. Definitions as data say it
|
|
477
|
+
through the field context: `useFieldGroup(definitions)` runs a list of definitions together, and
|
|
478
|
+
every option function of each one receives `ctx.values`, the group's values by field id.
|
|
479
|
+
|
|
480
|
+
```tsx
|
|
481
|
+
const printOptions: FieldDefinition[] = [
|
|
482
|
+
{ kind: 'oneOf', id: 'layout', choices: [{ value: 'rendered' }, { value: 'original' }] },
|
|
483
|
+
{ kind: 'oneOf', id: 'paper', choices: (ctx) => (ctx.values.layout === 'rendered' ? A_SIZES : ALL_SIZES) },
|
|
484
|
+
{ kind: 'numeric', id: 'copies', min: 1, visible: (ctx) => ctx.values.layout === 'original' },
|
|
485
|
+
];
|
|
486
|
+
|
|
487
|
+
function PrintDialog() {
|
|
488
|
+
const group = useFieldGroup(printOptions);
|
|
489
|
+
return <>{group.fields.map((f) => <FieldWidget key={f.id} field={f} item />)}</>;
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
It returns `fields`, each field's controls exactly as its kind's hook returns them, in definition
|
|
494
|
+
order; `byId`, the same controls by id; `values`, the shown values by id as of this render (a
|
|
495
|
+
plain object, which keeps its identity until a shown value changes, so an effect keyed on it runs
|
|
496
|
+
only then); `isDefault(id)` (an id not in the group throws), `changedCount` and `resetAll()`
|
|
497
|
+
("more filters (3)", "clear all"). The controls are typed `FieldControls`, which every widget
|
|
498
|
+
takes; for a kind's own controls (a tree's `nodes`, numeric's `format`), cast by kind:
|
|
499
|
+
`group.byId.toc as OneOfTreeFieldControls<string>`.
|
|
500
|
+
|
|
501
|
+
**References.** Every option function of a group's definition receives `ctx.values` (`label`,
|
|
502
|
+
`description`, `placeholder`, `visible` / `hidden`, `enabled` / `disabled`, `choices`, a tree's
|
|
503
|
+
`nodes`, `min` / `max`, numeric's `format(n, ctx)`, ...), beside the keys of the app's own field
|
|
504
|
+
context (the nearest `FieldContextProvider`), which keep working. A function the controls keep
|
|
505
|
+
and call later (`format`, through `field.format(n)`) sees the group's values too. `initialValue`
|
|
506
|
+
cannot read them. In a plain `FieldDefinition` the context is untyped (`any`); an app wanting
|
|
507
|
+
`ctx.values` typed declares `values` in its context type (`FieldDefinition<Ctx>`,
|
|
508
|
+
`createFieldContext<Ctx>()`).
|
|
509
|
+
|
|
510
|
+
**The fallback rule.** A field's shown value is its kept value checked as a stored value is
|
|
511
|
+
(`sanitizeStored`), with its options evaluated in the group's context. A value that another
|
|
512
|
+
field's change made invalid (a paper size the layout no longer offers) shows the field's
|
|
513
|
+
fallback, and the other fields see that fallback. Nothing is rewritten: the kept value shows
|
|
514
|
+
again once it is valid again (the layout back). A hidden field keeps its value, and the others
|
|
515
|
+
still see it.
|
|
516
|
+
|
|
517
|
+
**Defaults follow the options.** A field's default is its `initialValue`, else its kind's
|
|
518
|
+
implicit initial value from its options as they are now (the first enabled choice of its current
|
|
519
|
+
`choices`, a tree's first choosable node, `min`, ...), so it moves with the fields those options
|
|
520
|
+
read. A field never set, or set to its current default, keeps nothing and shows its current
|
|
521
|
+
default as it moves. `isDefault(id)` is useStoredFields' rule: nothing kept, or the kept value or
|
|
522
|
+
the value shown equals the current default.
|
|
523
|
+
|
|
524
|
+
**Errors.** These fail loudly, naming the field and the option where there is one:
|
|
525
|
+
|
|
526
|
+
- an option reading an id not in the group: `Field 'paper': option 'choices': no field 'layot'
|
|
527
|
+
in the group (fields: layout, paper, copies)`;
|
|
528
|
+
- reading `ctx.values` outside a group, with a `FieldContextProvider` above: `... ctx.values is
|
|
529
|
+
only available inside a field group`; with none, a function declaring `ctx` gets the existing
|
|
530
|
+
`... is a function of the field context, but no FieldContextProvider is above it`;
|
|
531
|
+
- `initialValue` reading `ctx.values`: `... initialValue cannot read other fields' values`;
|
|
532
|
+
- fields whose values depend on each other (A's choices read B, and B's read A): `Fields 'a' ->
|
|
533
|
+
'b' -> 'a' depend on each other's values`. Options that never affect a value (`visible`,
|
|
534
|
+
`enabled`, `label`, `unit`, `format`, ...) cannot form a cycle;
|
|
535
|
+
- two definitions with the same id; a mixed-boolean definition (it shows an aggregate of other
|
|
536
|
+
data, not a value of its own); an app field context that already has `values` (the group
|
|
537
|
+
would shadow it);
|
|
538
|
+
- a list of another shape than the first render's. The hooks run per field, so the ids and kinds
|
|
539
|
+
stay the same, in the same order: to swap lists, remount the component running the group with
|
|
540
|
+
a React `key`. The definitions' contents may change, and new objects of the same shape on
|
|
541
|
+
every render (inline literals) are fine.
|
|
542
|
+
|
|
543
|
+
**Storage**, for the whole group, is the runner's choice. By default the group keeps the values
|
|
544
|
+
in its own state, as a store keeps them: a field without a kept value shows its current default,
|
|
545
|
+
and a value set equal to it is not kept. A fallback is silent here, as it is the designed
|
|
546
|
+
behaviour, not bad input. `resetAll()` clears every kept value.
|
|
547
|
+
|
|
548
|
+
With `useFieldGroup(definitions, { stored: true })` the values live in the nearest `ArgStore`
|
|
549
|
+
(the URL through vultus-react-router's `<ReactRouterArgStore>`, or localStorage) under each
|
|
550
|
+
field's id, as `useStoredField` keeps a single field there, all read in one store subscription:
|
|
551
|
+
|
|
552
|
+
```tsx
|
|
553
|
+
const filters: FieldDefinition[] = [
|
|
554
|
+
{ kind: 'text', id: 'search' },
|
|
555
|
+
{ kind: 'oneOfTree', id: 'toc', optional: true, nodes: CHAPTERS, widget: 'list', visible: (ctx) => ctx.values.search === '' },
|
|
556
|
+
];
|
|
557
|
+
|
|
558
|
+
function Filters() {
|
|
559
|
+
const group = useFieldGroup(filters, { stored: true }); // ?search=...&toc=...
|
|
560
|
+
return <>{group.fields.map((f) => <FieldWidget key={f.id} field={f} />)}</>;
|
|
561
|
+
}
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
An absent key reads as the field's current default, and a value equal to it is written as an
|
|
565
|
+
absent key (with `'replace'`). The default compared with is the one under the store's values at
|
|
566
|
+
the moment of the write (a store reads its own writes back at once), so, as in the group's own
|
|
567
|
+
state, `layout.setValue('original'); paper.setValue('a4')` in one handler keeps `a4` even where
|
|
568
|
+
`a4` was paper's default under the old layout. Each field's `hrefFor` links a value through the
|
|
569
|
+
store, as rendered (`undefined` where the store has no links). The fallback rule is the same,
|
|
570
|
+
and the stored value is never rewritten (the search above hides `toc`; `?toc=` stays). A stored
|
|
571
|
+
raw value that does not parse, or does not fit its field, warns once, in the render that first
|
|
572
|
+
reads it, as `useStoredField`'s does; one that does not parse reads as the current default. A
|
|
573
|
+
value that another field's change makes fall back later does not warn: that is how a group
|
|
574
|
+
behaves, not bad input. Nor does a raw value the group itself wrote:
|
|
575
|
+
`layout.setValue('rendered'); paper.setValue('letter')` in one handler (Letter offered under the
|
|
576
|
+
original layout) stores `letter`, which falls back at once; the warnings are for raw values from
|
|
577
|
+
elsewhere (the URL, another tab). `resetAll(method = 'replace')` removes every field's key in one store
|
|
578
|
+
write (one history entry). Switching between the two storages is a change of shape: it throws
|
|
579
|
+
(remount with a React `key`).
|
|
580
|
+
|
|
581
|
+
**Rendering.** vultus-antd's `<FieldWidget>` renders the controls (by the definition's `widget`
|
|
582
|
+
hint; `item` for a labelled form item), in order as above or by id
|
|
583
|
+
(`<FieldWidget field={group.byId.paper} />`). A request goes through the kind's own checks (a
|
|
584
|
+
paper size the layout does not offer is refused with a warning, as the kind's hook alone refuses
|
|
585
|
+
it). The group then keeps the value and re-renders, so every option is computed again.
|
|
586
|
+
|
|
469
587
|
## Components
|
|
470
588
|
|
|
471
589
|
`VultusComponentsContext` (default `{}`) / `useVultusComponents()` is how an app lends its own
|
package/dist/FieldContext.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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;
|
|
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"}
|
package/dist/FieldContext.js
CHANGED
|
@@ -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
|
-
/**
|
|
22
|
-
|
|
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
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
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
|
|
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
|
|
33
|
-
throw new MissingKeyError(
|
|
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
|
-
/**
|
|
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
|
-
|
|
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
|
package/dist/FieldContext.js.map
CHANGED
|
@@ -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
|
|
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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"}
|