@dynamicforms/vue-forms 1.1.0 → 2.0.3

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/dist/index.d.ts CHANGED
@@ -15,6 +15,43 @@ import { TranslateStringsCallback } from '@dynamicforms/translatable';
15
15
  export declare class AbortEventHandlingException extends Error {
16
16
  }
17
17
 
18
+ /**
19
+ * What a form element accepts and what it sends. The four values follow HTML: `'editable'` and `'readonly'` send
20
+ * the element's value the way an `<input>` and an `<input readonly>` are submitted, `'disabled'` sends nothing the
21
+ * way an `<input disabled>` is left out, and `'disabled-null'` sends `null` in the element's place.
22
+ *
23
+ * | access | accepts input | contributes to its container's `value` |
24
+ * |-------------------|---------------|----------------------------------------|
25
+ * | `'editable'` | yes | its value |
26
+ * | `'readonly'` | no | its value |
27
+ * | `'disabled'` | no | nothing: the key or row is left out |
28
+ * | `'disabled-null'` | no | `null` |
29
+ *
30
+ * An element that contributes no value of its own is not counted in its container's validity. `fullValue` carries
31
+ * every element whatever its access.
32
+ */
33
+ export declare type Access = 'editable' | 'readonly' | 'disabled' | 'disabled-null';
34
+
35
+ /** Told once an element's `access` has been written. */
36
+ export declare class AccessChangedAction extends FieldActionBase {
37
+ constructor(executorFn: (field: FieldBase, supr: FieldActionExecute, newValue: Access, oldValue: Access) => void);
38
+ static get classIdentifier(): symbol;
39
+ execute(field: FieldBase, supr: FieldActionExecute, newValue: Access, oldValue: Access): void;
40
+ }
41
+
42
+ /**
43
+ * Asked before an element's `access` is written. A handler answers with the access to write instead, or throws
44
+ * `AbortEventHandlingException` to refuse the write.
45
+ */
46
+ export declare class AccessChangingAction extends FieldActionBase {
47
+ constructor(executorFn: (field: FieldBase, supr: FieldActionExecute, newValue: Access, oldValue: Access) => Access);
48
+ static get classIdentifier(): symbol;
49
+ execute(field: FieldBase, supr: FieldActionExecute, newValue: Access, oldValue: Access): Access;
50
+ }
51
+
52
+ /** every access, in the order of the table above */
53
+ export declare const accessValues: readonly Access[];
54
+
18
55
  export declare class Action<T extends ActionValue = ActionValue, X extends object = Omit<Extras, keyof ActionValue>> extends Field<T, X> {
19
56
  get [Symbol.toStringTag](): string;
20
57
  protected init(params?: IFieldParams<T, X>): void;
@@ -30,7 +67,7 @@ export declare class Action<T extends ActionValue = ActionValue, X extends objec
30
67
  get label(): T['label'];
31
68
  /**
32
69
  * The two setters hand the value setter a new object rather than writing into the one the action holds, so each
33
- * is an ordinary value change: the handlers fire, isChanged answers over it, and a disabled action refuses it.
70
+ * is an ordinary value change: the handlers fire and isChanged answers over it.
34
71
  * The new object is built only for a member that differs from the one held - the value setter compares by
35
72
  * identity and every copy is a new object, so without the comparison here a write of the value already held
36
73
  * would announce a change and invalidate the value cache of every container above.
@@ -219,8 +256,12 @@ declare interface CompareToBindingState<T> extends ValidatorBindingState {
219
256
  */
220
257
  declare type CompareToTarget = FieldBase | string | ((field: FieldBase) => FieldBase | null | undefined);
221
258
 
222
- export declare class ConditionalEnabledAction extends ConditionalStatementAction {
223
- constructor(statement: Statement);
259
+ /**
260
+ * Sets the access of the elements it is registered on from the statement's result: `whenTrue` while the statement
261
+ * holds, `whenFalse` otherwise.
262
+ */
263
+ export declare class ConditionalAccessAction extends ConditionalStatementAction {
264
+ constructor(statement: Statement, whenTrue?: Access, whenFalse?: Access);
224
265
  }
225
266
 
226
267
  declare type ConditionalExecutorFn = (field: FieldBase, currentResult: boolean, previousResult: boolean | undefined) => void;
@@ -270,8 +311,77 @@ export declare class ConditionalValueAction<T> extends ConditionalStatementActio
270
311
  constructor(statement: Statement, trueValue: T);
271
312
  }
272
313
 
314
+ /**
315
+ * Sets the visibility of the elements it is registered on from the statement's result: `whenTrue` while the
316
+ * statement holds, `whenFalse` otherwise. Visibility is presentation alone, so what the elements send is left to
317
+ * their access.
318
+ */
273
319
  export declare class ConditionalVisibilityAction extends ConditionalStatementAction {
274
- constructor(statement: Statement);
320
+ constructor(statement: Statement, whenTrue?: Visibility, whenFalse?: Visibility);
321
+ }
322
+
323
+ /**
324
+ * A form element that holds other elements and composes its state out of theirs: `Group`, which holds named
325
+ * members, and `List`, which holds rows. Every element's `parent` is a `Container`.
326
+ *
327
+ * What a container answers for over its children is the same whatever holds them: `valid` and `busy` are composed
328
+ * of theirs, `touched` is true where any child is touched and propagates an assignment down, `validate(true)`
329
+ * revalidates every child before the container forms its own verdict, and a child's change of value or verdict
330
+ * reaches the container through `notifyValueChanged()` and the tallies below. How the children are reached - by
331
+ * name or by position - is the subclass's.
332
+ */
333
+ export declare abstract class Container<T = any, X extends object = Extras> extends FieldBase<T, X> {
334
+ get [Symbol.toStringTag](): string;
335
+ /**
336
+ * The children this container holds, read through the tracked view of its state: a verdict or a flag composed
337
+ * over them is formed again when a child is added or removed.
338
+ */
339
+ protected abstract get children(): readonly FieldBase[];
340
+ get touched(): boolean;
341
+ set touched(touched: boolean);
342
+ get valid(): boolean;
343
+ get busy(): boolean;
344
+ validate(revalidate?: boolean): void;
345
+ /**
346
+ * Records that a child changed its value, so that the transaction in progress works out at commit what this
347
+ * container's own value became and announces it once. The mutation methods call it themselves; you rarely need
348
+ * to.
349
+ */
350
+ notifyValueChanged(): void;
351
+ protected get composesValue(): boolean;
352
+ /**
353
+ * A container with nothing listening for what it holds does not compose it at all, so the copy it keeps is from
354
+ * before the changes nobody received. A registration that adds a listener brings it up to date here, and what
355
+ * the listener is then told about is the change that follows it.
356
+ */
357
+ protected refreshPreviousValue(): void;
358
+ /** A container holds every member's value whatever the member sends: its `fullValue`. */
359
+ protected get holding(): any;
360
+ /**
361
+ * The composed verdict `valid` answers with, memoised by Vue. The walk over the children is what makes an error
362
+ * pushed into one of them visible without a validate() call, and the computed keeps that walk from repeating
363
+ * while nothing it read has moved.
364
+ */
365
+ private get validRead();
366
+ /**
367
+ * The composed answer `busy` gives, memoised by Vue. An `Action` counts its executions in a counter of its own,
368
+ * which no container is told about, so the answer is composed over the children instead of tallied; the computed
369
+ * keeps the walk from repeating while nothing it read has moved, and a child that is itself a container answers
370
+ * from its own computed.
371
+ */
372
+ private get busyRead();
373
+ /**
374
+ * Records that a child started or stopped answering `validating` with true, and carries the transition further
375
+ * up where it changes this container's own answer.
376
+ */
377
+ protected childValidatingChanged(started: boolean): void;
378
+ /**
379
+ * Records a child's new verdict in this container's tally. The child reports it as it settles, and the commit
380
+ * settles the deepest element first, so the tally a container reads when its own turn comes is finished. The
381
+ * delta is applied here rather than recomputed by walking the children at commit, which would cost
382
+ * `O(children)` per container and turn a list fill back into the quadratic walk this tally exists to avoid.
383
+ */
384
+ protected childValidityChanged(nowValid: boolean): void;
275
385
  }
276
386
 
277
387
  /**
@@ -283,38 +393,28 @@ declare interface ContainerSlots<T = any> extends ElementSlots<T> {
283
393
  cachedValueVersion: number;
284
394
  }
285
395
 
286
- /** What a form element's visibility is when nothing sets it. It is a starting value, never a fallback for input. */
287
- export declare const defaultDisplayMode = DisplayMode.FULL;
288
-
289
396
  /**
290
- * DisplayMode enum provides an enumeration for supported ways of rendering a particular object in the DOM
397
+ * Told what an element contributes to its container's `value` once that changed over a transaction: the element's
398
+ * value where its access sends it, `null` for `'disabled-null'`, and `undefined` for `'disabled'`, whose key or row
399
+ * is left out. The pair carried is (contribution now, contribution at the last announcement).
400
+ *
401
+ * It answers a different question from `ValueChangedAction`, which reports what the element holds. A write into a
402
+ * `'disabled'` field changes what the field holds and not what it sends, so it fires `ValueChangedAction` alone;
403
+ * switching a field's access changes what it sends and not what it holds, so it fires this action alone. On a
404
+ * container, what it holds is its `fullValue` and what it sends is its `value`, so a change of a member's access
405
+ * reaches the containers above as a change of their contribution, never of their value.
291
406
  */
292
- export declare enum DisplayMode {
293
- SUPPRESS = 1,// Field will be entirely suppressed. it will not render (not even to JSON) and will not parse for PUT
294
- HIDDEN = 5,// Field will render as <input type="hidden"> or <tr data-field_name>
295
- INVISIBLE = 8,// Field will render completely, but with display: none. Equal to setting its style = {display: none}
296
- FULL = 10
407
+ export declare class ContributionChangedAction<T = any> extends FieldActionBase {
408
+ constructor(executorFn: (field: FieldBase<T>, supr: FieldActionExecute<T>, newValue: unknown, oldValue: unknown) => void);
409
+ static get classIdentifier(): symbol;
410
+ execute(field: FieldBase<T>, supr: FieldActionExecute<T>, newValue: unknown, oldValue: unknown): void;
297
411
  }
298
412
 
299
- export declare namespace DisplayMode {
300
- /**
301
- * Resolves a constant's name, case insensitive, to the constant it names. Anything else - a misspelled name, a
302
- * value that is not a string - throws an `Error` naming it. A mode nobody defined is an error at the point it
303
- * arrives, not a field that renders as `FULL` and is never questioned.
304
- */
305
- export function fromString(mode: string): DisplayMode;
306
- /**
307
- * Resolves a DisplayMode number, or a constant's name (case insensitive), to a DisplayMode. A number that is
308
- * none of the constants, a string that names none, and input that is neither a number nor a string all throw an
309
- * `Error` naming the value. Ask `isDefined` where the answer is to be judged rather than raised.
310
- */
311
- export function fromAny(mode: any): DisplayMode;
312
- /**
313
- * Answers whether the input is a DisplayMode: a number that is one of the constants, or a string naming one,
314
- * case insensitive. This is the way to ask that does not throw; it answers `false` where `fromAny` raises.
315
- */
316
- export function isDefined(mode: number | string): boolean;
317
- }
413
+ /** What an element's access is when nothing sets it. */
414
+ export declare const defaultAccess: Access;
415
+
416
+ /** What an element's visibility is when nothing sets it. */
417
+ export declare const defaultVisibility: Visibility;
318
418
 
319
419
  /**
320
420
  * The mutable state of one element, held in an object of its own beside the element rather than in the element's
@@ -340,11 +440,24 @@ export declare namespace DisplayMode {
340
440
  declare interface ElementSlots<T = any> {
341
441
  /** the value the element was given at construction; isChanged compares against it */
342
442
  originalValue: T;
343
- /** the value the last ValueChangedAction reported; the next transaction measures its net change against it */
443
+ /**
444
+ * What the last ValueChangedAction reported the element as holding - its value, and a container's fullValue; the
445
+ * next transaction measures its net change against it
446
+ */
344
447
  announcedValue: T;
448
+ /**
449
+ * What the last ContributionChangedAction reported the element as contributing to its container: its value,
450
+ * `null`, or `undefined` for nothing
451
+ */
452
+ announcedContribution: unknown;
453
+ /**
454
+ * What a container's own validators last ran over - what it sends; the next transaction runs them where that
455
+ * moved. A leaf's validators run at the write and the access switch, and leave it untouched.
456
+ */
457
+ validatedValue: unknown;
345
458
  errors: ValidationError[];
346
- visibility: DisplayMode;
347
- enabled: boolean;
459
+ visibility: Visibility;
460
+ access: Access;
348
461
  /** counts the writes that changed the value of the element or of anything below it */
349
462
  valueVersion: number;
350
463
  /** how many asynchronous validation runs are in flight on this element */
@@ -352,7 +465,7 @@ declare interface ElementSlots<T = any> {
352
465
  /** how many direct children answer `validating` with true; a child that starts or stops running moves it */
353
466
  validatingChildren: number;
354
467
  /** the container that holds this element, absent while none does; takeChild writes it, releaseChild clears it */
355
- parent: FieldBase | undefined;
468
+ parent: Container | undefined;
356
469
  /** the name the containing Group holds this element under; a List row carries none */
357
470
  fieldName: string | undefined;
358
471
  /** generation of the validators attached to the element; clearValidators() raises it */
@@ -375,18 +488,35 @@ declare interface ElementSlots<T = any> {
375
488
  invalidChildren: number;
376
489
  }
377
490
 
491
+ /**
492
+ * Told once a write of `access` changed `enabled`: a switch into or out of `'editable'`. It fires after
493
+ * `AccessChangedAction`, and a switch between two accesses that are not `'editable'` does not fire it.
494
+ */
378
495
  export declare class EnabledChangedAction extends FieldActionBase {
379
496
  constructor(executorFn: (field: FieldBase, supr: FieldActionExecute, newValue: boolean, oldValue: boolean) => void);
380
497
  static get classIdentifier(): symbol;
381
498
  execute(field: FieldBase, supr: FieldActionExecute, newValue: boolean, oldValue: boolean): void;
382
499
  }
383
500
 
501
+ /**
502
+ * Asked before a write of `access` that would change `enabled`: a switch into or out of `'editable'`. It is asked
503
+ * after `AccessChangingAction`, over the access that would be written. `enabled` is read from `access`, so the
504
+ * answer cannot set it: answering with the value `enabled` has now, or throwing `AbortEventHandlingException`,
505
+ * refuses the write of `access`, and answering with the new value, `null` or `undefined` lets it through.
506
+ */
384
507
  export declare class EnabledChangingAction extends FieldActionBase {
385
508
  constructor(executorFn: (field: FieldBase, supr: FieldActionExecute, newValue: boolean, oldValue: boolean) => boolean);
386
509
  static get classIdentifier(): symbol;
387
510
  execute(field: FieldBase, supr: FieldActionExecute, newValue: boolean, oldValue: boolean): boolean;
388
511
  }
389
512
 
513
+ /**
514
+ * Where an error comes from. `'validator'` is an error a validator produced, `'server'` one the server returned and
515
+ * `'application'` one the application's own code computed and wrote into `errors`. Any other string is an origin of
516
+ * the application's own.
517
+ */
518
+ export declare type ErrorOrigin = 'validator' | 'server' | 'application' | (string & {});
519
+
390
520
  export declare class ExecuteAction extends FieldActionBase {
391
521
  constructor(executorFn: (field: FieldBase, supr: FieldActionExecute, params: any) => any);
392
522
  static get classIdentifier(): symbol;
@@ -437,12 +567,6 @@ export declare class Field<T = any, X extends object = Extras> extends FieldBase
437
567
  protected init(params?: IFieldParams<T, X>): void;
438
568
  get value(): T;
439
569
  set value(newValue: T);
440
- /**
441
- * The container that holds this field. A `List` holds rows and a row is a `Group`, so a field is never a `List`'s
442
- * child and the link is a `Group` wherever there is one: `field.parent?.fields.other` is the sibling lookup, and
443
- * it is typed here.
444
- */
445
- get parent(): Group | undefined;
446
570
  get touched(): boolean;
447
571
  set touched(touched: boolean);
448
572
  bind(data?: T, overrides?: IBindParams<T, X>): this;
@@ -529,7 +653,7 @@ export declare abstract class FieldBase<T = any, X extends object = Extras> {
529
653
  * one answers `declaration` with.
530
654
  *
531
655
  * `data` of `undefined` is no data supplied and the new element carries what this one holds; an explicit `null`
532
- * is data and clears. `overrides` states the rest: `originalValue` is read by key presence, `enabled` and
656
+ * is data and clears. `overrides` states the rest: `originalValue` is read by key presence, `access` and
533
657
  * `visibility` fall back to this element's, and extended properties it names are written over the ones carried
534
658
  * over. The new element is detached - no `parent`, no `fieldName` - so it is free to be taken by a container.
535
659
  */
@@ -574,7 +698,7 @@ export declare abstract class FieldBase<T = any, X extends object = Extras> {
574
698
  setExtendedValues(values: Partial<X>): void;
575
699
  /**
576
700
  * The extended properties a parameter object carries: every key the element does not answer for itself. A key
577
- * the element answers for at the time the parameters are applied - `value`, `enabled`, an accessor a subclass
701
+ * the element answers for at the time the parameters are applied - `value`, `access`, an accessor a subclass
578
702
  * adds - is the element's own; a key that only Object.prototype answers for is nobody's declaration and counts
579
703
  * as extended, and `validators` and `actions` are neither, since they state what to register on the element.
580
704
  *
@@ -627,7 +751,8 @@ export declare abstract class FieldBase<T = any, X extends object = Extras> {
627
751
  endValidating(): void;
628
752
  /**
629
753
  * Records that a child started or stopped answering `validating` with true, and carries the transition further
630
- * up where it changes this element's own answer.
754
+ * up where it changes this element's own answer. Only a `Container` has children, and it implements this; it is
755
+ * declared here because a child tells its container through it.
631
756
  */
632
757
  protected childValidatingChanged(started: boolean): void;
633
758
  /**
@@ -639,15 +764,6 @@ export declare abstract class FieldBase<T = any, X extends object = Extras> {
639
764
  * idle reads both.
640
765
  */
641
766
  get busy(): boolean;
642
- /**
643
- * The composed answer a container gives `busy`, memoised by Vue. An `Action` counts its executions in a counter
644
- * of its own, which no container is told about, so the answer is composed over the members instead of tallied;
645
- * the computed keeps the walk from repeating while nothing it read has moved, and a member that is itself a
646
- * container answers from its own computed.
647
- */
648
- protected get busyRead(): boolean;
649
- /** What busyRead computes. A container answers over its members; anything else executes nothing. */
650
- protected composeBusy(): boolean;
651
767
  /**
652
768
  * Resolves once nothing at or below this element is running - no asynchronous validation, no `Action.execute()`
653
769
  * that has yet to settle. It is what a submit path awaits instead of polling `validating` and `busy`, and it
@@ -675,14 +791,14 @@ export declare abstract class FieldBase<T = any, X extends object = Extras> {
675
791
  * so an effect rendering off the link - `v-if="field.parent"` - re-runs when a container takes the element or
676
792
  * releases it.
677
793
  *
678
- * A `List` holds rows and a row is a `Group`, so only a container can be a `List`'s child: `Field` narrows the
679
- * type to `Group | undefined`, and the sibling lookup `field.parent?.fields.other` is typed on a field.
794
+ * The type is `Container`, which names no members: a sibling lookup states which container it expects, either
795
+ * with `field.parent instanceof Group` or with a cast where the structure guarantees it.
680
796
  */
681
- get parent(): Group | List | undefined;
797
+ get parent(): Container | undefined;
682
798
  /**
683
- * The same link at the type the internals reach through. The protected members a container is told things
684
- * through - childValidatingChanged, childValidityChanged - are declared here, and a union of two subclasses is
685
- * not an instance of this class, which is what a protected access needs.
799
+ * The same link at the type the internals reach through. The hooks a child tells its container things through -
800
+ * childValidatingChanged, childValidityChanged - are declared here, and a protected member is reachable only
801
+ * through the class that declares it; `Container` overrides them, so the link is read as a `FieldBase`.
686
802
  */
687
803
  private get container();
688
804
  /** when member of a Group, fieldName specifies the name of this field. Written by the group, read-only after */
@@ -776,9 +892,8 @@ export declare abstract class FieldBase<T = any, X extends object = Extras> {
776
892
  * construction rather than a change of it: the element announces no ValueChangedAction, and what the hook
777
893
  * leaves is what its eager actions and its validators run over, once. An element whose parameters named no
778
894
  * `originalValue` is baselined on the value the hook left and so starts unchanged; one that named a baseline is
779
- * measured against it, as any element is. A `Field` writes
780
- * `_value`, which reaches the slot on an element built `enabled: false` as well - the value setter, which a
781
- * disabled field refuses, states a change, and this is not one.
895
+ * measured against it, as any element is. A `Field` writes `_value`: the value setter states a change, and
896
+ * this is not one.
782
897
  *
783
898
  * A container completes itself through its members, and a member carries a construction of its own: the write
784
899
  * reaches it as any later one would, so the member announces it and reports itself changed. A member that is to
@@ -788,9 +903,9 @@ export declare abstract class FieldBase<T = any, X extends object = Extras> {
788
903
  */
789
904
  protected constructed(params?: object): void;
790
905
  /**
791
- * Re-reads the value that the next ValueChangedAction will report as the one it replaces. A leaf records what
792
- * it announced at every announcement, so its copy is always current and there is nothing to re-read; a
793
- * container that skipped composing a value nobody was listening for overrides this.
906
+ * Re-reads what the next announcements will report as replaced. A contribution is composed only where something
907
+ * listens for it, so the copy is re-read here; a leaf records what it holds at every announcement, so that copy
908
+ * is always current, and a container that skipped composing what nobody was listening for re-reads its own too.
794
909
  */
795
910
  protected refreshPreviousValue(): void;
796
911
  /**
@@ -827,40 +942,95 @@ export declare abstract class FieldBase<T = any, X extends object = Extras> {
827
942
  /** Resets a member. It is what lets a container reach the reset of a child whose class it does not know. */
828
943
  protected resetChild(child: FieldBase, source: FieldBase, value: any): void;
829
944
  /**
830
- * Records a child's new verdict in this element's tally. The child reports it as it settles, and the commit
831
- * settles the deepest element first, so the tally a container reads when its own turn comes is finished.
832
- * The delta is applied here rather than recomputed by walking the members at commit, which would cost
833
- * `O(members)` per container and turn a list fill back into the quadratic walk this tally exists to avoid.
945
+ * Records a child's new verdict in this element's tally. Only a `Container` has children, and it implements
946
+ * this; it is declared here for the reason `childValidatingChanged` is.
834
947
  */
835
948
  protected childValidityChanged(nowValid: boolean): void;
836
949
  /**
837
- * The composed verdict a container answers `valid` with, memoised by Vue. The walk over the members is what
838
- * makes an error pushed into one of them visible without a validate() call, and the computed keeps that walk
839
- * from repeating while nothing it read has moved.
950
+ * How a rendering layer shows this element. It is presentation alone: what the element sends and whether it is
951
+ * validated are its `access`, and no visibility changes either.
840
952
  */
841
- protected get validRead(): boolean;
842
- /** What validRead computes. A leaf answers over its own errors; a container adds its members. */
843
- protected composeValid(): boolean;
844
- get visibility(): DisplayMode;
845
- set visibility(newValue: DisplayMode);
846
- get enabled(): boolean;
847
- set enabled(newValue: boolean);
953
+ get visibility(): Visibility;
954
+ set visibility(newValue: Visibility);
848
955
  /**
849
- * Whether this element and every container above it are enabled. A rendering layer binds one read instead of
850
- * walking the parent chain: a disabled `Group` states that its section cannot be edited, and the inputs
851
- * rendered from the members inside it read that here.
852
- *
853
- * It is a read and nothing else. `enabled` on each element stays exactly what was written to it, a write to a
854
- * member of a disabled container is accepted the way it always was, and what a container serializes is decided
855
- * by the members' own `enabled`. Where a whole subtree is to stop serializing, the members are disabled.
956
+ * What this element accepts and what it sends: `'editable'` and `'readonly'` send its value, `'disabled'` sends
957
+ * nothing and `'disabled-null'` sends `null`, and only `'editable'` accepts input. The validators run over what
958
+ * the element sends and only where it is sent at all, as `effectiveAccess` states, so a switch of access runs
959
+ * them again here and below.
960
+ */
961
+ get access(): Access;
962
+ set access(newValue: Access);
963
+ /**
964
+ * The access this element has once the containers above it are taken into account. A container that sends nothing
965
+ * or `null` in place of what it holds sends none of its members, so below a `'disabled'` or `'disabled-null'`
966
+ * container every element is `'disabled'`; below a `'readonly'` one an `'editable'` element is `'readonly'`.
967
+ * Anywhere else it is the element's own access.
856
968
  *
857
- * `enabled` is the only member with a reading of this kind, and it is not a scheme the other members follow.
858
- * `visibility` has none because `SUPPRESS` states that an element is absent from the value as well, so folding
859
- * it down the tree would decide serialization rather than report it; `value` has none because a container
860
- * composes its own from its members rather than passing one down. A rendering layer that needs a third thing
861
- * folded down the tree has `provide`/`inject`, which is where the render tree's own context belongs.
969
+ * It is what decides whether the element's validators run: an element that is `'disabled'` here is sent nowhere,
970
+ * so its validators reach no verdict and it carries none of their errors. Anywhere else they run over what the
971
+ * element sends - its value, or `null`.
972
+ */
973
+ get effectiveAccess(): Access;
974
+ /**
975
+ * Whether `effectiveAccess` is `'disabled'`, read off the untracked state. A validator asks it on every run, where
976
+ * nothing renders off the answer and a tracked walk up the containers would cost every write a read per level.
977
+ */
978
+ [SentNowhere](): boolean;
979
+ /**
980
+ * True where `access` is `'editable'`: the element accepts input. It reads `access` and nothing else, and it is a
981
+ * statement about input rather than about data - `'readonly'` is not enabled and still sends its value. What an
982
+ * element sends is read from `access`.
983
+ */
984
+ get enabled(): boolean;
985
+ /**
986
+ * True where `effectiveAccess` is `'editable'`: this element and every container above it accept input. A
987
+ * rendering layer binds one read instead of walking the parent chain: a container that is not editable states
988
+ * that its section cannot be edited, and the inputs rendered from the members inside it read that here.
862
989
  */
863
990
  get effectiveEnabled(): boolean;
991
+ /** The effective access of this element and of every element below it, read before a change that may move it. */
992
+ private effectiveAccessFromHere;
993
+ /** The effective access of every element below this one, read before a change that may move it. */
994
+ private effectiveAccessBelow;
995
+ /**
996
+ * Runs the validators again on every element whose effective access moved since `before` was read: one that stops
997
+ * being sent drops their errors, and one that starts being sent is checked over what it now sends.
998
+ */
999
+ private revalidateWhereChanged;
1000
+ /**
1001
+ * What this element contributes to its container's `value` or `fullValue`: its own value, `null` in its place, or
1002
+ * nothing. It is the one place the rule is stated - every container composes its values by asking it.
1003
+ *
1004
+ * `fullValue` states everything the form holds, so every element contributes its value there. `value` states
1005
+ * what the form sends, and `access` decides it: `'disabled'` leaves the element out and `'disabled-null'` sends
1006
+ * `null`, whatever a container holds below it.
1007
+ */
1008
+ protected serializesAs(purpose: 'value' | 'fullValue'): 'value' | 'null' | 'omit';
1009
+ /** What `child` contributes to this container, asked the way `childComposesValue` asks what it is. */
1010
+ protected childSerializesAs(child: FieldBase, purpose: 'value' | 'fullValue'): 'value' | 'null' | 'omit';
1011
+ /**
1012
+ * What this element sends to its container's `value`: its value where its access sends it, `null` for
1013
+ * `'disabled-null'`, and `undefined` for `'disabled'`, whose key or row is left out. It is what the element's
1014
+ * validators run over and what `ContributionChangedAction` reports.
1015
+ */
1016
+ get contribution(): unknown;
1017
+ /**
1018
+ * What `ValueChangedAction` reports this element as holding: its value. A container holds every member's value
1019
+ * whatever the member sends, so it answers with its `fullValue`.
1020
+ */
1021
+ protected get holding(): any;
1022
+ /**
1023
+ * Whether the container holding this element counts its verdict: every element that sends something, `null`
1024
+ * included. A `'disabled'` element sends nothing, so it is not counted - an error written into it by hand no more
1025
+ * than one from a validator, which does not run there.
1026
+ */
1027
+ private get countsInContainer();
1028
+ /**
1029
+ * Carries a change of what this element sends: the element is enrolled so the commit measures its contribution
1030
+ * and re-forms its verdict, the container's value is built again, and an element that is invalid enters or leaves
1031
+ * the container's tally as it starts or stops being counted.
1032
+ */
1033
+ private contributionChanged;
864
1034
  /**
865
1035
  * True for an element whose value is composed of its members'. The commit builds such a value only where
866
1036
  * something receives it, compares it by content rather than by identity, and runs the element's own validators
@@ -876,12 +1046,22 @@ export declare abstract class FieldBase<T = any, X extends object = Extras> {
876
1046
  */
877
1047
  protected childComposesValue(child: FieldBase): boolean;
878
1048
  /**
879
- * Announces what this element's value became over the transaction. The pair carried is (value now, value at the
880
- * last announcement), so a value that went A -> B -> A within the transaction says nothing, and the events an
881
- * operation states rather than an element's state - an item added, an item removed - are emitted first, in the
882
- * order the operations happened.
1049
+ * Announces what this element holds and what it sends, as they became over the transaction. Each pair carried is
1050
+ * (now, at the last announcement), so a value that went A -> B -> A within the transaction says nothing, and the
1051
+ * events an operation states rather than an element's state - an item added, an item removed - are emitted first,
1052
+ * in the order the operations happened.
1053
+ *
1054
+ * A container's validators read what it sends, which is composed here and nowhere else, so they run first, where
1055
+ * that moved; a leaf's have run at the write. `ValueChangedAction` reports what the element holds, and
1056
+ * `ContributionChangedAction` what it sends to its container.
883
1057
  */
884
1058
  protected [TxAnnounceValue](tx: Transaction, dirty: boolean, force: boolean, structural?: TxStructuralEvent[]): void;
1059
+ /**
1060
+ * Records what this element holds and sends as what was last announced, so the commit that follows reports no
1061
+ * change of either. A construction calls it over the state it ends on, and so does an element brought to the
1062
+ * state a fresh binding would be in.
1063
+ */
1064
+ protected recordAnnounced(): void;
885
1065
  /**
886
1066
  * Forms the verdict this element ends the transaction with and announces a transition of it. The container is
887
1067
  * told first, so a handler reads a tally that already includes this verdict, and it is enrolled in the same
@@ -949,25 +1129,41 @@ declare interface FieldSlots<T = any> extends ElementSlots<T> {
949
1129
 
950
1130
  /**
951
1131
  * What Group.fullValue reads back. The indexed access reads each field's fullValue getter, so a nested group
952
- * contributes its own full structure rather than the partial one its `value` builds, and the recursion carries
953
- * the guarantee all the way down: every key is present and none of them is null.
1132
+ * contributes its own full structure rather than the partial one its `value` builds. Every member is present
1133
+ * whatever its access.
954
1134
  */
955
1135
  export declare type FieldsToFullValues<T extends GenericFieldsInterface> = {
956
1136
  [K in keyof T]: T[K]['fullValue'];
957
1137
  };
958
1138
 
1139
+ /**
1140
+ * Converts a field structure into the matching value structure. The indexed access reads each field's value
1141
+ * getter, so a nested Group contributes its own value structure and a List contributes its row array; inferring
1142
+ * from FieldBase<infer U> instead would pick up the value setter, which is deliberately wider than the getter on
1143
+ * Group. Every member may be `null`, because a member whose access is `'disabled-null'` contributes `null` in place
1144
+ * of its value.
1145
+ */
959
1146
  export declare type FieldsToValues<T extends GenericFieldsInterface> = {
960
- [K in keyof T]: T[K]['value'];
1147
+ [K in keyof T]: T[K]['value'] | null;
961
1148
  };
962
1149
 
963
1150
  declare namespace Form {
964
1151
  export {
965
- DisplayMode,
966
- defaultDisplayMode,
1152
+ Access,
1153
+ accessValues,
1154
+ defaultAccess,
1155
+ isAccess,
1156
+ Visibility,
1157
+ visibilityValues,
1158
+ defaultVisibility,
1159
+ isVisibility,
967
1160
  transaction,
968
1161
  TransactionControl,
969
1162
  FieldActionBase,
970
1163
  ActionsMap,
1164
+ AccessChangedAction,
1165
+ AccessChangingAction,
1166
+ ContributionChangedAction,
971
1167
  EnabledChangedAction,
972
1168
  EnabledChangingAction,
973
1169
  ExecuteAction,
@@ -980,7 +1176,7 @@ declare namespace Form {
980
1176
  Operator,
981
1177
  ConditionalStatementAction,
982
1178
  ConditionalVisibilityAction,
983
- ConditionalEnabledAction,
1179
+ ConditionalAccessAction,
984
1180
  ConditionalValueAction,
985
1181
  OperandType,
986
1182
  Statement,
@@ -988,6 +1184,7 @@ declare namespace Form {
988
1184
  Action,
989
1185
  NullableAction,
990
1186
  MessagesWidget,
1187
+ Container,
991
1188
  Field,
992
1189
  NullableField,
993
1190
  IFieldConstructorActionsList,
@@ -1007,6 +1204,8 @@ declare namespace Form {
1007
1204
  NullableGroup,
1008
1205
  isEqual,
1009
1206
  ListValue,
1207
+ ListValueInput,
1208
+ ListFullValue,
1010
1209
  List,
1011
1210
  NullableList,
1012
1211
  Validators,
@@ -1024,10 +1223,13 @@ declare namespace Form {
1024
1223
  RenderContentCallable,
1025
1224
  RenderContent,
1026
1225
  RenderContentRef,
1226
+ ErrorOrigin,
1027
1227
  ValidationError,
1028
1228
  ValidationErrorText,
1029
1229
  ValidationErrorRenderContent,
1030
- RenderableValue
1230
+ RenderableValue,
1231
+ view,
1232
+ View
1031
1233
  }
1032
1234
  }
1033
1235
  export default Form;
@@ -1052,7 +1254,7 @@ export declare type GenericFieldsInterface = Record<string, FieldBase>;
1052
1254
  /** The current configuration. The object is the module's own record, and reading it again reports later writes. */
1053
1255
  export declare function getConfig(): FormsConfig;
1054
1256
 
1055
- export declare class Group<T extends GenericFieldsInterface = GenericFieldsInterface, X extends object = Extras> extends FieldBase<GroupValue<T>, X> {
1257
+ export declare class Group<T extends GenericFieldsInterface = GenericFieldsInterface, X extends object = Extras> extends Container<GroupValue<T>, X> {
1056
1258
  get [Symbol.toStringTag](): string;
1057
1259
  protected get state(): GroupSlots<GroupValue<T>>;
1058
1260
  protected get raw(): GroupSlots<GroupValue<T>>;
@@ -1112,6 +1314,7 @@ export declare class Group<T extends GenericFieldsInterface = GenericFieldsInter
1112
1314
  */
1113
1315
  get fields(): T;
1114
1316
  protected get members(): FieldBase[];
1317
+ protected get children(): readonly FieldBase[];
1115
1318
  get value(): GroupValue<T>;
1116
1319
  /**
1117
1320
  * Writes the members that the given value carries. The members are written one by one and the group says
@@ -1126,26 +1329,11 @@ export declare class Group<T extends GenericFieldsInterface = GenericFieldsInter
1126
1329
  * supplies that per member, so a group reset from the template it was bound from matches a fresh binding of it.
1127
1330
  */
1128
1331
  protected resetTo(source: FieldBase, value: any): void;
1129
- get touched(): boolean;
1130
- set touched(touched: boolean);
1131
- get fullValue(): FieldsToFullValues<T>;
1132
1332
  /**
1133
- * Records that a member changed its value, so that the transaction in progress works out at commit what this
1134
- * group's own value became and announces it once. A mutation method calls it itself; you rarely need to.
1333
+ * Everything the group holds: every member's `fullValue`, whatever the member's access. Where `value` states what
1334
+ * the group sends, this states what it holds, and it is what a binding of the group carries.
1135
1335
  */
1136
- notifyValueChanged(): void;
1137
- protected get composesValue(): boolean;
1138
- /**
1139
- * A group with nothing listening for its value does not compose one at all, so the copy it holds is from before
1140
- * the changes nobody received. A registration that adds a listener brings it up to date here, and what the
1141
- * listener is then told about is the change that follows it.
1142
- */
1143
- protected refreshPreviousValue(): void;
1144
- get valid(): boolean;
1145
- protected composeValid(): boolean;
1146
- get busy(): boolean;
1147
- protected composeBusy(): boolean;
1148
- validate(revalidate?: boolean): void;
1336
+ get fullValue(): FieldsToFullValues<T>;
1149
1337
  /**
1150
1338
  * States that `res` was built from the members handed to it. A subclass whose constructor takes something other
1151
1339
  * than `(fields, params)` - one that composes its own members and passes them to super - never sees them, and
@@ -1161,6 +1349,13 @@ export declare class Group<T extends GenericFieldsInterface = GenericFieldsInter
1161
1349
  rebind(data: GroupValueInput<T>): this;
1162
1350
  }
1163
1351
 
1352
+ /** the data keys of a group's view */
1353
+ declare type GroupData<F extends GenericFieldsInterface> = {
1354
+ readonly [K in keyof F as F[K] extends Container ? K : never]: Slot<F[K]>;
1355
+ } & {
1356
+ -readonly [K in keyof F as F[K] extends Container ? never : K]: Slot<F[K]>;
1357
+ };
1358
+
1164
1359
  /** what a Group holds beyond the container slots: the names of its members, in the order it took them */
1165
1360
  declare interface GroupSlots<T = any> extends ContainerSlots<T> {
1166
1361
  /**
@@ -1172,12 +1367,12 @@ declare interface GroupSlots<T = any> extends ContainerSlots<T> {
1172
1367
  }
1173
1368
 
1174
1369
  /**
1175
- * What Group.value reads back: the values of the fields that serialize, or null when none does. Every key is
1176
- * optional, because a field that is disabled is left out of the object the group builds.
1370
+ * What Group.value reads back: the values of the members that serialize, and `{}` where none does. Every key is
1371
+ * optional, because a member whose access is `'disabled'` is left out of the object the group builds.
1177
1372
  */
1178
- export declare type GroupValue<T extends GenericFieldsInterface> = Partial<FieldsToValues<T>> | null;
1373
+ export declare type GroupValue<T extends GenericFieldsInterface> = Partial<FieldsToValues<T>>;
1179
1374
 
1180
- /** what Group.value and the Group constructor accept: keys left out are simply not assigned */
1375
+ /** what Group.value and the Group constructor accept: keys left out are simply not assigned, and null clears */
1181
1376
  export declare type GroupValueInput<T extends GenericFieldsInterface> = Partial<FieldsToValues<T>> | null;
1182
1377
 
1183
1378
  /**
@@ -1186,7 +1381,7 @@ export declare type GroupValueInput<T extends GenericFieldsInterface> = Partial<
1186
1381
  * `validators` and `actions` are carried from the declaration rather than supplied, and `touched` and `errors`
1187
1382
  * are what the binding establishes for itself as it validates.
1188
1383
  */
1189
- export declare type IBindParams<T = any, X extends object = Extras> = Partial<Pick<IFieldConstructorParams<T>, 'originalValue' | 'enabled' | 'visibility'>> & Partial<NoInfer<X>>;
1384
+ export declare type IBindParams<T = any, X extends object = Extras> = Partial<Pick<IFieldConstructorParams<T>, 'originalValue' | 'access' | 'visibility'>> & Partial<NoInfer<X>>;
1190
1385
 
1191
1386
  export declare interface IFieldConstructorActionsList {
1192
1387
  actions?: FieldActionBase[];
@@ -1196,15 +1391,15 @@ export declare interface IFieldConstructorActionsList {
1196
1391
  /**
1197
1392
  * Parameters accepted by field constructors and by bind overrides.
1198
1393
  *
1199
- * Only writable members are listed. valid, validating, busy, fullValue and isChanged are getter-only, so assigning
1200
- * them throws a TypeError. So are parent and fieldName: a container writes the slots behind them when it takes
1201
- * an element, and nobody else can, which is why the type rejects them.
1394
+ * Only writable members are listed. valid, validating, busy, fullValue, isChanged, enabled and effectiveEnabled are
1395
+ * getter-only, so assigning them throws a TypeError. So are parent and fieldName: a container writes the slots
1396
+ * behind them when it takes an element, and nobody else can, which is why the type rejects them.
1202
1397
  */
1203
1398
  export declare type IFieldConstructorParams<T = any> = {
1204
1399
  value: T;
1205
1400
  originalValue: T;
1206
- enabled: boolean;
1207
- visibility: DisplayMode;
1401
+ access: Access;
1402
+ visibility: Visibility;
1208
1403
  touched: boolean;
1209
1404
  errors: ValidationError[];
1210
1405
  } & IFieldConstructorActionsList;
@@ -1226,6 +1421,9 @@ declare class InAllowedValues<T = any> extends Validator {
1226
1421
  constructor(allowedValues: AllowedValues<T>, message?: RenderContentRef);
1227
1422
  }
1228
1423
 
1424
+ /** Answers whether `value` is one of the four accesses. */
1425
+ export declare function isAccess(value: unknown): value is Access;
1426
+
1229
1427
  export declare function isCallableFunction(msg?: RenderContentRef): msg is RenderContentCallable;
1230
1428
 
1231
1429
  /**
@@ -1245,16 +1443,20 @@ export declare function isEqual(a: unknown, b: unknown): boolean;
1245
1443
  */
1246
1444
  export declare function isSimpleComponentDef(msg?: RenderContentRef): msg is SimpleComponentDef;
1247
1445
 
1446
+ /** Answers whether `value` is one of the four visibilities. */
1447
+ export declare function isVisibility(value: unknown): value is Visibility;
1448
+
1248
1449
  declare class LengthInRange extends Validator {
1249
1450
  constructor(minLength: number, maxLength: number, message?: RenderContentRef);
1250
1451
  }
1251
1452
 
1252
- export declare class List<T extends GenericFieldsInterface = GenericFieldsInterface, X extends object = Extras> extends FieldBase<ListValue, X> {
1453
+ export declare class List<R extends FieldBase = Group, X extends object = Extras> extends Container<ListValue<R>, X> {
1253
1454
  get [Symbol.toStringTag](): string;
1254
- protected get state(): ListSlots<T>;
1255
- protected get raw(): ListSlots<T>;
1455
+ protected get state(): ListSlots<R>;
1456
+ protected get raw(): ListSlots<R>;
1256
1457
  private _itemTemplate?;
1257
- constructor(itemTemplate?: Group<T>, params?: IFieldParams<ListValue, X>);
1458
+ constructor(itemTemplate?: undefined, params?: IFieldParams<ListValueInput<R>, X>);
1459
+ constructor(itemTemplate: R, params?: IFieldParams<ListValueInput<R>, X>);
1258
1460
  /** The row array is copied as well: a rollback puts back the set the list held, not the array it went on to hold. */
1259
1461
  protected [TxCapture](): TxSnapshot;
1260
1462
  /**
@@ -1263,9 +1465,14 @@ export declare class List<T extends GenericFieldsInterface = GenericFieldsInterf
1263
1465
  */
1264
1466
  private static baseline;
1265
1467
  private processSetValueItem;
1468
+ /**
1469
+ * The row a list without an item template builds from `item`: a `Group` of fields from a plain object, a `List`
1470
+ * from an array, and a `Field` holding anything else.
1471
+ */
1472
+ private static elementFor;
1266
1473
  /**
1267
1474
  * Builds the item that fills a gap left by an insert beyond the end of the list: the item template bound to its
1268
- * own values, or an empty group when the list has no template.
1475
+ * own values, or, where the list has no template, an empty element of the kind `item` is built into.
1269
1476
  */
1270
1477
  private createPaddingItem;
1271
1478
  /** Records that the set of rows changed, so `items` rebuilds the frozen array it hands out at the next read. */
@@ -1273,44 +1480,26 @@ export declare class List<T extends GenericFieldsInterface = GenericFieldsInterf
1273
1480
  /** True where `next` is a different set of rows than `previous`: another count, or another row at a position. */
1274
1481
  private static rowsDiffer;
1275
1482
  private setValueInternal;
1276
- get value(): ListValue;
1277
- set value(newValue: ListValue);
1483
+ get value(): ListValue<R>;
1484
+ set value(newValue: ListValueInput<R>);
1278
1485
  /**
1279
1486
  * The rows are taken from `source` where the caller supplied no value of its own, so a list nested in a row that
1280
1487
  * a whole-list assignment reuses ends up holding what the template gives it rather than what it held before.
1281
1488
  */
1282
1489
  protected resetTo(source: FieldBase, value: any): void;
1283
- get touched(): boolean;
1284
- set touched(touched: boolean);
1285
- bind(data?: ListValue, overrides?: IBindParams<ListValue, X>): List<T, X>;
1490
+ bind(data?: ListValueInput<R>, overrides?: IBindParams<ListValueInput<R>, X>): List<R, X>;
1491
+ protected get members(): FieldBase[];
1492
+ protected get children(): readonly FieldBase[];
1286
1493
  /**
1287
- * Records that a row changed its value, so that the transaction in progress works out at commit what this
1288
- * list's own value became and announces it once. The mutation methods call it themselves; you rarely need to.
1494
+ * The full value of every row. Where `value` states what the list sends, this states what the list holds: every
1495
+ * row whatever its access, and a group row carrying every field of its own. It is what a binding or a reset
1496
+ * carries.
1289
1497
  */
1290
- notifyValueChanged(): void;
1291
- protected get composesValue(): boolean;
1292
- /**
1293
- * A list with nothing listening for its value does not compose one at all, so the copy it holds is from before
1294
- * the changes nobody received. A registration that adds a listener brings it up to date here, and what the
1295
- * listener is then told about is the change that follows it.
1296
- */
1297
- protected refreshPreviousValue(): void;
1298
- get valid(): boolean;
1299
- protected composeValid(): boolean;
1300
- get busy(): boolean;
1301
- protected composeBusy(): boolean;
1302
- validate(revalidate?: boolean): void;
1303
- protected get members(): FieldBase[];
1498
+ get fullValue(): ListFullValue<R>;
1304
1499
  /**
1305
1500
  * How many rows this list holds. The read is tracked, so a template rendering off it re-renders as rows come and
1306
1501
  * go.
1307
1502
  */
1308
- /**
1309
- * Every row of this list, each one built from all of its fields. Where `value` states what the list serializes -
1310
- * rows composed of the fields that are enabled, and null where the list is empty - this states what the list
1311
- * holds: the disabled fields are in it too, and an empty list reads back as an empty array rather than as null.
1312
- */
1313
- get fullValue(): FieldsToFullValues<T>[];
1314
1503
  get length(): number;
1315
1504
  /**
1316
1505
  * The rows this list holds, oldest position first. The array is a frozen copy: it states what the list held at
@@ -1321,17 +1510,27 @@ export declare class List<T extends GenericFieldsInterface = GenericFieldsInterf
1321
1510
  * row changes what the list serializes without changing which rows it holds, and the array a reader took stays
1322
1511
  * the same one across such a write.
1323
1512
  */
1324
- get items(): readonly Group<T>[];
1325
- get(index: number): Group<T> | undefined;
1513
+ get items(): readonly R[];
1514
+ get(index: number): R | undefined;
1326
1515
  push(item: any): number;
1327
- pop(): Group<T> | undefined;
1328
- remove(index: number): Group<T> | undefined;
1516
+ pop(): R | undefined;
1517
+ remove(index: number): R | undefined;
1329
1518
  insert(item: any, index: number): number;
1330
1519
  /** Drops every row this list holds out of its tally, so a row that changes its verdict later is not counted. */
1331
1520
  private releaseRows;
1332
1521
  clear(): void;
1333
1522
  }
1334
1523
 
1524
+ /** the array a list's view is: every read an array has, and the mutations taken as the list's own operations */
1525
+ declare type ListData<R extends FieldBase> = Omit<Slot<R>[], 'push' | 'unshift' | 'splice' | 'fill' | 'copyWithin'> & {
1526
+ push(...items: RowInput<R>[]): number;
1527
+ unshift(...items: RowInput<R>[]): number;
1528
+ splice(start: number, deleteCount?: number, ...items: RowInput<R>[]): Slot<R>[];
1529
+ };
1530
+
1531
+ /** what List.fullValue reads back: the full value of every row, whatever its access */
1532
+ export declare type ListFullValue<R extends FieldBase = Group> = R['fullValue'][];
1533
+
1335
1534
  export declare class ListItemAddedAction extends FieldActionBase {
1336
1535
  constructor(executorFn: (field: FieldBase, supr: FieldActionExecute, item: any, index: number) => void);
1337
1536
  static get classIdentifier(): symbol;
@@ -1345,20 +1544,26 @@ export declare class ListItemRemovedAction extends FieldActionBase {
1345
1544
  }
1346
1545
 
1347
1546
  /** what a List holds beyond the container slots: the rows themselves */
1348
- declare interface ListSlots<T extends GenericFieldsInterface = GenericFieldsInterface> extends ContainerSlots<ListValue> {
1349
- rows: Group<T>[] | null;
1547
+ declare interface ListSlots<R extends FieldBase = Group> extends ContainerSlots<ListValue<R>> {
1548
+ rows: R[] | null;
1350
1549
  /**
1351
1550
  * Counts the changes to the set of rows. `items` rebuilds the frozen array it hands out when it moves, and
1352
1551
  * only then: a write inside a row changes what the list serializes without changing which rows it holds.
1353
1552
  */
1354
1553
  rowsVersion: number;
1355
1554
  /** the frozen array `items` last handed out, together with the rows version it was built from */
1356
- cachedItems: readonly Group<T>[] | null;
1555
+ cachedItems: readonly R[] | null;
1357
1556
  cachedItemsVersion: number;
1358
1557
  }
1359
1558
 
1360
- /** what List.value reads back: one plain object per item, or null when the list is empty */
1361
- export declare type ListValue = Record<string, any>[] | null;
1559
+ /**
1560
+ * What a List of R reads back: the value of each row it sends, `null` for a row whose access is `'disabled-null'`,
1561
+ * and `[]` while it sends none
1562
+ */
1563
+ export declare type ListValue<R extends FieldBase = Group> = (R['value'] | null)[];
1564
+
1565
+ /** what List.value and the List constructor accept: an array of rows, or null, which empties the list */
1566
+ export declare type ListValueInput<R extends FieldBase = Group> = ListValue<R> | null;
1362
1567
 
1363
1568
  declare class MaxLength extends Validator {
1364
1569
  constructor(maxLength: number, message?: RenderContentRef);
@@ -1470,6 +1675,12 @@ declare interface RequiredOptions {
1470
1675
  trim?: boolean;
1471
1676
  }
1472
1677
 
1678
+ /** what a list's view takes as a row: the data a row is built from, an element, or the view of one */
1679
+ declare type RowInput<R extends FieldBase> = R['value'] | R | View<R>;
1680
+
1681
+ /** asked by a validator before it runs: whether the element is sent nowhere, read without tracking */
1682
+ declare const SentNowhere: unique symbol;
1683
+
1473
1684
  /** Writes the members `newConfig` names and leaves the rest as they stand. */
1474
1685
  export declare function setConfig(newConfig: Partial<FormsConfig>): void;
1475
1686
 
@@ -1482,6 +1693,9 @@ export declare interface SimpleComponentDef {
1482
1693
  componentVHtml?: string;
1483
1694
  }
1484
1695
 
1696
+ /** a member of the form in the shape a view hands it out: the view of a container, the value of anything else */
1697
+ declare type Slot<E> = E extends Container ? View<E> : E extends FieldBase ? E['value'] : never;
1698
+
1485
1699
  export declare class Statement {
1486
1700
  private readonly operand1;
1487
1701
  private readonly operator;
@@ -1706,12 +1920,21 @@ declare interface TxStructuralEvent {
1706
1920
  */
1707
1921
  export declare class ValidationError {
1708
1922
  code?: string | undefined;
1923
+ private readonly statedOrigin?;
1709
1924
  /**
1710
- * Machine-readable identifier of what failed, in kebab-case. Every validator this library ships states one, so
1711
- * code that reacts to a particular failure does not have to match the message text, which is translated and
1712
- * configurable. It is optional: an error built by hand carries whatever its author gives it, or nothing.
1925
+ * @param code Machine-readable identifier of what failed, in kebab-case. Every validator this library ships states
1926
+ * one, so code that reacts to a particular failure does not have to match the message text, which is translated
1927
+ * and configurable. It is optional: an error built by hand carries whatever its author gives it, or nothing.
1928
+ * @param statedOrigin Where the error comes from, where its author states it; see `origin`.
1713
1929
  */
1714
- constructor(code?: string | undefined);
1930
+ constructor(code?: string | undefined, statedOrigin?: ErrorOrigin | undefined);
1931
+ /**
1932
+ * Where the error comes from: the origin its author stated, and otherwise `'validator'` for an error a validator
1933
+ * produced - a validator stamps every error it hands a field - and `'application'` for one written into `errors`
1934
+ * by any other code. It is what a rendering layer reads to decide when to show the error, and what code reads to
1935
+ * withdraw the errors of one origin and leave the rest.
1936
+ */
1937
+ get origin(): ErrorOrigin;
1715
1938
  /**
1716
1939
  * True where `other` is an error of this class that renders exactly as this one does and reports the same code.
1717
1940
  * Two runs of one validator over an unchanged value produce two instances of one message, and this is what lets
@@ -1736,7 +1959,7 @@ export declare class ValidationErrorRenderContent extends ValidationError {
1736
1959
  classes: ClassTypes;
1737
1960
  private text;
1738
1961
  private textType;
1739
- constructor(text: RenderContentRef, classes?: ClassTypes, code?: string);
1962
+ constructor(text: RenderContentRef, classes?: ClassTypes, code?: string, origin?: ErrorOrigin);
1740
1963
  get resolvedText(): RenderContentNonCallable;
1741
1964
  get getTextType(): "string" | "md" | "component";
1742
1965
  get componentName(): string;
@@ -1751,7 +1974,7 @@ export declare class ValidationErrorRenderContent extends ValidationError {
1751
1974
  export declare class ValidationErrorText extends ValidationError {
1752
1975
  text: string;
1753
1976
  classes: ClassTypes;
1754
- constructor(text: string, classes?: ClassTypes, code?: string);
1977
+ constructor(text: string, classes?: ClassTypes, code?: string, origin?: ErrorOrigin);
1755
1978
  get componentName(): string;
1756
1979
  get componentBody(): string;
1757
1980
  get extraClasses(): ClassTypes;
@@ -1866,16 +2089,57 @@ declare class ValueInRange<T = any> extends Validator {
1866
2089
  constructor(minValue: T, maxValue: T, message?: RenderContentRef);
1867
2090
  }
1868
2091
 
2092
+ /**
2093
+ * An element seen as its data: the members of a group, or the rows of a list, as plain properties, and the element
2094
+ * itself as `$`. See `view()`.
2095
+ */
2096
+ export declare type View<E extends FieldBase> = (E extends Group<infer F, any> ? GroupData<F> : E extends List<infer R, any> ? ListData<R> : unknown) & {
2097
+ readonly $: E;
2098
+ };
2099
+
2100
+ /**
2101
+ * The element seen as its data. A group's members and a list's rows are plain properties of the view - a field as
2102
+ * its value, a container as its own view - and `$` is the element itself: `view.$.valid`,
2103
+ * `view.$.access = 'readonly'`, `view.$.registerAction(...)`.
2104
+ *
2105
+ * A member reads what the element holds, by the rule `fullValue` follows: every member is there whatever its access,
2106
+ * so a disabled field reads and writes like any other. Every read goes
2107
+ * through the element's tracked state, so an effect reading `view.address.city` re-runs when that field changes and
2108
+ * not when another one does.
2109
+ *
2110
+ * A list's view is an array: it reads like one, and `push`, `pop`, `shift`, `unshift`, `splice`, `sort` and
2111
+ * `reverse` are carried out as the list's own operations, so every row keeps its element and its state.
2112
+ *
2113
+ * One element has one view: `view(element) === view(element)`, and `view()` of a view hands it back.
2114
+ */
2115
+ export declare function view<V extends View<any>>(of: V): V;
2116
+
2117
+ export declare function view<E extends FieldBase>(element: E): View<E>;
2118
+
2119
+ /**
2120
+ * How a rendering layer shows a form element. It is presentation alone: what an element sends and whether it is
2121
+ * validated are its `access`, and no visibility changes either.
2122
+ *
2123
+ * - `'full'`: rendered and shown
2124
+ * - `'invisible'`: rendered and keeps its space in the layout, but is not painted (`visibility: hidden`)
2125
+ * - `'hidden'`: rendered but not displayed, taking no space (`display: none`)
2126
+ * - `'suppress'`: not rendered at all
2127
+ */
2128
+ export declare type Visibility = 'full' | 'invisible' | 'hidden' | 'suppress';
2129
+
1869
2130
  export declare class VisibilityChangedAction extends FieldActionBase {
1870
- constructor(executorFn: (field: FieldBase, supr: FieldActionExecute, newValue: DisplayMode, oldValue: DisplayMode) => void);
2131
+ constructor(executorFn: (field: FieldBase, supr: FieldActionExecute, newValue: Visibility, oldValue: Visibility) => void);
1871
2132
  static get classIdentifier(): symbol;
1872
- execute(field: FieldBase, supr: FieldActionExecute, newValue: DisplayMode, oldValue: DisplayMode): void;
2133
+ execute(field: FieldBase, supr: FieldActionExecute, newValue: Visibility, oldValue: Visibility): void;
1873
2134
  }
1874
2135
 
1875
2136
  export declare class VisibilityChangingAction extends FieldActionBase {
1876
- constructor(executorFn: (field: FieldBase, supr: FieldActionExecute, newValue: DisplayMode, oldValue: DisplayMode) => DisplayMode);
2137
+ constructor(executorFn: (field: FieldBase, supr: FieldActionExecute, newValue: Visibility, oldValue: Visibility) => Visibility);
1877
2138
  static get classIdentifier(): symbol;
1878
- execute(field: FieldBase, supr: FieldActionExecute, newValue: DisplayMode, oldValue: DisplayMode): DisplayMode;
2139
+ execute(field: FieldBase, supr: FieldActionExecute, newValue: Visibility, oldValue: Visibility): Visibility;
1879
2140
  }
1880
2141
 
2142
+ /** every visibility, from shown to not rendered */
2143
+ export declare const visibilityValues: readonly Visibility[];
2144
+
1881
2145
  export { }