@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.cjs
CHANGED
|
@@ -417,7 +417,9 @@ var round = (n, decimals) => {
|
|
|
417
417
|
return Object.is(r, -0) ? 0 : r;
|
|
418
418
|
};
|
|
419
419
|
function calculatedValue(result, field2) {
|
|
420
|
-
|
|
420
|
+
return valueAs(result, calculatedProps(field2));
|
|
421
|
+
}
|
|
422
|
+
function valueAs(result, { format, decimals }) {
|
|
421
423
|
if (result === null || Array.isArray(result)) return void 0;
|
|
422
424
|
if (format === "number" || format === "percent") {
|
|
423
425
|
const n = formulaNumber(result);
|
|
@@ -444,19 +446,6 @@ var extract = (value, column) => column !== void 0 ? value.flatMap((row) => {
|
|
|
444
446
|
const cell = row[column];
|
|
445
447
|
return typeof cell === "string" || typeof cell === "number" ? [cell] : [];
|
|
446
448
|
}) : value.flatMap((v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean" ? [v] : []);
|
|
447
|
-
var extracted = /* @__PURE__ */ new WeakMap();
|
|
448
|
-
function cachedList(value, column) {
|
|
449
|
-
let byColumn = extracted.get(value);
|
|
450
|
-
if (!byColumn) extracted.set(value, byColumn = /* @__PURE__ */ new Map());
|
|
451
|
-
const key = column ?? "";
|
|
452
|
-
let list = byColumn.get(key);
|
|
453
|
-
if (!list) byColumn.set(key, list = ownFormulaList(extract(value, column)));
|
|
454
|
-
return list;
|
|
455
|
-
}
|
|
456
|
-
function readAnswer(value, column) {
|
|
457
|
-
if (Array.isArray(value)) return cachedList(value, column);
|
|
458
|
-
return column !== void 0 ? null : formulaInput(value);
|
|
459
|
-
}
|
|
460
449
|
function formulaInput(value, column) {
|
|
461
450
|
if (value === void 0 || value === null) return null;
|
|
462
451
|
if (Array.isArray(value) && value.length > MAX_FORMULA_ITEMS) return null;
|
|
@@ -475,9 +464,19 @@ function refNodes(node, out = []) {
|
|
|
475
464
|
else if (node.kind === "call") for (const a of node.args) refNodes(a, out);
|
|
476
465
|
return out;
|
|
477
466
|
}
|
|
467
|
+
function formulaSize(node) {
|
|
468
|
+
if (node.kind === "unary") return 1 + formulaSize(node.arg);
|
|
469
|
+
if (node.kind === "binary") return 1 + formulaSize(node.left) + formulaSize(node.right);
|
|
470
|
+
if (node.kind === "if") return 1 + formulaSize(node.test) + formulaSize(node.then) + formulaSize(node.else);
|
|
471
|
+
if (node.kind === "call") return node.args.reduce((n, a) => n + formulaSize(a), 1);
|
|
472
|
+
return 1;
|
|
473
|
+
}
|
|
474
|
+
function spend(budget, amount) {
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
478
477
|
var UNREAD = /* @__PURE__ */ Symbol("unread");
|
|
479
478
|
var OVER = /* @__PURE__ */ Symbol("over");
|
|
480
|
-
function calculator(definition) {
|
|
479
|
+
function calculator(definition, work) {
|
|
481
480
|
const compiled = [];
|
|
482
481
|
const idByKey = /* @__PURE__ */ new Map();
|
|
483
482
|
for (const block of definition.blocks) {
|
|
@@ -486,7 +485,8 @@ function calculator(definition) {
|
|
|
486
485
|
}
|
|
487
486
|
for (const block of definition.blocks) {
|
|
488
487
|
if (block.kind !== "field" || !isCalculated(block)) continue;
|
|
489
|
-
const
|
|
488
|
+
const props2 = calculatedProps(block);
|
|
489
|
+
const parsed = parseFormula(props2.formula);
|
|
490
490
|
const reads = [];
|
|
491
491
|
const slots = /* @__PURE__ */ new Map();
|
|
492
492
|
const byKey = /* @__PURE__ */ new Map();
|
|
@@ -500,33 +500,64 @@ function calculator(definition) {
|
|
|
500
500
|
}
|
|
501
501
|
slots.set(ref, slot);
|
|
502
502
|
}
|
|
503
|
-
compiled.push({ field: block, ast: parsed.ok ? parsed.ast : null, reads, slots, last: null });
|
|
503
|
+
compiled.push({ field: block, props: props2, ast: parsed.ok ? parsed.ast : null, size: parsed.ok ? formulaSize(parsed.ast) : 0, reads, slots, last: null });
|
|
504
504
|
}
|
|
505
|
+
const extracted = /* @__PURE__ */ new WeakMap();
|
|
506
|
+
const cachedList = (value, column) => {
|
|
507
|
+
let byColumn = extracted.get(value);
|
|
508
|
+
if (!byColumn) extracted.set(value, byColumn = /* @__PURE__ */ new Map());
|
|
509
|
+
const key = column ?? "";
|
|
510
|
+
let list = byColumn.get(key);
|
|
511
|
+
if (!list) {
|
|
512
|
+
byColumn.set(key, list = ownFormulaList(extract(value, column)));
|
|
513
|
+
}
|
|
514
|
+
return list;
|
|
515
|
+
};
|
|
516
|
+
const readAnswer = (value, column) => {
|
|
517
|
+
if (Array.isArray(value)) return cachedList(value, column);
|
|
518
|
+
return column !== void 0 ? null : formulaInput(value);
|
|
519
|
+
};
|
|
520
|
+
const forget = (value) => {
|
|
521
|
+
if (!value || typeof value !== "object") return;
|
|
522
|
+
if (Array.isArray(value)) extracted.delete(value);
|
|
523
|
+
for (const entry of compiled) if (entry.last?.inputs.includes(value)) entry.last = null;
|
|
524
|
+
};
|
|
505
525
|
const withCalculated = (values, path) => {
|
|
506
526
|
if (!compiled.length) return values;
|
|
507
527
|
const visible = new Set(path);
|
|
508
528
|
let next = values;
|
|
529
|
+
let copied = false;
|
|
509
530
|
let budget = MAX_SETTLE_ITEMS;
|
|
510
531
|
const within = /* @__PURE__ */ new Map();
|
|
511
|
-
const input = ({ id
|
|
532
|
+
const input = ({ id }) => {
|
|
512
533
|
if (id === void 0 || !visible.has(id) || !Object.prototype.hasOwnProperty.call(next, id)) return UNREAD;
|
|
513
534
|
const value = next[id];
|
|
514
535
|
if (!Array.isArray(value)) return value;
|
|
515
|
-
let ok = within.get(
|
|
536
|
+
let ok = within.get(id);
|
|
516
537
|
if (ok === void 0) {
|
|
517
538
|
ok = value.length <= MAX_FORMULA_ITEMS && value.length <= budget;
|
|
518
539
|
if (ok) budget -= value.length;
|
|
519
|
-
within.set(
|
|
540
|
+
within.set(id, ok);
|
|
520
541
|
}
|
|
521
542
|
return ok ? value : OVER;
|
|
522
543
|
};
|
|
523
544
|
for (const entry of compiled) {
|
|
524
545
|
const { field: field2, ast } = entry;
|
|
525
|
-
const
|
|
546
|
+
const { reads } = entry;
|
|
547
|
+
const inputs = new Array(reads.length);
|
|
548
|
+
let over = false;
|
|
549
|
+
let same = entry.last !== null;
|
|
550
|
+
for (let i = 0; i < reads.length; i++) {
|
|
551
|
+
const v = input(reads[i]);
|
|
552
|
+
inputs[i] = v;
|
|
553
|
+
if (v === OVER) over = true;
|
|
554
|
+
if (same && entry.last.inputs[i] !== v) same = false;
|
|
555
|
+
}
|
|
526
556
|
let value;
|
|
527
|
-
if (
|
|
557
|
+
if (same) {
|
|
528
558
|
value = entry.last.value;
|
|
529
559
|
} else {
|
|
560
|
+
spend(work, entry.size);
|
|
530
561
|
const resolved = new Array(inputs.length);
|
|
531
562
|
const read = (ref) => {
|
|
532
563
|
const slot = entry.slots.get(ref);
|
|
@@ -534,19 +565,25 @@ function calculator(definition) {
|
|
|
534
565
|
let v = resolved[slot];
|
|
535
566
|
if (v === void 0) {
|
|
536
567
|
const raw = inputs[slot];
|
|
537
|
-
v = resolved[slot] = raw === UNREAD ? null : readAnswer(raw,
|
|
568
|
+
v = resolved[slot] = raw === UNREAD ? null : readAnswer(raw, reads[slot].column);
|
|
538
569
|
}
|
|
539
570
|
return v;
|
|
540
571
|
};
|
|
541
|
-
value = ast && !
|
|
572
|
+
value = ast && !over ? valueAs(evaluateFormula(ast, read), entry.props) : void 0;
|
|
542
573
|
entry.last = { inputs, value };
|
|
543
574
|
}
|
|
544
575
|
const current = Object.prototype.hasOwnProperty.call(next, field2.id) ? next[field2.id] : void 0;
|
|
545
|
-
if (current !== value)
|
|
576
|
+
if (current !== value) {
|
|
577
|
+
if (!copied) {
|
|
578
|
+
next = { ...next };
|
|
579
|
+
copied = true;
|
|
580
|
+
}
|
|
581
|
+
next[field2.id] = value;
|
|
582
|
+
}
|
|
546
583
|
}
|
|
547
584
|
return next;
|
|
548
585
|
};
|
|
549
|
-
return { active: compiled.length > 0, withCalculated };
|
|
586
|
+
return { active: compiled.length > 0, ids: new Set(compiled.map((c) => c.field.id)), withCalculated, forget };
|
|
550
587
|
}
|
|
551
588
|
var numberOps = ["eq", "neq", "lt", "lte", "gt", "gte", "in", "answered", "empty"];
|
|
552
589
|
var calculatedFieldType = {
|
|
@@ -798,6 +835,81 @@ var structuredFieldTypes = [
|
|
|
798
835
|
}
|
|
799
836
|
];
|
|
800
837
|
|
|
838
|
+
// src/photo.ts
|
|
839
|
+
var PHOTO_TYPE = "photo";
|
|
840
|
+
var UPLOAD_FIELD_TYPES = [PHOTO_TYPE];
|
|
841
|
+
var PHOTO_FORMATS = {
|
|
842
|
+
jpeg: ["image/jpeg"],
|
|
843
|
+
png: ["image/png"],
|
|
844
|
+
heic: ["image/heic", "image/heif"],
|
|
845
|
+
webp: ["image/webp"]
|
|
846
|
+
};
|
|
847
|
+
var FORMAT_NAMES = { jpeg: "JPEG", png: "PNG", heic: "HEIC", webp: "WebP" };
|
|
848
|
+
var ALL_FORMATS = Object.keys(PHOTO_FORMATS);
|
|
849
|
+
var DEFAULT_PHOTO_FILES = 3;
|
|
850
|
+
var MAX_PHOTO_FILES = 5;
|
|
851
|
+
var DEFAULT_PHOTO_SIZE_MB = 10;
|
|
852
|
+
var MAX_PHOTO_SIZE_MB = 25;
|
|
853
|
+
var MAX_PHOTO_ID_LENGTH = 200;
|
|
854
|
+
var MAX_PHOTO_NAME_LENGTH = 255;
|
|
855
|
+
var isPhotoFormat = (v) => typeof v === "string" && Object.prototype.hasOwnProperty.call(PHOTO_FORMATS, v);
|
|
856
|
+
var wholeIn = (v, min, max) => typeof v === "number" && Number.isInteger(v) && v >= min && v <= max;
|
|
857
|
+
function photoLimits(field2) {
|
|
858
|
+
const maxFiles = wholeIn(field2.props?.maxFiles, 1, MAX_PHOTO_FILES) ? field2.props.maxFiles : DEFAULT_PHOTO_FILES;
|
|
859
|
+
const maxSizeMb = wholeIn(field2.props?.maxSizeMb, 1, MAX_PHOTO_SIZE_MB) ? field2.props.maxSizeMb : DEFAULT_PHOTO_SIZE_MB;
|
|
860
|
+
const raw = field2.props?.formats;
|
|
861
|
+
const picked = Array.isArray(raw) ? ALL_FORMATS.filter((f2) => raw.includes(f2)) : [];
|
|
862
|
+
const formats = picked.length ? picked : [...ALL_FORMATS];
|
|
863
|
+
return {
|
|
864
|
+
maxFiles,
|
|
865
|
+
maxSizeMb,
|
|
866
|
+
maxBytes: maxSizeMb * 1024 * 1024,
|
|
867
|
+
formats,
|
|
868
|
+
mimeTypes: formats.flatMap((f2) => PHOTO_FORMATS[f2])
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
function isPhotoRef(v) {
|
|
872
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return false;
|
|
873
|
+
const r = v;
|
|
874
|
+
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;
|
|
875
|
+
}
|
|
876
|
+
function photoRefs(value) {
|
|
877
|
+
if (!Array.isArray(value)) return [];
|
|
878
|
+
const refs = [];
|
|
879
|
+
for (const r of value) if (isPhotoRef(r)) refs.push({ id: r.id, name: r.name, type: r.type, size: r.size });
|
|
880
|
+
return refs;
|
|
881
|
+
}
|
|
882
|
+
var plural2 = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;
|
|
883
|
+
function photoFormatList(formats) {
|
|
884
|
+
const names = formats.map((f2) => FORMAT_NAMES[f2]);
|
|
885
|
+
return names.length > 1 ? `${names.slice(0, -1).join(", ")} or ${names[names.length - 1]}` : names[0] ?? "";
|
|
886
|
+
}
|
|
887
|
+
var photoTypeMessage = (field2) => `Use a ${photoFormatList(photoLimits(field2).formats)} photo.`;
|
|
888
|
+
var photoSizeMessage = (field2) => `Each photo must be ${photoLimits(field2).maxSizeMb} MB or smaller.`;
|
|
889
|
+
var photoCountMessage = (field2) => `Add at most ${plural2(photoLimits(field2).maxFiles, "photo")}.`;
|
|
890
|
+
var photoFieldType = {
|
|
891
|
+
type: PHOTO_TYPE,
|
|
892
|
+
label: "Photo",
|
|
893
|
+
category: "media",
|
|
894
|
+
value: { json: true },
|
|
895
|
+
operators: ["answered", "empty"],
|
|
896
|
+
a11y: { semantics: "group" },
|
|
897
|
+
isEmpty: (value) => value === void 0 || value === null || Array.isArray(value) && value.length === 0,
|
|
898
|
+
validate: (value, field2) => {
|
|
899
|
+
if (!Array.isArray(value) || !value.every(isPhotoRef)) return "Add a photo.";
|
|
900
|
+
const limits = photoLimits(field2);
|
|
901
|
+
if (value.length > limits.maxFiles) return photoCountMessage(field2);
|
|
902
|
+
const refs = value;
|
|
903
|
+
if (new Set(refs.map((r) => r.id)).size !== refs.length) return "Each photo can be added once.";
|
|
904
|
+
if (refs.some((r) => !limits.mimeTypes.includes(r.type.toLowerCase()))) return photoTypeMessage(field2);
|
|
905
|
+
if (refs.some((r) => r.size > limits.maxBytes)) return photoSizeMessage(field2);
|
|
906
|
+
return null;
|
|
907
|
+
},
|
|
908
|
+
normalize: (value) => Array.isArray(value) && value.every(isPhotoRef) ? photoRefs(value) : value,
|
|
909
|
+
summarize: (value) => photoRefs(value).map((r) => r.name || "Photo").join(", "),
|
|
910
|
+
samples: () => [[{ id: "sample-photo", name: "photo.jpg", type: "image/jpeg", size: 1024 }]]
|
|
911
|
+
};
|
|
912
|
+
|
|
801
913
|
// src/fields.ts
|
|
802
914
|
var REGISTRY = /* @__PURE__ */ Symbol.for("@marktiderman/genesis-forms/field-types");
|
|
803
915
|
var globalScope = globalThis;
|
|
@@ -840,6 +952,20 @@ function summarizeValue(value, field2) {
|
|
|
840
952
|
if (Array.isArray(value)) return value.join(", ");
|
|
841
953
|
return String(value);
|
|
842
954
|
}
|
|
955
|
+
var OTHER_MAX_LENGTH = 200;
|
|
956
|
+
function otherOption(field2) {
|
|
957
|
+
const other = field2.props?.other;
|
|
958
|
+
if (other === true) return { label: "Other" };
|
|
959
|
+
if (other && typeof other === "object" && !Array.isArray(other)) {
|
|
960
|
+
const label = typeof other.label === "string" && other.label.trim() ? other.label.trim() : "Other";
|
|
961
|
+
return { label };
|
|
962
|
+
}
|
|
963
|
+
return null;
|
|
964
|
+
}
|
|
965
|
+
function isOtherValue(field2, value) {
|
|
966
|
+
return otherOption(field2) !== null && typeof value === "string" && !choiceOptions(field2).some((o) => o.value === value);
|
|
967
|
+
}
|
|
968
|
+
var typedOther = (field2, value) => isOtherValue(field2, value) && value.trim() !== "" && value.length <= OTHER_MAX_LENGTH;
|
|
843
969
|
function choiceOptions(field2) {
|
|
844
970
|
const raw = field2.props?.options;
|
|
845
971
|
if (!Array.isArray(raw)) return [];
|
|
@@ -847,6 +973,42 @@ function choiceOptions(field2) {
|
|
|
847
973
|
(o) => o && typeof o === "object" && !Array.isArray(o) && typeof o.value === "string" ? [{ value: o.value, label: typeof o.label === "string" ? o.label : void 0 }] : []
|
|
848
974
|
);
|
|
849
975
|
}
|
|
976
|
+
function optionsSource(field2) {
|
|
977
|
+
const raw = field2.props?.optionsFrom;
|
|
978
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
979
|
+
return raw.source === "host" && typeof raw.key === "string" && raw.key ? { source: "host", key: raw.key } : void 0;
|
|
980
|
+
}
|
|
981
|
+
function hostList(hostOptions, key) {
|
|
982
|
+
if (!hostOptions || !Object.prototype.hasOwnProperty.call(hostOptions, key)) return [];
|
|
983
|
+
const list = hostOptions[key];
|
|
984
|
+
if (!Array.isArray(list)) return [];
|
|
985
|
+
const seen = /* @__PURE__ */ new Set();
|
|
986
|
+
const out = [];
|
|
987
|
+
for (const o of list) {
|
|
988
|
+
if (!o || typeof o !== "object" || Array.isArray(o)) continue;
|
|
989
|
+
const { value, label } = o;
|
|
990
|
+
if (typeof value !== "string" || !value || seen.has(value)) continue;
|
|
991
|
+
seen.add(value);
|
|
992
|
+
out.push(typeof label === "string" ? { value, label } : { value });
|
|
993
|
+
}
|
|
994
|
+
return out;
|
|
995
|
+
}
|
|
996
|
+
function withHostOptions(definition, hostOptions) {
|
|
997
|
+
let changed = false;
|
|
998
|
+
const blocks = definition.blocks.map((block) => {
|
|
999
|
+
if (block.kind !== "field") return block;
|
|
1000
|
+
const from = optionsSource(block);
|
|
1001
|
+
if (!from) return block;
|
|
1002
|
+
const own2 = choiceOptions(block);
|
|
1003
|
+
const taken = new Set(own2.map((o) => o.value));
|
|
1004
|
+
const added = hostList(hostOptions, from.key).filter((o) => !taken.has(o.value));
|
|
1005
|
+
if (!added.length) return block;
|
|
1006
|
+
changed = true;
|
|
1007
|
+
const options = [...own2, ...added].map((o) => o.label === void 0 ? { value: o.value } : { value: o.value, label: o.label });
|
|
1008
|
+
return { ...block, props: { ...block.props, options } };
|
|
1009
|
+
});
|
|
1010
|
+
return changed ? { ...definition, blocks } : definition;
|
|
1011
|
+
}
|
|
850
1012
|
function optionLabel(field2, value) {
|
|
851
1013
|
const option = choiceOptions(field2).find((o) => o.value === value);
|
|
852
1014
|
return option?.label ?? value;
|
|
@@ -965,7 +1127,7 @@ var builtins = [
|
|
|
965
1127
|
value: { json: true },
|
|
966
1128
|
operators: ["eq", "neq", "in", "answered", "empty"],
|
|
967
1129
|
a11y: { semantics: "group" },
|
|
968
|
-
validate: (value, field2) => typeof value === "string" && choiceOptions(field2).some((o) => o.value === value) ? null : "Choose one of the options.",
|
|
1130
|
+
validate: (value, field2) => typeof value === "string" && (choiceOptions(field2).some((o) => o.value === value) || typedOther(field2, value)) ? null : "Choose one of the options.",
|
|
969
1131
|
summarize: (value, field2) => optionLabel(field2, String(value))
|
|
970
1132
|
},
|
|
971
1133
|
{
|
|
@@ -977,7 +1139,8 @@ var builtins = [
|
|
|
977
1139
|
a11y: { semantics: "group" },
|
|
978
1140
|
validate: (value, field2) => {
|
|
979
1141
|
const allowed = new Set(choiceOptions(field2).map((o) => o.value));
|
|
980
|
-
|
|
1142
|
+
const others = Array.isArray(value) ? value.filter((v) => typeof v === "string" && !allowed.has(v)) : [];
|
|
1143
|
+
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.";
|
|
981
1144
|
},
|
|
982
1145
|
summarize: (value, field2) => Array.isArray(value) ? value.map((v) => optionLabel(field2, String(v))).join(", ") : String(value)
|
|
983
1146
|
},
|
|
@@ -998,7 +1161,7 @@ var builtins = [
|
|
|
998
1161
|
value: { json: true },
|
|
999
1162
|
operators: ["eq", "neq", "in", "answered", "empty"],
|
|
1000
1163
|
a11y: { semantics: "control" },
|
|
1001
|
-
validate: (value, field2) => typeof value === "string" && choiceOptions(field2).some((o) => o.value === value) ? null : "Choose one of the options.",
|
|
1164
|
+
validate: (value, field2) => typeof value === "string" && (choiceOptions(field2).some((o) => o.value === value) || typedOther(field2, value)) ? null : "Choose one of the options.",
|
|
1002
1165
|
summarize: (value, field2) => optionLabel(field2, String(value))
|
|
1003
1166
|
},
|
|
1004
1167
|
{
|
|
@@ -1108,7 +1271,7 @@ function dateLimits(field2) {
|
|
|
1108
1271
|
if (typeof max === "string" && isIsoDate(max)) out.max = max;
|
|
1109
1272
|
return out;
|
|
1110
1273
|
}
|
|
1111
|
-
for (const manifest of [...builtins, ...structuredFieldTypes, calculatedFieldType]) registerFieldType(manifest);
|
|
1274
|
+
for (const manifest of [...builtins, ...structuredFieldTypes, calculatedFieldType, photoFieldType]) registerFieldType(manifest);
|
|
1112
1275
|
|
|
1113
1276
|
// src/logic.ts
|
|
1114
1277
|
function own(record, key) {
|
|
@@ -1181,8 +1344,8 @@ function rulesAllow(def, blockId, scope) {
|
|
|
1181
1344
|
}
|
|
1182
1345
|
function walkPath(def, scope) {
|
|
1183
1346
|
const list = steps(def);
|
|
1184
|
-
|
|
1185
|
-
|
|
1347
|
+
let index;
|
|
1348
|
+
let position;
|
|
1186
1349
|
const jumps = (def.logic ?? []).filter(
|
|
1187
1350
|
(r) => r.effect === "jump"
|
|
1188
1351
|
);
|
|
@@ -1206,6 +1369,7 @@ function walkPath(def, scope) {
|
|
|
1206
1369
|
ending = jump.to.ending;
|
|
1207
1370
|
break;
|
|
1208
1371
|
}
|
|
1372
|
+
index ??= new Map(list.map((b, at) => [b.id, at]));
|
|
1209
1373
|
const target = index.get(jump.to);
|
|
1210
1374
|
if (target !== void 0 && target > i) {
|
|
1211
1375
|
i = nextVisible(target);
|
|
@@ -1215,6 +1379,7 @@ function walkPath(def, scope) {
|
|
|
1215
1379
|
i = nextVisible(i + 1);
|
|
1216
1380
|
}
|
|
1217
1381
|
const scopeAt = (blockId, inclusive = false) => {
|
|
1382
|
+
position ??= new Map(def.blocks.map((b, i2) => [b.id, i2]));
|
|
1218
1383
|
const at = position.get(blockId) ?? -1;
|
|
1219
1384
|
const values = /* @__PURE__ */ Object.create(null);
|
|
1220
1385
|
for (const id of path) {
|
|
@@ -1406,6 +1571,22 @@ function parseForm(input) {
|
|
|
1406
1571
|
}
|
|
1407
1572
|
}
|
|
1408
1573
|
if (type === "consent") optionalText(props2.text, `${path}.text`);
|
|
1574
|
+
if (type === PHOTO_TYPE) {
|
|
1575
|
+
if (props2.maxFiles !== void 0 && !(isInt(props2.maxFiles) && props2.maxFiles >= 1 && props2.maxFiles <= MAX_PHOTO_FILES)) {
|
|
1576
|
+
issue(`${path}.maxFiles`, `Must be a whole number from 1 to ${MAX_PHOTO_FILES}.`);
|
|
1577
|
+
}
|
|
1578
|
+
if (props2.maxSizeMb !== void 0 && !(isInt(props2.maxSizeMb) && props2.maxSizeMb >= 1 && props2.maxSizeMb <= MAX_PHOTO_SIZE_MB)) {
|
|
1579
|
+
issue(`${path}.maxSizeMb`, `Must be a whole number from 1 to ${MAX_PHOTO_SIZE_MB}.`);
|
|
1580
|
+
}
|
|
1581
|
+
if (props2.formats !== void 0) {
|
|
1582
|
+
const formats = props2.formats;
|
|
1583
|
+
if (!Array.isArray(formats) || formats.length === 0 || !formats.every(isPhotoFormat)) {
|
|
1584
|
+
issue(`${path}.formats`, "Must be a list of one or more of jpeg, png, heic and webp.");
|
|
1585
|
+
} else if (new Set(formats).size !== formats.length) {
|
|
1586
|
+
issue(`${path}.formats`, "Name each format once.");
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1409
1590
|
};
|
|
1410
1591
|
if (!isObject2(input)) {
|
|
1411
1592
|
issue("", "A form definition must be an object.");
|
|
@@ -1426,6 +1607,7 @@ function parseForm(input) {
|
|
|
1426
1607
|
else {
|
|
1427
1608
|
optionalBoolean(input.settings.anonymous, "settings.anonymous");
|
|
1428
1609
|
optionalBoolean(input.settings.clearHiddenValues, "settings.clearHiddenValues");
|
|
1610
|
+
optionalBoolean(input.settings.saveProgress, "settings.saveProgress");
|
|
1429
1611
|
}
|
|
1430
1612
|
}
|
|
1431
1613
|
if (input.meta !== void 0 && (!isObject2(input.meta) || !isJson(input.meta))) {
|
|
@@ -1466,6 +1648,14 @@ function parseForm(input) {
|
|
|
1466
1648
|
issue(`${path}.type`, `Unknown field type "${String(block.type)}".`);
|
|
1467
1649
|
}
|
|
1468
1650
|
if (block.props !== void 0) {
|
|
1651
|
+
const from = isObject2(block.props) ? block.props.optionsFrom : void 0;
|
|
1652
|
+
if (from !== void 0) {
|
|
1653
|
+
if (!isObject2(from) || from.source !== "host" || typeof from.key !== "string" || !from.key) {
|
|
1654
|
+
issue(`${path}.props.optionsFrom`, 'Must be { source: "host", key } with a non-empty key.');
|
|
1655
|
+
} else if (typeof block.type === "string" && !CHOICE_TYPES.has(block.type)) {
|
|
1656
|
+
warnings.push({ path: `${path}.props.optionsFrom`, message: "Only single choice, multiple choice and dropdown questions take options from the app." });
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1469
1659
|
if (!isObject2(block.props) || !isJson(block.props)) issue(`${path}.props`, "Must be a JSON object.");
|
|
1470
1660
|
else if (block.props.options !== void 0) {
|
|
1471
1661
|
const options = block.props.options;
|
|
@@ -1476,10 +1666,20 @@ function parseForm(input) {
|
|
|
1476
1666
|
if (!isObject2(o) || typeof o.value !== "string") issue(at, "Each option needs a string value.");
|
|
1477
1667
|
else optionalText(o.label, `${at}.label`);
|
|
1478
1668
|
});
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1669
|
+
if (from === void 0) {
|
|
1670
|
+
choices.set(
|
|
1671
|
+
block.id,
|
|
1672
|
+
new Set(options.flatMap((o) => isObject2(o) && typeof o.value === "string" ? [o.value] : []))
|
|
1673
|
+
);
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
const other = isObject2(block.props) ? block.props.other : void 0;
|
|
1678
|
+
if (other !== void 0) {
|
|
1679
|
+
if (other !== true && other !== false && !(isObject2(other) && (other.label === void 0 || typeof other.label === "string"))) {
|
|
1680
|
+
issue(`${path}.props.other`, "Must be true, false or { label }.");
|
|
1681
|
+
} else if (other !== false && typeof block.type === "string" && !CHOICE_TYPES.has(block.type)) {
|
|
1682
|
+
warnings.push({ path: `${path}.props.other`, message: 'Only single choice, multiple choice and dropdown questions take an "Other" answer.' });
|
|
1483
1683
|
}
|
|
1484
1684
|
}
|
|
1485
1685
|
const { max, maxLength: maxLength2 } = isObject2(block.props) ? block.props : {};
|
|
@@ -1554,6 +1754,8 @@ function parseForm(input) {
|
|
|
1554
1754
|
} else if (ref.column !== void 0) issue(path, `"${ref.key}" is not a table, so it has no column "${ref.column}".`);
|
|
1555
1755
|
else if (targetType === "media-notes" || targetType === "text-highlights") {
|
|
1556
1756
|
warnings.push({ path, message: `"${ref.key}" holds notes, not numbers; the formula reads it as blank.` });
|
|
1757
|
+
} else if (targetType === PHOTO_TYPE) {
|
|
1758
|
+
warnings.push({ path, message: `"${ref.key}" holds photos, not numbers; the formula reads it as blank.` });
|
|
1557
1759
|
}
|
|
1558
1760
|
}
|
|
1559
1761
|
});
|
|
@@ -1773,9 +1975,15 @@ function field(type, key, options, props2) {
|
|
|
1773
1975
|
return block;
|
|
1774
1976
|
}
|
|
1775
1977
|
var props = (all) => Object.fromEntries(Object.entries(all).filter((e) => e[1] !== void 0));
|
|
1776
|
-
var choiceProps = (
|
|
1777
|
-
|
|
1778
|
-
|
|
1978
|
+
var choiceProps = (o) => {
|
|
1979
|
+
const out = {};
|
|
1980
|
+
if (o.options || !o.optionsFrom) {
|
|
1981
|
+
out.options = (o.options ?? []).map((x) => x.label ? { value: x.value, label: x.label } : { value: x.value });
|
|
1982
|
+
}
|
|
1983
|
+
if (o.optionsFrom) out.optionsFrom = { source: o.optionsFrom.source, key: o.optionsFrom.key };
|
|
1984
|
+
if (o.other) out.other = o.other === true ? true : props({ label: o.other.label });
|
|
1985
|
+
return out;
|
|
1986
|
+
};
|
|
1779
1987
|
var hiddenSpec = (type, o) => ({
|
|
1780
1988
|
type,
|
|
1781
1989
|
source: o.source ?? "url",
|
|
@@ -1799,11 +2007,11 @@ var f = {
|
|
|
1799
2007
|
),
|
|
1800
2008
|
/** A 0-to-10 Net Promoter Score. The end labels default to "Not likely" and "Very likely" in the renderer. */
|
|
1801
2009
|
nps: (key, o) => field("nps", key, o, props({ lowLabel: o.lowLabel || void 0, highLabel: o.highLabel || void 0 })),
|
|
1802
|
-
singleChoice: (key, o) => field("single-choice", key, o, choiceProps(o
|
|
1803
|
-
multiChoice: (key, o) => field("multi-choice", key, o, choiceProps(o
|
|
2010
|
+
singleChoice: (key, o) => field("single-choice", key, o, choiceProps(o)),
|
|
2011
|
+
multiChoice: (key, o) => field("multi-choice", key, o, choiceProps(o)),
|
|
1804
2012
|
yesNo: (key, o) => field("yes-no", key, o),
|
|
1805
2013
|
/** One option from a compact menu: for a long list (a country, a class), where single choice would be a wall of buttons. */
|
|
1806
|
-
dropdown: (key, o) => field("dropdown", key, o, choiceProps(o
|
|
2014
|
+
dropdown: (key, o) => field("dropdown", key, o, choiceProps(o)),
|
|
1807
2015
|
/** A number, optionally between `min` and `max` and on a `step` (from `min`, else 0): `step: 1` for whole numbers. */
|
|
1808
2016
|
number: (key, o) => field("number", key, o, props({ min: o.min, max: o.max, step: o.step })),
|
|
1809
2017
|
/** A calendar day, stored as `YYYY-MM-DD`, optionally between `min` and `max` (also `YYYY-MM-DD`). */
|
|
@@ -1855,6 +2063,17 @@ var f = {
|
|
|
1855
2063
|
o,
|
|
1856
2064
|
props({ text: o.text, maxHighlights: o.maxHighlights })
|
|
1857
2065
|
),
|
|
2066
|
+
/**
|
|
2067
|
+
* Up to a few photos (a picture of broken equipment). The answer holds the
|
|
2068
|
+
* references the host's upload returned, never the bytes; `formats` from
|
|
2069
|
+
* jpeg, png, heic and webp (default all four).
|
|
2070
|
+
*/
|
|
2071
|
+
photo: (key, o) => field(
|
|
2072
|
+
"photo",
|
|
2073
|
+
key,
|
|
2074
|
+
o,
|
|
2075
|
+
props({ maxFiles: o.maxFiles, maxSizeMb: o.maxSizeMb, formats: o.formats ? [...o.formats] : void 0 })
|
|
2076
|
+
),
|
|
1858
2077
|
/** Any registered field type, including plugins. */
|
|
1859
2078
|
custom: (type, key, o) => field(type, key, o, o.props),
|
|
1860
2079
|
heading: (id, text) => ({ kind: "content", id, type: "heading", text }),
|
|
@@ -2026,10 +2245,20 @@ function validateField(field2, value, options = {}) {
|
|
|
2026
2245
|
}
|
|
2027
2246
|
|
|
2028
2247
|
// src/engine.ts
|
|
2248
|
+
function readsAny(node, ids) {
|
|
2249
|
+
if (Array.isArray(node)) return node.some((n) => readsAny(n, ids));
|
|
2250
|
+
if (!node || typeof node !== "object") return false;
|
|
2251
|
+
for (const [k, v] of Object.entries(node)) {
|
|
2252
|
+
if (k === "field" && typeof v === "string" && ids.has(v)) return true;
|
|
2253
|
+
if (typeof v === "object" && readsAny(v, ids)) return true;
|
|
2254
|
+
}
|
|
2255
|
+
return false;
|
|
2256
|
+
}
|
|
2029
2257
|
function createForm(definition, options = {}) {
|
|
2030
2258
|
return build(definition, options).engine;
|
|
2031
2259
|
}
|
|
2032
|
-
function build(
|
|
2260
|
+
function build(given, options, replaying = false, budget) {
|
|
2261
|
+
const definition = withHostOptions(given, options.hostOptions);
|
|
2033
2262
|
const fields = fieldMap(definition);
|
|
2034
2263
|
const byKey = new Map([...fields.values()].map((f2) => [f2.key, f2]));
|
|
2035
2264
|
const blocks = new Map(definition.blocks.map((b) => [b.id, b]));
|
|
@@ -2047,15 +2276,24 @@ function build(definition, options, replaying = false) {
|
|
|
2047
2276
|
if (!declared.has(name)) initialHidden[name] = value;
|
|
2048
2277
|
}
|
|
2049
2278
|
Object.assign(initialHidden, coerceHidden(definition, options.hidden).values);
|
|
2050
|
-
const calc = calculator(definition);
|
|
2279
|
+
const calc = calculator(definition, budget);
|
|
2280
|
+
const pathOf = (values, hidden) => {
|
|
2281
|
+
spend(budget, definition.blocks.length);
|
|
2282
|
+
return computePath(definition, scopeOf(values, hidden));
|
|
2283
|
+
};
|
|
2284
|
+
const logicReadsCalculated = calc.active && readsAny(definition.logic, calc.ids);
|
|
2051
2285
|
const settle = (values, hidden) => {
|
|
2052
|
-
let { path } =
|
|
2286
|
+
let { path } = pathOf(values, hidden);
|
|
2053
2287
|
if (!calc.active) return { values, path };
|
|
2288
|
+
if (!logicReadsCalculated) return { values: calc.withCalculated(values, path), path };
|
|
2054
2289
|
for (let round2 = 0; round2 < 4; round2++) {
|
|
2055
2290
|
const next = calc.withCalculated(values, path);
|
|
2056
2291
|
if (next === values) break;
|
|
2057
2292
|
values = next;
|
|
2058
|
-
|
|
2293
|
+
const again = pathOf(values, hidden).path;
|
|
2294
|
+
const same = again.length === path.length && again.every((id, i) => id === path[i]);
|
|
2295
|
+
path = again;
|
|
2296
|
+
if (same) break;
|
|
2059
2297
|
}
|
|
2060
2298
|
return { values, path };
|
|
2061
2299
|
};
|
|
@@ -2066,6 +2304,7 @@ function build(definition, options, replaying = false) {
|
|
|
2066
2304
|
path: first.path,
|
|
2067
2305
|
current: first.path[0] ?? null,
|
|
2068
2306
|
history: [],
|
|
2307
|
+
furthest: first.path[0] ?? null,
|
|
2069
2308
|
errors: {},
|
|
2070
2309
|
status: "in_progress",
|
|
2071
2310
|
ending: null,
|
|
@@ -2097,14 +2336,30 @@ function build(definition, options, replaying = false) {
|
|
|
2097
2336
|
return errors;
|
|
2098
2337
|
};
|
|
2099
2338
|
let unsettled = false;
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
unsettled
|
|
2103
|
-
|
|
2104
|
-
|
|
2339
|
+
let formulasStale = false;
|
|
2340
|
+
const settleNow = (needValues = true) => {
|
|
2341
|
+
if (unsettled && calc.active && !logicReadsCalculated && !needValues) {
|
|
2342
|
+
unsettled = false;
|
|
2343
|
+
formulasStale = true;
|
|
2344
|
+
state = { ...state, path: pathOf(state.values, state.hidden).path };
|
|
2345
|
+
return;
|
|
2346
|
+
}
|
|
2347
|
+
if (unsettled) {
|
|
2348
|
+
unsettled = false;
|
|
2349
|
+
formulasStale = false;
|
|
2350
|
+
const { values, path } = settle(state.values, state.hidden);
|
|
2351
|
+
state = { ...state, values, path };
|
|
2352
|
+
} else if (formulasStale && needValues) {
|
|
2353
|
+
formulasStale = false;
|
|
2354
|
+
state = { ...state, values: calc.withCalculated(state.values, state.path) };
|
|
2355
|
+
}
|
|
2105
2356
|
};
|
|
2106
2357
|
const answer = (id, value, event) => {
|
|
2107
|
-
if (state.status === "completed" ||
|
|
2358
|
+
if (state.status === "completed" || isCalculated(fields.get(id))) return;
|
|
2359
|
+
if (own(state.values, id) === value) {
|
|
2360
|
+
if (value === null || typeof value !== "object") return;
|
|
2361
|
+
calc.forget(value);
|
|
2362
|
+
}
|
|
2108
2363
|
const errors = { ...state.errors };
|
|
2109
2364
|
delete errors[id];
|
|
2110
2365
|
if (batch) {
|
|
@@ -2150,7 +2405,8 @@ function build(definition, options, replaying = false) {
|
|
|
2150
2405
|
emit({ ...state, events });
|
|
2151
2406
|
return true;
|
|
2152
2407
|
}
|
|
2153
|
-
|
|
2408
|
+
const furthest = state.furthest && state.path.indexOf(state.furthest) >= state.path.indexOf(target) ? state.furthest : target;
|
|
2409
|
+
emit({ ...state, current: target, history: [...state.history, state.current], furthest, events });
|
|
2154
2410
|
return true;
|
|
2155
2411
|
},
|
|
2156
2412
|
back() {
|
|
@@ -2170,7 +2426,7 @@ function build(definition, options, replaying = false) {
|
|
|
2170
2426
|
emit({ ...state, errors, current: firstError, events });
|
|
2171
2427
|
return false;
|
|
2172
2428
|
}
|
|
2173
|
-
const { ending } =
|
|
2429
|
+
const { ending } = pathOf(state.values, state.hidden);
|
|
2174
2430
|
emit({ ...state, errors: {}, status: "completed", ending, events });
|
|
2175
2431
|
return true;
|
|
2176
2432
|
},
|
|
@@ -2195,6 +2451,15 @@ function build(definition, options, replaying = false) {
|
|
|
2195
2451
|
settleNow();
|
|
2196
2452
|
batch = wasBatch;
|
|
2197
2453
|
}
|
|
2454
|
+
const resumeAt = options.resumeAt;
|
|
2455
|
+
if (resumeAt && !replaying && state.path.includes(resumeAt)) {
|
|
2456
|
+
for (let i = 0; i < state.path.length && state.current !== resumeAt; i++) {
|
|
2457
|
+
if (!engine.next()) {
|
|
2458
|
+
state = { ...state, errors: {} };
|
|
2459
|
+
break;
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2198
2463
|
const apply = (event) => {
|
|
2199
2464
|
if (event.type === "answer") {
|
|
2200
2465
|
if (fields.has(event.field)) {
|
|
@@ -2202,10 +2467,11 @@ function build(definition, options, replaying = false) {
|
|
|
2202
2467
|
answer(event.field, event.value, logged);
|
|
2203
2468
|
}
|
|
2204
2469
|
} else if (event.type === "next") {
|
|
2205
|
-
settleNow();
|
|
2470
|
+
settleNow(false);
|
|
2471
|
+
if (formulasStale && isCalculated(fields.get(state.current ?? ""))) settleNow(true);
|
|
2206
2472
|
engine.next();
|
|
2207
2473
|
} else if (event.type === "back") {
|
|
2208
|
-
settleNow();
|
|
2474
|
+
settleNow(false);
|
|
2209
2475
|
engine.back();
|
|
2210
2476
|
} else if (event.type === "submit") {
|
|
2211
2477
|
settleNow();
|
|
@@ -2220,12 +2486,46 @@ function build(definition, options, replaying = false) {
|
|
|
2220
2486
|
return { engine, apply, finish };
|
|
2221
2487
|
}
|
|
2222
2488
|
function replay(definition, events, options = {}) {
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2489
|
+
return replayWithin(definition, events, options);
|
|
2490
|
+
}
|
|
2491
|
+
function replayWithin(definition, events, options, maxWork) {
|
|
2492
|
+
const budget = void 0 ;
|
|
2493
|
+
const { engine, apply, finish } = build(definition, { ...options, initialValues: void 0, clock: () => void 0 }, true, budget);
|
|
2494
|
+
try {
|
|
2495
|
+
for (const event of events) apply(event);
|
|
2496
|
+
finish();
|
|
2497
|
+
} finally {
|
|
2498
|
+
}
|
|
2226
2499
|
return engine;
|
|
2227
2500
|
}
|
|
2228
2501
|
|
|
2502
|
+
// src/progress.ts
|
|
2503
|
+
function furthestReached(state, definition) {
|
|
2504
|
+
const at = (id) => id ? state.path.indexOf(id) : -1;
|
|
2505
|
+
let furthest = Math.max(at(state.current), at(state.furthest));
|
|
2506
|
+
for (const id of state.history) furthest = Math.max(furthest, at(id));
|
|
2507
|
+
const fields = fieldMap(definition);
|
|
2508
|
+
for (let i = state.path.length - 1; i > furthest; i--) {
|
|
2509
|
+
const field2 = fields.get(state.path[i]);
|
|
2510
|
+
if (field2 && !isEmptyValue(own(state.values, field2.id), field2)) {
|
|
2511
|
+
furthest = i;
|
|
2512
|
+
break;
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
return furthest >= 0 ? state.path[furthest] : null;
|
|
2516
|
+
}
|
|
2517
|
+
function formProgress(engine) {
|
|
2518
|
+
const state = engine.getState();
|
|
2519
|
+
const furthest = furthestReached(state, engine.definition);
|
|
2520
|
+
const index = furthest ? state.path.indexOf(furthest) : -1;
|
|
2521
|
+
const fields = fieldMap(engine.definition);
|
|
2522
|
+
let fieldId = null;
|
|
2523
|
+
for (let i = index; i >= 0 && fieldId === null; i--) {
|
|
2524
|
+
if (fields.has(state.path[i])) fieldId = state.path[i];
|
|
2525
|
+
}
|
|
2526
|
+
return { step: index + 1, total: state.path.length, fieldId };
|
|
2527
|
+
}
|
|
2528
|
+
|
|
2229
2529
|
// src/explain.ts
|
|
2230
2530
|
function explain(source, blockId, options = {}) {
|
|
2231
2531
|
const input = "getState" in source ? { definition: source.definition, values: source.getState().values, hidden: source.getState().hidden } : source;
|
|
@@ -2364,6 +2664,8 @@ function describeCondition(condition, def, fields = fieldMap(def)) {
|
|
|
2364
2664
|
|
|
2365
2665
|
exports.CALCULATED_TYPE = CALCULATED_TYPE;
|
|
2366
2666
|
exports.COMPUTED_FIELD_TYPES = COMPUTED_FIELD_TYPES;
|
|
2667
|
+
exports.DEFAULT_PHOTO_FILES = DEFAULT_PHOTO_FILES;
|
|
2668
|
+
exports.DEFAULT_PHOTO_SIZE_MB = DEFAULT_PHOTO_SIZE_MB;
|
|
2367
2669
|
exports.FORMULA_FUNCTIONS = FORMULA_FUNCTIONS;
|
|
2368
2670
|
exports.HIGHLIGHT_NOTE_MESSAGE = HIGHLIGHT_NOTE_MESSAGE;
|
|
2369
2671
|
exports.MAX_CALCULATED_DECIMALS = MAX_CALCULATED_DECIMALS;
|
|
@@ -2373,12 +2675,20 @@ exports.MAX_FORM_FORMULA_LENGTH = MAX_FORM_FORMULA_LENGTH;
|
|
|
2373
2675
|
exports.MAX_HIDDEN_STRING_LENGTH = MAX_HIDDEN_STRING_LENGTH;
|
|
2374
2676
|
exports.MAX_HIGHLIGHT_NOTE_LENGTH = MAX_HIGHLIGHT_NOTE_LENGTH;
|
|
2375
2677
|
exports.MAX_HIGHLIGHT_QUOTE_LENGTH = MAX_HIGHLIGHT_QUOTE_LENGTH;
|
|
2678
|
+
exports.MAX_PHOTO_FILES = MAX_PHOTO_FILES;
|
|
2679
|
+
exports.MAX_PHOTO_ID_LENGTH = MAX_PHOTO_ID_LENGTH;
|
|
2680
|
+
exports.MAX_PHOTO_NAME_LENGTH = MAX_PHOTO_NAME_LENGTH;
|
|
2681
|
+
exports.MAX_PHOTO_SIZE_MB = MAX_PHOTO_SIZE_MB;
|
|
2376
2682
|
exports.MAX_SETTLE_ITEMS = MAX_SETTLE_ITEMS;
|
|
2377
2683
|
exports.MAX_TABLE_CELL_LENGTH = MAX_TABLE_CELL_LENGTH;
|
|
2378
2684
|
exports.MAX_TABLE_COLUMNS = MAX_TABLE_COLUMNS;
|
|
2379
2685
|
exports.MAX_TIMESTAMP_SECONDS = MAX_TIMESTAMP_SECONDS;
|
|
2686
|
+
exports.OTHER_MAX_LENGTH = OTHER_MAX_LENGTH;
|
|
2687
|
+
exports.PHOTO_FORMATS = PHOTO_FORMATS;
|
|
2688
|
+
exports.PHOTO_TYPE = PHOTO_TYPE;
|
|
2380
2689
|
exports.REQUIRED_MESSAGE = REQUIRED_MESSAGE;
|
|
2381
2690
|
exports.STRUCTURED_FIELD_TYPES = STRUCTURED_FIELD_TYPES;
|
|
2691
|
+
exports.UPLOAD_FIELD_TYPES = UPLOAD_FIELD_TYPES;
|
|
2382
2692
|
exports.calculatedProps = calculatedProps;
|
|
2383
2693
|
exports.calculatedValue = calculatedValue;
|
|
2384
2694
|
exports.canonicalJson = canonicalJson;
|
|
@@ -2395,24 +2705,37 @@ exports.evaluateFormula = evaluateFormula;
|
|
|
2395
2705
|
exports.explain = explain;
|
|
2396
2706
|
exports.f = f;
|
|
2397
2707
|
exports.fingerprint = fingerprint;
|
|
2708
|
+
exports.formProgress = formProgress;
|
|
2398
2709
|
exports.formatCalculated = formatCalculated;
|
|
2399
2710
|
exports.formatTimestamp = formatTimestamp;
|
|
2400
2711
|
exports.formulaInput = formulaInput;
|
|
2401
2712
|
exports.formulaNumber = formulaNumber;
|
|
2402
2713
|
exports.formulaRefs = formulaRefs;
|
|
2714
|
+
exports.furthestReached = furthestReached;
|
|
2403
2715
|
exports.getFieldType = getFieldType;
|
|
2404
2716
|
exports.isEmptyValue = isEmptyValue;
|
|
2405
2717
|
exports.isFormEvent = isFormEvent;
|
|
2406
2718
|
exports.isIsoDate = isIsoDate;
|
|
2407
2719
|
exports.isJson = isJson;
|
|
2720
|
+
exports.isOtherValue = isOtherValue;
|
|
2721
|
+
exports.isPhotoFormat = isPhotoFormat;
|
|
2722
|
+
exports.isPhotoRef = isPhotoRef;
|
|
2408
2723
|
exports.isSensitive = isSensitive;
|
|
2409
2724
|
exports.listFieldTypes = listFieldTypes;
|
|
2410
2725
|
exports.listLimits = listLimits;
|
|
2411
2726
|
exports.normalizeValue = normalizeValue;
|
|
2412
2727
|
exports.numberLimits = numberLimits;
|
|
2728
|
+
exports.optionsSource = optionsSource;
|
|
2729
|
+
exports.otherOption = otherOption;
|
|
2413
2730
|
exports.parseForm = parseForm;
|
|
2414
2731
|
exports.parseFormula = parseFormula;
|
|
2415
2732
|
exports.parseTimestamp = parseTimestamp;
|
|
2733
|
+
exports.photoCountMessage = photoCountMessage;
|
|
2734
|
+
exports.photoFormatList = photoFormatList;
|
|
2735
|
+
exports.photoLimits = photoLimits;
|
|
2736
|
+
exports.photoRefs = photoRefs;
|
|
2737
|
+
exports.photoSizeMessage = photoSizeMessage;
|
|
2738
|
+
exports.photoTypeMessage = photoTypeMessage;
|
|
2416
2739
|
exports.ratingDisplay = ratingDisplay;
|
|
2417
2740
|
exports.recall = recall;
|
|
2418
2741
|
exports.registerFieldType = registerFieldType;
|
|
@@ -2426,5 +2749,6 @@ exports.tableColumns = tableColumns;
|
|
|
2426
2749
|
exports.tableLimits = tableLimits;
|
|
2427
2750
|
exports.validateField = validateField;
|
|
2428
2751
|
exports.when = when;
|
|
2752
|
+
exports.withHostOptions = withHostOptions;
|
|
2429
2753
|
//# sourceMappingURL=index.cjs.map
|
|
2430
2754
|
//# sourceMappingURL=index.cjs.map
|