@bach.software/vue-dynamic-form 0.7.0 → 0.8.0

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.
Files changed (31) hide show
  1. package/dist/examples.cjs.js +8 -8
  2. package/dist/examples.cjs.js.map +1 -1
  3. package/dist/examples.es.js +689 -542
  4. package/dist/examples.es.js.map +1 -1
  5. package/dist/mapEachMetadataItem-CZmoxEoA.js +1234 -0
  6. package/dist/mapEachMetadataItem-CZmoxEoA.js.map +1 -0
  7. package/dist/mapEachMetadataItem-Dw1U9jf2.cjs +2 -0
  8. package/dist/mapEachMetadataItem-Dw1U9jf2.cjs.map +1 -0
  9. package/dist/src/components/__tests__/DynamicFormItem.test-helpers.d.ts +8 -0
  10. package/dist/src/components/__tests__/DynamicFormItemArray.test-helpers.d.ts +2 -0
  11. package/dist/src/components/__tests__/DynamicFormItemChoice.test-helpers.d.ts +9 -0
  12. package/dist/src/examples/__tests__/TestFormTemplate.testcases.d.ts +233 -0
  13. package/dist/src/index.d.ts +1 -0
  14. package/dist/src/types/FieldMetadata.d.ts +32 -1
  15. package/dist/src/utils/__tests__/deepEqual.test.d.ts +1 -0
  16. package/dist/src/utils/__tests__/hashField.test.d.ts +1 -0
  17. package/dist/src/utils/__tests__/isPathInSection.test.d.ts +1 -0
  18. package/dist/src/utils/buildRestrictionValidations.d.ts +11 -0
  19. package/dist/src/utils/deepEqual.d.ts +9 -0
  20. package/dist/src/utils/isPathInSection.d.ts +9 -0
  21. package/dist/src/utils/removeNullValues.d.ts +4 -0
  22. package/dist/tsconfig.tsbuildinfo +1 -1
  23. package/dist/vue-dynamic-form.cjs.js +1 -1
  24. package/dist/vue-dynamic-form.cjs.js.map +1 -1
  25. package/dist/vue-dynamic-form.es.js +22 -21
  26. package/dist/vue-dynamic-form.es.js.map +1 -1
  27. package/package.json +2 -1
  28. package/dist/mapEachMetadataItem-DwSDJyzo.cjs +0 -2
  29. package/dist/mapEachMetadataItem-DwSDJyzo.cjs.map +0 -1
  30. package/dist/mapEachMetadataItem-DxEO1PDs.js +0 -1186
  31. package/dist/mapEachMetadataItem-DxEO1PDs.js.map +0 -1
@@ -9,6 +9,12 @@ export declare function renderCount(wrapper: ReturnType<typeof mount>, path: str
9
9
  export declare function setupState(wrapper: ReturnType<typeof mount>, path: string): Record<string, any> | undefined;
10
10
  /** Reads the number of times `combinedValidation` was recomputed for a given field. Returns -1 if the field is not found. */
11
11
  export declare function constructValidationCount(wrapper: ReturnType<typeof mount>, path: string): number;
12
+ /**
13
+ * Reads the current `combinedValidation` rules array reference for a given field, for
14
+ * reference-identity assertions. `vm.$.setupState` is `proxyRefs(...)`, which already unwraps
15
+ * the ref on access, so no trailing `.value` is needed here.
16
+ */
17
+ export declare function combinedValidationRules(wrapper: ReturnType<typeof mount>, path: string): unknown;
12
18
  /** Reads the number of times `computedField` was recomputed for a given field. Returns -1 if the field is not found. */
13
19
  export declare function fieldComputeCount(wrapper: ReturnType<typeof mount>, path: string): number;
14
20
  /** Reads the number of times the `field` computed (bound to `props.fieldMetadata`) was recomputed. Returns -1 if the field is not found. */
@@ -17,5 +23,7 @@ export declare function fieldChangedCount(wrapper: ReturnType<typeof mount>, pat
17
23
  export declare function valueChangedCount(wrapper: ReturnType<typeof mount>, path: string): number;
18
24
  /** Reads the number of times the notify value change fired for a given field. Returns -1 if the field is not found. */
19
25
  export declare function notifyValueUpdateCount(wrapper: ReturnType<typeof mount>, path: string): number;
26
+ /** Reads the number of times the non-input subtree silent-validate watcher actually ran (not suppressed) for a given field. Returns -1 if the field is not found. */
27
+ export declare function subtreeValidateCount(wrapper: ReturnType<typeof mount>, path: string): number;
20
28
  /** Returns the current vee-validate form values from the TestForm wrapper. */
21
29
  export declare function formValues(wrapper: ReturnType<typeof mount>): Record<string, any>;
@@ -7,3 +7,5 @@ import type { mount } from '@vue/test-utils';
7
7
  export declare function setupState(wrapper: ReturnType<typeof mount>, path: string): Record<string, any> | undefined;
8
8
  /** Reads how many times the array's `combinedValidation` computed has run. Returns -1 if the array is not found. */
9
9
  export declare function arrayConstructValidationCount(wrapper: ReturnType<typeof mount>, path: string): number;
10
+ /** Reads the array's own `meta.valid`, kept live by the silent validate in the values watcher. Returns undefined if the array is not found. */
11
+ export declare function arrayMetaValid(wrapper: ReturnType<typeof mount>, path: string): boolean | undefined;
@@ -62,6 +62,15 @@ export declare function canAddChoiceOccurrence(wrapper: ReturnType<typeof mount>
62
62
  export declare function usedChoiceOccurrences(wrapper: ReturnType<typeof mount>, choicePath: string): number | undefined;
63
63
  /** Reads the number of rules currently present in `combinedValidation` for the choice at `path`. */
64
64
  export declare function combinedValidationCount(wrapper: ReturnType<typeof mount>, path: string): number;
65
+ /**
66
+ * Reads a branch's own raw form value directly off the choice's `branchValueRefs`, resolving
67
+ * `branchKey` to its internal numeric index via the choice's own metadata. Unlike the fixture's
68
+ * rendered input, this reads the value even when the branch isn't mounted (e.g. before any
69
+ * `addChoiceOccurrence` call).
70
+ */
71
+ export declare function branchValue(wrapper: ReturnType<typeof mount>, choicePath: string, branchKey: string): unknown;
72
+ /** Reads the `effectiveValuesCount` computed (feeding `xsd_choiceMinOccurs`) for the choice at `path`. */
73
+ export declare function effectiveValuesCount(wrapper: ReturnType<typeof mount>, path: string): number | undefined;
65
74
  /** Reads the `maxOccursTotalBreach` computed (the offending branch's cap, or undefined) for the choice at `path`. */
66
75
  export declare function maxOccursTotalBreach(wrapper: ReturnType<typeof mount>, path: string): number | undefined;
67
76
  /**
@@ -471,6 +471,62 @@ export declare const restrictionsSampleValues: {
471
471
  customValidation: string;
472
472
  };
473
473
  };
474
+ export declare const liveValidityTestCase: import("vue").Raw<import("vue").DefineComponent<import("vue").ExtractPropTypes<{
475
+ initialValues: {
476
+ type: PropType<GenericObject>;
477
+ default: undefined;
478
+ };
479
+ initialEdit: {
480
+ type: PropType<boolean | undefined>;
481
+ default: undefined;
482
+ };
483
+ hideFieldsWithoutValue: {
484
+ type: PropType<boolean | undefined>;
485
+ default: undefined;
486
+ };
487
+ settings: {
488
+ type: PropType<DynamicFormSettings | undefined>;
489
+ default: undefined;
490
+ };
491
+ keepValuesOnUnmount: {
492
+ type: PropType<boolean | undefined>;
493
+ default: undefined;
494
+ };
495
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
496
+ [key: string]: any;
497
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
498
+ initialValues: {
499
+ type: PropType<GenericObject>;
500
+ default: undefined;
501
+ };
502
+ initialEdit: {
503
+ type: PropType<boolean | undefined>;
504
+ default: undefined;
505
+ };
506
+ hideFieldsWithoutValue: {
507
+ type: PropType<boolean | undefined>;
508
+ default: undefined;
509
+ };
510
+ settings: {
511
+ type: PropType<DynamicFormSettings | undefined>;
512
+ default: undefined;
513
+ };
514
+ keepValuesOnUnmount: {
515
+ type: PropType<boolean | undefined>;
516
+ default: undefined;
517
+ };
518
+ }>> & Readonly<{}>, {
519
+ initialValues: GenericObject;
520
+ keepValuesOnUnmount: boolean | undefined;
521
+ settings: DynamicFormSettings | undefined;
522
+ initialEdit: boolean | undefined;
523
+ hideFieldsWithoutValue: boolean | undefined;
524
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>>;
525
+ export declare const liveValiditySampleValues: {
526
+ contact: {
527
+ email: string;
528
+ };
529
+ };
474
530
  export declare const arrayOccurrenceTestCase: import("vue").Raw<import("vue").DefineComponent<import("vue").ExtractPropTypes<{
475
531
  initialValues: {
476
532
  type: PropType<GenericObject>;
@@ -801,6 +857,64 @@ export declare const explicitChoiceSampleValues: {
801
857
  };
802
858
  };
803
859
  };
860
+ export declare const presenceValueTestCase: import("vue").Raw<import("vue").DefineComponent<import("vue").ExtractPropTypes<{
861
+ initialValues: {
862
+ type: PropType<GenericObject>;
863
+ default: undefined;
864
+ };
865
+ initialEdit: {
866
+ type: PropType<boolean | undefined>;
867
+ default: undefined;
868
+ };
869
+ hideFieldsWithoutValue: {
870
+ type: PropType<boolean | undefined>;
871
+ default: undefined;
872
+ };
873
+ settings: {
874
+ type: PropType<DynamicFormSettings | undefined>;
875
+ default: undefined;
876
+ };
877
+ keepValuesOnUnmount: {
878
+ type: PropType<boolean | undefined>;
879
+ default: undefined;
880
+ };
881
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
882
+ [key: string]: any;
883
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
884
+ initialValues: {
885
+ type: PropType<GenericObject>;
886
+ default: undefined;
887
+ };
888
+ initialEdit: {
889
+ type: PropType<boolean | undefined>;
890
+ default: undefined;
891
+ };
892
+ hideFieldsWithoutValue: {
893
+ type: PropType<boolean | undefined>;
894
+ default: undefined;
895
+ };
896
+ settings: {
897
+ type: PropType<DynamicFormSettings | undefined>;
898
+ default: undefined;
899
+ };
900
+ keepValuesOnUnmount: {
901
+ type: PropType<boolean | undefined>;
902
+ default: undefined;
903
+ };
904
+ }>> & Readonly<{}>, {
905
+ initialValues: GenericObject;
906
+ keepValuesOnUnmount: boolean | undefined;
907
+ settings: DynamicFormSettings | undefined;
908
+ initialEdit: boolean | undefined;
909
+ hideFieldsWithoutValue: boolean | undefined;
910
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>>;
911
+ export declare const presenceValueSampleValues: {
912
+ checkoutSection: {
913
+ checkout: {
914
+ express: boolean;
915
+ };
916
+ };
917
+ };
804
918
  export declare const preserveOnSwitchTestCase: import("vue").Raw<import("vue").DefineComponent<import("vue").ExtractPropTypes<{
805
919
  initialValues: {
806
920
  type: PropType<GenericObject>;
@@ -861,6 +975,66 @@ export declare const preserveOnSwitchSampleValues: {
861
975
  };
862
976
  };
863
977
  };
978
+ export declare const choiceSelectionResetTestCase: import("vue").Raw<import("vue").DefineComponent<import("vue").ExtractPropTypes<{
979
+ initialValues: {
980
+ type: PropType<GenericObject>;
981
+ default: undefined;
982
+ };
983
+ initialEdit: {
984
+ type: PropType<boolean | undefined>;
985
+ default: undefined;
986
+ };
987
+ hideFieldsWithoutValue: {
988
+ type: PropType<boolean | undefined>;
989
+ default: undefined;
990
+ };
991
+ settings: {
992
+ type: PropType<DynamicFormSettings | undefined>;
993
+ default: undefined;
994
+ };
995
+ keepValuesOnUnmount: {
996
+ type: PropType<boolean | undefined>;
997
+ default: undefined;
998
+ };
999
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
1000
+ [key: string]: any;
1001
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
1002
+ initialValues: {
1003
+ type: PropType<GenericObject>;
1004
+ default: undefined;
1005
+ };
1006
+ initialEdit: {
1007
+ type: PropType<boolean | undefined>;
1008
+ default: undefined;
1009
+ };
1010
+ hideFieldsWithoutValue: {
1011
+ type: PropType<boolean | undefined>;
1012
+ default: undefined;
1013
+ };
1014
+ settings: {
1015
+ type: PropType<DynamicFormSettings | undefined>;
1016
+ default: undefined;
1017
+ };
1018
+ keepValuesOnUnmount: {
1019
+ type: PropType<boolean | undefined>;
1020
+ default: undefined;
1021
+ };
1022
+ }>> & Readonly<{}>, {
1023
+ initialValues: GenericObject;
1024
+ keepValuesOnUnmount: boolean | undefined;
1025
+ settings: DynamicFormSettings | undefined;
1026
+ initialEdit: boolean | undefined;
1027
+ hideFieldsWithoutValue: boolean | undefined;
1028
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>>;
1029
+ export declare const choiceSelectionResetSampleValues: {
1030
+ resetSection: {
1031
+ contact: {
1032
+ email: {
1033
+ address: string;
1034
+ };
1035
+ };
1036
+ };
1037
+ };
864
1038
  export declare const explicitRepeatableChoiceTestCase: import("vue").Raw<import("vue").DefineComponent<import("vue").ExtractPropTypes<{
865
1039
  initialValues: {
866
1040
  type: PropType<GenericObject>;
@@ -1179,6 +1353,65 @@ export declare const computedPropsSampleValues: {
1179
1353
  childA: string;
1180
1354
  };
1181
1355
  };
1356
+ export declare const dynamicRulesTestCase: import("vue").Raw<import("vue").DefineComponent<import("vue").ExtractPropTypes<{
1357
+ initialValues: {
1358
+ type: PropType<GenericObject>;
1359
+ default: undefined;
1360
+ };
1361
+ initialEdit: {
1362
+ type: PropType<boolean | undefined>;
1363
+ default: undefined;
1364
+ };
1365
+ hideFieldsWithoutValue: {
1366
+ type: PropType<boolean | undefined>;
1367
+ default: undefined;
1368
+ };
1369
+ settings: {
1370
+ type: PropType<DynamicFormSettings | undefined>;
1371
+ default: undefined;
1372
+ };
1373
+ keepValuesOnUnmount: {
1374
+ type: PropType<boolean | undefined>;
1375
+ default: undefined;
1376
+ };
1377
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
1378
+ [key: string]: any;
1379
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
1380
+ initialValues: {
1381
+ type: PropType<GenericObject>;
1382
+ default: undefined;
1383
+ };
1384
+ initialEdit: {
1385
+ type: PropType<boolean | undefined>;
1386
+ default: undefined;
1387
+ };
1388
+ hideFieldsWithoutValue: {
1389
+ type: PropType<boolean | undefined>;
1390
+ default: undefined;
1391
+ };
1392
+ settings: {
1393
+ type: PropType<DynamicFormSettings | undefined>;
1394
+ default: undefined;
1395
+ };
1396
+ keepValuesOnUnmount: {
1397
+ type: PropType<boolean | undefined>;
1398
+ default: undefined;
1399
+ };
1400
+ }>> & Readonly<{}>, {
1401
+ initialValues: GenericObject;
1402
+ keepValuesOnUnmount: boolean | undefined;
1403
+ settings: DynamicFormSettings | undefined;
1404
+ initialEdit: boolean | undefined;
1405
+ hideFieldsWithoutValue: boolean | undefined;
1406
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>>;
1407
+ export declare const dynamicRulesSampleValues: {
1408
+ dynamicRules: {
1409
+ country: string;
1410
+ postalCode: string;
1411
+ businessOrder: boolean;
1412
+ vatNumber: string;
1413
+ };
1414
+ };
1182
1415
  export declare const attributesTestCase: import("vue").Raw<import("vue").DefineComponent<import("vue").ExtractPropTypes<{
1183
1416
  initialValues: {
1184
1417
  type: PropType<GenericObject>;
@@ -16,6 +16,7 @@ export * from './types/MetadataConfiguration';
16
16
  export * from './types/RequireOnly';
17
17
  export * from './types/ValidationMessage';
18
18
  export * from './utils/checkTreeHasValue';
19
+ export * from './utils/isPathInSection';
19
20
  export * from './utils/mapEachMetadataItem';
20
21
  export * from './utils/removeNullValues';
21
22
  export * from './utils/setInPath';
@@ -219,6 +219,37 @@ export type FieldMetadata<ExtendedFieldTypes extends string = string, ExtendedPr
219
219
  * `computedProps` cannot flip it mid-form.
220
220
  */
221
221
  wizard?: boolean | WizardConfig;
222
+ /**
223
+ * The value stored in the form when the user selects this choice branch.
224
+ *
225
+ * Normally a branch has fields, and filling those in is what marks the branch as selected.
226
+ * A branch without any fields has nothing to fill in, so without help its value stays
227
+ * `undefined`: validation thinks nothing was selected, and the selection is lost when the
228
+ * form values are submitted or loaded back in. Set `presenceValue` to fix that: the moment
229
+ * the user picks the branch, this value is written as the branch's value, so the selection
230
+ * validates and survives a save/reload round-trip.
231
+ *
232
+ * Any JSON-serializable value works (`true`, `'selected'`, `{}`, ...), except `null` and the
233
+ * empty string: those read as selected but still fail the branch's own required check, so the
234
+ * selection would show an error. When the form loads existing values, the branch shows as
235
+ * selected whenever its value is not `undefined`.
236
+ *
237
+ * Selecting the branch is a session action: `resetForm()` clears a marker written by a click
238
+ * this session and deselects the branch, while a marker that was part of the loaded values is
239
+ * restored and keeps the branch selected.
240
+ *
241
+ * Only useful on a non-repeatable (`maxOccurs: 1`) branch without `children`, inside a
242
+ * `choice` with `explicitChoiceSelection: true`. On other branches it is ignored, because
243
+ * their values already show that they were selected (a repeated branch has its occurrences,
244
+ * a branch with children has its filled-in fields). Using it on a branch with `children`
245
+ * logs a development warning.
246
+ *
247
+ * Two things to keep in mind:
248
+ * - Prefer a non-empty value: if you clean up the submitted values with `removeNullValues`,
249
+ * an empty `{}` or `[]` marker is removed and the selection is lost.
250
+ * - This is static metadata only; `computedProps` cannot set or change it at runtime.
251
+ */
252
+ presenceValue?: unknown;
222
253
  /**
223
254
  * Attributes are additional metadata that can be attached to a field.
224
255
  * These attributes can be used to provide extra information about the field,
@@ -300,7 +331,7 @@ export interface WizardGotoStepOptions {
300
331
  allowForwardJump?: boolean;
301
332
  validateOnJump?: boolean;
302
333
  }
303
- export type ComputedPropsFieldType<ExtendedFieldTypes extends string = string, ExtendedProperties extends object = object> = Omit<FieldMetadata<ExtendedFieldTypes, ExtendedProperties>, 'name' | 'path' | 'parent' | 'children' | 'choice' | 'attributes' | 'fieldOptions' | 'computedProps' | 'maxOccurs' | 'maxOccursTotal' | 'isComplexType' | 'computeOnChildValueChange' | 'explicitChoiceSelection' | 'preserveOnSwitch' | 'displayOrder' | 'preserveOrder' | 'wizard'> & Readonly<{
334
+ export type ComputedPropsFieldType<ExtendedFieldTypes extends string = string, ExtendedProperties extends object = object> = Omit<FieldMetadata<ExtendedFieldTypes, ExtendedProperties>, 'name' | 'path' | 'parent' | 'children' | 'choice' | 'attributes' | 'fieldOptions' | 'computedProps' | 'maxOccurs' | 'maxOccursTotal' | 'isComplexType' | 'computeOnChildValueChange' | 'explicitChoiceSelection' | 'preserveOnSwitch' | 'displayOrder' | 'preserveOrder' | 'wizard' | 'presenceValue'> & Readonly<{
304
335
  name: string;
305
336
  path: string;
306
337
  parent: FieldMetadata<ExtendedFieldTypes, ExtendedProperties>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import type { GenericValidateFunction } from 'vee-validate';
2
+ import type { DynamicFormSettings } from '../types/DynamicFormSettings';
3
+ import type { FieldMetadata } from '../types/FieldMetadata';
4
+ /**
5
+ * Builds the XSD restriction rules plus any custom validation declared directly on a field,
6
+ * shared by every place that registers a vee-validate field for that metadata (a plain field, or
7
+ * a choice-hosting field whose own restriction/validation is folded into its nested choice).
8
+ * Required/minOccurs is intentionally not part of this: it is a separate concern each caller
9
+ * decides for itself.
10
+ */
11
+ export declare function buildRestrictionValidations(restriction: FieldMetadata['restriction'] | undefined, validation: FieldMetadata['validation'], messages: DynamicFormSettings['messages'] | undefined): GenericValidateFunction[];
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Compares two values by content instead of by reference. Primitives, plain objects, arrays and
3
+ * Dates are compared recursively; everything else (functions, class instances, Maps, ...) only
4
+ * counts as equal when it is the exact same reference.
5
+ *
6
+ * Mirrors the value scope of `deepCloneValue`. Useful to detect "rebuilt but identical" objects,
7
+ * such as metadata that computedProps functions recreate on every run.
8
+ */
9
+ export declare function deepEqual(a: unknown, b: unknown): boolean;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Checks whether a field path falls at or under a section path.
3
+ * Matches the section itself, `section.child`, and `section[0]`, but not
4
+ * unrelated paths that happen to share a prefix string (e.g. `addressLine` vs `address`).
5
+ *
6
+ * @param path - Dot-notated field path (e.g. `'address.street'` or `'contacts[0].email'`)
7
+ * @param sectionPath - Dot-notated path prefix (e.g. `'address'` or `'contacts[0]'`)
8
+ */
9
+ export declare function isPathInSection(path: string, sectionPath: string): boolean;
@@ -1,5 +1,9 @@
1
1
  /**
2
2
  * Removes all null value's from object properties and array's.
3
+ *
4
+ * Note: an empty-object or empty-array `presenceValue` marker on a choice branch is stripped
5
+ * back to `undefined` by this cleanup, same as any other empty object/array; use a non-empty
6
+ * marker if the branch's selection must survive this round-trip.
3
7
  * @param element any value
4
8
  */
5
9
  export declare function removeNullValues<T>(element: T): T | undefined;