@bluprynt/forms-core 4.0.1 → 4.1.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.
- package/README.md +12 -1
- package/dist/form-definition.schema.json +388 -2
- package/dist/index.cjs +1395 -41
- package/dist/index.d.cts +637 -47
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +637 -47
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1391 -42
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -86,6 +86,18 @@ const resolveRelativeDate = (relative, now) => {
|
|
|
86
86
|
*
|
|
87
87
|
* **Date handling**: condition values that are relative date expressions
|
|
88
88
|
* (e.g. `"+7d"`) are resolved against `ctx.now` before comparison.
|
|
89
|
+
*
|
|
90
|
+
* **Multiselect handling**: when `ctx.fieldTypes` reports the referenced field
|
|
91
|
+
* as `multiselect`, its array value is compared as a set instead of a scalar:
|
|
92
|
+
* `set` means "at least one option chosen", `eq`/`ne` compare set membership
|
|
93
|
+
* ignoring order and duplicates, `in`/`notin` test whether *any* chosen option
|
|
94
|
+
* appears in the condition's list, and the ordering operators are always
|
|
95
|
+
* `false`. Fields of every other type -- including `array` -- keep the original
|
|
96
|
+
* scalar semantics.
|
|
97
|
+
*
|
|
98
|
+
* **Object-valued fields** (`file`, `sustainability`) go through the scalar path
|
|
99
|
+
* too, so only `set`/`notset` are meaningful: any object present counts as
|
|
100
|
+
* `set`, and `eq`/`ne`/`in`/`notin` compare by reference and so never match.
|
|
89
101
|
*/
|
|
90
102
|
var ConditionEvaluator = class {
|
|
91
103
|
/**
|
|
@@ -104,6 +116,7 @@ var ConditionEvaluator = class {
|
|
|
104
116
|
evalSimple(cond, ctx) {
|
|
105
117
|
if (ctx.visibilityMap && ctx.visibilityMap.get(cond.field) === false) return cond.op === "notset";
|
|
106
118
|
const fieldValue = ctx.values[String(cond.field)];
|
|
119
|
+
if (ctx.fieldTypes?.get(cond.field) === "multiselect") return this.evalMultiselect(cond, fieldValue);
|
|
107
120
|
switch (cond.op) {
|
|
108
121
|
case "set": return fieldValue !== null && fieldValue !== void 0 && fieldValue !== "";
|
|
109
122
|
case "notset": return fieldValue === null || fieldValue === void 0 || fieldValue === "";
|
|
@@ -118,6 +131,32 @@ var ConditionEvaluator = class {
|
|
|
118
131
|
default: return false;
|
|
119
132
|
}
|
|
120
133
|
}
|
|
134
|
+
evalMultiselect(cond, fieldValue) {
|
|
135
|
+
const selected = Array.isArray(fieldValue) ? fieldValue : [];
|
|
136
|
+
const candidates = cond.value;
|
|
137
|
+
switch (cond.op) {
|
|
138
|
+
case "set": return selected.length > 0;
|
|
139
|
+
case "notset": return selected.length === 0;
|
|
140
|
+
case "eq": return this.sameSet(selected, candidates);
|
|
141
|
+
case "ne": return !this.sameSet(selected, candidates);
|
|
142
|
+
case "in": return Array.isArray(candidates) && selected.some((item) => candidates.includes(item));
|
|
143
|
+
case "notin": return Array.isArray(candidates) && !selected.some((item) => candidates.includes(item));
|
|
144
|
+
default: return false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Compares the chosen options against a condition value as sets, ignoring
|
|
149
|
+
* order and duplicates. A scalar condition value is read as a one-element
|
|
150
|
+
* set, so `{ op: 'eq', value: 'a' }` means "`a` is the only option chosen".
|
|
151
|
+
*/
|
|
152
|
+
sameSet(selected, expected) {
|
|
153
|
+
const expectedItems = Array.isArray(expected) ? expected : [expected];
|
|
154
|
+
const selectedSet = new Set(selected);
|
|
155
|
+
const expectedSet = new Set(expectedItems);
|
|
156
|
+
if (selectedSet.size !== expectedSet.size) return false;
|
|
157
|
+
for (const item of expectedSet) if (!selectedSet.has(item)) return false;
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
121
160
|
resolveIfDate(value, now) {
|
|
122
161
|
if (isRelativeDate(value)) return resolveRelativeDate(value, now);
|
|
123
162
|
return value;
|
|
@@ -378,6 +417,93 @@ var DependencyGraph = class DependencyGraph {
|
|
|
378
417
|
}
|
|
379
418
|
};
|
|
380
419
|
//#endregion
|
|
420
|
+
//#region src/validators/array-obj-validator.ts
|
|
421
|
+
const isRow = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
422
|
+
/**
|
|
423
|
+
* Validates an `array_obj` field: the row list itself, then every sub-field of
|
|
424
|
+
* every row.
|
|
425
|
+
*
|
|
426
|
+
* Sub-field errors keep the container's `fieldId` -- matching the key the
|
|
427
|
+
* `fieldErrors` map stores them under -- and carry `itemIndex` (the row) plus
|
|
428
|
+
* `itemFieldId` (the sub-field). A row-level `TYPE` error carries `itemIndex`
|
|
429
|
+
* only.
|
|
430
|
+
*/
|
|
431
|
+
var ArrayObjValidator = class {
|
|
432
|
+
validate(ctx) {
|
|
433
|
+
const { fieldId, value, now } = ctx;
|
|
434
|
+
const { items, validateField } = ctx;
|
|
435
|
+
const validation = ctx.validation;
|
|
436
|
+
const errors = [];
|
|
437
|
+
if (value === null || value === void 0) return errors;
|
|
438
|
+
if (!Array.isArray(value)) {
|
|
439
|
+
errors.push({
|
|
440
|
+
fieldId,
|
|
441
|
+
rule: "TYPE",
|
|
442
|
+
message: "Must be an array",
|
|
443
|
+
params: { expectedType: "array" }
|
|
444
|
+
});
|
|
445
|
+
return errors;
|
|
446
|
+
}
|
|
447
|
+
if (validation?.minItems !== void 0 && value.length < validation.minItems) errors.push({
|
|
448
|
+
fieldId,
|
|
449
|
+
rule: "MIN_ITEMS",
|
|
450
|
+
message: `Must have at least ${validation.minItems} items`,
|
|
451
|
+
params: {
|
|
452
|
+
minItems: validation.minItems,
|
|
453
|
+
actual: value.length
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
if (validation?.maxItems !== void 0 && value.length > validation.maxItems) errors.push({
|
|
457
|
+
fieldId,
|
|
458
|
+
rule: "MAX_ITEMS",
|
|
459
|
+
message: `Must have at most ${validation.maxItems} items`,
|
|
460
|
+
params: {
|
|
461
|
+
maxItems: validation.maxItems,
|
|
462
|
+
actual: value.length
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
if (!items) return errors;
|
|
466
|
+
for (let i = 0; i < value.length; i++) {
|
|
467
|
+
const raw = value[i];
|
|
468
|
+
if (raw !== null && raw !== void 0 && !isRow(raw)) {
|
|
469
|
+
errors.push({
|
|
470
|
+
fieldId,
|
|
471
|
+
rule: "TYPE",
|
|
472
|
+
message: "Must be an object",
|
|
473
|
+
params: { expectedType: "object" },
|
|
474
|
+
itemIndex: i
|
|
475
|
+
});
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
const row = isRow(raw) ? raw : {};
|
|
479
|
+
for (const subField of items) {
|
|
480
|
+
if (subField.type === "static") continue;
|
|
481
|
+
const fakeEntry = {
|
|
482
|
+
id: subField.id,
|
|
483
|
+
type: subField.type,
|
|
484
|
+
condition: void 0,
|
|
485
|
+
validation: subField.validation,
|
|
486
|
+
parentId: fieldId,
|
|
487
|
+
options: subField.options,
|
|
488
|
+
item: void 0,
|
|
489
|
+
items: void 0,
|
|
490
|
+
label: subField.label,
|
|
491
|
+
title: void 0
|
|
492
|
+
};
|
|
493
|
+
const subErrors = validateField(subField.id, row[String(subField.id)], fakeEntry, now);
|
|
494
|
+
errors.push(...subErrors.map((err) => ({
|
|
495
|
+
...err,
|
|
496
|
+
fieldId,
|
|
497
|
+
itemIndex: i,
|
|
498
|
+
itemFieldId: subField.id,
|
|
499
|
+
message: `${subField.label}: ${err.message}`
|
|
500
|
+
})));
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return errors;
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
//#endregion
|
|
381
507
|
//#region src/validators/array-validator.ts
|
|
382
508
|
var ArrayValidator = class {
|
|
383
509
|
validate(ctx) {
|
|
@@ -413,7 +539,7 @@ var ArrayValidator = class {
|
|
|
413
539
|
actual: value.length
|
|
414
540
|
}
|
|
415
541
|
});
|
|
416
|
-
if (item) for (let i = 0; i < value.length; i++) {
|
|
542
|
+
if (item && item.type !== "static") for (let i = 0; i < value.length; i++) {
|
|
417
543
|
const fakeEntry = {
|
|
418
544
|
id: fieldId,
|
|
419
545
|
type: item.type,
|
|
@@ -422,6 +548,7 @@ var ArrayValidator = class {
|
|
|
422
548
|
parentId: void 0,
|
|
423
549
|
options: item.options,
|
|
424
550
|
item: void 0,
|
|
551
|
+
items: void 0,
|
|
425
552
|
label: item.label,
|
|
426
553
|
title: void 0
|
|
427
554
|
};
|
|
@@ -435,6 +562,32 @@ var ArrayValidator = class {
|
|
|
435
562
|
}
|
|
436
563
|
};
|
|
437
564
|
//#endregion
|
|
565
|
+
//#region src/validators/blockchain-validator.ts
|
|
566
|
+
var BlockchainValidator = class {
|
|
567
|
+
validate(ctx) {
|
|
568
|
+
const { fieldId, value } = ctx;
|
|
569
|
+
const validation = ctx.validation;
|
|
570
|
+
const errors = [];
|
|
571
|
+
const isEmpty = value === null || value === void 0 || value === "";
|
|
572
|
+
if (validation?.required && isEmpty) {
|
|
573
|
+
errors.push({
|
|
574
|
+
fieldId,
|
|
575
|
+
rule: "REQUIRED",
|
|
576
|
+
message: "Value is required"
|
|
577
|
+
});
|
|
578
|
+
return errors;
|
|
579
|
+
}
|
|
580
|
+
if (isEmpty) return errors;
|
|
581
|
+
if (typeof value !== "string") errors.push({
|
|
582
|
+
fieldId,
|
|
583
|
+
rule: "TYPE",
|
|
584
|
+
message: "Must be a blockchain address string",
|
|
585
|
+
params: { expectedType: "blockchain" }
|
|
586
|
+
});
|
|
587
|
+
return errors;
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
//#endregion
|
|
438
591
|
//#region src/validators/boolean-validator.ts
|
|
439
592
|
var BooleanValidator = class {
|
|
440
593
|
validate(ctx) {
|
|
@@ -532,6 +685,51 @@ var FileValidator = class {
|
|
|
532
685
|
}
|
|
533
686
|
};
|
|
534
687
|
//#endregion
|
|
688
|
+
//#region src/validators/multiselect-validator.ts
|
|
689
|
+
/**
|
|
690
|
+
* Validates `multiselect` fields, whose value is an array of the chosen
|
|
691
|
+
* options' `value`s.
|
|
692
|
+
*
|
|
693
|
+
* An absent value and an empty array both count as "nothing selected", so both
|
|
694
|
+
* fail `required`. Option membership is reported as a single field-level
|
|
695
|
+
* `INVALID_OPTION` error rather than one error per offending element: the
|
|
696
|
+
* viewer filters out errors carrying an `itemIndex` on the non-array render
|
|
697
|
+
* path, so indexed errors would never be displayed.
|
|
698
|
+
*/
|
|
699
|
+
var MultiselectValidator = class {
|
|
700
|
+
validate(ctx) {
|
|
701
|
+
const { fieldId, value } = ctx;
|
|
702
|
+
const validation = ctx.validation;
|
|
703
|
+
const options = ctx.options;
|
|
704
|
+
const errors = [];
|
|
705
|
+
const isEmpty = value === null || value === void 0 || Array.isArray(value) && value.length === 0;
|
|
706
|
+
if (validation?.required && isEmpty) {
|
|
707
|
+
errors.push({
|
|
708
|
+
fieldId,
|
|
709
|
+
rule: "REQUIRED",
|
|
710
|
+
message: "Value is required"
|
|
711
|
+
});
|
|
712
|
+
return errors;
|
|
713
|
+
}
|
|
714
|
+
if (isEmpty) return errors;
|
|
715
|
+
if (!Array.isArray(value)) {
|
|
716
|
+
errors.push({
|
|
717
|
+
fieldId,
|
|
718
|
+
rule: "TYPE",
|
|
719
|
+
message: "Must be an array",
|
|
720
|
+
params: { expectedType: "multiselect" }
|
|
721
|
+
});
|
|
722
|
+
return errors;
|
|
723
|
+
}
|
|
724
|
+
if (options && value.some((selected) => !options.some((opt) => opt.value === selected))) errors.push({
|
|
725
|
+
fieldId,
|
|
726
|
+
rule: "INVALID_OPTION",
|
|
727
|
+
message: "Value is not a valid option"
|
|
728
|
+
});
|
|
729
|
+
return errors;
|
|
730
|
+
}
|
|
731
|
+
};
|
|
732
|
+
//#endregion
|
|
535
733
|
//#region src/validators/number-validator.ts
|
|
536
734
|
var NumberValidator = class {
|
|
537
735
|
validate(ctx) {
|
|
@@ -659,6 +857,53 @@ var StringValidator = class {
|
|
|
659
857
|
}
|
|
660
858
|
};
|
|
661
859
|
//#endregion
|
|
860
|
+
//#region src/validators/sustainability-validator.ts
|
|
861
|
+
const OPTIONAL_TEXT_PROPERTIES = ["ccri", "cmc"];
|
|
862
|
+
var SustainabilityValidator = class {
|
|
863
|
+
validate(ctx) {
|
|
864
|
+
const { fieldId, value } = ctx;
|
|
865
|
+
const validation = ctx.validation;
|
|
866
|
+
const errors = [];
|
|
867
|
+
if (value === null || value === void 0) {
|
|
868
|
+
if (validation?.required) errors.push({
|
|
869
|
+
fieldId,
|
|
870
|
+
rule: "REQUIRED",
|
|
871
|
+
message: "Value is required"
|
|
872
|
+
});
|
|
873
|
+
return errors;
|
|
874
|
+
}
|
|
875
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
876
|
+
errors.push({
|
|
877
|
+
fieldId,
|
|
878
|
+
rule: "TYPE",
|
|
879
|
+
message: "Must be a valid sustainability object",
|
|
880
|
+
params: { expectedType: "sustainability" }
|
|
881
|
+
});
|
|
882
|
+
return errors;
|
|
883
|
+
}
|
|
884
|
+
const record = value;
|
|
885
|
+
const address = record.address ?? "";
|
|
886
|
+
if (typeof address !== "string" || OPTIONAL_TEXT_PROPERTIES.some((key) => !isOptionalText(record[key]))) {
|
|
887
|
+
errors.push({
|
|
888
|
+
fieldId,
|
|
889
|
+
rule: "TYPE",
|
|
890
|
+
message: "Must be a valid sustainability object",
|
|
891
|
+
params: { expectedType: "sustainability" }
|
|
892
|
+
});
|
|
893
|
+
return errors;
|
|
894
|
+
}
|
|
895
|
+
if (validation?.required && address === "") errors.push({
|
|
896
|
+
fieldId,
|
|
897
|
+
rule: "REQUIRED",
|
|
898
|
+
message: "Value is required"
|
|
899
|
+
});
|
|
900
|
+
return errors;
|
|
901
|
+
}
|
|
902
|
+
};
|
|
903
|
+
function isOptionalText(value) {
|
|
904
|
+
return value === void 0 || value === null || typeof value === "string";
|
|
905
|
+
}
|
|
906
|
+
//#endregion
|
|
662
907
|
//#region src/field-validator.ts
|
|
663
908
|
/**
|
|
664
909
|
* Validates form values against the schema's validation rules.
|
|
@@ -675,9 +920,19 @@ var StringValidator = class {
|
|
|
675
920
|
* - `date` -- `required`, `minDate`, `maxDate`. Relative date boundaries
|
|
676
921
|
* are resolved against `now`.
|
|
677
922
|
* - `select` -- `required`, plus the value must be one of the defined options.
|
|
923
|
+
* - `multiselect` -- `required` (an absent value and an empty array both fail),
|
|
924
|
+
* plus every selected value must be one of the defined options.
|
|
925
|
+
* - `static` -- never validated; static blocks hold no value.
|
|
926
|
+
* - `blockchain` -- `required` only. The CAIP address format is never checked.
|
|
927
|
+
* - `sustainability` -- `required` (the value's `address` must be a non-empty
|
|
928
|
+
* string) plus a shape check; `ccri` and `cmc` are optional text.
|
|
678
929
|
* - `array` -- `minItems`, `maxItems`, plus each item is validated
|
|
679
930
|
* individually according to the array's {@link ArrayItemDef}. Item-level
|
|
680
931
|
* errors carry an `itemIndex`.
|
|
932
|
+
* - `array_obj` -- `minItems`, `maxItems`, plus every sub-field of every row is
|
|
933
|
+
* validated according to the field's {@link ArrayObjItemDef} list. Sub-field
|
|
934
|
+
* errors carry an `itemIndex` (the row) and an `itemFieldId` (the sub-field),
|
|
935
|
+
* while `fieldId` stays the container's id.
|
|
681
936
|
*
|
|
682
937
|
* For all types, if `required` fails, no further rules are checked for that
|
|
683
938
|
* field (early return). If the value is empty/absent and `required` is not
|
|
@@ -697,8 +952,12 @@ var FieldValidator = class {
|
|
|
697
952
|
boolean: new BooleanValidator(),
|
|
698
953
|
date: new DateValidator(),
|
|
699
954
|
select: new SelectValidator(),
|
|
955
|
+
multiselect: new MultiselectValidator(),
|
|
700
956
|
array: new ArrayValidator(),
|
|
701
|
-
|
|
957
|
+
array_obj: new ArrayObjValidator(),
|
|
958
|
+
file: new FileValidator(),
|
|
959
|
+
blockchain: new BlockchainValidator(),
|
|
960
|
+
sustainability: new SustainabilityValidator()
|
|
702
961
|
};
|
|
703
962
|
}
|
|
704
963
|
/**
|
|
@@ -739,6 +998,17 @@ var FieldValidator = class {
|
|
|
739
998
|
};
|
|
740
999
|
return validator.validate(ctx);
|
|
741
1000
|
}
|
|
1001
|
+
if (entry.type === "array_obj") {
|
|
1002
|
+
const ctx = {
|
|
1003
|
+
fieldId,
|
|
1004
|
+
value,
|
|
1005
|
+
validation: entry.validation,
|
|
1006
|
+
now,
|
|
1007
|
+
items: entry.items,
|
|
1008
|
+
validateField: this.validateField.bind(this)
|
|
1009
|
+
};
|
|
1010
|
+
return validator.validate(ctx);
|
|
1011
|
+
}
|
|
742
1012
|
return validator.validate({
|
|
743
1013
|
fieldId,
|
|
744
1014
|
value,
|
|
@@ -793,11 +1063,17 @@ var FormDefinitionEditor = class {
|
|
|
793
1063
|
}
|
|
794
1064
|
/**
|
|
795
1065
|
* Returns the next available numeric id (max existing + 1).
|
|
1066
|
+
*
|
|
1067
|
+
* `array_obj` sub-field ids share the form-wide id space, so they count
|
|
1068
|
+
* here too -- otherwise a new top-level field could collide with one.
|
|
796
1069
|
*/
|
|
797
1070
|
nextId() {
|
|
798
1071
|
let max = 0;
|
|
799
1072
|
this.walkAll(this.definition.content, (item) => {
|
|
800
1073
|
if (item.id > max) max = item.id;
|
|
1074
|
+
if (item.type === "array_obj") {
|
|
1075
|
+
for (const subField of item.items ?? []) if (subField.id > max) max = subField.id;
|
|
1076
|
+
}
|
|
801
1077
|
});
|
|
802
1078
|
return max + 1;
|
|
803
1079
|
}
|
|
@@ -936,6 +1212,7 @@ var FormDefinitionEditor = class {
|
|
|
936
1212
|
const item = this.findItem(id);
|
|
937
1213
|
if (!item) throw new Error(`Item with id ${id} not found`);
|
|
938
1214
|
if (item.type === "section") throw new Error("Sections do not have validation");
|
|
1215
|
+
if (item.type === "static") throw new Error("Static fields do not have validation");
|
|
939
1216
|
const field = item;
|
|
940
1217
|
if (validation === void 0) delete field.validation;
|
|
941
1218
|
else field.validation = validation;
|
|
@@ -952,12 +1229,12 @@ var FormDefinitionEditor = class {
|
|
|
952
1229
|
return this;
|
|
953
1230
|
}
|
|
954
1231
|
/**
|
|
955
|
-
* Sets the
|
|
1232
|
+
* Sets the options for a `select` or `multiselect` field.
|
|
956
1233
|
*/
|
|
957
1234
|
setOptions(id, options) {
|
|
958
1235
|
const item = this.findItem(id);
|
|
959
1236
|
if (!item) throw new Error(`Item with id ${id} not found`);
|
|
960
|
-
if (item.type !== "select") throw new Error(`Field ${id} is not a select field`);
|
|
1237
|
+
if (item.type !== "select" && item.type !== "multiselect") throw new Error(`Field ${id} is not a select or multiselect field`);
|
|
961
1238
|
const field = item;
|
|
962
1239
|
field.options = options;
|
|
963
1240
|
return this;
|
|
@@ -974,6 +1251,94 @@ var FormDefinitionEditor = class {
|
|
|
974
1251
|
return this;
|
|
975
1252
|
}
|
|
976
1253
|
/**
|
|
1254
|
+
* Replaces the whole sub-field list of an `array_obj` field.
|
|
1255
|
+
*
|
|
1256
|
+
* @throws If the id is not found or does not refer to an `array_obj` field.
|
|
1257
|
+
*/
|
|
1258
|
+
setArrayItems(id, itemDefs) {
|
|
1259
|
+
this.assertArrayObjField(id).items = itemDefs;
|
|
1260
|
+
return this;
|
|
1261
|
+
}
|
|
1262
|
+
/**
|
|
1263
|
+
* Returns the sub-field list of an `array_obj` field.
|
|
1264
|
+
*
|
|
1265
|
+
* @throws If the id is not found or does not refer to an `array_obj` field.
|
|
1266
|
+
*/
|
|
1267
|
+
getArrayItems(id) {
|
|
1268
|
+
return this.assertArrayObjField(id).items ?? [];
|
|
1269
|
+
}
|
|
1270
|
+
/**
|
|
1271
|
+
* Sets or clears the layout hint of an `array_obj` field.
|
|
1272
|
+
*
|
|
1273
|
+
* Presentation metadata only -- the engine never reads it. Passing
|
|
1274
|
+
* `undefined` removes the key, which reads as `'list'`.
|
|
1275
|
+
*
|
|
1276
|
+
* @throws If the id is not found or does not refer to an `array_obj` field.
|
|
1277
|
+
*/
|
|
1278
|
+
setArrayKind(id, kind) {
|
|
1279
|
+
const field = this.assertArrayObjField(id);
|
|
1280
|
+
if (kind === void 0) delete field.kind;
|
|
1281
|
+
else field.kind = kind;
|
|
1282
|
+
return this;
|
|
1283
|
+
}
|
|
1284
|
+
/**
|
|
1285
|
+
* Appends a sub-field to an `array_obj` field. The sub-field's `id` is
|
|
1286
|
+
* auto-assigned when omitted.
|
|
1287
|
+
*
|
|
1288
|
+
* @returns The id of the sub-field that was added.
|
|
1289
|
+
* @throws If the id is not found, does not refer to an `array_obj` field,
|
|
1290
|
+
* or the requested sub-field id is already taken.
|
|
1291
|
+
*/
|
|
1292
|
+
addArrayItemField(id, subField) {
|
|
1293
|
+
const field = this.assertArrayObjField(id);
|
|
1294
|
+
const subFieldId = subField.id ?? this.nextId();
|
|
1295
|
+
this.assertIdAvailable(subFieldId);
|
|
1296
|
+
field.items?.push({
|
|
1297
|
+
...subField,
|
|
1298
|
+
id: subFieldId
|
|
1299
|
+
});
|
|
1300
|
+
return subFieldId;
|
|
1301
|
+
}
|
|
1302
|
+
/**
|
|
1303
|
+
* Merges properties into an existing `array_obj` sub-field.
|
|
1304
|
+
*
|
|
1305
|
+
* Like {@link updateField}, omitted properties are kept rather than
|
|
1306
|
+
* removed -- pass a property explicitly as `undefined` to clear it.
|
|
1307
|
+
*
|
|
1308
|
+
* @throws If the field or the sub-field is not found.
|
|
1309
|
+
*/
|
|
1310
|
+
updateArrayItemField(id, subFieldId, patch) {
|
|
1311
|
+
const subField = this.assertArrayObjField(id).items?.find((f) => f.id === subFieldId);
|
|
1312
|
+
if (!subField) throw new Error(`Sub-field with id ${subFieldId} not found in field ${id}`);
|
|
1313
|
+
Object.assign(subField, patch, { id: subFieldId });
|
|
1314
|
+
return this;
|
|
1315
|
+
}
|
|
1316
|
+
/**
|
|
1317
|
+
* Removes a sub-field from an `array_obj` field.
|
|
1318
|
+
*
|
|
1319
|
+
* @throws If the field or the sub-field is not found.
|
|
1320
|
+
*/
|
|
1321
|
+
removeArrayItemField(id, subFieldId) {
|
|
1322
|
+
const field = this.assertArrayObjField(id);
|
|
1323
|
+
const index = field.items?.findIndex((f) => f.id === subFieldId) ?? -1;
|
|
1324
|
+
if (index < 0) throw new Error(`Sub-field with id ${subFieldId} not found in field ${id}`);
|
|
1325
|
+
field.items?.splice(index, 1);
|
|
1326
|
+
return this;
|
|
1327
|
+
}
|
|
1328
|
+
/**
|
|
1329
|
+
* Moves a sub-field of an `array_obj` field to another position.
|
|
1330
|
+
*
|
|
1331
|
+
* @throws If the field is not found or either index is out of range.
|
|
1332
|
+
*/
|
|
1333
|
+
moveArrayItemField(id, fromIndex, toIndex) {
|
|
1334
|
+
const items = this.assertArrayObjField(id).items ?? [];
|
|
1335
|
+
if (fromIndex < 0 || fromIndex >= items.length) throw new Error(`Index ${fromIndex} out of range`);
|
|
1336
|
+
if (toIndex < 0 || toIndex >= items.length) throw new Error(`Index ${toIndex} out of range`);
|
|
1337
|
+
const [moved] = items.splice(fromIndex, 1);
|
|
1338
|
+
if (moved) items.splice(toIndex, 0, moved);
|
|
1339
|
+
return this;
|
|
1340
|
+
}
|
|
1341
|
+
/**
|
|
977
1342
|
* Sets the label for a field.
|
|
978
1343
|
*/
|
|
979
1344
|
setLabel(id, label) {
|
|
@@ -985,6 +1350,18 @@ var FormDefinitionEditor = class {
|
|
|
985
1350
|
return this;
|
|
986
1351
|
}
|
|
987
1352
|
/**
|
|
1353
|
+
* Sets the displayed text of a `static` field.
|
|
1354
|
+
*
|
|
1355
|
+
* @throws If the id is not found or does not refer to a static field.
|
|
1356
|
+
*/
|
|
1357
|
+
setText(id, text) {
|
|
1358
|
+
const item = this.findItem(id);
|
|
1359
|
+
if (!item) throw new Error(`Item with id ${id} not found`);
|
|
1360
|
+
if (item.type !== "static") throw new Error(`Field ${id} is not a static field`);
|
|
1361
|
+
item.text = text;
|
|
1362
|
+
return this;
|
|
1363
|
+
}
|
|
1364
|
+
/**
|
|
988
1365
|
* Sets the description for a field or section.
|
|
989
1366
|
*/
|
|
990
1367
|
setFieldDescription(id, description) {
|
|
@@ -995,6 +1372,41 @@ var FormDefinitionEditor = class {
|
|
|
995
1372
|
return this;
|
|
996
1373
|
}
|
|
997
1374
|
/**
|
|
1375
|
+
* Sets the placeholder for a field or section.
|
|
1376
|
+
*
|
|
1377
|
+
* Passing `undefined` removes the property. Unlike {@link updateField},
|
|
1378
|
+
* which merges and therefore cannot clear, this genuinely deletes the key.
|
|
1379
|
+
*/
|
|
1380
|
+
setPlaceholder(id, placeholder) {
|
|
1381
|
+
return this.setMetadata(id, "placeholder", placeholder);
|
|
1382
|
+
}
|
|
1383
|
+
/**
|
|
1384
|
+
* Sets the answer guidelines for a field or section.
|
|
1385
|
+
*
|
|
1386
|
+
* Passing `undefined` removes the property.
|
|
1387
|
+
*/
|
|
1388
|
+
setAnswerGuidelines(id, answerGuidelines) {
|
|
1389
|
+
return this.setMetadata(id, "answer_guidelines", answerGuidelines);
|
|
1390
|
+
}
|
|
1391
|
+
/**
|
|
1392
|
+
* Sets the external reference id for a field or section.
|
|
1393
|
+
*
|
|
1394
|
+
* Passing `undefined` removes the property.
|
|
1395
|
+
*/
|
|
1396
|
+
setReferenceId(id, referenceId) {
|
|
1397
|
+
return this.setMetadata(id, "reference_id", referenceId);
|
|
1398
|
+
}
|
|
1399
|
+
/**
|
|
1400
|
+
* Assigns or deletes one optional string property on a field or section.
|
|
1401
|
+
*/
|
|
1402
|
+
setMetadata(id, property, value) {
|
|
1403
|
+
const item = this.findItem(id);
|
|
1404
|
+
if (!item) throw new Error(`Item with id ${id} not found`);
|
|
1405
|
+
if (value === void 0) delete item[property];
|
|
1406
|
+
else item[property] = value;
|
|
1407
|
+
return this;
|
|
1408
|
+
}
|
|
1409
|
+
/**
|
|
998
1410
|
* Returns a deep clone of the current form definition.
|
|
999
1411
|
*/
|
|
1000
1412
|
toJSON() {
|
|
@@ -1009,6 +1421,30 @@ var FormDefinitionEditor = class {
|
|
|
1009
1421
|
}
|
|
1010
1422
|
assertIdAvailable(id) {
|
|
1011
1423
|
if (this.findItem(id)) throw new Error(`Item with id ${id} already exists`);
|
|
1424
|
+
if (this.findArrayObjItem(id)) throw new Error(`Item with id ${id} already exists`);
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Finds an `array_obj` sub-field anywhere in the definition by its id.
|
|
1428
|
+
*/
|
|
1429
|
+
findArrayObjItem(id) {
|
|
1430
|
+
let found;
|
|
1431
|
+
this.walkAll(this.definition.content, (item) => {
|
|
1432
|
+
if (found || item.type !== "array_obj") return;
|
|
1433
|
+
const subField = (item.items ?? []).find((f) => f.id === id);
|
|
1434
|
+
if (subField) found = {
|
|
1435
|
+
field: item,
|
|
1436
|
+
subField
|
|
1437
|
+
};
|
|
1438
|
+
});
|
|
1439
|
+
return found;
|
|
1440
|
+
}
|
|
1441
|
+
assertArrayObjField(id) {
|
|
1442
|
+
const item = this.findItem(id);
|
|
1443
|
+
if (!item) throw new Error(`Item with id ${id} not found`);
|
|
1444
|
+
if (item.type !== "array_obj") throw new Error(`Field ${id} is not an array_obj field`);
|
|
1445
|
+
const field = item;
|
|
1446
|
+
if (!field.items) field.items = [];
|
|
1447
|
+
return field;
|
|
1012
1448
|
}
|
|
1013
1449
|
insertItem(item, parentId, index) {
|
|
1014
1450
|
const target = this.getTargetContent(parentId);
|
|
@@ -1220,6 +1656,11 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1220
1656
|
"properties": { "required": { "type": "boolean" } },
|
|
1221
1657
|
"additionalProperties": false
|
|
1222
1658
|
},
|
|
1659
|
+
"multiselectValidation": {
|
|
1660
|
+
"type": "object",
|
|
1661
|
+
"properties": { "required": { "type": "boolean" } },
|
|
1662
|
+
"additionalProperties": false
|
|
1663
|
+
},
|
|
1223
1664
|
"arrayValidation": {
|
|
1224
1665
|
"type": "object",
|
|
1225
1666
|
"properties": {
|
|
@@ -1234,11 +1675,35 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1234
1675
|
},
|
|
1235
1676
|
"additionalProperties": false
|
|
1236
1677
|
},
|
|
1678
|
+
"arrayObjValidation": {
|
|
1679
|
+
"type": "object",
|
|
1680
|
+
"properties": {
|
|
1681
|
+
"minItems": {
|
|
1682
|
+
"type": "integer",
|
|
1683
|
+
"minimum": 0
|
|
1684
|
+
},
|
|
1685
|
+
"maxItems": {
|
|
1686
|
+
"type": "integer",
|
|
1687
|
+
"minimum": 1
|
|
1688
|
+
}
|
|
1689
|
+
},
|
|
1690
|
+
"additionalProperties": false
|
|
1691
|
+
},
|
|
1237
1692
|
"fileValidation": {
|
|
1238
1693
|
"type": "object",
|
|
1239
1694
|
"properties": { "required": { "type": "boolean" } },
|
|
1240
1695
|
"additionalProperties": false
|
|
1241
1696
|
},
|
|
1697
|
+
"blockchainValidation": {
|
|
1698
|
+
"type": "object",
|
|
1699
|
+
"properties": { "required": { "type": "boolean" } },
|
|
1700
|
+
"additionalProperties": false
|
|
1701
|
+
},
|
|
1702
|
+
"sustainabilityValidation": {
|
|
1703
|
+
"type": "object",
|
|
1704
|
+
"properties": { "required": { "type": "boolean" } },
|
|
1705
|
+
"additionalProperties": false
|
|
1706
|
+
},
|
|
1242
1707
|
"selectOption": {
|
|
1243
1708
|
"type": "object",
|
|
1244
1709
|
"required": ["value", "label"],
|
|
@@ -1255,6 +1720,9 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1255
1720
|
"type": { "const": "string" },
|
|
1256
1721
|
"label": { "type": "string" },
|
|
1257
1722
|
"description": { "type": "string" },
|
|
1723
|
+
"placeholder": { "type": "string" },
|
|
1724
|
+
"answer_guidelines": { "type": "string" },
|
|
1725
|
+
"reference_id": { "type": "string" },
|
|
1258
1726
|
"validation": { "$ref": "#/$defs/stringValidation" }
|
|
1259
1727
|
},
|
|
1260
1728
|
"additionalProperties": false
|
|
@@ -1266,6 +1734,9 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1266
1734
|
"type": { "const": "number" },
|
|
1267
1735
|
"label": { "type": "string" },
|
|
1268
1736
|
"description": { "type": "string" },
|
|
1737
|
+
"placeholder": { "type": "string" },
|
|
1738
|
+
"answer_guidelines": { "type": "string" },
|
|
1739
|
+
"reference_id": { "type": "string" },
|
|
1269
1740
|
"validation": { "$ref": "#/$defs/numberValidation" }
|
|
1270
1741
|
},
|
|
1271
1742
|
"additionalProperties": false
|
|
@@ -1277,6 +1748,9 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1277
1748
|
"type": { "const": "boolean" },
|
|
1278
1749
|
"label": { "type": "string" },
|
|
1279
1750
|
"description": { "type": "string" },
|
|
1751
|
+
"placeholder": { "type": "string" },
|
|
1752
|
+
"answer_guidelines": { "type": "string" },
|
|
1753
|
+
"reference_id": { "type": "string" },
|
|
1280
1754
|
"validation": { "$ref": "#/$defs/booleanValidation" }
|
|
1281
1755
|
},
|
|
1282
1756
|
"additionalProperties": false
|
|
@@ -1288,6 +1762,9 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1288
1762
|
"type": { "const": "date" },
|
|
1289
1763
|
"label": { "type": "string" },
|
|
1290
1764
|
"description": { "type": "string" },
|
|
1765
|
+
"placeholder": { "type": "string" },
|
|
1766
|
+
"answer_guidelines": { "type": "string" },
|
|
1767
|
+
"reference_id": { "type": "string" },
|
|
1291
1768
|
"validation": { "$ref": "#/$defs/dateValidation" }
|
|
1292
1769
|
},
|
|
1293
1770
|
"additionalProperties": false
|
|
@@ -1303,6 +1780,9 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1303
1780
|
"type": { "const": "select" },
|
|
1304
1781
|
"label": { "type": "string" },
|
|
1305
1782
|
"description": { "type": "string" },
|
|
1783
|
+
"placeholder": { "type": "string" },
|
|
1784
|
+
"answer_guidelines": { "type": "string" },
|
|
1785
|
+
"reference_id": { "type": "string" },
|
|
1306
1786
|
"options": {
|
|
1307
1787
|
"type": "array",
|
|
1308
1788
|
"minItems": 1,
|
|
@@ -1319,19 +1799,335 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1319
1799
|
"type": { "const": "file" },
|
|
1320
1800
|
"label": { "type": "string" },
|
|
1321
1801
|
"description": { "type": "string" },
|
|
1802
|
+
"placeholder": { "type": "string" },
|
|
1803
|
+
"answer_guidelines": { "type": "string" },
|
|
1804
|
+
"reference_id": { "type": "string" },
|
|
1322
1805
|
"validation": { "$ref": "#/$defs/fileValidation" }
|
|
1323
1806
|
},
|
|
1324
1807
|
"additionalProperties": false
|
|
1325
1808
|
},
|
|
1326
|
-
"
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1809
|
+
"arrayItemBlockchain": {
|
|
1810
|
+
"type": "object",
|
|
1811
|
+
"required": ["type", "label"],
|
|
1812
|
+
"properties": {
|
|
1813
|
+
"type": { "const": "blockchain" },
|
|
1814
|
+
"label": { "type": "string" },
|
|
1815
|
+
"description": { "type": "string" },
|
|
1816
|
+
"placeholder": { "type": "string" },
|
|
1817
|
+
"answer_guidelines": { "type": "string" },
|
|
1818
|
+
"reference_id": { "type": "string" },
|
|
1819
|
+
"validation": { "$ref": "#/$defs/blockchainValidation" }
|
|
1820
|
+
},
|
|
1821
|
+
"additionalProperties": false
|
|
1822
|
+
},
|
|
1823
|
+
"arrayItemSustainability": {
|
|
1824
|
+
"type": "object",
|
|
1825
|
+
"required": ["type", "label"],
|
|
1826
|
+
"properties": {
|
|
1827
|
+
"type": { "const": "sustainability" },
|
|
1828
|
+
"label": { "type": "string" },
|
|
1829
|
+
"description": { "type": "string" },
|
|
1830
|
+
"placeholder": { "type": "string" },
|
|
1831
|
+
"answer_guidelines": { "type": "string" },
|
|
1832
|
+
"reference_id": { "type": "string" },
|
|
1833
|
+
"validation": { "$ref": "#/$defs/sustainabilityValidation" }
|
|
1834
|
+
},
|
|
1835
|
+
"additionalProperties": false
|
|
1836
|
+
},
|
|
1837
|
+
"arrayItemMultiselect": {
|
|
1838
|
+
"type": "object",
|
|
1839
|
+
"required": [
|
|
1840
|
+
"type",
|
|
1841
|
+
"label",
|
|
1842
|
+
"options"
|
|
1843
|
+
],
|
|
1844
|
+
"properties": {
|
|
1845
|
+
"type": { "const": "multiselect" },
|
|
1846
|
+
"label": { "type": "string" },
|
|
1847
|
+
"description": { "type": "string" },
|
|
1848
|
+
"placeholder": { "type": "string" },
|
|
1849
|
+
"answer_guidelines": { "type": "string" },
|
|
1850
|
+
"reference_id": { "type": "string" },
|
|
1851
|
+
"options": {
|
|
1852
|
+
"type": "array",
|
|
1853
|
+
"minItems": 1,
|
|
1854
|
+
"items": { "$ref": "#/$defs/selectOption" }
|
|
1855
|
+
},
|
|
1856
|
+
"validation": { "$ref": "#/$defs/multiselectValidation" }
|
|
1857
|
+
},
|
|
1858
|
+
"additionalProperties": false
|
|
1859
|
+
},
|
|
1860
|
+
"arrayItemStatic": {
|
|
1861
|
+
"type": "object",
|
|
1862
|
+
"required": ["type", "text"],
|
|
1863
|
+
"properties": {
|
|
1864
|
+
"type": { "const": "static" },
|
|
1865
|
+
"text": { "type": "string" },
|
|
1866
|
+
"label": { "type": "string" },
|
|
1867
|
+
"description": { "type": "string" },
|
|
1868
|
+
"placeholder": { "type": "string" },
|
|
1869
|
+
"answer_guidelines": { "type": "string" },
|
|
1870
|
+
"reference_id": { "type": "string" }
|
|
1871
|
+
},
|
|
1872
|
+
"additionalProperties": false
|
|
1873
|
+
},
|
|
1874
|
+
"arrayItem": { "oneOf": [
|
|
1875
|
+
{ "$ref": "#/$defs/arrayItemString" },
|
|
1876
|
+
{ "$ref": "#/$defs/arrayItemNumber" },
|
|
1877
|
+
{ "$ref": "#/$defs/arrayItemBoolean" },
|
|
1878
|
+
{ "$ref": "#/$defs/arrayItemDate" },
|
|
1879
|
+
{ "$ref": "#/$defs/arrayItemSelect" },
|
|
1880
|
+
{ "$ref": "#/$defs/arrayItemFile" },
|
|
1881
|
+
{ "$ref": "#/$defs/arrayItemBlockchain" },
|
|
1882
|
+
{ "$ref": "#/$defs/arrayItemSustainability" },
|
|
1883
|
+
{ "$ref": "#/$defs/arrayItemMultiselect" },
|
|
1884
|
+
{ "$ref": "#/$defs/arrayItemStatic" }
|
|
1885
|
+
] },
|
|
1886
|
+
"arrayObjItemString": {
|
|
1887
|
+
"type": "object",
|
|
1888
|
+
"required": [
|
|
1889
|
+
"id",
|
|
1890
|
+
"type",
|
|
1891
|
+
"label"
|
|
1892
|
+
],
|
|
1893
|
+
"properties": {
|
|
1894
|
+
"id": {
|
|
1895
|
+
"type": "integer",
|
|
1896
|
+
"minimum": 1
|
|
1897
|
+
},
|
|
1898
|
+
"type": { "const": "string" },
|
|
1899
|
+
"label": { "type": "string" },
|
|
1900
|
+
"description": { "type": "string" },
|
|
1901
|
+
"placeholder": { "type": "string" },
|
|
1902
|
+
"answer_guidelines": { "type": "string" },
|
|
1903
|
+
"reference_id": { "type": "string" },
|
|
1904
|
+
"validation": { "$ref": "#/$defs/stringValidation" }
|
|
1905
|
+
},
|
|
1906
|
+
"additionalProperties": false
|
|
1907
|
+
},
|
|
1908
|
+
"arrayObjItemNumber": {
|
|
1909
|
+
"type": "object",
|
|
1910
|
+
"required": [
|
|
1911
|
+
"id",
|
|
1912
|
+
"type",
|
|
1913
|
+
"label"
|
|
1914
|
+
],
|
|
1915
|
+
"properties": {
|
|
1916
|
+
"id": {
|
|
1917
|
+
"type": "integer",
|
|
1918
|
+
"minimum": 1
|
|
1919
|
+
},
|
|
1920
|
+
"type": { "const": "number" },
|
|
1921
|
+
"label": { "type": "string" },
|
|
1922
|
+
"description": { "type": "string" },
|
|
1923
|
+
"placeholder": { "type": "string" },
|
|
1924
|
+
"answer_guidelines": { "type": "string" },
|
|
1925
|
+
"reference_id": { "type": "string" },
|
|
1926
|
+
"validation": { "$ref": "#/$defs/numberValidation" }
|
|
1927
|
+
},
|
|
1928
|
+
"additionalProperties": false
|
|
1929
|
+
},
|
|
1930
|
+
"arrayObjItemBoolean": {
|
|
1931
|
+
"type": "object",
|
|
1932
|
+
"required": [
|
|
1933
|
+
"id",
|
|
1934
|
+
"type",
|
|
1935
|
+
"label"
|
|
1936
|
+
],
|
|
1937
|
+
"properties": {
|
|
1938
|
+
"id": {
|
|
1939
|
+
"type": "integer",
|
|
1940
|
+
"minimum": 1
|
|
1941
|
+
},
|
|
1942
|
+
"type": { "const": "boolean" },
|
|
1943
|
+
"label": { "type": "string" },
|
|
1944
|
+
"description": { "type": "string" },
|
|
1945
|
+
"placeholder": { "type": "string" },
|
|
1946
|
+
"answer_guidelines": { "type": "string" },
|
|
1947
|
+
"reference_id": { "type": "string" },
|
|
1948
|
+
"validation": { "$ref": "#/$defs/booleanValidation" }
|
|
1949
|
+
},
|
|
1950
|
+
"additionalProperties": false
|
|
1951
|
+
},
|
|
1952
|
+
"arrayObjItemDate": {
|
|
1953
|
+
"type": "object",
|
|
1954
|
+
"required": [
|
|
1955
|
+
"id",
|
|
1956
|
+
"type",
|
|
1957
|
+
"label"
|
|
1958
|
+
],
|
|
1959
|
+
"properties": {
|
|
1960
|
+
"id": {
|
|
1961
|
+
"type": "integer",
|
|
1962
|
+
"minimum": 1
|
|
1963
|
+
},
|
|
1964
|
+
"type": { "const": "date" },
|
|
1965
|
+
"label": { "type": "string" },
|
|
1966
|
+
"description": { "type": "string" },
|
|
1967
|
+
"placeholder": { "type": "string" },
|
|
1968
|
+
"answer_guidelines": { "type": "string" },
|
|
1969
|
+
"reference_id": { "type": "string" },
|
|
1970
|
+
"validation": { "$ref": "#/$defs/dateValidation" }
|
|
1971
|
+
},
|
|
1972
|
+
"additionalProperties": false
|
|
1973
|
+
},
|
|
1974
|
+
"arrayObjItemSelect": {
|
|
1975
|
+
"type": "object",
|
|
1976
|
+
"required": [
|
|
1977
|
+
"id",
|
|
1978
|
+
"type",
|
|
1979
|
+
"label",
|
|
1980
|
+
"options"
|
|
1981
|
+
],
|
|
1982
|
+
"properties": {
|
|
1983
|
+
"id": {
|
|
1984
|
+
"type": "integer",
|
|
1985
|
+
"minimum": 1
|
|
1986
|
+
},
|
|
1987
|
+
"type": { "const": "select" },
|
|
1988
|
+
"label": { "type": "string" },
|
|
1989
|
+
"description": { "type": "string" },
|
|
1990
|
+
"placeholder": { "type": "string" },
|
|
1991
|
+
"answer_guidelines": { "type": "string" },
|
|
1992
|
+
"reference_id": { "type": "string" },
|
|
1993
|
+
"options": {
|
|
1994
|
+
"type": "array",
|
|
1995
|
+
"minItems": 1,
|
|
1996
|
+
"items": { "$ref": "#/$defs/selectOption" }
|
|
1997
|
+
},
|
|
1998
|
+
"validation": { "$ref": "#/$defs/selectValidation" }
|
|
1999
|
+
},
|
|
2000
|
+
"additionalProperties": false
|
|
2001
|
+
},
|
|
2002
|
+
"arrayObjItemMultiselect": {
|
|
2003
|
+
"type": "object",
|
|
2004
|
+
"required": [
|
|
2005
|
+
"id",
|
|
2006
|
+
"type",
|
|
2007
|
+
"label",
|
|
2008
|
+
"options"
|
|
2009
|
+
],
|
|
2010
|
+
"properties": {
|
|
2011
|
+
"id": {
|
|
2012
|
+
"type": "integer",
|
|
2013
|
+
"minimum": 1
|
|
2014
|
+
},
|
|
2015
|
+
"type": { "const": "multiselect" },
|
|
2016
|
+
"label": { "type": "string" },
|
|
2017
|
+
"description": { "type": "string" },
|
|
2018
|
+
"placeholder": { "type": "string" },
|
|
2019
|
+
"answer_guidelines": { "type": "string" },
|
|
2020
|
+
"reference_id": { "type": "string" },
|
|
2021
|
+
"options": {
|
|
2022
|
+
"type": "array",
|
|
2023
|
+
"minItems": 1,
|
|
2024
|
+
"items": { "$ref": "#/$defs/selectOption" }
|
|
2025
|
+
},
|
|
2026
|
+
"validation": { "$ref": "#/$defs/multiselectValidation" }
|
|
2027
|
+
},
|
|
2028
|
+
"additionalProperties": false
|
|
2029
|
+
},
|
|
2030
|
+
"arrayObjItemFile": {
|
|
2031
|
+
"type": "object",
|
|
2032
|
+
"required": [
|
|
2033
|
+
"id",
|
|
2034
|
+
"type",
|
|
2035
|
+
"label"
|
|
2036
|
+
],
|
|
2037
|
+
"properties": {
|
|
2038
|
+
"id": {
|
|
2039
|
+
"type": "integer",
|
|
2040
|
+
"minimum": 1
|
|
2041
|
+
},
|
|
2042
|
+
"type": { "const": "file" },
|
|
2043
|
+
"label": { "type": "string" },
|
|
2044
|
+
"description": { "type": "string" },
|
|
2045
|
+
"placeholder": { "type": "string" },
|
|
2046
|
+
"answer_guidelines": { "type": "string" },
|
|
2047
|
+
"reference_id": { "type": "string" },
|
|
2048
|
+
"validation": { "$ref": "#/$defs/fileValidation" }
|
|
2049
|
+
},
|
|
2050
|
+
"additionalProperties": false
|
|
2051
|
+
},
|
|
2052
|
+
"arrayObjItemBlockchain": {
|
|
2053
|
+
"type": "object",
|
|
2054
|
+
"required": [
|
|
2055
|
+
"id",
|
|
2056
|
+
"type",
|
|
2057
|
+
"label"
|
|
2058
|
+
],
|
|
2059
|
+
"properties": {
|
|
2060
|
+
"id": {
|
|
2061
|
+
"type": "integer",
|
|
2062
|
+
"minimum": 1
|
|
2063
|
+
},
|
|
2064
|
+
"type": { "const": "blockchain" },
|
|
2065
|
+
"label": { "type": "string" },
|
|
2066
|
+
"description": { "type": "string" },
|
|
2067
|
+
"placeholder": { "type": "string" },
|
|
2068
|
+
"answer_guidelines": { "type": "string" },
|
|
2069
|
+
"reference_id": { "type": "string" },
|
|
2070
|
+
"validation": { "$ref": "#/$defs/blockchainValidation" }
|
|
2071
|
+
},
|
|
2072
|
+
"additionalProperties": false
|
|
2073
|
+
},
|
|
2074
|
+
"arrayObjItemSustainability": {
|
|
2075
|
+
"type": "object",
|
|
2076
|
+
"required": [
|
|
2077
|
+
"id",
|
|
2078
|
+
"type",
|
|
2079
|
+
"label"
|
|
2080
|
+
],
|
|
2081
|
+
"properties": {
|
|
2082
|
+
"id": {
|
|
2083
|
+
"type": "integer",
|
|
2084
|
+
"minimum": 1
|
|
2085
|
+
},
|
|
2086
|
+
"type": { "const": "sustainability" },
|
|
2087
|
+
"label": { "type": "string" },
|
|
2088
|
+
"description": { "type": "string" },
|
|
2089
|
+
"placeholder": { "type": "string" },
|
|
2090
|
+
"answer_guidelines": { "type": "string" },
|
|
2091
|
+
"reference_id": { "type": "string" },
|
|
2092
|
+
"validation": { "$ref": "#/$defs/sustainabilityValidation" }
|
|
2093
|
+
},
|
|
2094
|
+
"additionalProperties": false
|
|
2095
|
+
},
|
|
2096
|
+
"arrayObjItemStatic": {
|
|
2097
|
+
"type": "object",
|
|
2098
|
+
"required": [
|
|
2099
|
+
"id",
|
|
2100
|
+
"type",
|
|
2101
|
+
"text"
|
|
2102
|
+
],
|
|
2103
|
+
"properties": {
|
|
2104
|
+
"id": {
|
|
2105
|
+
"type": "integer",
|
|
2106
|
+
"minimum": 1
|
|
2107
|
+
},
|
|
2108
|
+
"type": { "const": "static" },
|
|
2109
|
+
"text": { "type": "string" },
|
|
2110
|
+
"label": { "type": "string" },
|
|
2111
|
+
"description": { "type": "string" },
|
|
2112
|
+
"placeholder": { "type": "string" },
|
|
2113
|
+
"answer_guidelines": { "type": "string" },
|
|
2114
|
+
"reference_id": { "type": "string" }
|
|
2115
|
+
},
|
|
2116
|
+
"additionalProperties": false
|
|
2117
|
+
},
|
|
2118
|
+
"arrayObjItem": { "oneOf": [
|
|
2119
|
+
{ "$ref": "#/$defs/arrayObjItemString" },
|
|
2120
|
+
{ "$ref": "#/$defs/arrayObjItemNumber" },
|
|
2121
|
+
{ "$ref": "#/$defs/arrayObjItemBoolean" },
|
|
2122
|
+
{ "$ref": "#/$defs/arrayObjItemDate" },
|
|
2123
|
+
{ "$ref": "#/$defs/arrayObjItemSelect" },
|
|
2124
|
+
{ "$ref": "#/$defs/arrayObjItemMultiselect" },
|
|
2125
|
+
{ "$ref": "#/$defs/arrayObjItemFile" },
|
|
2126
|
+
{ "$ref": "#/$defs/arrayObjItemBlockchain" },
|
|
2127
|
+
{ "$ref": "#/$defs/arrayObjItemSustainability" },
|
|
2128
|
+
{ "$ref": "#/$defs/arrayObjItemStatic" }
|
|
2129
|
+
] },
|
|
2130
|
+
"stringField": {
|
|
1335
2131
|
"type": "object",
|
|
1336
2132
|
"required": [
|
|
1337
2133
|
"id",
|
|
@@ -1346,6 +2142,9 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1346
2142
|
"type": { "const": "string" },
|
|
1347
2143
|
"label": { "type": "string" },
|
|
1348
2144
|
"description": { "type": "string" },
|
|
2145
|
+
"placeholder": { "type": "string" },
|
|
2146
|
+
"answer_guidelines": { "type": "string" },
|
|
2147
|
+
"reference_id": { "type": "string" },
|
|
1349
2148
|
"condition": { "$ref": "#/$defs/condition" },
|
|
1350
2149
|
"validation": { "$ref": "#/$defs/stringValidation" }
|
|
1351
2150
|
},
|
|
@@ -1366,6 +2165,9 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1366
2165
|
"type": { "const": "number" },
|
|
1367
2166
|
"label": { "type": "string" },
|
|
1368
2167
|
"description": { "type": "string" },
|
|
2168
|
+
"placeholder": { "type": "string" },
|
|
2169
|
+
"answer_guidelines": { "type": "string" },
|
|
2170
|
+
"reference_id": { "type": "string" },
|
|
1369
2171
|
"condition": { "$ref": "#/$defs/condition" },
|
|
1370
2172
|
"validation": { "$ref": "#/$defs/numberValidation" }
|
|
1371
2173
|
},
|
|
@@ -1386,6 +2188,9 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1386
2188
|
"type": { "const": "boolean" },
|
|
1387
2189
|
"label": { "type": "string" },
|
|
1388
2190
|
"description": { "type": "string" },
|
|
2191
|
+
"placeholder": { "type": "string" },
|
|
2192
|
+
"answer_guidelines": { "type": "string" },
|
|
2193
|
+
"reference_id": { "type": "string" },
|
|
1389
2194
|
"condition": { "$ref": "#/$defs/condition" },
|
|
1390
2195
|
"validation": { "$ref": "#/$defs/booleanValidation" }
|
|
1391
2196
|
},
|
|
@@ -1406,6 +2211,9 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1406
2211
|
"type": { "const": "date" },
|
|
1407
2212
|
"label": { "type": "string" },
|
|
1408
2213
|
"description": { "type": "string" },
|
|
2214
|
+
"placeholder": { "type": "string" },
|
|
2215
|
+
"answer_guidelines": { "type": "string" },
|
|
2216
|
+
"reference_id": { "type": "string" },
|
|
1409
2217
|
"condition": { "$ref": "#/$defs/condition" },
|
|
1410
2218
|
"validation": { "$ref": "#/$defs/dateValidation" }
|
|
1411
2219
|
},
|
|
@@ -1427,6 +2235,9 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1427
2235
|
"type": { "const": "select" },
|
|
1428
2236
|
"label": { "type": "string" },
|
|
1429
2237
|
"description": { "type": "string" },
|
|
2238
|
+
"placeholder": { "type": "string" },
|
|
2239
|
+
"answer_guidelines": { "type": "string" },
|
|
2240
|
+
"reference_id": { "type": "string" },
|
|
1430
2241
|
"condition": { "$ref": "#/$defs/condition" },
|
|
1431
2242
|
"options": {
|
|
1432
2243
|
"type": "array",
|
|
@@ -1437,6 +2248,58 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1437
2248
|
},
|
|
1438
2249
|
"additionalProperties": false
|
|
1439
2250
|
},
|
|
2251
|
+
"multiselectField": {
|
|
2252
|
+
"type": "object",
|
|
2253
|
+
"required": [
|
|
2254
|
+
"id",
|
|
2255
|
+
"type",
|
|
2256
|
+
"label",
|
|
2257
|
+
"options"
|
|
2258
|
+
],
|
|
2259
|
+
"properties": {
|
|
2260
|
+
"id": {
|
|
2261
|
+
"type": "integer",
|
|
2262
|
+
"minimum": 1
|
|
2263
|
+
},
|
|
2264
|
+
"type": { "const": "multiselect" },
|
|
2265
|
+
"label": { "type": "string" },
|
|
2266
|
+
"description": { "type": "string" },
|
|
2267
|
+
"placeholder": { "type": "string" },
|
|
2268
|
+
"answer_guidelines": { "type": "string" },
|
|
2269
|
+
"reference_id": { "type": "string" },
|
|
2270
|
+
"condition": { "$ref": "#/$defs/condition" },
|
|
2271
|
+
"options": {
|
|
2272
|
+
"type": "array",
|
|
2273
|
+
"minItems": 1,
|
|
2274
|
+
"items": { "$ref": "#/$defs/selectOption" }
|
|
2275
|
+
},
|
|
2276
|
+
"validation": { "$ref": "#/$defs/multiselectValidation" }
|
|
2277
|
+
},
|
|
2278
|
+
"additionalProperties": false
|
|
2279
|
+
},
|
|
2280
|
+
"staticField": {
|
|
2281
|
+
"type": "object",
|
|
2282
|
+
"required": [
|
|
2283
|
+
"id",
|
|
2284
|
+
"type",
|
|
2285
|
+
"text"
|
|
2286
|
+
],
|
|
2287
|
+
"properties": {
|
|
2288
|
+
"id": {
|
|
2289
|
+
"type": "integer",
|
|
2290
|
+
"minimum": 1
|
|
2291
|
+
},
|
|
2292
|
+
"type": { "const": "static" },
|
|
2293
|
+
"text": { "type": "string" },
|
|
2294
|
+
"label": { "type": "string" },
|
|
2295
|
+
"description": { "type": "string" },
|
|
2296
|
+
"placeholder": { "type": "string" },
|
|
2297
|
+
"answer_guidelines": { "type": "string" },
|
|
2298
|
+
"reference_id": { "type": "string" },
|
|
2299
|
+
"condition": { "$ref": "#/$defs/condition" }
|
|
2300
|
+
},
|
|
2301
|
+
"additionalProperties": false
|
|
2302
|
+
},
|
|
1440
2303
|
"arrayField": {
|
|
1441
2304
|
"type": "object",
|
|
1442
2305
|
"required": [
|
|
@@ -1453,12 +2316,48 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1453
2316
|
"type": { "const": "array" },
|
|
1454
2317
|
"label": { "type": "string" },
|
|
1455
2318
|
"description": { "type": "string" },
|
|
2319
|
+
"placeholder": { "type": "string" },
|
|
2320
|
+
"answer_guidelines": { "type": "string" },
|
|
2321
|
+
"reference_id": { "type": "string" },
|
|
1456
2322
|
"condition": { "$ref": "#/$defs/condition" },
|
|
1457
2323
|
"item": { "$ref": "#/$defs/arrayItem" },
|
|
1458
2324
|
"validation": { "$ref": "#/$defs/arrayValidation" }
|
|
1459
2325
|
},
|
|
1460
2326
|
"additionalProperties": false
|
|
1461
2327
|
},
|
|
2328
|
+
"arrayObjField": {
|
|
2329
|
+
"type": "object",
|
|
2330
|
+
"required": [
|
|
2331
|
+
"id",
|
|
2332
|
+
"type",
|
|
2333
|
+
"label",
|
|
2334
|
+
"items"
|
|
2335
|
+
],
|
|
2336
|
+
"properties": {
|
|
2337
|
+
"id": {
|
|
2338
|
+
"type": "integer",
|
|
2339
|
+
"minimum": 1
|
|
2340
|
+
},
|
|
2341
|
+
"type": { "const": "array_obj" },
|
|
2342
|
+
"label": { "type": "string" },
|
|
2343
|
+
"description": { "type": "string" },
|
|
2344
|
+
"placeholder": { "type": "string" },
|
|
2345
|
+
"answer_guidelines": { "type": "string" },
|
|
2346
|
+
"reference_id": { "type": "string" },
|
|
2347
|
+
"condition": { "$ref": "#/$defs/condition" },
|
|
2348
|
+
"items": {
|
|
2349
|
+
"type": "array",
|
|
2350
|
+
"minItems": 1,
|
|
2351
|
+
"items": { "$ref": "#/$defs/arrayObjItem" }
|
|
2352
|
+
},
|
|
2353
|
+
"kind": {
|
|
2354
|
+
"type": "string",
|
|
2355
|
+
"enum": ["list", "table"]
|
|
2356
|
+
},
|
|
2357
|
+
"validation": { "$ref": "#/$defs/arrayObjValidation" }
|
|
2358
|
+
},
|
|
2359
|
+
"additionalProperties": false
|
|
2360
|
+
},
|
|
1462
2361
|
"fileField": {
|
|
1463
2362
|
"type": "object",
|
|
1464
2363
|
"required": [
|
|
@@ -1474,19 +2373,73 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1474
2373
|
"type": { "const": "file" },
|
|
1475
2374
|
"label": { "type": "string" },
|
|
1476
2375
|
"description": { "type": "string" },
|
|
2376
|
+
"placeholder": { "type": "string" },
|
|
2377
|
+
"answer_guidelines": { "type": "string" },
|
|
2378
|
+
"reference_id": { "type": "string" },
|
|
1477
2379
|
"condition": { "$ref": "#/$defs/condition" },
|
|
1478
2380
|
"validation": { "$ref": "#/$defs/fileValidation" }
|
|
1479
2381
|
},
|
|
1480
2382
|
"additionalProperties": false
|
|
1481
2383
|
},
|
|
2384
|
+
"blockchainField": {
|
|
2385
|
+
"type": "object",
|
|
2386
|
+
"required": [
|
|
2387
|
+
"id",
|
|
2388
|
+
"type",
|
|
2389
|
+
"label"
|
|
2390
|
+
],
|
|
2391
|
+
"properties": {
|
|
2392
|
+
"id": {
|
|
2393
|
+
"type": "integer",
|
|
2394
|
+
"minimum": 1
|
|
2395
|
+
},
|
|
2396
|
+
"type": { "const": "blockchain" },
|
|
2397
|
+
"label": { "type": "string" },
|
|
2398
|
+
"description": { "type": "string" },
|
|
2399
|
+
"placeholder": { "type": "string" },
|
|
2400
|
+
"answer_guidelines": { "type": "string" },
|
|
2401
|
+
"reference_id": { "type": "string" },
|
|
2402
|
+
"condition": { "$ref": "#/$defs/condition" },
|
|
2403
|
+
"validation": { "$ref": "#/$defs/blockchainValidation" }
|
|
2404
|
+
},
|
|
2405
|
+
"additionalProperties": false
|
|
2406
|
+
},
|
|
2407
|
+
"sustainabilityField": {
|
|
2408
|
+
"type": "object",
|
|
2409
|
+
"required": [
|
|
2410
|
+
"id",
|
|
2411
|
+
"type",
|
|
2412
|
+
"label"
|
|
2413
|
+
],
|
|
2414
|
+
"properties": {
|
|
2415
|
+
"id": {
|
|
2416
|
+
"type": "integer",
|
|
2417
|
+
"minimum": 1
|
|
2418
|
+
},
|
|
2419
|
+
"type": { "const": "sustainability" },
|
|
2420
|
+
"label": { "type": "string" },
|
|
2421
|
+
"description": { "type": "string" },
|
|
2422
|
+
"placeholder": { "type": "string" },
|
|
2423
|
+
"answer_guidelines": { "type": "string" },
|
|
2424
|
+
"reference_id": { "type": "string" },
|
|
2425
|
+
"condition": { "$ref": "#/$defs/condition" },
|
|
2426
|
+
"validation": { "$ref": "#/$defs/sustainabilityValidation" }
|
|
2427
|
+
},
|
|
2428
|
+
"additionalProperties": false
|
|
2429
|
+
},
|
|
1482
2430
|
"fieldItem": { "oneOf": [
|
|
1483
2431
|
{ "$ref": "#/$defs/stringField" },
|
|
1484
2432
|
{ "$ref": "#/$defs/numberField" },
|
|
1485
2433
|
{ "$ref": "#/$defs/booleanField" },
|
|
1486
2434
|
{ "$ref": "#/$defs/dateField" },
|
|
1487
2435
|
{ "$ref": "#/$defs/selectField" },
|
|
2436
|
+
{ "$ref": "#/$defs/multiselectField" },
|
|
1488
2437
|
{ "$ref": "#/$defs/arrayField" },
|
|
1489
|
-
{ "$ref": "#/$defs/
|
|
2438
|
+
{ "$ref": "#/$defs/arrayObjField" },
|
|
2439
|
+
{ "$ref": "#/$defs/fileField" },
|
|
2440
|
+
{ "$ref": "#/$defs/staticField" },
|
|
2441
|
+
{ "$ref": "#/$defs/blockchainField" },
|
|
2442
|
+
{ "$ref": "#/$defs/sustainabilityField" }
|
|
1490
2443
|
] },
|
|
1491
2444
|
"section": {
|
|
1492
2445
|
"type": "object",
|
|
@@ -1504,6 +2457,9 @@ const validateFn = new Ajv2020({ allErrors: true }).compile({
|
|
|
1504
2457
|
"type": { "const": "section" },
|
|
1505
2458
|
"title": { "type": "string" },
|
|
1506
2459
|
"description": { "type": "string" },
|
|
2460
|
+
"placeholder": { "type": "string" },
|
|
2461
|
+
"answer_guidelines": { "type": "string" },
|
|
2462
|
+
"reference_id": { "type": "string" },
|
|
1507
2463
|
"condition": { "$ref": "#/$defs/condition" },
|
|
1508
2464
|
"content": {
|
|
1509
2465
|
"type": "array",
|
|
@@ -1543,17 +2499,44 @@ const itemRequiredProperties = new Map([
|
|
|
1543
2499
|
"label",
|
|
1544
2500
|
"options"
|
|
1545
2501
|
])],
|
|
2502
|
+
["multiselect", new Set([
|
|
2503
|
+
"id",
|
|
2504
|
+
"type",
|
|
2505
|
+
"label",
|
|
2506
|
+
"options"
|
|
2507
|
+
])],
|
|
1546
2508
|
["array", new Set([
|
|
1547
2509
|
"id",
|
|
1548
2510
|
"type",
|
|
1549
2511
|
"label",
|
|
1550
2512
|
"item"
|
|
1551
2513
|
])],
|
|
2514
|
+
["array_obj", new Set([
|
|
2515
|
+
"id",
|
|
2516
|
+
"type",
|
|
2517
|
+
"label",
|
|
2518
|
+
"items"
|
|
2519
|
+
])],
|
|
1552
2520
|
["file", new Set([
|
|
1553
2521
|
"id",
|
|
1554
2522
|
"type",
|
|
1555
2523
|
"label"
|
|
1556
2524
|
])],
|
|
2525
|
+
["blockchain", new Set([
|
|
2526
|
+
"id",
|
|
2527
|
+
"type",
|
|
2528
|
+
"label"
|
|
2529
|
+
])],
|
|
2530
|
+
["sustainability", new Set([
|
|
2531
|
+
"id",
|
|
2532
|
+
"type",
|
|
2533
|
+
"label"
|
|
2534
|
+
])],
|
|
2535
|
+
["static", new Set([
|
|
2536
|
+
"id",
|
|
2537
|
+
"type",
|
|
2538
|
+
"text"
|
|
2539
|
+
])],
|
|
1557
2540
|
["section", new Set([
|
|
1558
2541
|
"id",
|
|
1559
2542
|
"type",
|
|
@@ -1567,6 +2550,9 @@ const itemAllowedProperties = new Map([
|
|
|
1567
2550
|
"type",
|
|
1568
2551
|
"label",
|
|
1569
2552
|
"description",
|
|
2553
|
+
"placeholder",
|
|
2554
|
+
"answer_guidelines",
|
|
2555
|
+
"reference_id",
|
|
1570
2556
|
"condition",
|
|
1571
2557
|
"validation"
|
|
1572
2558
|
])],
|
|
@@ -1575,6 +2561,9 @@ const itemAllowedProperties = new Map([
|
|
|
1575
2561
|
"type",
|
|
1576
2562
|
"label",
|
|
1577
2563
|
"description",
|
|
2564
|
+
"placeholder",
|
|
2565
|
+
"answer_guidelines",
|
|
2566
|
+
"reference_id",
|
|
1578
2567
|
"condition",
|
|
1579
2568
|
"validation"
|
|
1580
2569
|
])],
|
|
@@ -1583,6 +2572,9 @@ const itemAllowedProperties = new Map([
|
|
|
1583
2572
|
"type",
|
|
1584
2573
|
"label",
|
|
1585
2574
|
"description",
|
|
2575
|
+
"placeholder",
|
|
2576
|
+
"answer_guidelines",
|
|
2577
|
+
"reference_id",
|
|
1586
2578
|
"condition",
|
|
1587
2579
|
"validation"
|
|
1588
2580
|
])],
|
|
@@ -1591,6 +2583,9 @@ const itemAllowedProperties = new Map([
|
|
|
1591
2583
|
"type",
|
|
1592
2584
|
"label",
|
|
1593
2585
|
"description",
|
|
2586
|
+
"placeholder",
|
|
2587
|
+
"answer_guidelines",
|
|
2588
|
+
"reference_id",
|
|
1594
2589
|
"condition",
|
|
1595
2590
|
"validation"
|
|
1596
2591
|
])],
|
|
@@ -1599,6 +2594,21 @@ const itemAllowedProperties = new Map([
|
|
|
1599
2594
|
"type",
|
|
1600
2595
|
"label",
|
|
1601
2596
|
"description",
|
|
2597
|
+
"placeholder",
|
|
2598
|
+
"answer_guidelines",
|
|
2599
|
+
"reference_id",
|
|
2600
|
+
"condition",
|
|
2601
|
+
"options",
|
|
2602
|
+
"validation"
|
|
2603
|
+
])],
|
|
2604
|
+
["multiselect", new Set([
|
|
2605
|
+
"id",
|
|
2606
|
+
"type",
|
|
2607
|
+
"label",
|
|
2608
|
+
"description",
|
|
2609
|
+
"placeholder",
|
|
2610
|
+
"answer_guidelines",
|
|
2611
|
+
"reference_id",
|
|
1602
2612
|
"condition",
|
|
1603
2613
|
"options",
|
|
1604
2614
|
"validation"
|
|
@@ -1608,23 +2618,78 @@ const itemAllowedProperties = new Map([
|
|
|
1608
2618
|
"type",
|
|
1609
2619
|
"label",
|
|
1610
2620
|
"description",
|
|
2621
|
+
"placeholder",
|
|
2622
|
+
"answer_guidelines",
|
|
2623
|
+
"reference_id",
|
|
1611
2624
|
"condition",
|
|
1612
2625
|
"item",
|
|
1613
2626
|
"validation"
|
|
1614
2627
|
])],
|
|
2628
|
+
["array_obj", new Set([
|
|
2629
|
+
"id",
|
|
2630
|
+
"type",
|
|
2631
|
+
"label",
|
|
2632
|
+
"description",
|
|
2633
|
+
"placeholder",
|
|
2634
|
+
"answer_guidelines",
|
|
2635
|
+
"reference_id",
|
|
2636
|
+
"condition",
|
|
2637
|
+
"items",
|
|
2638
|
+
"kind",
|
|
2639
|
+
"validation"
|
|
2640
|
+
])],
|
|
1615
2641
|
["file", new Set([
|
|
1616
2642
|
"id",
|
|
1617
2643
|
"type",
|
|
1618
2644
|
"label",
|
|
1619
2645
|
"description",
|
|
2646
|
+
"placeholder",
|
|
2647
|
+
"answer_guidelines",
|
|
2648
|
+
"reference_id",
|
|
2649
|
+
"condition",
|
|
2650
|
+
"validation"
|
|
2651
|
+
])],
|
|
2652
|
+
["blockchain", new Set([
|
|
2653
|
+
"id",
|
|
2654
|
+
"type",
|
|
2655
|
+
"label",
|
|
2656
|
+
"description",
|
|
2657
|
+
"placeholder",
|
|
2658
|
+
"answer_guidelines",
|
|
2659
|
+
"reference_id",
|
|
2660
|
+
"condition",
|
|
2661
|
+
"validation"
|
|
2662
|
+
])],
|
|
2663
|
+
["sustainability", new Set([
|
|
2664
|
+
"id",
|
|
2665
|
+
"type",
|
|
2666
|
+
"label",
|
|
2667
|
+
"description",
|
|
2668
|
+
"placeholder",
|
|
2669
|
+
"answer_guidelines",
|
|
2670
|
+
"reference_id",
|
|
1620
2671
|
"condition",
|
|
1621
2672
|
"validation"
|
|
1622
2673
|
])],
|
|
2674
|
+
["static", new Set([
|
|
2675
|
+
"id",
|
|
2676
|
+
"type",
|
|
2677
|
+
"text",
|
|
2678
|
+
"label",
|
|
2679
|
+
"description",
|
|
2680
|
+
"placeholder",
|
|
2681
|
+
"answer_guidelines",
|
|
2682
|
+
"reference_id",
|
|
2683
|
+
"condition"
|
|
2684
|
+
])],
|
|
1623
2685
|
["section", new Set([
|
|
1624
2686
|
"id",
|
|
1625
2687
|
"type",
|
|
1626
2688
|
"title",
|
|
1627
2689
|
"description",
|
|
2690
|
+
"placeholder",
|
|
2691
|
+
"answer_guidelines",
|
|
2692
|
+
"reference_id",
|
|
1628
2693
|
"condition",
|
|
1629
2694
|
"content"
|
|
1630
2695
|
])]
|
|
@@ -1642,12 +2707,17 @@ const itemAllowedProperties = new Map([
|
|
|
1642
2707
|
* ### Semantic validation (`validate`)
|
|
1643
2708
|
* Checks for logical issues that go beyond JSON schema validity:
|
|
1644
2709
|
* 1. **Duplicate IDs** (`DUPLICATE_ID`) -- every content item id must be unique.
|
|
2710
|
+
* `array_obj` sub-field ids share that id space and are checked with it.
|
|
1645
2711
|
* 2. **Nesting depth** (`NESTING_DEPTH`) -- sections may not be nested more
|
|
1646
2712
|
* than 3 levels deep.
|
|
1647
2713
|
* 3. **Unknown field references** (`UNKNOWN_FIELD_REF`) -- conditions must
|
|
1648
2714
|
* only reference field ids that exist in the registry.
|
|
1649
|
-
* 4. **Condition references
|
|
1650
|
-
* must not reference section
|
|
2715
|
+
* 4. **Condition references a valueless item** (`CONDITION_REFS_SECTION`,
|
|
2716
|
+
* `CONDITION_REFS_STATIC`) -- conditions must not reference section or
|
|
2717
|
+
* static ids, because neither holds a value.
|
|
2718
|
+
* 4b. **Condition references an `array_obj` sub-field** (`CONDITION_REFS_ARRAY_OBJ_ITEM`)
|
|
2719
|
+
* -- a sub-field holds one value per row, so a form-level condition cannot
|
|
2720
|
+
* say which row it means.
|
|
1651
2721
|
* 5. **Constraint contradictions** (`INVALID_MIN_MAX`) -- e.g. `minLength > maxLength`,
|
|
1652
2722
|
* `min > max`, `minDate > maxDate` (absolute dates only), `minItems > maxItems`.
|
|
1653
2723
|
* 6. **Invalid regex** (`INVALID_REGEX`) -- string field `pattern` values must
|
|
@@ -1845,22 +2915,51 @@ var FormDefinitionValidator = class {
|
|
|
1845
2915
|
const issues = [];
|
|
1846
2916
|
this.checkDuplicateIds(definition.content, issues);
|
|
1847
2917
|
this.checkNestingDepth(definition.content, 0, issues);
|
|
1848
|
-
this.
|
|
1849
|
-
this.
|
|
2918
|
+
const arrayObjItemIds = this.collectArrayObjItemIds(definition.content);
|
|
2919
|
+
this.checkConditionRefsArrayObjItem(registry, arrayObjItemIds, issues);
|
|
2920
|
+
this.checkConditionRefs(registry, arrayObjItemIds, issues);
|
|
2921
|
+
this.checkConditionRefsValueless(registry, issues);
|
|
1850
2922
|
this.checkConstraintContradictions(registry, issues);
|
|
1851
2923
|
this.checkInvalidRegex(registry, issues);
|
|
1852
2924
|
return issues;
|
|
1853
2925
|
}
|
|
1854
2926
|
checkDuplicateIds(content, issues) {
|
|
1855
2927
|
const seen = /* @__PURE__ */ new Set();
|
|
1856
|
-
|
|
1857
|
-
if (seen.has(
|
|
2928
|
+
const record = (id) => {
|
|
2929
|
+
if (seen.has(id)) issues.push({
|
|
1858
2930
|
code: "DUPLICATE_ID",
|
|
1859
|
-
message: `Duplicate id: ${
|
|
1860
|
-
itemId:
|
|
2931
|
+
message: `Duplicate id: ${id}`,
|
|
2932
|
+
itemId: id
|
|
1861
2933
|
});
|
|
1862
|
-
else seen.add(
|
|
2934
|
+
else seen.add(id);
|
|
2935
|
+
};
|
|
2936
|
+
this.walkItems(content, (item) => {
|
|
2937
|
+
record(item.id);
|
|
2938
|
+
if (item.type === "array_obj") for (const subField of item.items ?? []) record(subField.id);
|
|
2939
|
+
});
|
|
2940
|
+
}
|
|
2941
|
+
collectArrayObjItemIds(content) {
|
|
2942
|
+
const ids = /* @__PURE__ */ new Map();
|
|
2943
|
+
this.walkItems(content, (item) => {
|
|
2944
|
+
if (item.type !== "array_obj") return;
|
|
2945
|
+
for (const subField of item.items ?? []) if (!ids.has(subField.id)) ids.set(subField.id, item.id);
|
|
1863
2946
|
});
|
|
2947
|
+
return ids;
|
|
2948
|
+
}
|
|
2949
|
+
checkConditionRefsArrayObjItem(registry, arrayObjItemIds, issues) {
|
|
2950
|
+
if (arrayObjItemIds.size === 0) return;
|
|
2951
|
+
for (const [id, entry] of registry) {
|
|
2952
|
+
if (!entry.condition) continue;
|
|
2953
|
+
for (const ref of DependencyGraph.extractFieldRefs(entry.condition)) {
|
|
2954
|
+
const containerId = arrayObjItemIds.get(ref);
|
|
2955
|
+
if (containerId === void 0) continue;
|
|
2956
|
+
issues.push({
|
|
2957
|
+
code: "CONDITION_REFS_ARRAY_OBJ_ITEM",
|
|
2958
|
+
message: `Condition references sub-field ${ref} of array_obj field ${containerId}, whose value is per-row and not addressable (in item ${id})`,
|
|
2959
|
+
itemId: id
|
|
2960
|
+
});
|
|
2961
|
+
}
|
|
2962
|
+
}
|
|
1864
2963
|
}
|
|
1865
2964
|
checkNestingDepth(content, depth, issues) {
|
|
1866
2965
|
for (const item of content) if (item.type === "section") if (depth >= 3) issues.push({
|
|
@@ -1870,28 +2969,37 @@ var FormDefinitionValidator = class {
|
|
|
1870
2969
|
});
|
|
1871
2970
|
else this.checkNestingDepth(item.content, depth + 1, issues);
|
|
1872
2971
|
}
|
|
1873
|
-
checkConditionRefs(registry, issues) {
|
|
2972
|
+
checkConditionRefs(registry, arrayObjItemIds, issues) {
|
|
1874
2973
|
for (const [id, entry] of registry) {
|
|
1875
2974
|
if (!entry.condition) continue;
|
|
1876
2975
|
const refs = DependencyGraph.extractFieldRefs(entry.condition);
|
|
1877
|
-
for (const ref of refs)
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
2976
|
+
for (const ref of refs) {
|
|
2977
|
+
if (arrayObjItemIds.has(ref)) continue;
|
|
2978
|
+
if (!registry.has(ref)) issues.push({
|
|
2979
|
+
code: "UNKNOWN_FIELD_REF",
|
|
2980
|
+
message: `Condition references unknown field: ${ref} (in item ${id})`,
|
|
2981
|
+
itemId: id
|
|
2982
|
+
});
|
|
2983
|
+
}
|
|
1882
2984
|
}
|
|
1883
2985
|
}
|
|
1884
|
-
|
|
2986
|
+
checkConditionRefsValueless(registry, issues) {
|
|
1885
2987
|
for (const [id, entry] of registry) {
|
|
1886
2988
|
if (!entry.condition) continue;
|
|
1887
2989
|
const refs = DependencyGraph.extractFieldRefs(entry.condition);
|
|
1888
2990
|
for (const ref of refs) {
|
|
1889
2991
|
const refEntry = registry.get(ref);
|
|
1890
|
-
if (refEntry
|
|
2992
|
+
if (!refEntry) continue;
|
|
2993
|
+
if (refEntry.type === "section") issues.push({
|
|
1891
2994
|
code: "CONDITION_REFS_SECTION",
|
|
1892
2995
|
message: `Condition references section ${ref}, which has no value (in item ${id})`,
|
|
1893
2996
|
itemId: id
|
|
1894
2997
|
});
|
|
2998
|
+
if (refEntry.type === "static") issues.push({
|
|
2999
|
+
code: "CONDITION_REFS_STATIC",
|
|
3000
|
+
message: `Condition references static field ${ref}, which has no value (in item ${id})`,
|
|
3001
|
+
itemId: id
|
|
3002
|
+
});
|
|
1895
3003
|
}
|
|
1896
3004
|
}
|
|
1897
3005
|
}
|
|
@@ -1932,7 +3040,8 @@ var FormDefinitionValidator = class {
|
|
|
1932
3040
|
}
|
|
1933
3041
|
break;
|
|
1934
3042
|
}
|
|
1935
|
-
case "array":
|
|
3043
|
+
case "array":
|
|
3044
|
+
case "array_obj": {
|
|
1936
3045
|
const v = entry.validation;
|
|
1937
3046
|
if (v.minItems !== void 0 && v.maxItems !== void 0 && v.maxItems < v.minItems) issues.push({
|
|
1938
3047
|
code: "INVALID_MIN_MAX",
|
|
@@ -2018,6 +3127,7 @@ var VisibilityResolver = class {
|
|
|
2018
3127
|
registry;
|
|
2019
3128
|
conditionEvaluator;
|
|
2020
3129
|
topologicalOrder;
|
|
3130
|
+
fieldTypes;
|
|
2021
3131
|
/**
|
|
2022
3132
|
* @param registry - The engine's field registry.
|
|
2023
3133
|
* @param conditionEvaluator - Evaluator for condition trees.
|
|
@@ -2027,6 +3137,7 @@ var VisibilityResolver = class {
|
|
|
2027
3137
|
this.registry = registry;
|
|
2028
3138
|
this.conditionEvaluator = conditionEvaluator;
|
|
2029
3139
|
this.topologicalOrder = topologicalOrder;
|
|
3140
|
+
this.fieldTypes = new Map([...registry].map(([id, entry]) => [id, entry.type]));
|
|
2030
3141
|
}
|
|
2031
3142
|
/**
|
|
2032
3143
|
* Determines whether a single field or section is visible.
|
|
@@ -2053,7 +3164,8 @@ var VisibilityResolver = class {
|
|
|
2053
3164
|
if (entry.condition) {
|
|
2054
3165
|
if (!this.conditionEvaluator.evalCondition(entry.condition, {
|
|
2055
3166
|
values,
|
|
2056
|
-
now
|
|
3167
|
+
now,
|
|
3168
|
+
fieldTypes: this.fieldTypes
|
|
2057
3169
|
})) return false;
|
|
2058
3170
|
}
|
|
2059
3171
|
if (entry.parentId !== void 0) return this.isVisible(entry.parentId, values, now);
|
|
@@ -2091,7 +3203,8 @@ var VisibilityResolver = class {
|
|
|
2091
3203
|
const visible = this.conditionEvaluator.evalCondition(entry.condition, {
|
|
2092
3204
|
values,
|
|
2093
3205
|
visibilityMap: result,
|
|
2094
|
-
now
|
|
3206
|
+
now,
|
|
3207
|
+
fieldTypes: this.fieldTypes
|
|
2095
3208
|
});
|
|
2096
3209
|
result.set(id, visible);
|
|
2097
3210
|
} else result.set(id, true);
|
|
@@ -2358,14 +3471,16 @@ var FormEngine = class FormEngine {
|
|
|
2358
3471
|
}
|
|
2359
3472
|
static walkContent(content, parentId, registry, contentOrder) {
|
|
2360
3473
|
for (const item of content) {
|
|
3474
|
+
const isValueField = item.type !== "section" && item.type !== "static";
|
|
2361
3475
|
const entry = {
|
|
2362
3476
|
id: item.id,
|
|
2363
3477
|
type: item.type,
|
|
2364
3478
|
condition: item.condition,
|
|
2365
|
-
validation:
|
|
3479
|
+
validation: isValueField ? item.validation : void 0,
|
|
2366
3480
|
parentId,
|
|
2367
|
-
options: item.type === "select" ? item.options : void 0,
|
|
3481
|
+
options: item.type === "select" || item.type === "multiselect" ? item.options : void 0,
|
|
2368
3482
|
item: item.type === "array" ? item.item : void 0,
|
|
3483
|
+
items: item.type === "array_obj" ? item.items : void 0,
|
|
2369
3484
|
label: item.type !== "section" ? item.label : void 0,
|
|
2370
3485
|
title: item.type === "section" ? item.title : void 0
|
|
2371
3486
|
};
|
|
@@ -2376,6 +3491,108 @@ var FormEngine = class FormEngine {
|
|
|
2376
3491
|
}
|
|
2377
3492
|
};
|
|
2378
3493
|
//#endregion
|
|
3494
|
+
//#region src/suggestions.ts
|
|
3495
|
+
/**
|
|
3496
|
+
* Pure helpers for reading and writing the `suggestions` block of a
|
|
3497
|
+
* {@link FormDocument}.
|
|
3498
|
+
*
|
|
3499
|
+
* Every function is total over legacy documents: `doc.suggestions` may be
|
|
3500
|
+
* `undefined` (documents written before suggestions existed) and each helper
|
|
3501
|
+
* treats that as "no suggestions". Writers never mutate their input -- they
|
|
3502
|
+
* return a new document -- and they drop the `suggestions` key entirely once it
|
|
3503
|
+
* would be empty, so a document that never had suggestions round-trips
|
|
3504
|
+
* unchanged.
|
|
3505
|
+
*
|
|
3506
|
+
* These helpers deliberately do **not** check that `fieldId` refers to an
|
|
3507
|
+
* existing, non-section field. That check belongs to the general-purpose
|
|
3508
|
+
* authoring API ({@link FormValuesEditor}); callers that already resolved a
|
|
3509
|
+
* field -- such as the viewer's render loop -- would only pay for it twice.
|
|
3510
|
+
*/
|
|
3511
|
+
/**
|
|
3512
|
+
* Returns the suggestion recorded for a field.
|
|
3513
|
+
*
|
|
3514
|
+
* @param doc - The form document to read from.
|
|
3515
|
+
* @param fieldId - Numeric id of the field.
|
|
3516
|
+
* @returns The suggestion, or `undefined` when the field has none.
|
|
3517
|
+
*/
|
|
3518
|
+
const getSuggestion = (doc, fieldId) => doc.suggestions?.[String(fieldId)];
|
|
3519
|
+
/**
|
|
3520
|
+
* Records a suggestion for a field, replacing any existing one.
|
|
3521
|
+
*
|
|
3522
|
+
* @param doc - The form document to update.
|
|
3523
|
+
* @param fieldId - Numeric id of the field.
|
|
3524
|
+
* @param suggestion - The suggestion to store. Deep-copied before storing.
|
|
3525
|
+
* @returns A new document carrying the suggestion.
|
|
3526
|
+
* @throws If `confidence` is not a finite number within `0..1`.
|
|
3527
|
+
*/
|
|
3528
|
+
const setSuggestion = (doc, fieldId, suggestion) => {
|
|
3529
|
+
const { confidence } = suggestion;
|
|
3530
|
+
if (!Number.isFinite(confidence) || confidence < 0 || confidence > 1) throw new Error(`Suggestion confidence must be a number between 0 and 1, received ${confidence}`);
|
|
3531
|
+
return {
|
|
3532
|
+
...doc,
|
|
3533
|
+
suggestions: {
|
|
3534
|
+
...doc.suggestions,
|
|
3535
|
+
[String(fieldId)]: deepCopy(suggestion)
|
|
3536
|
+
}
|
|
3537
|
+
};
|
|
3538
|
+
};
|
|
3539
|
+
/**
|
|
3540
|
+
* Removes the suggestion recorded for a field, leaving the field's value alone.
|
|
3541
|
+
*
|
|
3542
|
+
* When the removed entry was the last one, the `suggestions` key is dropped
|
|
3543
|
+
* from the document rather than left as an empty object.
|
|
3544
|
+
*
|
|
3545
|
+
* @param doc - The form document to update.
|
|
3546
|
+
* @param fieldId - Numeric id of the field.
|
|
3547
|
+
* @returns A new document without that suggestion, or `doc` itself when there
|
|
3548
|
+
* was nothing to remove.
|
|
3549
|
+
*/
|
|
3550
|
+
const removeSuggestion = (doc, fieldId) => {
|
|
3551
|
+
const key = String(fieldId);
|
|
3552
|
+
if (!doc.suggestions || !(key in doc.suggestions)) return doc;
|
|
3553
|
+
const { [key]: _removed, ...rest } = doc.suggestions;
|
|
3554
|
+
if (Object.keys(rest).length === 0) {
|
|
3555
|
+
const { suggestions: _dropped, ...withoutSuggestions } = doc;
|
|
3556
|
+
return withoutSuggestions;
|
|
3557
|
+
}
|
|
3558
|
+
return {
|
|
3559
|
+
...doc,
|
|
3560
|
+
suggestions: rest
|
|
3561
|
+
};
|
|
3562
|
+
};
|
|
3563
|
+
/**
|
|
3564
|
+
* Copies a field's suggested value into the document's values, keeping the
|
|
3565
|
+
* suggestion in place so the origin of the answer stays visible.
|
|
3566
|
+
*
|
|
3567
|
+
* The value is deep-copied: array and object suggestions must not become
|
|
3568
|
+
* aliases of the stored value, or later in-place edits (e.g. appending an array
|
|
3569
|
+
* item) would silently rewrite the suggestion too.
|
|
3570
|
+
*
|
|
3571
|
+
* @param doc - The form document to update.
|
|
3572
|
+
* @param fieldId - Numeric id of the field.
|
|
3573
|
+
* @returns A new document with the value applied, or `doc` itself when the
|
|
3574
|
+
* field has no suggestion.
|
|
3575
|
+
*/
|
|
3576
|
+
const applySuggestion = (doc, fieldId) => {
|
|
3577
|
+
const suggestion = getSuggestion(doc, fieldId);
|
|
3578
|
+
if (!suggestion) return doc;
|
|
3579
|
+
return {
|
|
3580
|
+
...doc,
|
|
3581
|
+
values: {
|
|
3582
|
+
...doc.values,
|
|
3583
|
+
[String(fieldId)]: deepCopy(suggestion.value)
|
|
3584
|
+
}
|
|
3585
|
+
};
|
|
3586
|
+
};
|
|
3587
|
+
/**
|
|
3588
|
+
* Returns all suggestions on a document as a plain object, never `undefined`.
|
|
3589
|
+
*
|
|
3590
|
+
* @param doc - The form document to read from.
|
|
3591
|
+
* @returns A copy of the suggestions map. Empty when the document has none.
|
|
3592
|
+
*/
|
|
3593
|
+
const getSuggestions = (doc) => ({ ...doc.suggestions });
|
|
3594
|
+
const deepCopy = (value) => value === void 0 ? value : JSON.parse(JSON.stringify(value));
|
|
3595
|
+
//#endregion
|
|
2379
3596
|
//#region src/form-values-editor.ts
|
|
2380
3597
|
/**
|
|
2381
3598
|
* Mutable editor for building and modifying form values against a {@link FormDefinition}.
|
|
@@ -2447,13 +3664,16 @@ var FormValuesEditor = class {
|
|
|
2447
3664
|
* If the field currently has no value, it is initialized to an empty array
|
|
2448
3665
|
* before appending.
|
|
2449
3666
|
*
|
|
2450
|
-
* @param fieldId - Numeric id of the array field.
|
|
2451
|
-
* @param value - The value to append. Defaults to `undefined
|
|
3667
|
+
* @param fieldId - Numeric id of the `array` or `array_obj` field.
|
|
3668
|
+
* @param value - The value to append. Defaults to `undefined` for an
|
|
3669
|
+
* `array` field and to an empty row (`{}`) for an `array_obj` field.
|
|
2452
3670
|
* @returns `this` for chaining.
|
|
2453
3671
|
* @throws If `fieldId` is not an array field.
|
|
2454
3672
|
*/
|
|
2455
3673
|
addArrayItem(fieldId, value) {
|
|
2456
|
-
this.getOrInitArray(fieldId)
|
|
3674
|
+
const arr = this.getOrInitArray(fieldId);
|
|
3675
|
+
const entry = this.engine.getFieldDef(fieldId);
|
|
3676
|
+
arr.push(value === void 0 && entry?.type === "array_obj" ? {} : value);
|
|
2457
3677
|
return this;
|
|
2458
3678
|
}
|
|
2459
3679
|
/**
|
|
@@ -2503,6 +3723,114 @@ var FormValuesEditor = class {
|
|
|
2503
3723
|
return this;
|
|
2504
3724
|
}
|
|
2505
3725
|
/**
|
|
3726
|
+
* Returns the value of one sub-field within one row of an `array_obj` field.
|
|
3727
|
+
*
|
|
3728
|
+
* @param fieldId - Numeric id of the `array_obj` field.
|
|
3729
|
+
* @param index - Zero-based row index.
|
|
3730
|
+
* @param subFieldId - Numeric id of the sub-field.
|
|
3731
|
+
* @returns The sub-field value, or `undefined` if not set.
|
|
3732
|
+
* @throws If the field is not an `array_obj`, the row index is out of
|
|
3733
|
+
* bounds, or the sub-field does not belong to the field.
|
|
3734
|
+
*/
|
|
3735
|
+
getArrayObjValue(fieldId, index, subFieldId) {
|
|
3736
|
+
return this.assertArrayObjRow(fieldId, index, subFieldId)[String(subFieldId)];
|
|
3737
|
+
}
|
|
3738
|
+
/**
|
|
3739
|
+
* Sets the value of one sub-field within one row of an `array_obj` field.
|
|
3740
|
+
*
|
|
3741
|
+
* @param fieldId - Numeric id of the `array_obj` field.
|
|
3742
|
+
* @param index - Zero-based row index.
|
|
3743
|
+
* @param subFieldId - Numeric id of the sub-field.
|
|
3744
|
+
* @param value - The value to set.
|
|
3745
|
+
* @returns `this` for chaining.
|
|
3746
|
+
* @throws If the field is not an `array_obj`, the row index is out of
|
|
3747
|
+
* bounds, or the sub-field does not belong to the field or is static.
|
|
3748
|
+
*/
|
|
3749
|
+
setArrayObjValue(fieldId, index, subFieldId, value) {
|
|
3750
|
+
this.assertArrayObjRow(fieldId, index, subFieldId)[String(subFieldId)] = value;
|
|
3751
|
+
return this;
|
|
3752
|
+
}
|
|
3753
|
+
/**
|
|
3754
|
+
* Removes one sub-field's value from one row of an `array_obj` field.
|
|
3755
|
+
*
|
|
3756
|
+
* @returns `this` for chaining.
|
|
3757
|
+
* @throws Under the same conditions as {@link setArrayObjValue}.
|
|
3758
|
+
*/
|
|
3759
|
+
clearArrayObjValue(fieldId, index, subFieldId) {
|
|
3760
|
+
delete this.assertArrayObjRow(fieldId, index, subFieldId)[String(subFieldId)];
|
|
3761
|
+
return this;
|
|
3762
|
+
}
|
|
3763
|
+
/**
|
|
3764
|
+
* Returns the suggestion recorded for a field.
|
|
3765
|
+
*
|
|
3766
|
+
* @param fieldId - Numeric id of the field.
|
|
3767
|
+
* @returns The suggestion, or `undefined` if the field has none.
|
|
3768
|
+
*/
|
|
3769
|
+
getSuggestion(fieldId) {
|
|
3770
|
+
return getSuggestion(this.doc, fieldId);
|
|
3771
|
+
}
|
|
3772
|
+
/**
|
|
3773
|
+
* Returns every suggestion on the document, keyed by stringified field id.
|
|
3774
|
+
*
|
|
3775
|
+
* @returns A copy of the suggestions map. Empty when there are none.
|
|
3776
|
+
*/
|
|
3777
|
+
getSuggestions() {
|
|
3778
|
+
return getSuggestions(this.doc);
|
|
3779
|
+
}
|
|
3780
|
+
/**
|
|
3781
|
+
* Records a suggestion for a field, replacing any existing one. The field's
|
|
3782
|
+
* value is left untouched.
|
|
3783
|
+
*
|
|
3784
|
+
* @param fieldId - Numeric id of the field.
|
|
3785
|
+
* @param suggestion - The suggestion to store.
|
|
3786
|
+
* @returns `this` for chaining.
|
|
3787
|
+
* @throws If `fieldId` is unknown, references a section, or `confidence`
|
|
3788
|
+
* falls outside `0..1`.
|
|
3789
|
+
*/
|
|
3790
|
+
setSuggestion(fieldId, suggestion) {
|
|
3791
|
+
this.assertField(fieldId);
|
|
3792
|
+
this.doc = setSuggestion(this.doc, fieldId, suggestion);
|
|
3793
|
+
return this;
|
|
3794
|
+
}
|
|
3795
|
+
/**
|
|
3796
|
+
* Removes the suggestion recorded for a field, leaving its value untouched.
|
|
3797
|
+
*
|
|
3798
|
+
* @param fieldId - Numeric id of the field.
|
|
3799
|
+
* @returns `this` for chaining.
|
|
3800
|
+
*/
|
|
3801
|
+
clearSuggestion(fieldId) {
|
|
3802
|
+
this.doc = removeSuggestion(this.doc, fieldId);
|
|
3803
|
+
return this;
|
|
3804
|
+
}
|
|
3805
|
+
/**
|
|
3806
|
+
* Accepts a field's suggestion: copies the suggested value into the field's
|
|
3807
|
+
* value and **keeps** the suggestion, so its source stays visible.
|
|
3808
|
+
*
|
|
3809
|
+
* No-op when the field has no suggestion.
|
|
3810
|
+
*
|
|
3811
|
+
* @param fieldId - Numeric id of the field.
|
|
3812
|
+
* @returns `this` for chaining.
|
|
3813
|
+
* @throws If `fieldId` is unknown or references a section.
|
|
3814
|
+
*/
|
|
3815
|
+
acceptSuggestion(fieldId) {
|
|
3816
|
+
this.assertField(fieldId);
|
|
3817
|
+
this.doc = applySuggestion(this.doc, fieldId);
|
|
3818
|
+
return this;
|
|
3819
|
+
}
|
|
3820
|
+
/**
|
|
3821
|
+
* Rejects a field's suggestion: removes it entirely, leaving the field's
|
|
3822
|
+
* value untouched.
|
|
3823
|
+
*
|
|
3824
|
+
* No-op when the field has no suggestion.
|
|
3825
|
+
*
|
|
3826
|
+
* @param fieldId - Numeric id of the field.
|
|
3827
|
+
* @returns `this` for chaining.
|
|
3828
|
+
*/
|
|
3829
|
+
rejectSuggestion(fieldId) {
|
|
3830
|
+
this.doc = removeSuggestion(this.doc, fieldId);
|
|
3831
|
+
return this;
|
|
3832
|
+
}
|
|
3833
|
+
/**
|
|
2506
3834
|
* Sets the `submittedAt` timestamp on the document.
|
|
2507
3835
|
*
|
|
2508
3836
|
* @param submittedAt - ISO 8601 timestamp string.
|
|
@@ -2558,6 +3886,7 @@ var FormValuesEditor = class {
|
|
|
2558
3886
|
const entry = this.engine.getFieldDef(fieldId);
|
|
2559
3887
|
if (!entry) throw new Error(`Field with id ${fieldId} not found`);
|
|
2560
3888
|
if (entry.type === "section") throw new Error(`Item ${fieldId} is a section, not a field`);
|
|
3889
|
+
if (entry.type === "static") throw new Error(`Item ${fieldId} is a static field and holds no value`);
|
|
2561
3890
|
}
|
|
2562
3891
|
/**
|
|
2563
3892
|
* Asserts that `fieldId` is an array field and returns the current array value.
|
|
@@ -2566,7 +3895,7 @@ var FormValuesEditor = class {
|
|
|
2566
3895
|
assertArray(fieldId) {
|
|
2567
3896
|
const entry = this.engine.getFieldDef(fieldId);
|
|
2568
3897
|
if (!entry) throw new Error(`Field with id ${fieldId} not found`);
|
|
2569
|
-
if (entry.type !== "array") throw new Error(`Field ${fieldId} is not an array field`);
|
|
3898
|
+
if (entry.type !== "array" && entry.type !== "array_obj") throw new Error(`Field ${fieldId} is not an array field`);
|
|
2570
3899
|
const val = this.doc.values[String(fieldId)];
|
|
2571
3900
|
if (!Array.isArray(val)) throw new Error(`Field ${fieldId} does not currently hold an array value`);
|
|
2572
3901
|
return val;
|
|
@@ -2577,7 +3906,7 @@ var FormValuesEditor = class {
|
|
|
2577
3906
|
getOrInitArray(fieldId) {
|
|
2578
3907
|
const entry = this.engine.getFieldDef(fieldId);
|
|
2579
3908
|
if (!entry) throw new Error(`Field with id ${fieldId} not found`);
|
|
2580
|
-
if (entry.type !== "array") throw new Error(`Field ${fieldId} is not an array field`);
|
|
3909
|
+
if (entry.type !== "array" && entry.type !== "array_obj") throw new Error(`Field ${fieldId} is not an array field`);
|
|
2581
3910
|
const key = String(fieldId);
|
|
2582
3911
|
let val = this.doc.values[key];
|
|
2583
3912
|
if (!Array.isArray(val)) {
|
|
@@ -2586,8 +3915,28 @@ var FormValuesEditor = class {
|
|
|
2586
3915
|
}
|
|
2587
3916
|
return val;
|
|
2588
3917
|
}
|
|
3918
|
+
/**
|
|
3919
|
+
* Asserts that `fieldId` is an `array_obj` field holding a row at `index`
|
|
3920
|
+
* with a writable sub-field `subFieldId`, and returns that row.
|
|
3921
|
+
* The row is created in place when it is absent or not an object.
|
|
3922
|
+
*/
|
|
3923
|
+
assertArrayObjRow(fieldId, index, subFieldId) {
|
|
3924
|
+
const entry = this.engine.getFieldDef(fieldId);
|
|
3925
|
+
if (!entry) throw new Error(`Field with id ${fieldId} not found`);
|
|
3926
|
+
if (entry.type !== "array_obj") throw new Error(`Field ${fieldId} is not an array_obj field`);
|
|
3927
|
+
const subField = (entry.items ?? []).find((f) => f.id === subFieldId);
|
|
3928
|
+
if (!subField) throw new Error(`Sub-field ${subFieldId} does not belong to field ${fieldId}`);
|
|
3929
|
+
if (subField.type === "static") throw new Error(`Sub-field ${subFieldId} is a static field and holds no value`);
|
|
3930
|
+
const arr = this.assertArray(fieldId);
|
|
3931
|
+
if (index < 0 || index >= arr.length) throw new Error(`Index ${index} is out of bounds for array field ${fieldId} (length ${arr.length})`);
|
|
3932
|
+
const row = arr[index];
|
|
3933
|
+
if (typeof row === "object" && row !== null && !Array.isArray(row)) return row;
|
|
3934
|
+
const created = {};
|
|
3935
|
+
arr[index] = created;
|
|
3936
|
+
return created;
|
|
3937
|
+
}
|
|
2589
3938
|
};
|
|
2590
3939
|
//#endregion
|
|
2591
|
-
export { ConditionEvaluator, DependencyGraph, DocumentError, FieldValidator, FormDefinitionEditor, FormDefinitionValidator, FormEngine, FormValuesEditor, VisibilityResolver };
|
|
3940
|
+
export { ConditionEvaluator, DependencyGraph, DocumentError, FieldValidator, FormDefinitionEditor, FormDefinitionValidator, FormEngine, FormValuesEditor, VisibilityResolver, applySuggestion, getSuggestion, getSuggestions, removeSuggestion, setSuggestion };
|
|
2592
3941
|
|
|
2593
3942
|
//# sourceMappingURL=index.mjs.map
|