vultus-core 0.5.2 → 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 +176 -4
- 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/field.d.ts +12 -1
- package/dist/field.d.ts.map +1 -1
- package/dist/field.js +6 -1
- package/dist/field.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 +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- 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/kinds.d.ts +19 -14
- package/dist/kinds.d.ts.map +1 -1
- package/dist/kinds.js +40 -14
- package/dist/kinds.js.map +1 -1
- package/dist/tree.d.ts +17 -0
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +27 -0
- 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/useOneOfTreeField.d.ts +79 -0
- package/dist/useOneOfTreeField.d.ts.map +1 -0
- package/dist/useOneOfTreeField.js +117 -0
- package/dist/useOneOfTreeField.js.map +1 -0
- package/dist/useStoredField.d.ts +9 -0
- package/dist/useStoredField.d.ts.map +1 -1
- package/dist/useStoredField.js +7 -5
- package/dist/useStoredField.js.map +1 -1
- package/package.json +1 -1
- package/src/FieldContext.tsx +73 -11
- package/src/field.ts +25 -5
- package/src/fieldGroupValues.ts +169 -0
- package/src/index.ts +7 -1
- package/src/kindHooks.ts +52 -0
- package/src/kinds.ts +38 -14
- package/src/tree.ts +34 -0
- package/src/useArg.ts +6 -2
- package/src/useFieldGroup.ts +346 -0
- package/src/useOneOfTreeField.ts +182 -0
- package/src/useStoredField.ts +10 -6
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` /
|
|
@@ -257,6 +258,12 @@ its descendants matches (with only the children that stay), and the rest
|
|
|
257
258
|
is trimmed, leaving the nodes given unchanged. Implicit initial value: the
|
|
258
259
|
empty list.
|
|
259
260
|
|
|
261
|
+
A `TreeNode`'s `choosable` (default `true`; a folder when `false`) is for the one-of tree, below;
|
|
262
|
+
this hook ignores it, so one node list can feed both kinds. Its helpers: `canChooseNode(node,
|
|
263
|
+
choose)` (choosable, enabled, and, under `choose: 'leaves'`, no children), `choosableValues(nodes,
|
|
264
|
+
choose)` (the values it accepts, in pre-order) and `treePath(nodes, value)` (the values from the
|
|
265
|
+
root down to `value`, inclusive; `[]` when no node has it).
|
|
266
|
+
|
|
260
267
|
```ts
|
|
261
268
|
const field = useManyOfTreeField({
|
|
262
269
|
id: 'categories',
|
|
@@ -265,6 +272,39 @@ const field = useManyOfTreeField({
|
|
|
265
272
|
field.toggle('a'); // field.value === ['a'] — 'topmost' collapses the subtree to the parent
|
|
266
273
|
```
|
|
267
274
|
|
|
275
|
+
### one-of tree (`useOneOfTreeField`)
|
|
276
|
+
|
|
277
|
+
The value is a single node id (`nodes`, the many-of tree's `TreeNode`), or `''` meaning nothing
|
|
278
|
+
chosen (Praeceptor's category picker, a table of contents). A node is choosable when its own
|
|
279
|
+
`choosable` is not `false` (a folder — a part heading with no page, a category group — is
|
|
280
|
+
`choosable: false`; the many-of tree ignores it, so one node list can feed both kinds), it is
|
|
281
|
+
enabled, and, under `choose: 'leaves'` (default `'any'`), has no children (`canChooseNode`,
|
|
282
|
+
`choosableValues`, `treePath` — see many-of tree, above). `setValue` refuses, with a warning (as
|
|
283
|
+
`useOneOfField` refuses a disabled choice): a value naming no node, a node that cannot be
|
|
284
|
+
chosen, and `''` unless `optional` (default `false`, as `oneOf`'s value is never empty); `clear()`
|
|
285
|
+
requests `''`. Controls add `nodes` (each with `choosable`, `current` — it is the value — and
|
|
286
|
+
`onPath` — an ancestor of it) and `byValue`, as the many-of tree's; `current` (the chosen node, or
|
|
287
|
+
undefined when the value is empty or names no node), `path` (the nodes from the root down to
|
|
288
|
+
`current`, inclusive; empty when there is none), `previous` / `next` (the choosable nodes just
|
|
289
|
+
before and after `current`'s own position in tree pre-order — so a `current` that cannot itself
|
|
290
|
+
be chosen, e.g. a value naming a folder or a node a context change disabled, still gets its true
|
|
291
|
+
neighbours; undefined at the ends, and with no `current`, `previous` undefined and `next` the
|
|
292
|
+
first choosable node), `optional`, `choose` and `expandedKeys`
|
|
293
|
+
(from `expand`, default `'selected'` — the value's ancestors, so a table of contents opens where
|
|
294
|
+
the reader is; `'top'`, `'none'` and `'all'` as the many-of tree's). The field's current state is
|
|
295
|
+
the chosen node's description, unless `valueDescriptions` words it differently (as `oneOf`).
|
|
296
|
+
Implicit initial value: `initialValue`, else `''` when `optional`, else the first node that can be
|
|
297
|
+
chosen in tree pre-order, else `''` (no node can be chosen; as `oneOf`'s undefined choice).
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
const field = useOneOfTreeField({
|
|
301
|
+
id: 'category',
|
|
302
|
+
nodes: [{ value: 'geo', choosable: false, children: [{ value: 'sik' }, { value: 'ter' }] }],
|
|
303
|
+
});
|
|
304
|
+
field.value; // 'sik' — the first node that can be chosen ('geo' is a folder)
|
|
305
|
+
field.next?.value; // 'ter'
|
|
306
|
+
```
|
|
307
|
+
|
|
268
308
|
### text (`useTextField`)
|
|
269
309
|
|
|
270
310
|
The value is a string. `control: 'input' | 'textarea'` (default `'input'`)
|
|
@@ -285,7 +325,7 @@ const field = useTextField({ id: 'search', control: 'input' });
|
|
|
285
325
|
A `FieldDefinition` is a field's options in their "inside" form (no `value`
|
|
286
326
|
plus `onChange` or `commit`), tagged with a required `kind` — one of
|
|
287
327
|
`'boolean'`, `'mixed-boolean'`, `'oneOf'`, `'manyOf'`, `'numeric'`,
|
|
288
|
-
`'range'`, `'manyOfTree'`, `'text'` (the same strings `FieldControls.type` already
|
|
328
|
+
`'range'`, `'manyOfTree'`, `'oneOfTree'`, `'text'` (the same strings `FieldControls.type` already
|
|
289
329
|
carries). `kind` stays optional on each hook's own options — a hook knows
|
|
290
330
|
its own kind, and throws if a definition names a different one — but is
|
|
291
331
|
required once a field becomes plain data: a module declares its filters as a
|
|
@@ -333,7 +373,7 @@ b)`) say how a value is kept as a string and compared; equality is the
|
|
|
333
373
|
type's own meaning (a list as a set, a range by both ends), used everywhere
|
|
334
374
|
two values of that type are compared — including whether a value is the
|
|
335
375
|
default, so it's left out of the store. `valueTypeOf(kind)` gives each field
|
|
336
|
-
kind's: `booleanType` (`'1'` / `'0'`), `stringType` (one-of, text),
|
|
376
|
+
kind's: `booleanType` (`'1'` / `'0'`), `stringType` (one-of, one-of tree, text),
|
|
337
377
|
`stringSetType` (many-of, many-of tree — a sorted comma list; a *present but empty*
|
|
338
378
|
value reads as the empty list, which differs from the key being absent
|
|
339
379
|
altogether), `numberType`, `rangeType` (`from..to`). A mixed-boolean field
|
|
@@ -381,7 +421,9 @@ is the definition's `id`, its value type comes from the kind, its default
|
|
|
381
421
|
is `initialValueOf`. It returns `{ options, isDefault, reset }` — `options`
|
|
382
422
|
is the definition in its outside form (`value` plus `onChange`, ready for
|
|
383
423
|
the kind's hook), with the stored raw value made to fit the definition as
|
|
384
|
-
it is now (`sanitizeStored`: unknown choices or nodes dropped
|
|
424
|
+
it is now (`sanitizeStored`: unknown choices or nodes dropped; a one-of
|
|
425
|
+
tree value naming no node, a folder or a node it cannot choose, or `''`
|
|
426
|
+
when the field is not optional, replaced by the initial value; numbers and
|
|
385
427
|
ranges clamped, and rounded when `integer`). A value that needed fixing up
|
|
386
428
|
warns once per field and per raw value — not again on every render, and not
|
|
387
429
|
at all when the key is simply absent (then the default applies, and an
|
|
@@ -392,6 +434,21 @@ definitions), `changedCount`, and `resetAll(method)` (one write for every
|
|
|
392
434
|
field). Being a summary, it never warns — only `useStoredField` on the
|
|
393
435
|
field itself does.
|
|
394
436
|
|
|
437
|
+
**Links.** Every kind's hook gives its controls `hrefFor(value)`: the link that requesting `value`
|
|
438
|
+
amounts to, or `undefined` where nothing gives one. With `value` + `onChange` or `value` +
|
|
439
|
+
`commit`, the caller passes it; inside the field it is always `undefined` (an `hrefFor` passed
|
|
440
|
+
anyway is ignored). `FieldControls` has it optional (`hrefFor?(value)`), so controls built by
|
|
441
|
+
hand need none; a widget calls `field.hrefFor?.(value)`. `useStoredField` wires its own from the
|
|
442
|
+
store (`useArg`'s `hrefFor`, itself from the store's), so a field stored over a URL store
|
|
443
|
+
(vultus-react-router's) links each value it could be set to, e.g.
|
|
444
|
+
`field.hrefFor?.(field.choices[0].value)` next to the field's own widget. A link built from
|
|
445
|
+
`hrefFor` is as fresh as the render that built it: a URL that changes without re-rendering its
|
|
446
|
+
component (another key of the query, the path) leaves it stale. Render an app's own links (a
|
|
447
|
+
previous / next pair) in a component that re-renders on location changes (with react-router,
|
|
448
|
+
one that calls `useLocation`), or compute them at interaction time (vultus-antd's
|
|
449
|
+
`OneOfTreeList` asks again as the pointer enters a link, on its focus, a button press, its
|
|
450
|
+
context menu, a modified click).
|
|
451
|
+
|
|
395
452
|
```tsx
|
|
396
453
|
const store = memoryStore();
|
|
397
454
|
|
|
@@ -410,6 +467,121 @@ function Category() {
|
|
|
410
467
|
}
|
|
411
468
|
```
|
|
412
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
|
+
|
|
413
585
|
## Components
|
|
414
586
|
|
|
415
587
|
`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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"}
|
package/dist/field.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type { ConfirmationSpec, Decision, ErrorRoutesRegistry, ExecutionContext,
|
|
|
9
9
|
* Design notes: unitas docs/2026-10-05-vultus-field-model-design.md.
|
|
10
10
|
*/
|
|
11
11
|
/** The field kinds (FieldControls.type and a FieldDefinition's `kind`). */
|
|
12
|
-
export type FieldKind = 'boolean' | 'mixed-boolean' | 'oneOf' | 'manyOf' | 'numeric' | 'range' | 'manyOfTree' | 'text';
|
|
12
|
+
export type FieldKind = 'boolean' | 'mixed-boolean' | 'oneOf' | 'manyOf' | 'numeric' | 'range' | 'manyOfTree' | 'oneOfTree' | 'text';
|
|
13
13
|
/** The widget to render a field with: a name, or a name with display options overriding its defaults. */
|
|
14
14
|
export type WidgetHint = string | {
|
|
15
15
|
name: string;
|
|
@@ -67,6 +67,7 @@ export type FieldStorage<TValue, TRequest = TValue, RouteId extends string = str
|
|
|
67
67
|
value?: never;
|
|
68
68
|
onChange?: never;
|
|
69
69
|
commit?: never;
|
|
70
|
+
hrefFor?: never;
|
|
70
71
|
}
|
|
71
72
|
/** Outside, changed locally: the caller owns the value and applies `onChange`. */
|
|
72
73
|
| {
|
|
@@ -74,6 +75,8 @@ export type FieldStorage<TValue, TRequest = TValue, RouteId extends string = str
|
|
|
74
75
|
onChange: (value: TRequest) => void;
|
|
75
76
|
initialValue?: never;
|
|
76
77
|
commit?: never;
|
|
78
|
+
/** The link that requesting `value` amounts to, where the caller has one (e.g. a URL store). */
|
|
79
|
+
hrefFor?: (value: TRequest) => string | undefined;
|
|
77
80
|
}
|
|
78
81
|
/** Outside, committed immediately: `commit.fire` stores the change (pending, messages, confirmation). */
|
|
79
82
|
| {
|
|
@@ -81,6 +84,7 @@ export type FieldStorage<TValue, TRequest = TValue, RouteId extends string = str
|
|
|
81
84
|
commit: FieldCommit<TRequest, RouteId>;
|
|
82
85
|
initialValue?: never;
|
|
83
86
|
onChange?: never;
|
|
87
|
+
hrefFor?: (value: TRequest) => string | undefined;
|
|
84
88
|
};
|
|
85
89
|
export type FieldOptions<TValue, TRequest = TValue, RouteId extends string = string, Ctx = any> = FieldBaseOptions<TValue, Ctx> & FieldStorage<TValue, TRequest, RouteId, Ctx>;
|
|
86
90
|
/** What a field widget receives: everything it shows, and the one way to change the value. */
|
|
@@ -106,6 +110,13 @@ export interface FieldControls<TValue, TRequest = TValue> {
|
|
|
106
110
|
messages: Message[];
|
|
107
111
|
/** The confirmation a widget must obtain before requesting `next`, if any. */
|
|
108
112
|
confirmationFor(next: TRequest): ConfirmationSpec | undefined;
|
|
113
|
+
/**
|
|
114
|
+
* The link that requesting `value` amounts to, where whoever keeps the value gave one (a URL
|
|
115
|
+
* store does); `undefined` otherwise, and always inside the field. Every kind's hook provides
|
|
116
|
+
* it; optional here so that controls built by hand (as before vultus-core 0.5.3) need none, so
|
|
117
|
+
* a widget calls it as `field.hrefFor?.(value)`.
|
|
118
|
+
*/
|
|
119
|
+
hrefFor?(value: TRequest): string | undefined;
|
|
109
120
|
widget: WidgetHint | undefined;
|
|
110
121
|
}
|
|
111
122
|
export type FieldStorageMode = 'inside' | 'local' | 'commit';
|
package/dist/field.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../src/field.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,gBAAgB,EAChB,QAAQ,EACR,mBAAmB,EACnB,gBAAgB,EAChB,OAAO,EACP,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB;;;;;;;;GAQG;AAEH,2EAA2E;AAC3E,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,eAAe,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,YAAY,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../src/field.ts"],"names":[],"mappings":"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"}
|
package/dist/field.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
2
|
import { getReason, getVerdict, invertDecision } from './decision.js';
|
|
3
3
|
import { useFieldContext } from './FieldContext.js';
|
|
4
4
|
import { resolveIn } from './resolve.js';
|
|
@@ -86,6 +86,10 @@ export function useFieldCore(type, opts, registry) {
|
|
|
86
86
|
const spec = opts.commit?.confirmation;
|
|
87
87
|
return typeof spec === 'function' ? spec(next) : spec;
|
|
88
88
|
};
|
|
89
|
+
// Inside the field nothing outside keeps the value, so nothing gives a link: an `hrefFor` that
|
|
90
|
+
// came anyway (untyped options; the types forbid it) is ignored.
|
|
91
|
+
const hrefForOpt = mode === 'inside' ? undefined : opts.hrefFor;
|
|
92
|
+
const hrefFor = useCallback((next) => hrefForOpt?.(next), [hrefForOpt]);
|
|
89
93
|
return {
|
|
90
94
|
type,
|
|
91
95
|
id: opts.id,
|
|
@@ -102,6 +106,7 @@ export function useFieldCore(type, opts, registry) {
|
|
|
102
106
|
commits: mode === 'commit',
|
|
103
107
|
messages: mode === 'commit' ? (setter.messages ?? []) : [],
|
|
104
108
|
confirmationFor,
|
|
109
|
+
hrefFor,
|
|
105
110
|
widget: opts.widget,
|
|
106
111
|
};
|
|
107
112
|
}
|
package/dist/field.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field.js","sourceRoot":"","sources":["../src/field.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"field.js","sourceRoot":"","sources":["../src/field.ts"],"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"}
|