@marktiderman/genesis-forms 0.4.1 → 0.5.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 +89 -5
- package/dist/destinations.cjs +92 -4
- package/dist/destinations.cjs.map +1 -1
- package/dist/destinations.d.cts +1 -1
- package/dist/destinations.d.ts +1 -1
- package/dist/destinations.js +92 -4
- package/dist/destinations.js.map +1 -1
- package/dist/{engine-Dz9J5ej2.d.ts → engine-BDq0XJ21.d.cts} +25 -2
- package/dist/{engine-BkNuzlna.d.cts → engine-Qzp6bX6O.d.ts} +25 -2
- package/dist/index.cjs +383 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +121 -76
- package/dist/index.d.ts +121 -76
- package/dist/index.js +360 -60
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +387 -62
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +39 -5
- package/dist/server.d.ts +39 -5
- package/dist/server.js +385 -63
- package/dist/server.js.map +1 -1
- package/dist/testing.cjs +386 -61
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +4 -4
- package/dist/testing.d.ts +4 -4
- package/dist/testing.js +386 -61
- package/dist/testing.js.map +1 -1
- package/dist/{types-BBKBQ8sp.d.cts → types-BhYUbLJ-.d.cts} +21 -1
- package/dist/{types-BBKBQ8sp.d.ts → types-BhYUbLJ-.d.ts} +21 -1
- package/dist/validate-Bs1lyoOl.d.ts +131 -0
- package/dist/validate-BsZ0YTQS.d.cts +131 -0
- package/package.json +1 -1
- package/dist/validate-BXXqi0fq.d.cts +0 -30
- package/dist/validate-BjNwF1UE.d.ts +0 -30
package/dist/index.js
CHANGED
|
@@ -415,7 +415,9 @@ var round = (n, decimals) => {
|
|
|
415
415
|
return Object.is(r, -0) ? 0 : r;
|
|
416
416
|
};
|
|
417
417
|
function calculatedValue(result, field2) {
|
|
418
|
-
|
|
418
|
+
return valueAs(result, calculatedProps(field2));
|
|
419
|
+
}
|
|
420
|
+
function valueAs(result, { format, decimals }) {
|
|
419
421
|
if (result === null || Array.isArray(result)) return void 0;
|
|
420
422
|
if (format === "number" || format === "percent") {
|
|
421
423
|
const n = formulaNumber(result);
|
|
@@ -442,19 +444,6 @@ var extract = (value, column) => column !== void 0 ? value.flatMap((row) => {
|
|
|
442
444
|
const cell = row[column];
|
|
443
445
|
return typeof cell === "string" || typeof cell === "number" ? [cell] : [];
|
|
444
446
|
}) : value.flatMap((v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean" ? [v] : []);
|
|
445
|
-
var extracted = /* @__PURE__ */ new WeakMap();
|
|
446
|
-
function cachedList(value, column) {
|
|
447
|
-
let byColumn = extracted.get(value);
|
|
448
|
-
if (!byColumn) extracted.set(value, byColumn = /* @__PURE__ */ new Map());
|
|
449
|
-
const key = column ?? "";
|
|
450
|
-
let list = byColumn.get(key);
|
|
451
|
-
if (!list) byColumn.set(key, list = ownFormulaList(extract(value, column)));
|
|
452
|
-
return list;
|
|
453
|
-
}
|
|
454
|
-
function readAnswer(value, column) {
|
|
455
|
-
if (Array.isArray(value)) return cachedList(value, column);
|
|
456
|
-
return column !== void 0 ? null : formulaInput(value);
|
|
457
|
-
}
|
|
458
447
|
function formulaInput(value, column) {
|
|
459
448
|
if (value === void 0 || value === null) return null;
|
|
460
449
|
if (Array.isArray(value) && value.length > MAX_FORMULA_ITEMS) return null;
|
|
@@ -473,9 +462,19 @@ function refNodes(node, out = []) {
|
|
|
473
462
|
else if (node.kind === "call") for (const a of node.args) refNodes(a, out);
|
|
474
463
|
return out;
|
|
475
464
|
}
|
|
465
|
+
function formulaSize(node) {
|
|
466
|
+
if (node.kind === "unary") return 1 + formulaSize(node.arg);
|
|
467
|
+
if (node.kind === "binary") return 1 + formulaSize(node.left) + formulaSize(node.right);
|
|
468
|
+
if (node.kind === "if") return 1 + formulaSize(node.test) + formulaSize(node.then) + formulaSize(node.else);
|
|
469
|
+
if (node.kind === "call") return node.args.reduce((n, a) => n + formulaSize(a), 1);
|
|
470
|
+
return 1;
|
|
471
|
+
}
|
|
472
|
+
function spend(budget, amount) {
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
476
475
|
var UNREAD = /* @__PURE__ */ Symbol("unread");
|
|
477
476
|
var OVER = /* @__PURE__ */ Symbol("over");
|
|
478
|
-
function calculator(definition) {
|
|
477
|
+
function calculator(definition, work) {
|
|
479
478
|
const compiled = [];
|
|
480
479
|
const idByKey = /* @__PURE__ */ new Map();
|
|
481
480
|
for (const block of definition.blocks) {
|
|
@@ -484,7 +483,8 @@ function calculator(definition) {
|
|
|
484
483
|
}
|
|
485
484
|
for (const block of definition.blocks) {
|
|
486
485
|
if (block.kind !== "field" || !isCalculated(block)) continue;
|
|
487
|
-
const
|
|
486
|
+
const props2 = calculatedProps(block);
|
|
487
|
+
const parsed = parseFormula(props2.formula);
|
|
488
488
|
const reads = [];
|
|
489
489
|
const slots = /* @__PURE__ */ new Map();
|
|
490
490
|
const byKey = /* @__PURE__ */ new Map();
|
|
@@ -498,33 +498,64 @@ function calculator(definition) {
|
|
|
498
498
|
}
|
|
499
499
|
slots.set(ref, slot);
|
|
500
500
|
}
|
|
501
|
-
compiled.push({ field: block, ast: parsed.ok ? parsed.ast : null, reads, slots, last: null });
|
|
501
|
+
compiled.push({ field: block, props: props2, ast: parsed.ok ? parsed.ast : null, size: parsed.ok ? formulaSize(parsed.ast) : 0, reads, slots, last: null });
|
|
502
502
|
}
|
|
503
|
+
const extracted = /* @__PURE__ */ new WeakMap();
|
|
504
|
+
const cachedList = (value, column) => {
|
|
505
|
+
let byColumn = extracted.get(value);
|
|
506
|
+
if (!byColumn) extracted.set(value, byColumn = /* @__PURE__ */ new Map());
|
|
507
|
+
const key = column ?? "";
|
|
508
|
+
let list = byColumn.get(key);
|
|
509
|
+
if (!list) {
|
|
510
|
+
byColumn.set(key, list = ownFormulaList(extract(value, column)));
|
|
511
|
+
}
|
|
512
|
+
return list;
|
|
513
|
+
};
|
|
514
|
+
const readAnswer = (value, column) => {
|
|
515
|
+
if (Array.isArray(value)) return cachedList(value, column);
|
|
516
|
+
return column !== void 0 ? null : formulaInput(value);
|
|
517
|
+
};
|
|
518
|
+
const forget = (value) => {
|
|
519
|
+
if (!value || typeof value !== "object") return;
|
|
520
|
+
if (Array.isArray(value)) extracted.delete(value);
|
|
521
|
+
for (const entry of compiled) if (entry.last?.inputs.includes(value)) entry.last = null;
|
|
522
|
+
};
|
|
503
523
|
const withCalculated = (values, path) => {
|
|
504
524
|
if (!compiled.length) return values;
|
|
505
525
|
const visible = new Set(path);
|
|
506
526
|
let next = values;
|
|
527
|
+
let copied = false;
|
|
507
528
|
let budget = MAX_SETTLE_ITEMS;
|
|
508
529
|
const within = /* @__PURE__ */ new Map();
|
|
509
|
-
const input = ({ id
|
|
530
|
+
const input = ({ id }) => {
|
|
510
531
|
if (id === void 0 || !visible.has(id) || !Object.prototype.hasOwnProperty.call(next, id)) return UNREAD;
|
|
511
532
|
const value = next[id];
|
|
512
533
|
if (!Array.isArray(value)) return value;
|
|
513
|
-
let ok = within.get(
|
|
534
|
+
let ok = within.get(id);
|
|
514
535
|
if (ok === void 0) {
|
|
515
536
|
ok = value.length <= MAX_FORMULA_ITEMS && value.length <= budget;
|
|
516
537
|
if (ok) budget -= value.length;
|
|
517
|
-
within.set(
|
|
538
|
+
within.set(id, ok);
|
|
518
539
|
}
|
|
519
540
|
return ok ? value : OVER;
|
|
520
541
|
};
|
|
521
542
|
for (const entry of compiled) {
|
|
522
543
|
const { field: field2, ast } = entry;
|
|
523
|
-
const
|
|
544
|
+
const { reads } = entry;
|
|
545
|
+
const inputs = new Array(reads.length);
|
|
546
|
+
let over = false;
|
|
547
|
+
let same = entry.last !== null;
|
|
548
|
+
for (let i = 0; i < reads.length; i++) {
|
|
549
|
+
const v = input(reads[i]);
|
|
550
|
+
inputs[i] = v;
|
|
551
|
+
if (v === OVER) over = true;
|
|
552
|
+
if (same && entry.last.inputs[i] !== v) same = false;
|
|
553
|
+
}
|
|
524
554
|
let value;
|
|
525
|
-
if (
|
|
555
|
+
if (same) {
|
|
526
556
|
value = entry.last.value;
|
|
527
557
|
} else {
|
|
558
|
+
spend(work, entry.size);
|
|
528
559
|
const resolved = new Array(inputs.length);
|
|
529
560
|
const read = (ref) => {
|
|
530
561
|
const slot = entry.slots.get(ref);
|
|
@@ -532,19 +563,25 @@ function calculator(definition) {
|
|
|
532
563
|
let v = resolved[slot];
|
|
533
564
|
if (v === void 0) {
|
|
534
565
|
const raw = inputs[slot];
|
|
535
|
-
v = resolved[slot] = raw === UNREAD ? null : readAnswer(raw,
|
|
566
|
+
v = resolved[slot] = raw === UNREAD ? null : readAnswer(raw, reads[slot].column);
|
|
536
567
|
}
|
|
537
568
|
return v;
|
|
538
569
|
};
|
|
539
|
-
value = ast && !
|
|
570
|
+
value = ast && !over ? valueAs(evaluateFormula(ast, read), entry.props) : void 0;
|
|
540
571
|
entry.last = { inputs, value };
|
|
541
572
|
}
|
|
542
573
|
const current = Object.prototype.hasOwnProperty.call(next, field2.id) ? next[field2.id] : void 0;
|
|
543
|
-
if (current !== value)
|
|
574
|
+
if (current !== value) {
|
|
575
|
+
if (!copied) {
|
|
576
|
+
next = { ...next };
|
|
577
|
+
copied = true;
|
|
578
|
+
}
|
|
579
|
+
next[field2.id] = value;
|
|
580
|
+
}
|
|
544
581
|
}
|
|
545
582
|
return next;
|
|
546
583
|
};
|
|
547
|
-
return { active: compiled.length > 0, withCalculated };
|
|
584
|
+
return { active: compiled.length > 0, ids: new Set(compiled.map((c) => c.field.id)), withCalculated, forget };
|
|
548
585
|
}
|
|
549
586
|
var numberOps = ["eq", "neq", "lt", "lte", "gt", "gte", "in", "answered", "empty"];
|
|
550
587
|
var calculatedFieldType = {
|
|
@@ -796,6 +833,81 @@ var structuredFieldTypes = [
|
|
|
796
833
|
}
|
|
797
834
|
];
|
|
798
835
|
|
|
836
|
+
// src/photo.ts
|
|
837
|
+
var PHOTO_TYPE = "photo";
|
|
838
|
+
var UPLOAD_FIELD_TYPES = [PHOTO_TYPE];
|
|
839
|
+
var PHOTO_FORMATS = {
|
|
840
|
+
jpeg: ["image/jpeg"],
|
|
841
|
+
png: ["image/png"],
|
|
842
|
+
heic: ["image/heic", "image/heif"],
|
|
843
|
+
webp: ["image/webp"]
|
|
844
|
+
};
|
|
845
|
+
var FORMAT_NAMES = { jpeg: "JPEG", png: "PNG", heic: "HEIC", webp: "WebP" };
|
|
846
|
+
var ALL_FORMATS = Object.keys(PHOTO_FORMATS);
|
|
847
|
+
var DEFAULT_PHOTO_FILES = 3;
|
|
848
|
+
var MAX_PHOTO_FILES = 5;
|
|
849
|
+
var DEFAULT_PHOTO_SIZE_MB = 10;
|
|
850
|
+
var MAX_PHOTO_SIZE_MB = 25;
|
|
851
|
+
var MAX_PHOTO_ID_LENGTH = 200;
|
|
852
|
+
var MAX_PHOTO_NAME_LENGTH = 255;
|
|
853
|
+
var isPhotoFormat = (v) => typeof v === "string" && Object.prototype.hasOwnProperty.call(PHOTO_FORMATS, v);
|
|
854
|
+
var wholeIn = (v, min, max) => typeof v === "number" && Number.isInteger(v) && v >= min && v <= max;
|
|
855
|
+
function photoLimits(field2) {
|
|
856
|
+
const maxFiles = wholeIn(field2.props?.maxFiles, 1, MAX_PHOTO_FILES) ? field2.props.maxFiles : DEFAULT_PHOTO_FILES;
|
|
857
|
+
const maxSizeMb = wholeIn(field2.props?.maxSizeMb, 1, MAX_PHOTO_SIZE_MB) ? field2.props.maxSizeMb : DEFAULT_PHOTO_SIZE_MB;
|
|
858
|
+
const raw = field2.props?.formats;
|
|
859
|
+
const picked = Array.isArray(raw) ? ALL_FORMATS.filter((f2) => raw.includes(f2)) : [];
|
|
860
|
+
const formats = picked.length ? picked : [...ALL_FORMATS];
|
|
861
|
+
return {
|
|
862
|
+
maxFiles,
|
|
863
|
+
maxSizeMb,
|
|
864
|
+
maxBytes: maxSizeMb * 1024 * 1024,
|
|
865
|
+
formats,
|
|
866
|
+
mimeTypes: formats.flatMap((f2) => PHOTO_FORMATS[f2])
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
function isPhotoRef(v) {
|
|
870
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return false;
|
|
871
|
+
const r = v;
|
|
872
|
+
return typeof r.id === "string" && r.id.length > 0 && r.id.length <= MAX_PHOTO_ID_LENGTH && typeof r.name === "string" && r.name.length <= MAX_PHOTO_NAME_LENGTH && typeof r.type === "string" && typeof r.size === "number" && Number.isInteger(r.size) && r.size > 0;
|
|
873
|
+
}
|
|
874
|
+
function photoRefs(value) {
|
|
875
|
+
if (!Array.isArray(value)) return [];
|
|
876
|
+
const refs = [];
|
|
877
|
+
for (const r of value) if (isPhotoRef(r)) refs.push({ id: r.id, name: r.name, type: r.type, size: r.size });
|
|
878
|
+
return refs;
|
|
879
|
+
}
|
|
880
|
+
var plural2 = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;
|
|
881
|
+
function photoFormatList(formats) {
|
|
882
|
+
const names = formats.map((f2) => FORMAT_NAMES[f2]);
|
|
883
|
+
return names.length > 1 ? `${names.slice(0, -1).join(", ")} or ${names[names.length - 1]}` : names[0] ?? "";
|
|
884
|
+
}
|
|
885
|
+
var photoTypeMessage = (field2) => `Use a ${photoFormatList(photoLimits(field2).formats)} photo.`;
|
|
886
|
+
var photoSizeMessage = (field2) => `Each photo must be ${photoLimits(field2).maxSizeMb} MB or smaller.`;
|
|
887
|
+
var photoCountMessage = (field2) => `Add at most ${plural2(photoLimits(field2).maxFiles, "photo")}.`;
|
|
888
|
+
var photoFieldType = {
|
|
889
|
+
type: PHOTO_TYPE,
|
|
890
|
+
label: "Photo",
|
|
891
|
+
category: "media",
|
|
892
|
+
value: { json: true },
|
|
893
|
+
operators: ["answered", "empty"],
|
|
894
|
+
a11y: { semantics: "group" },
|
|
895
|
+
isEmpty: (value) => value === void 0 || value === null || Array.isArray(value) && value.length === 0,
|
|
896
|
+
validate: (value, field2) => {
|
|
897
|
+
if (!Array.isArray(value) || !value.every(isPhotoRef)) return "Add a photo.";
|
|
898
|
+
const limits = photoLimits(field2);
|
|
899
|
+
if (value.length > limits.maxFiles) return photoCountMessage(field2);
|
|
900
|
+
const refs = value;
|
|
901
|
+
if (new Set(refs.map((r) => r.id)).size !== refs.length) return "Each photo can be added once.";
|
|
902
|
+
if (refs.some((r) => !limits.mimeTypes.includes(r.type.toLowerCase()))) return photoTypeMessage(field2);
|
|
903
|
+
if (refs.some((r) => r.size > limits.maxBytes)) return photoSizeMessage(field2);
|
|
904
|
+
return null;
|
|
905
|
+
},
|
|
906
|
+
normalize: (value) => Array.isArray(value) && value.every(isPhotoRef) ? photoRefs(value) : value,
|
|
907
|
+
summarize: (value) => photoRefs(value).map((r) => r.name || "Photo").join(", "),
|
|
908
|
+
samples: () => [[{ id: "sample-photo", name: "photo.jpg", type: "image/jpeg", size: 1024 }]]
|
|
909
|
+
};
|
|
910
|
+
|
|
799
911
|
// src/fields.ts
|
|
800
912
|
var REGISTRY = /* @__PURE__ */ Symbol.for("@marktiderman/genesis-forms/field-types");
|
|
801
913
|
var globalScope = globalThis;
|
|
@@ -838,6 +950,20 @@ function summarizeValue(value, field2) {
|
|
|
838
950
|
if (Array.isArray(value)) return value.join(", ");
|
|
839
951
|
return String(value);
|
|
840
952
|
}
|
|
953
|
+
var OTHER_MAX_LENGTH = 200;
|
|
954
|
+
function otherOption(field2) {
|
|
955
|
+
const other = field2.props?.other;
|
|
956
|
+
if (other === true) return { label: "Other" };
|
|
957
|
+
if (other && typeof other === "object" && !Array.isArray(other)) {
|
|
958
|
+
const label = typeof other.label === "string" && other.label.trim() ? other.label.trim() : "Other";
|
|
959
|
+
return { label };
|
|
960
|
+
}
|
|
961
|
+
return null;
|
|
962
|
+
}
|
|
963
|
+
function isOtherValue(field2, value) {
|
|
964
|
+
return otherOption(field2) !== null && typeof value === "string" && !choiceOptions(field2).some((o) => o.value === value);
|
|
965
|
+
}
|
|
966
|
+
var typedOther = (field2, value) => isOtherValue(field2, value) && value.trim() !== "" && value.length <= OTHER_MAX_LENGTH;
|
|
841
967
|
function choiceOptions(field2) {
|
|
842
968
|
const raw = field2.props?.options;
|
|
843
969
|
if (!Array.isArray(raw)) return [];
|
|
@@ -845,6 +971,42 @@ function choiceOptions(field2) {
|
|
|
845
971
|
(o) => o && typeof o === "object" && !Array.isArray(o) && typeof o.value === "string" ? [{ value: o.value, label: typeof o.label === "string" ? o.label : void 0 }] : []
|
|
846
972
|
);
|
|
847
973
|
}
|
|
974
|
+
function optionsSource(field2) {
|
|
975
|
+
const raw = field2.props?.optionsFrom;
|
|
976
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
977
|
+
return raw.source === "host" && typeof raw.key === "string" && raw.key ? { source: "host", key: raw.key } : void 0;
|
|
978
|
+
}
|
|
979
|
+
function hostList(hostOptions, key) {
|
|
980
|
+
if (!hostOptions || !Object.prototype.hasOwnProperty.call(hostOptions, key)) return [];
|
|
981
|
+
const list = hostOptions[key];
|
|
982
|
+
if (!Array.isArray(list)) return [];
|
|
983
|
+
const seen = /* @__PURE__ */ new Set();
|
|
984
|
+
const out = [];
|
|
985
|
+
for (const o of list) {
|
|
986
|
+
if (!o || typeof o !== "object" || Array.isArray(o)) continue;
|
|
987
|
+
const { value, label } = o;
|
|
988
|
+
if (typeof value !== "string" || !value || seen.has(value)) continue;
|
|
989
|
+
seen.add(value);
|
|
990
|
+
out.push(typeof label === "string" ? { value, label } : { value });
|
|
991
|
+
}
|
|
992
|
+
return out;
|
|
993
|
+
}
|
|
994
|
+
function withHostOptions(definition, hostOptions) {
|
|
995
|
+
let changed = false;
|
|
996
|
+
const blocks = definition.blocks.map((block) => {
|
|
997
|
+
if (block.kind !== "field") return block;
|
|
998
|
+
const from = optionsSource(block);
|
|
999
|
+
if (!from) return block;
|
|
1000
|
+
const own2 = choiceOptions(block);
|
|
1001
|
+
const taken = new Set(own2.map((o) => o.value));
|
|
1002
|
+
const added = hostList(hostOptions, from.key).filter((o) => !taken.has(o.value));
|
|
1003
|
+
if (!added.length) return block;
|
|
1004
|
+
changed = true;
|
|
1005
|
+
const options = [...own2, ...added].map((o) => o.label === void 0 ? { value: o.value } : { value: o.value, label: o.label });
|
|
1006
|
+
return { ...block, props: { ...block.props, options } };
|
|
1007
|
+
});
|
|
1008
|
+
return changed ? { ...definition, blocks } : definition;
|
|
1009
|
+
}
|
|
848
1010
|
function optionLabel(field2, value) {
|
|
849
1011
|
const option = choiceOptions(field2).find((o) => o.value === value);
|
|
850
1012
|
return option?.label ?? value;
|
|
@@ -963,7 +1125,7 @@ var builtins = [
|
|
|
963
1125
|
value: { json: true },
|
|
964
1126
|
operators: ["eq", "neq", "in", "answered", "empty"],
|
|
965
1127
|
a11y: { semantics: "group" },
|
|
966
|
-
validate: (value, field2) => typeof value === "string" && choiceOptions(field2).some((o) => o.value === value) ? null : "Choose one of the options.",
|
|
1128
|
+
validate: (value, field2) => typeof value === "string" && (choiceOptions(field2).some((o) => o.value === value) || typedOther(field2, value)) ? null : "Choose one of the options.",
|
|
967
1129
|
summarize: (value, field2) => optionLabel(field2, String(value))
|
|
968
1130
|
},
|
|
969
1131
|
{
|
|
@@ -975,7 +1137,8 @@ var builtins = [
|
|
|
975
1137
|
a11y: { semantics: "group" },
|
|
976
1138
|
validate: (value, field2) => {
|
|
977
1139
|
const allowed = new Set(choiceOptions(field2).map((o) => o.value));
|
|
978
|
-
|
|
1140
|
+
const others = Array.isArray(value) ? value.filter((v) => typeof v === "string" && !allowed.has(v)) : [];
|
|
1141
|
+
return Array.isArray(value) && new Set(value).size === value.length && value.every((v) => typeof v === "string") && (others.length === 0 || others.length === 1 && typedOther(field2, others[0])) ? null : "Choose from the options.";
|
|
979
1142
|
},
|
|
980
1143
|
summarize: (value, field2) => Array.isArray(value) ? value.map((v) => optionLabel(field2, String(v))).join(", ") : String(value)
|
|
981
1144
|
},
|
|
@@ -996,7 +1159,7 @@ var builtins = [
|
|
|
996
1159
|
value: { json: true },
|
|
997
1160
|
operators: ["eq", "neq", "in", "answered", "empty"],
|
|
998
1161
|
a11y: { semantics: "control" },
|
|
999
|
-
validate: (value, field2) => typeof value === "string" && choiceOptions(field2).some((o) => o.value === value) ? null : "Choose one of the options.",
|
|
1162
|
+
validate: (value, field2) => typeof value === "string" && (choiceOptions(field2).some((o) => o.value === value) || typedOther(field2, value)) ? null : "Choose one of the options.",
|
|
1000
1163
|
summarize: (value, field2) => optionLabel(field2, String(value))
|
|
1001
1164
|
},
|
|
1002
1165
|
{
|
|
@@ -1106,7 +1269,7 @@ function dateLimits(field2) {
|
|
|
1106
1269
|
if (typeof max === "string" && isIsoDate(max)) out.max = max;
|
|
1107
1270
|
return out;
|
|
1108
1271
|
}
|
|
1109
|
-
for (const manifest of [...builtins, ...structuredFieldTypes, calculatedFieldType]) registerFieldType(manifest);
|
|
1272
|
+
for (const manifest of [...builtins, ...structuredFieldTypes, calculatedFieldType, photoFieldType]) registerFieldType(manifest);
|
|
1110
1273
|
|
|
1111
1274
|
// src/logic.ts
|
|
1112
1275
|
function own(record, key) {
|
|
@@ -1179,8 +1342,8 @@ function rulesAllow(def, blockId, scope) {
|
|
|
1179
1342
|
}
|
|
1180
1343
|
function walkPath(def, scope) {
|
|
1181
1344
|
const list = steps(def);
|
|
1182
|
-
|
|
1183
|
-
|
|
1345
|
+
let index;
|
|
1346
|
+
let position;
|
|
1184
1347
|
const jumps = (def.logic ?? []).filter(
|
|
1185
1348
|
(r) => r.effect === "jump"
|
|
1186
1349
|
);
|
|
@@ -1204,6 +1367,7 @@ function walkPath(def, scope) {
|
|
|
1204
1367
|
ending = jump.to.ending;
|
|
1205
1368
|
break;
|
|
1206
1369
|
}
|
|
1370
|
+
index ??= new Map(list.map((b, at) => [b.id, at]));
|
|
1207
1371
|
const target = index.get(jump.to);
|
|
1208
1372
|
if (target !== void 0 && target > i) {
|
|
1209
1373
|
i = nextVisible(target);
|
|
@@ -1213,6 +1377,7 @@ function walkPath(def, scope) {
|
|
|
1213
1377
|
i = nextVisible(i + 1);
|
|
1214
1378
|
}
|
|
1215
1379
|
const scopeAt = (blockId, inclusive = false) => {
|
|
1380
|
+
position ??= new Map(def.blocks.map((b, i2) => [b.id, i2]));
|
|
1216
1381
|
const at = position.get(blockId) ?? -1;
|
|
1217
1382
|
const values = /* @__PURE__ */ Object.create(null);
|
|
1218
1383
|
for (const id of path) {
|
|
@@ -1404,6 +1569,22 @@ function parseForm(input) {
|
|
|
1404
1569
|
}
|
|
1405
1570
|
}
|
|
1406
1571
|
if (type === "consent") optionalText(props2.text, `${path}.text`);
|
|
1572
|
+
if (type === PHOTO_TYPE) {
|
|
1573
|
+
if (props2.maxFiles !== void 0 && !(isInt(props2.maxFiles) && props2.maxFiles >= 1 && props2.maxFiles <= MAX_PHOTO_FILES)) {
|
|
1574
|
+
issue(`${path}.maxFiles`, `Must be a whole number from 1 to ${MAX_PHOTO_FILES}.`);
|
|
1575
|
+
}
|
|
1576
|
+
if (props2.maxSizeMb !== void 0 && !(isInt(props2.maxSizeMb) && props2.maxSizeMb >= 1 && props2.maxSizeMb <= MAX_PHOTO_SIZE_MB)) {
|
|
1577
|
+
issue(`${path}.maxSizeMb`, `Must be a whole number from 1 to ${MAX_PHOTO_SIZE_MB}.`);
|
|
1578
|
+
}
|
|
1579
|
+
if (props2.formats !== void 0) {
|
|
1580
|
+
const formats = props2.formats;
|
|
1581
|
+
if (!Array.isArray(formats) || formats.length === 0 || !formats.every(isPhotoFormat)) {
|
|
1582
|
+
issue(`${path}.formats`, "Must be a list of one or more of jpeg, png, heic and webp.");
|
|
1583
|
+
} else if (new Set(formats).size !== formats.length) {
|
|
1584
|
+
issue(`${path}.formats`, "Name each format once.");
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1407
1588
|
};
|
|
1408
1589
|
if (!isObject2(input)) {
|
|
1409
1590
|
issue("", "A form definition must be an object.");
|
|
@@ -1424,6 +1605,7 @@ function parseForm(input) {
|
|
|
1424
1605
|
else {
|
|
1425
1606
|
optionalBoolean(input.settings.anonymous, "settings.anonymous");
|
|
1426
1607
|
optionalBoolean(input.settings.clearHiddenValues, "settings.clearHiddenValues");
|
|
1608
|
+
optionalBoolean(input.settings.saveProgress, "settings.saveProgress");
|
|
1427
1609
|
}
|
|
1428
1610
|
}
|
|
1429
1611
|
if (input.meta !== void 0 && (!isObject2(input.meta) || !isJson(input.meta))) {
|
|
@@ -1464,6 +1646,14 @@ function parseForm(input) {
|
|
|
1464
1646
|
issue(`${path}.type`, `Unknown field type "${String(block.type)}".`);
|
|
1465
1647
|
}
|
|
1466
1648
|
if (block.props !== void 0) {
|
|
1649
|
+
const from = isObject2(block.props) ? block.props.optionsFrom : void 0;
|
|
1650
|
+
if (from !== void 0) {
|
|
1651
|
+
if (!isObject2(from) || from.source !== "host" || typeof from.key !== "string" || !from.key) {
|
|
1652
|
+
issue(`${path}.props.optionsFrom`, 'Must be { source: "host", key } with a non-empty key.');
|
|
1653
|
+
} else if (typeof block.type === "string" && !CHOICE_TYPES.has(block.type)) {
|
|
1654
|
+
warnings.push({ path: `${path}.props.optionsFrom`, message: "Only single choice, multiple choice and dropdown questions take options from the app." });
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1467
1657
|
if (!isObject2(block.props) || !isJson(block.props)) issue(`${path}.props`, "Must be a JSON object.");
|
|
1468
1658
|
else if (block.props.options !== void 0) {
|
|
1469
1659
|
const options = block.props.options;
|
|
@@ -1474,10 +1664,20 @@ function parseForm(input) {
|
|
|
1474
1664
|
if (!isObject2(o) || typeof o.value !== "string") issue(at, "Each option needs a string value.");
|
|
1475
1665
|
else optionalText(o.label, `${at}.label`);
|
|
1476
1666
|
});
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1667
|
+
if (from === void 0) {
|
|
1668
|
+
choices.set(
|
|
1669
|
+
block.id,
|
|
1670
|
+
new Set(options.flatMap((o) => isObject2(o) && typeof o.value === "string" ? [o.value] : []))
|
|
1671
|
+
);
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
const other = isObject2(block.props) ? block.props.other : void 0;
|
|
1676
|
+
if (other !== void 0) {
|
|
1677
|
+
if (other !== true && other !== false && !(isObject2(other) && (other.label === void 0 || typeof other.label === "string"))) {
|
|
1678
|
+
issue(`${path}.props.other`, "Must be true, false or { label }.");
|
|
1679
|
+
} else if (other !== false && typeof block.type === "string" && !CHOICE_TYPES.has(block.type)) {
|
|
1680
|
+
warnings.push({ path: `${path}.props.other`, message: 'Only single choice, multiple choice and dropdown questions take an "Other" answer.' });
|
|
1481
1681
|
}
|
|
1482
1682
|
}
|
|
1483
1683
|
const { max, maxLength: maxLength2 } = isObject2(block.props) ? block.props : {};
|
|
@@ -1552,6 +1752,8 @@ function parseForm(input) {
|
|
|
1552
1752
|
} else if (ref.column !== void 0) issue(path, `"${ref.key}" is not a table, so it has no column "${ref.column}".`);
|
|
1553
1753
|
else if (targetType === "media-notes" || targetType === "text-highlights") {
|
|
1554
1754
|
warnings.push({ path, message: `"${ref.key}" holds notes, not numbers; the formula reads it as blank.` });
|
|
1755
|
+
} else if (targetType === PHOTO_TYPE) {
|
|
1756
|
+
warnings.push({ path, message: `"${ref.key}" holds photos, not numbers; the formula reads it as blank.` });
|
|
1555
1757
|
}
|
|
1556
1758
|
}
|
|
1557
1759
|
});
|
|
@@ -1771,9 +1973,15 @@ function field(type, key, options, props2) {
|
|
|
1771
1973
|
return block;
|
|
1772
1974
|
}
|
|
1773
1975
|
var props = (all) => Object.fromEntries(Object.entries(all).filter((e) => e[1] !== void 0));
|
|
1774
|
-
var choiceProps = (
|
|
1775
|
-
|
|
1776
|
-
|
|
1976
|
+
var choiceProps = (o) => {
|
|
1977
|
+
const out = {};
|
|
1978
|
+
if (o.options || !o.optionsFrom) {
|
|
1979
|
+
out.options = (o.options ?? []).map((x) => x.label ? { value: x.value, label: x.label } : { value: x.value });
|
|
1980
|
+
}
|
|
1981
|
+
if (o.optionsFrom) out.optionsFrom = { source: o.optionsFrom.source, key: o.optionsFrom.key };
|
|
1982
|
+
if (o.other) out.other = o.other === true ? true : props({ label: o.other.label });
|
|
1983
|
+
return out;
|
|
1984
|
+
};
|
|
1777
1985
|
var hiddenSpec = (type, o) => ({
|
|
1778
1986
|
type,
|
|
1779
1987
|
source: o.source ?? "url",
|
|
@@ -1797,11 +2005,11 @@ var f = {
|
|
|
1797
2005
|
),
|
|
1798
2006
|
/** A 0-to-10 Net Promoter Score. The end labels default to "Not likely" and "Very likely" in the renderer. */
|
|
1799
2007
|
nps: (key, o) => field("nps", key, o, props({ lowLabel: o.lowLabel || void 0, highLabel: o.highLabel || void 0 })),
|
|
1800
|
-
singleChoice: (key, o) => field("single-choice", key, o, choiceProps(o
|
|
1801
|
-
multiChoice: (key, o) => field("multi-choice", key, o, choiceProps(o
|
|
2008
|
+
singleChoice: (key, o) => field("single-choice", key, o, choiceProps(o)),
|
|
2009
|
+
multiChoice: (key, o) => field("multi-choice", key, o, choiceProps(o)),
|
|
1802
2010
|
yesNo: (key, o) => field("yes-no", key, o),
|
|
1803
2011
|
/** One option from a compact menu: for a long list (a country, a class), where single choice would be a wall of buttons. */
|
|
1804
|
-
dropdown: (key, o) => field("dropdown", key, o, choiceProps(o
|
|
2012
|
+
dropdown: (key, o) => field("dropdown", key, o, choiceProps(o)),
|
|
1805
2013
|
/** A number, optionally between `min` and `max` and on a `step` (from `min`, else 0): `step: 1` for whole numbers. */
|
|
1806
2014
|
number: (key, o) => field("number", key, o, props({ min: o.min, max: o.max, step: o.step })),
|
|
1807
2015
|
/** A calendar day, stored as `YYYY-MM-DD`, optionally between `min` and `max` (also `YYYY-MM-DD`). */
|
|
@@ -1853,6 +2061,17 @@ var f = {
|
|
|
1853
2061
|
o,
|
|
1854
2062
|
props({ text: o.text, maxHighlights: o.maxHighlights })
|
|
1855
2063
|
),
|
|
2064
|
+
/**
|
|
2065
|
+
* Up to a few photos (a picture of broken equipment). The answer holds the
|
|
2066
|
+
* references the host's upload returned, never the bytes; `formats` from
|
|
2067
|
+
* jpeg, png, heic and webp (default all four).
|
|
2068
|
+
*/
|
|
2069
|
+
photo: (key, o) => field(
|
|
2070
|
+
"photo",
|
|
2071
|
+
key,
|
|
2072
|
+
o,
|
|
2073
|
+
props({ maxFiles: o.maxFiles, maxSizeMb: o.maxSizeMb, formats: o.formats ? [...o.formats] : void 0 })
|
|
2074
|
+
),
|
|
1856
2075
|
/** Any registered field type, including plugins. */
|
|
1857
2076
|
custom: (type, key, o) => field(type, key, o, o.props),
|
|
1858
2077
|
heading: (id, text) => ({ kind: "content", id, type: "heading", text }),
|
|
@@ -2024,10 +2243,20 @@ function validateField(field2, value, options = {}) {
|
|
|
2024
2243
|
}
|
|
2025
2244
|
|
|
2026
2245
|
// src/engine.ts
|
|
2246
|
+
function readsAny(node, ids) {
|
|
2247
|
+
if (Array.isArray(node)) return node.some((n) => readsAny(n, ids));
|
|
2248
|
+
if (!node || typeof node !== "object") return false;
|
|
2249
|
+
for (const [k, v] of Object.entries(node)) {
|
|
2250
|
+
if (k === "field" && typeof v === "string" && ids.has(v)) return true;
|
|
2251
|
+
if (typeof v === "object" && readsAny(v, ids)) return true;
|
|
2252
|
+
}
|
|
2253
|
+
return false;
|
|
2254
|
+
}
|
|
2027
2255
|
function createForm(definition, options = {}) {
|
|
2028
2256
|
return build(definition, options).engine;
|
|
2029
2257
|
}
|
|
2030
|
-
function build(
|
|
2258
|
+
function build(given, options, replaying = false, budget) {
|
|
2259
|
+
const definition = withHostOptions(given, options.hostOptions);
|
|
2031
2260
|
const fields = fieldMap(definition);
|
|
2032
2261
|
const byKey = new Map([...fields.values()].map((f2) => [f2.key, f2]));
|
|
2033
2262
|
const blocks = new Map(definition.blocks.map((b) => [b.id, b]));
|
|
@@ -2045,15 +2274,24 @@ function build(definition, options, replaying = false) {
|
|
|
2045
2274
|
if (!declared.has(name)) initialHidden[name] = value;
|
|
2046
2275
|
}
|
|
2047
2276
|
Object.assign(initialHidden, coerceHidden(definition, options.hidden).values);
|
|
2048
|
-
const calc = calculator(definition);
|
|
2277
|
+
const calc = calculator(definition, budget);
|
|
2278
|
+
const pathOf = (values, hidden) => {
|
|
2279
|
+
spend(budget, definition.blocks.length);
|
|
2280
|
+
return computePath(definition, scopeOf(values, hidden));
|
|
2281
|
+
};
|
|
2282
|
+
const logicReadsCalculated = calc.active && readsAny(definition.logic, calc.ids);
|
|
2049
2283
|
const settle = (values, hidden) => {
|
|
2050
|
-
let { path } =
|
|
2284
|
+
let { path } = pathOf(values, hidden);
|
|
2051
2285
|
if (!calc.active) return { values, path };
|
|
2286
|
+
if (!logicReadsCalculated) return { values: calc.withCalculated(values, path), path };
|
|
2052
2287
|
for (let round2 = 0; round2 < 4; round2++) {
|
|
2053
2288
|
const next = calc.withCalculated(values, path);
|
|
2054
2289
|
if (next === values) break;
|
|
2055
2290
|
values = next;
|
|
2056
|
-
|
|
2291
|
+
const again = pathOf(values, hidden).path;
|
|
2292
|
+
const same = again.length === path.length && again.every((id, i) => id === path[i]);
|
|
2293
|
+
path = again;
|
|
2294
|
+
if (same) break;
|
|
2057
2295
|
}
|
|
2058
2296
|
return { values, path };
|
|
2059
2297
|
};
|
|
@@ -2064,6 +2302,7 @@ function build(definition, options, replaying = false) {
|
|
|
2064
2302
|
path: first.path,
|
|
2065
2303
|
current: first.path[0] ?? null,
|
|
2066
2304
|
history: [],
|
|
2305
|
+
furthest: first.path[0] ?? null,
|
|
2067
2306
|
errors: {},
|
|
2068
2307
|
status: "in_progress",
|
|
2069
2308
|
ending: null,
|
|
@@ -2095,14 +2334,30 @@ function build(definition, options, replaying = false) {
|
|
|
2095
2334
|
return errors;
|
|
2096
2335
|
};
|
|
2097
2336
|
let unsettled = false;
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
unsettled
|
|
2101
|
-
|
|
2102
|
-
|
|
2337
|
+
let formulasStale = false;
|
|
2338
|
+
const settleNow = (needValues = true) => {
|
|
2339
|
+
if (unsettled && calc.active && !logicReadsCalculated && !needValues) {
|
|
2340
|
+
unsettled = false;
|
|
2341
|
+
formulasStale = true;
|
|
2342
|
+
state = { ...state, path: pathOf(state.values, state.hidden).path };
|
|
2343
|
+
return;
|
|
2344
|
+
}
|
|
2345
|
+
if (unsettled) {
|
|
2346
|
+
unsettled = false;
|
|
2347
|
+
formulasStale = false;
|
|
2348
|
+
const { values, path } = settle(state.values, state.hidden);
|
|
2349
|
+
state = { ...state, values, path };
|
|
2350
|
+
} else if (formulasStale && needValues) {
|
|
2351
|
+
formulasStale = false;
|
|
2352
|
+
state = { ...state, values: calc.withCalculated(state.values, state.path) };
|
|
2353
|
+
}
|
|
2103
2354
|
};
|
|
2104
2355
|
const answer = (id, value, event) => {
|
|
2105
|
-
if (state.status === "completed" ||
|
|
2356
|
+
if (state.status === "completed" || isCalculated(fields.get(id))) return;
|
|
2357
|
+
if (own(state.values, id) === value) {
|
|
2358
|
+
if (value === null || typeof value !== "object") return;
|
|
2359
|
+
calc.forget(value);
|
|
2360
|
+
}
|
|
2106
2361
|
const errors = { ...state.errors };
|
|
2107
2362
|
delete errors[id];
|
|
2108
2363
|
if (batch) {
|
|
@@ -2148,7 +2403,8 @@ function build(definition, options, replaying = false) {
|
|
|
2148
2403
|
emit({ ...state, events });
|
|
2149
2404
|
return true;
|
|
2150
2405
|
}
|
|
2151
|
-
|
|
2406
|
+
const furthest = state.furthest && state.path.indexOf(state.furthest) >= state.path.indexOf(target) ? state.furthest : target;
|
|
2407
|
+
emit({ ...state, current: target, history: [...state.history, state.current], furthest, events });
|
|
2152
2408
|
return true;
|
|
2153
2409
|
},
|
|
2154
2410
|
back() {
|
|
@@ -2168,7 +2424,7 @@ function build(definition, options, replaying = false) {
|
|
|
2168
2424
|
emit({ ...state, errors, current: firstError, events });
|
|
2169
2425
|
return false;
|
|
2170
2426
|
}
|
|
2171
|
-
const { ending } =
|
|
2427
|
+
const { ending } = pathOf(state.values, state.hidden);
|
|
2172
2428
|
emit({ ...state, errors: {}, status: "completed", ending, events });
|
|
2173
2429
|
return true;
|
|
2174
2430
|
},
|
|
@@ -2193,6 +2449,15 @@ function build(definition, options, replaying = false) {
|
|
|
2193
2449
|
settleNow();
|
|
2194
2450
|
batch = wasBatch;
|
|
2195
2451
|
}
|
|
2452
|
+
const resumeAt = options.resumeAt;
|
|
2453
|
+
if (resumeAt && !replaying && state.path.includes(resumeAt)) {
|
|
2454
|
+
for (let i = 0; i < state.path.length && state.current !== resumeAt; i++) {
|
|
2455
|
+
if (!engine.next()) {
|
|
2456
|
+
state = { ...state, errors: {} };
|
|
2457
|
+
break;
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2196
2461
|
const apply = (event) => {
|
|
2197
2462
|
if (event.type === "answer") {
|
|
2198
2463
|
if (fields.has(event.field)) {
|
|
@@ -2200,10 +2465,11 @@ function build(definition, options, replaying = false) {
|
|
|
2200
2465
|
answer(event.field, event.value, logged);
|
|
2201
2466
|
}
|
|
2202
2467
|
} else if (event.type === "next") {
|
|
2203
|
-
settleNow();
|
|
2468
|
+
settleNow(false);
|
|
2469
|
+
if (formulasStale && isCalculated(fields.get(state.current ?? ""))) settleNow(true);
|
|
2204
2470
|
engine.next();
|
|
2205
2471
|
} else if (event.type === "back") {
|
|
2206
|
-
settleNow();
|
|
2472
|
+
settleNow(false);
|
|
2207
2473
|
engine.back();
|
|
2208
2474
|
} else if (event.type === "submit") {
|
|
2209
2475
|
settleNow();
|
|
@@ -2218,12 +2484,46 @@ function build(definition, options, replaying = false) {
|
|
|
2218
2484
|
return { engine, apply, finish };
|
|
2219
2485
|
}
|
|
2220
2486
|
function replay(definition, events, options = {}) {
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2487
|
+
return replayWithin(definition, events, options);
|
|
2488
|
+
}
|
|
2489
|
+
function replayWithin(definition, events, options, maxWork) {
|
|
2490
|
+
const budget = void 0 ;
|
|
2491
|
+
const { engine, apply, finish } = build(definition, { ...options, initialValues: void 0, clock: () => void 0 }, true, budget);
|
|
2492
|
+
try {
|
|
2493
|
+
for (const event of events) apply(event);
|
|
2494
|
+
finish();
|
|
2495
|
+
} finally {
|
|
2496
|
+
}
|
|
2224
2497
|
return engine;
|
|
2225
2498
|
}
|
|
2226
2499
|
|
|
2500
|
+
// src/progress.ts
|
|
2501
|
+
function furthestReached(state, definition) {
|
|
2502
|
+
const at = (id) => id ? state.path.indexOf(id) : -1;
|
|
2503
|
+
let furthest = Math.max(at(state.current), at(state.furthest));
|
|
2504
|
+
for (const id of state.history) furthest = Math.max(furthest, at(id));
|
|
2505
|
+
const fields = fieldMap(definition);
|
|
2506
|
+
for (let i = state.path.length - 1; i > furthest; i--) {
|
|
2507
|
+
const field2 = fields.get(state.path[i]);
|
|
2508
|
+
if (field2 && !isEmptyValue(own(state.values, field2.id), field2)) {
|
|
2509
|
+
furthest = i;
|
|
2510
|
+
break;
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
return furthest >= 0 ? state.path[furthest] : null;
|
|
2514
|
+
}
|
|
2515
|
+
function formProgress(engine) {
|
|
2516
|
+
const state = engine.getState();
|
|
2517
|
+
const furthest = furthestReached(state, engine.definition);
|
|
2518
|
+
const index = furthest ? state.path.indexOf(furthest) : -1;
|
|
2519
|
+
const fields = fieldMap(engine.definition);
|
|
2520
|
+
let fieldId = null;
|
|
2521
|
+
for (let i = index; i >= 0 && fieldId === null; i--) {
|
|
2522
|
+
if (fields.has(state.path[i])) fieldId = state.path[i];
|
|
2523
|
+
}
|
|
2524
|
+
return { step: index + 1, total: state.path.length, fieldId };
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2227
2527
|
// src/explain.ts
|
|
2228
2528
|
function explain(source, blockId, options = {}) {
|
|
2229
2529
|
const input = "getState" in source ? { definition: source.definition, values: source.getState().values, hidden: source.getState().hidden } : source;
|
|
@@ -2360,6 +2660,6 @@ function describeCondition(condition, def, fields = fieldMap(def)) {
|
|
|
2360
2660
|
return `${left} ${op} ${right}`;
|
|
2361
2661
|
}
|
|
2362
2662
|
|
|
2363
|
-
export { CALCULATED_TYPE, COMPUTED_FIELD_TYPES, FORMULA_FUNCTIONS, HIGHLIGHT_NOTE_MESSAGE, MAX_CALCULATED_DECIMALS, MAX_FORMULA_ITEMS, MAX_FORMULA_LENGTH, MAX_FORM_FORMULA_LENGTH, MAX_HIDDEN_STRING_LENGTH, MAX_HIGHLIGHT_NOTE_LENGTH, MAX_HIGHLIGHT_QUOTE_LENGTH, MAX_SETTLE_ITEMS, MAX_TABLE_CELL_LENGTH, MAX_TABLE_COLUMNS, MAX_TIMESTAMP_SECONDS, REQUIRED_MESSAGE, STRUCTURED_FIELD_TYPES, calculatedProps, calculatedValue, canonicalJson, choiceOptions, coerceHidden, coerceHiddenValue, computePath, createForm, dateLimits, defineForm, describeCondition, evaluate, evaluateFormula, explain, f, fingerprint, formatCalculated, formatTimestamp, formulaInput, formulaNumber, formulaRefs, getFieldType, isEmptyValue, isFormEvent, isIsoDate, isJson, isSensitive, listFieldTypes, listLimits, normalizeValue, numberLimits, parseForm, parseFormula, parseTimestamp, ratingDisplay, recall, registerFieldType, renameFormulaKey, replay, ruleVisible, scaleLabels, steps, summarizeValue, tableColumns, tableLimits, validateField, when };
|
|
2663
|
+
export { CALCULATED_TYPE, COMPUTED_FIELD_TYPES, DEFAULT_PHOTO_FILES, DEFAULT_PHOTO_SIZE_MB, FORMULA_FUNCTIONS, HIGHLIGHT_NOTE_MESSAGE, MAX_CALCULATED_DECIMALS, MAX_FORMULA_ITEMS, MAX_FORMULA_LENGTH, MAX_FORM_FORMULA_LENGTH, MAX_HIDDEN_STRING_LENGTH, MAX_HIGHLIGHT_NOTE_LENGTH, MAX_HIGHLIGHT_QUOTE_LENGTH, MAX_PHOTO_FILES, MAX_PHOTO_ID_LENGTH, MAX_PHOTO_NAME_LENGTH, MAX_PHOTO_SIZE_MB, MAX_SETTLE_ITEMS, MAX_TABLE_CELL_LENGTH, MAX_TABLE_COLUMNS, MAX_TIMESTAMP_SECONDS, OTHER_MAX_LENGTH, PHOTO_FORMATS, PHOTO_TYPE, REQUIRED_MESSAGE, STRUCTURED_FIELD_TYPES, UPLOAD_FIELD_TYPES, calculatedProps, calculatedValue, canonicalJson, choiceOptions, coerceHidden, coerceHiddenValue, computePath, createForm, dateLimits, defineForm, describeCondition, evaluate, evaluateFormula, explain, f, fingerprint, formProgress, formatCalculated, formatTimestamp, formulaInput, formulaNumber, formulaRefs, furthestReached, getFieldType, isEmptyValue, isFormEvent, isIsoDate, isJson, isOtherValue, isPhotoFormat, isPhotoRef, isSensitive, listFieldTypes, listLimits, normalizeValue, numberLimits, optionsSource, otherOption, parseForm, parseFormula, parseTimestamp, photoCountMessage, photoFormatList, photoLimits, photoRefs, photoSizeMessage, photoTypeMessage, ratingDisplay, recall, registerFieldType, renameFormulaKey, replay, ruleVisible, scaleLabels, steps, summarizeValue, tableColumns, tableLimits, validateField, when, withHostOptions };
|
|
2364
2664
|
//# sourceMappingURL=index.js.map
|
|
2365
2665
|
//# sourceMappingURL=index.js.map
|