@dynamicforms/vue-forms 0.13.0 → 0.16.1

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
@@ -4,10 +4,16 @@ import { DefineComponent } from 'vue';
4
4
  import { PublicProps } from 'vue';
5
5
  import { Ref } from 'vue';
6
6
 
7
+ /**
8
+ * Thrown from a handler to end the run it is in. What the trigger answers with is the exception itself rather than
9
+ * `null`, so a caller can tell a run a handler ended from one that reached no handler at all - and the setters
10
+ * that ask a `*Changing*` handler read it as a refusal and write nothing.
11
+ */
7
12
  export declare class AbortEventHandlingException extends Error {
8
13
  }
9
14
 
10
15
  export declare class Action<T extends ActionValue = ActionValue, X extends object = {}> extends Field<T, X> {
16
+ get [Symbol.toStringTag](): string;
11
17
  protected init(params?: IFieldParams<T, X>): void;
12
18
  /**
13
19
  * A copy of the value this action holds, carrying one member rewritten. A member handed undefined is dropped
@@ -47,18 +53,22 @@ export declare class Action<T extends ActionValue = ActionValue, X extends objec
47
53
  declare type ActionExecutor = (field: FieldBase, supr: FieldActionExecute, ...params: any[]) => any;
48
54
 
49
55
  /**
50
- * The actions one element has registered, grouped by the identifier they are triggered under. Within a group the
51
- * actions stand in registration order and are run from the end backwards, so the newest registration is the
56
+ * The actions one declaration has registered, in registration order. A trigger walks them from the end backwards
57
+ * and passes over the ones registered under another identifier, so the newest registration of an identifier is its
52
58
  * outermost handler and reaches the ones before it through the `supr` it is handed. A handler that does not call
53
59
  * `supr` ends the run there, and one that calls it may transform what it answers with.
60
+ *
61
+ * The order is the whole index. An element carries a handful of actions, and a walk over that many is cheaper than
62
+ * a keyed lookup as well as smaller: measured over three actions, the walk is about twice as fast as `Map.get` and
63
+ * the two maps it replaces cost about 500 bytes per declaration.
54
64
  */
55
65
  export declare class ActionsMap {
56
- /** every action registered here, in registration order across all identifiers */
57
- private readonly registeredActions;
58
- /** the actions of one identifier, in registration order */
59
- private readonly chains;
60
- /** the eager actions of one identifier, in registration order; a subsequence of the chain under that identifier */
61
- private readonly eagerChains;
66
+ /**
67
+ * Every action registered here, in registration order. It is replaced rather than written when an action is
68
+ * dropped, so a run already walking it finishes on the array it started with and the removal takes effect from
69
+ * the next trigger.
70
+ */
71
+ private actions;
62
72
  /**
63
73
  * Registers `action`. It becomes the outermost handler of its identifier, or - where `before` is given and is
64
74
  * registered here under the same identifier - takes that action's place in the order, so `before` wraps it and
@@ -66,11 +76,7 @@ export declare class ActionsMap {
66
76
  * inside a handler already there.
67
77
  */
68
78
  register(action: FieldActionBase, before?: FieldActionBase): void;
69
- /**
70
- * Drops `action` from this map and answers whether it was in it. The lists it stood in are replaced rather than
71
- * written, so a run already walking one finishes on the list it started with and the removal takes effect from
72
- * the next trigger.
73
- */
79
+ /** Drops `action` and answers whether it was registered here. */
74
80
  unregister(action: FieldActionBase): boolean;
75
81
  /** True where something is registered under `identifier`. */
76
82
  willTrigger(identifier: symbol): boolean;
@@ -80,29 +86,35 @@ export declare class ActionsMap {
80
86
  trigger<T extends FieldActionBase>(ActionClass: (abstract new (...args: any[]) => T) & {
81
87
  classIdentifier: symbol;
82
88
  }, field: FieldBase, ...params: any[]): any;
83
- /** Runs the eager actions of every identifier, each group on its own. */
89
+ /**
90
+ * Runs the eager actions of every identifier, each group on its own. A group is entered at its outermost eager
91
+ * action, which is the last one registered under that identifier.
92
+ */
84
93
  triggerEager(field: FieldBase, ...params: any[]): void;
85
94
  /** Runs the eager actions registered under `identifier` and nothing else. */
86
95
  triggerEagerFor(identifier: symbol, field: FieldBase, ...params: any[]): any;
87
- /** the validators registered in this map, in registration order */
96
+ /** the validators registered here, in registration order */
88
97
  get validators(): Validator[];
89
- clone(): ActionsMap;
90
98
  /**
91
- * Tells every action in this map that it serves `owner`. A copied map holds the instances the original holds, so
92
- * the element that took the copy on is announced to them here, the way registering an action announces the
93
- * element it was registered on.
99
+ * Tells every action here that it serves `owner`. A binding reads the map its declaration holds, so this is what
100
+ * announces the new element to the actions already in it - the way registering an action announces the elements
101
+ * it comes to serve.
94
102
  */
95
103
  bindTo(owner: FieldBase): void;
104
+ /** True where no eager action of `identifier` stands after `index`, which makes `index` the group's entry. */
105
+ private static outermostEager;
96
106
  /**
97
- * Walks `chain` from the end backwards, handing each action a `supr` that continues at the one before it. The
98
- * closures exist for the length of the run and only as deep as the run actually goes, so a chain nobody walks to
99
- * the bottom costs nothing for the part left unreached.
107
+ * Enters a group at its outermost action. An abort ends the run and is answered with rather than raised: the
108
+ * exception is what the caller receives, so a run a handler ended is told apart from one that reached no handler
109
+ * and from one whose handler answered null.
100
110
  */
101
- private step;
102
- /** Walks a chain, answering null where there is none. An abort ends the run and is not an error to the caller. */
103
111
  private run;
104
- private insert;
105
- private remove;
112
+ /**
113
+ * Walks from `index` backwards to the first action of `identifier`, handing it a `supr` that continues at the one
114
+ * before it. The actions registered under other identifiers are passed over, so the array needs no grouping of
115
+ * its own; the closures exist for the length of the run and only as deep as the run actually goes.
116
+ */
117
+ private walk;
106
118
  }
107
119
 
108
120
  export declare interface ActionValue {
@@ -241,6 +253,9 @@ declare interface ContainerSlots<T = any> extends ElementSlots<T> {
241
253
  cachedValueVersion: number;
242
254
  }
243
255
 
256
+ /** What a form element's visibility is when nothing sets it. It is a starting value, never a fallback for input. */
257
+ export declare const defaultDisplayMode = DisplayMode.FULL;
258
+
244
259
  /**
245
260
  * DisplayMode enum provides an enumeration for supported ways of rendering a particular object in the DOM
246
261
  */
@@ -252,8 +267,22 @@ export declare enum DisplayMode {
252
267
  }
253
268
 
254
269
  export declare namespace DisplayMode {
270
+ /**
271
+ * Resolves a constant's name, case insensitive, to the constant it names. Anything else - a misspelled name, a
272
+ * value that is not a string - throws an `Error` naming it. A mode nobody defined is an error at the point it
273
+ * arrives, not a field that renders as `FULL` and is never questioned.
274
+ */
255
275
  export function fromString(mode: string): DisplayMode;
276
+ /**
277
+ * Resolves a DisplayMode number, or a constant's name (case insensitive), to a DisplayMode. A number that is
278
+ * none of the constants, a string that names none, and input that is neither a number nor a string all throw an
279
+ * `Error` naming the value. Ask `isDefined` where the answer is to be judged rather than raised.
280
+ */
256
281
  export function fromAny(mode: any): DisplayMode;
282
+ /**
283
+ * Answers whether the input is a DisplayMode: a number that is one of the constants, or a string naming one,
284
+ * case insensitive. This is the way to ask that does not throw; it answers `false` where `fromAny` raises.
285
+ */
257
286
  export function isDefined(mode: number | string): boolean;
258
287
  }
259
288
 
@@ -316,8 +345,6 @@ declare interface ElementSlots<T = any> {
316
345
  invalidChildren: number;
317
346
  }
318
347
 
319
- export declare const EmptyField: Field<string, {}>;
320
-
321
348
  export declare class EnabledChangedAction extends FieldActionBase {
322
349
  constructor(executorFn: (field: FieldBase, supr: FieldActionExecute, newValue: boolean, oldValue: boolean) => void);
323
350
  static get classIdentifier(): symbol;
@@ -337,6 +364,7 @@ export declare class ExecuteAction extends FieldActionBase {
337
364
  }
338
365
 
339
366
  export declare class Field<T = any, X extends object = {}> extends FieldBase<T, X> {
367
+ get [Symbol.toStringTag](): string;
340
368
  protected get state(): FieldSlots<T>;
341
369
  protected get raw(): FieldSlots<T>;
342
370
  /** the value slot itself, without the notifications the value setter carries around a write */
@@ -355,6 +383,12 @@ export declare class Field<T = any, X extends object = {}> extends FieldBase<T,
355
383
  protected init(params?: IFieldParams<T, X>): void;
356
384
  get value(): T;
357
385
  set value(newValue: T);
386
+ /**
387
+ * The container that holds this field. A `List` holds rows and a row is a `Group`, so a field is never a `List`'s
388
+ * child and the link is a `Group` wherever there is one: `field.parent?.fields.other` is the sibling lookup, and
389
+ * it is typed here.
390
+ */
391
+ get parent(): Group | undefined;
358
392
  get touched(): boolean;
359
393
  set touched(touched: boolean);
360
394
  bind(data?: T, overrides?: IBindParams<T, X>): this;
@@ -412,6 +446,19 @@ export declare abstract class FieldBase<T = any, X extends object = {}> {
412
446
  */
413
447
  get __v_skip(): boolean;
414
448
  get __v_isReactive(): boolean;
449
+ /**
450
+ * Names the element's class, which is what a structural comparison of two elements answers on. An element keeps
451
+ * its state in private class fields, so a walk over own keys reaches none of it; lodash reads this tag through
452
+ * Object.prototype.toString before it compares anything, and a tag it does not know ends the comparison there.
453
+ * Two elements are therefore equal only where they are the same element. What they hold is compared as
454
+ * isEqual(a.value, b.value).
455
+ *
456
+ * It is an accessor on the prototype, so an element carries nothing for it, and `Object.prototype.toString`
457
+ * answers `[object Field]` rather than `[object Object]`. Each class states its own name as a literal: a
458
+ * minifier renames the class itself, so reading the constructor's name would report whatever the build called
459
+ * it.
460
+ */
461
+ get [Symbol.toStringTag](): string;
415
462
  constructor(slots: ElementSlots<T>);
416
463
  /** the tracked view of this element's state; a subclass narrows the return type to its own slots */
417
464
  protected get state(): ElementSlots<T>;
@@ -569,8 +616,17 @@ export declare abstract class FieldBase<T = any, X extends object = {}> {
569
616
  * undefined while no container holds it. The container writes it; everyone else reads it. The read is tracked,
570
617
  * so an effect rendering off the link - `v-if="field.parent"` - re-runs when a container takes the element or
571
618
  * releases it.
619
+ *
620
+ * A `List` holds rows and a row is a `Group`, so only a container can be a `List`'s child: `Field` narrows the
621
+ * type to `Group | undefined`, and the sibling lookup `field.parent?.fields.other` is typed on a field.
572
622
  */
573
- get parent(): Group | undefined;
623
+ get parent(): Group | List | undefined;
624
+ /**
625
+ * The same link at the type the internals reach through. The protected members a container is told things
626
+ * through - childValidatingChanged, childValidityChanged - are declared here, and a union of two subclasses is
627
+ * not an instance of this class, which is what a protected access needs.
628
+ */
629
+ private get container();
574
630
  /** when member of a Group, fieldName specifies the name of this field. Written by the group, read-only after */
575
631
  get fieldName(): string | undefined;
576
632
  /**
@@ -608,13 +664,30 @@ export declare abstract class FieldBase<T = any, X extends object = {}> {
608
664
  /** Runs this element's eager actions over the value it holds and re-forms the verdict they reach. */
609
665
  private rerunEagerActions;
610
666
  /**
611
- * The map this element registers its actions in, absent while it has registered none. Code that only triggers
612
- * reads this slot rather than `actions`, so an element with nothing registered stays free of a map: `actions`
613
- * allocates one for whoever asks, and a trigger over an empty map does nothing anyway.
667
+ * The map an element that was declared rather than bound registers its actions in, absent while it has registered
668
+ * none. A binding holds no map of its own: `boundActions` reads the one its declaration holds.
614
669
  */
615
670
  protected _actions?: ActionsMap;
671
+ /**
672
+ * The actions this element answers to, absent where nothing is registered. A binding holds the very map its
673
+ * declaration holds rather than a copy of it, so the slot is read directly: what a trigger costs is one property
674
+ * read, and a rule registered on a `List`'s item template reaches every row through the map they share - the
675
+ * rows built before the registration as much as the ones built after.
676
+ */
677
+ protected get boundActions(): ActionsMap | undefined;
678
+ /** Records that `binding` was made from this element, so a later registration can reach it. */
679
+ protected noteBinding(binding: FieldBase): void;
680
+ /**
681
+ * The bindings made from this element that are still alive, and this element itself. The dead references are
682
+ * dropped as they are found, which is what keeps the set from growing over the life of a long-lived declaration.
683
+ */
684
+ protected get boundElements(): FieldBase[];
685
+ /**
686
+ * The map registrations go into: the declaration's, since that is where behaviour lives. The map is made on the
687
+ * first registration and handed to every binding already made from the declaration, so all of them go on reading
688
+ * one map through a slot of their own.
689
+ */
616
690
  protected get actions(): ActionsMap;
617
- protected set actions(newValue: ActionsMap);
618
691
  /**
619
692
  * Counts the writes that have changed the value of this element or of anything below it. A container reads it
620
693
  * before answering from its value cache, and the read is an ordinary tracked one, so an effect that took a
@@ -637,6 +710,25 @@ export declare abstract class FieldBase<T = any, X extends object = {}> {
637
710
  * different list whatever the items compare as - so the commit announces it without composing a comparison.
638
711
  */
639
712
  protected propagateValueChanged(force?: boolean): void;
713
+ /**
714
+ * The last step of a construction: it runs inside the transaction the construction is, with the parameters
715
+ * applied and the value in place, before the element records what it was built as.
716
+ *
717
+ * A subclass overrides it to complete what the element was built with. What it writes here is part of the
718
+ * construction rather than a change of it: the element announces no ValueChangedAction, and what the hook
719
+ * leaves is what its eager actions and its validators run over, once. An element whose parameters named no
720
+ * `originalValue` is baselined on the value the hook left and so starts unchanged; one that named a baseline is
721
+ * measured against it, as any element is. A `Field` writes
722
+ * `_value`, which reaches the slot on an element built `enabled: false` as well - the value setter, which a
723
+ * disabled field refuses, states a change, and this is not one.
724
+ *
725
+ * A container completes itself through its members, and a member carries a construction of its own: the write
726
+ * reaches it as any later one would, so the member announces it and reports itself changed. A member that is to
727
+ * start unchanged is baselined here as well - `this.fields.x.originalValue = this.fields.x.value`.
728
+ *
729
+ * `params` is the parameter object the constructor received, where it received one.
730
+ */
731
+ protected constructed(params?: object): void;
640
732
  /**
641
733
  * Re-reads the value that the next ValueChangedAction will report as the one it replaces. A leaf records what
642
734
  * it announced at every announcement, so its copy is always current and there is nothing to re-read; a
@@ -701,6 +793,12 @@ export declare abstract class FieldBase<T = any, X extends object = {}> {
701
793
  * pass of its own.
702
794
  */
703
795
  protected get composesValue(): boolean;
796
+ /**
797
+ * Whether `child` composes its value from members of its own. It is what lets a container tell a nested
798
+ * container from a leaf without knowing the classes below it, the way `resetChild` reaches a reset it does not
799
+ * know the shape of.
800
+ */
801
+ protected childComposesValue(child: FieldBase): boolean;
704
802
  /**
705
803
  * Announces what this element's value became over the transaction. The pair carried is (value now, value at the
706
804
  * last announcement), so a value that went A -> B -> A within the transaction says nothing, and the events an
@@ -789,6 +887,7 @@ export declare type FieldsToValues<T extends GenericFieldsInterface> = {
789
887
  declare namespace Form {
790
888
  export {
791
889
  DisplayMode,
890
+ defaultDisplayMode,
792
891
  transaction,
793
892
  TransactionControl,
794
893
  FieldActionBase,
@@ -815,7 +914,6 @@ declare namespace Form {
815
914
  MessagesWidget,
816
915
  Field,
817
916
  NullableField,
818
- EmptyField,
819
917
  IFieldConstructorActionsList,
820
918
  IFieldConstructorParams,
821
919
  IFieldParams,
@@ -848,11 +946,7 @@ declare namespace Form {
848
946
  ValidationError,
849
947
  ValidationErrorText,
850
948
  ValidationErrorRenderContent,
851
- RenderableValue,
852
- ValidationFunctionResult,
853
- ValidationFunction,
854
- ValidatorBindingState,
855
- Validator
949
+ RenderableValue
856
950
  }
857
951
  }
858
952
  export default Form;
@@ -878,6 +972,7 @@ export declare type GenericFieldsInterface = Record<string, FieldBase>;
878
972
  export declare function getConfig(): FormsConfig;
879
973
 
880
974
  export declare class Group<T extends GenericFieldsInterface = GenericFieldsInterface, X extends object = {}> extends FieldBase<GroupValue<T>, X> {
975
+ get [Symbol.toStringTag](): string;
881
976
  protected get state(): GroupSlots<GroupValue<T>>;
882
977
  protected get raw(): GroupSlots<GroupValue<T>>;
883
978
  private readonly _fields;
@@ -970,6 +1065,13 @@ export declare class Group<T extends GenericFieldsInterface = GenericFieldsInter
970
1065
  get busy(): boolean;
971
1066
  protected composeBusy(): boolean;
972
1067
  validate(revalidate?: boolean): void;
1068
+ /**
1069
+ * States that `res` was built from the members handed to it. A subclass whose constructor takes something other
1070
+ * than `(fields, params)` - one that composes its own members and passes them to super - never sees them, and
1071
+ * would answer with a binding carrying the declaration's data instead of the record's. That is a difference no
1072
+ * reader would find, so it is refused here rather than returned.
1073
+ */
1074
+ private static assertTookFields;
973
1075
  bind(data?: GroupValueInput<T>, overrides?: IBindParams<GroupValueInput<T>, X>): Group<T, X>;
974
1076
  /**
975
1077
  * A record need not name every member: a key it leaves out is taken from the declaration, the same way a member
@@ -998,12 +1100,12 @@ export declare type GroupValue<T extends GenericFieldsInterface> = Partial<Field
998
1100
  export declare type GroupValueInput<T extends GenericFieldsInterface> = Partial<FieldsToValues<T>> | null;
999
1101
 
1000
1102
  /**
1001
- * What bind() accepts beside the data it binds: everything a constructor takes except the value, which the data
1002
- * argument states. Of the members named here, bind() reads `originalValue`, `enabled` and `visibility`;
1003
- * `validators` and `actions` state what to register and are carried by the binding from its declaration, and the
1004
- * rest are the element's to establish.
1103
+ * What bind() accepts beside the data it binds: the three members a binding takes over from the element it was
1104
+ * bound from, and the extended properties. What is left out is left out because a binding cannot honour it -
1105
+ * `validators` and `actions` are carried from the declaration rather than supplied, and `touched` and `errors`
1106
+ * are what the binding establishes for itself as it validates.
1005
1107
  */
1006
- export declare type IBindParams<T = any, X extends object = {}> = Partial<Omit<IFieldConstructorParams<T>, 'value'>> & Partial<NoInfer<X>>;
1108
+ export declare type IBindParams<T = any, X extends object = {}> = Partial<Pick<IFieldConstructorParams<T>, 'originalValue' | 'enabled' | 'visibility'>> & Partial<NoInfer<X>>;
1007
1109
 
1008
1110
  export declare interface IFieldConstructorActionsList {
1009
1111
  actions?: FieldActionBase[];
@@ -1058,6 +1160,7 @@ declare class LengthInRange extends Validator {
1058
1160
  }
1059
1161
 
1060
1162
  export declare class List<T extends GenericFieldsInterface = GenericFieldsInterface, X extends object = {}> extends FieldBase<ListValue, X> {
1163
+ get [Symbol.toStringTag](): string;
1061
1164
  protected get state(): ListSlots<T>;
1062
1165
  protected get raw(): ListSlots<T>;
1063
1166
  private _itemTemplate?;
@@ -1300,7 +1403,14 @@ export declare class Statement {
1300
1403
  * operands is at fault, so the error points at the place the name was written.
1301
1404
  */
1302
1405
  private static validateOperand;
1303
- /** @throws TypeError where an operand the statement reads is undefined or a function. */
1406
+ /**
1407
+ * `NOT` reads one operand, so it is stated with one. Every other operator compares two and takes both, and so
1408
+ * does an operator held in a variable - `Operator.fromString()` answers with the type rather than with the
1409
+ * constant, and the compiler cannot tell from it which of the two forms is meant.
1410
+ *
1411
+ * @throws TypeError where an operand the statement reads is undefined or a function.
1412
+ */
1413
+ constructor(operand1: OperandType, operator: Operator.NOT);
1304
1414
  constructor(operand1: OperandType, operator: Operator, operand2: OperandType);
1305
1415
  /**
1306
1416
  * The value an operand contributes. A field operand names a field of the record the statement is evaluated in:
@@ -1483,6 +1593,17 @@ export declare class ValidationError {
1483
1593
  * configurable. It is optional: an error built by hand carries whatever its author gives it, or nothing.
1484
1594
  */
1485
1595
  constructor(code?: string | undefined);
1596
+ /**
1597
+ * True where `other` is an error of this class that renders exactly as this one does and reports the same code.
1598
+ * Two runs of one validator over an unchanged value produce two instances of one message, and this is what lets
1599
+ * the validator hand the field back the instance it already holds rather than a fresh one: an equal error is not
1600
+ * a new error, and nothing re-renders over a verdict that did not move.
1601
+ *
1602
+ * The comparison is over what renders - the component, its bindings, its body and the classes - because that is
1603
+ * what a reader of `field.errors` sees. A structural comparison of the errors themselves answers nothing useful:
1604
+ * `ValidationErrorRenderContent` holds a Vue `computed`, and two of those are never structurally equal.
1605
+ */
1606
+ sameAs(other: ValidationError): boolean;
1486
1607
  get componentName(): string;
1487
1608
  get componentBindings(): {};
1488
1609
  get componentBody(): string;
@@ -1523,15 +1644,15 @@ export declare class ValidationErrorText extends ValidationError {
1523
1644
  * was unwound - so an asynchronous check hands it to the work it commissions and stops paying for an answer nobody
1524
1645
  * will read. A function that has nothing to cancel ignores it.
1525
1646
  */
1526
- export declare type ValidationFunction<T = any> = (newValue: T, oldValue: T, field: FieldBase<T>, signal: AbortSignal) => ValidationFunctionResult | Promise<ValidationFunctionResult>;
1647
+ declare type ValidationFunction<T = any> = (newValue: T, oldValue: T, field: FieldBase<T>, signal: AbortSignal) => ValidationFunctionResult | Promise<ValidationFunctionResult>;
1527
1648
 
1528
- export declare type ValidationFunctionResult = ValidationError[] | null;
1649
+ declare type ValidationFunctionResult = ValidationError[] | null;
1529
1650
 
1530
1651
  /**
1531
1652
  * Validator is a specialized action that performs validation when a field's value changes.
1532
1653
  * It automatically adds/removes validation errors from the field's errors array.
1533
1654
  */
1534
- export declare class Validator<T = any> extends ValueChangedAction {
1655
+ declare class Validator<T = any> extends ValueChangedAction {
1535
1656
  private readonly source;
1536
1657
  /**
1537
1658
  * Creates a new validator
@@ -1582,7 +1703,7 @@ export declare class Validator<T = any> extends ValueChangedAction {
1582
1703
  }
1583
1704
 
1584
1705
  /** What a validator remembers about one field it is registered on; a subclass widens it. */
1585
- export declare interface ValidatorBindingState {
1706
+ declare interface ValidatorBindingState {
1586
1707
  run: number;
1587
1708
  /** cancels the asynchronous run in flight over the field, absent while no run is waiting for its verdict */
1588
1709
  abandon?: () => void;
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@dynamicforms/vue-forms",
3
3
  "private": false,
4
- "version": "0.13.0",
4
+ "version": "0.16.1",
5
5
  "type": "module",
6
6
  "description": "A lightweight Vue.js library for form state management with built-in validation, conditional logic, nested structures, and a rich event system. UI-agnostic and TypeScript-first.",
7
- "author": "Jure Erznožnik",
7
+ "author": "Jure Erzno\u017enik",
8
8
  "files": [
9
9
  "dist/*"
10
10
  ],
@@ -61,23 +61,35 @@
61
61
  "vue": "^3.5.2"
62
62
  },
63
63
  "devDependencies": {
64
+ "@eslint/js": "^10.0.1",
64
65
  "@types/lodash-es": "^4.17.12",
65
66
  "@types/markdown-it-attrs": "^4.1.3",
66
- "@types/node": "^24.5.2",
67
+ "@types/node": "^26.2.0",
68
+ "@typescript-eslint/eslint-plugin": "^8.67.0",
69
+ "@typescript-eslint/parser": "^8.67.0",
67
70
  "@vitejs/plugin-vue": "^6",
68
71
  "@vitest/coverage-v8": "^3",
69
72
  "@vue/test-utils": "^2.2.4",
70
73
  "@vue/tsconfig": "^0.7.0",
71
74
  "baseline-browser-mapping": "^2.8.31",
72
- "eslint-config-velis": "^2.0.11",
75
+ "eslint": "^10.4.0",
76
+ "eslint-config-prettier": "^10.1.8",
77
+ "eslint-config-velis": "^3.0.0",
78
+ "eslint-import-resolver-typescript": "^4.4.5",
79
+ "eslint-plugin-import-x": "^4.17.1",
80
+ "eslint-plugin-prettier": "^5.5.6",
81
+ "eslint-plugin-unicorn": "^73.0.0",
82
+ "eslint-plugin-vue": "^10.10.0",
73
83
  "jsdom": "^26.0.0",
74
84
  "markdown-it-attrs": "^4.3.1",
85
+ "prettier": "^3.9.6",
75
86
  "rollup-plugin-visualizer": "^5.14.0",
76
87
  "typescript": "^5",
77
88
  "vite": "^7",
78
89
  "vite-plugin-dts": "^4",
79
90
  "vite-plugin-eslint": "^1.8.1",
80
91
  "vitest": "^3",
92
+ "vue-eslint-parser": "^10.4.1",
81
93
  "vue-markdown-render": "^2.3.0",
82
94
  "vue-tsc": "^2"
83
95
  }
package/readme.md CHANGED
@@ -38,6 +38,8 @@ mechanism applies at every level of a nested form.
38
38
  - **Validation**: built-in validators, custom synchronous and asynchronous rules, cross-field comparisons, and
39
39
  errors that carry a `code` and render as text, markdown or a component of your own
40
40
  - **Conditional logic**: visibility, enablement and values declared as statements over other fields
41
+ - **Extended properties**: a field carries whatever your UI renders it with — a label, a hint, a width — declared
42
+ as a second type argument, checked by the compiler and read through `extra`
41
43
  - **Display modes**: control field visibility with different display modes (Full, Hidden, Invisible, Suppress)
42
44
  - **TypeScript support**: full type definitions, and a group's value type inferred from the fields it holds
43
45
  - **Lightweight**: `vue` (^3.5.2) is the only peer dependency and `lodash-es` the only runtime one