@marktiderman/genesis-forms 0.5.0 → 0.6.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 +128 -0
- package/dist/destinations.cjs +55 -3
- 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 +55 -3
- package/dist/destinations.js.map +1 -1
- package/dist/{engine-BDq0XJ21.d.cts → engine-CpfOz8FN.d.ts} +10 -3
- package/dist/{engine-Qzp6bX6O.d.ts → engine-DC4YTPdr.d.cts} +10 -3
- package/dist/index.cjs +484 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -7
- package/dist/index.d.ts +29 -7
- package/dist/index.js +461 -63
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +541 -21
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +193 -3
- package/dist/server.d.ts +193 -3
- package/dist/server.js +522 -22
- package/dist/server.js.map +1 -1
- package/dist/testing.cjs +314 -21
- 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 +314 -21
- package/dist/testing.js.map +1 -1
- package/dist/{types-BhYUbLJ-.d.cts → types-oAckGR_Z.d.cts} +10 -0
- package/dist/{types-BhYUbLJ-.d.ts → types-oAckGR_Z.d.ts} +10 -0
- package/dist/validate-B5WKHbst.d.cts +322 -0
- package/dist/validate-GpTXPwyl.d.ts +322 -0
- package/package.json +1 -1
- package/dist/validate-Bs1lyoOl.d.ts +0 -131
- package/dist/validate-BsZ0YTQS.d.cts +0 -131
package/dist/index.js
CHANGED
|
@@ -950,6 +950,65 @@ function summarizeValue(value, field2) {
|
|
|
950
950
|
if (Array.isArray(value)) return value.join(", ");
|
|
951
951
|
return String(value);
|
|
952
952
|
}
|
|
953
|
+
var OPTION_LIMITS = {
|
|
954
|
+
/** Characters in a description. */
|
|
955
|
+
description: 500,
|
|
956
|
+
/** Characters in an image URL. */
|
|
957
|
+
image: 2048,
|
|
958
|
+
/** Attributes on one option. */
|
|
959
|
+
attributes: 20,
|
|
960
|
+
/** Characters in an attribute's name. */
|
|
961
|
+
attributeName: 64,
|
|
962
|
+
/** Characters in one attribute value. */
|
|
963
|
+
attributeValue: 200,
|
|
964
|
+
/** Values in one attribute's list. */
|
|
965
|
+
attributeItems: 50
|
|
966
|
+
};
|
|
967
|
+
function isHttpsUrl(url) {
|
|
968
|
+
return typeof url === "string" && url.length <= OPTION_LIMITS.image && /^https:\/\/[^\s/?#@\\]+(?:[/?#][^\s]*)?$/i.test(url) && // No control characters anywhere (a line break would end a CSV row or an HTML attribute).
|
|
969
|
+
![...url].some((c) => c.charCodeAt(0) < 32 || c.charCodeAt(0) === 127);
|
|
970
|
+
}
|
|
971
|
+
function attributeName(name) {
|
|
972
|
+
return name.trim() !== "" && name.length <= OPTION_LIMITS.attributeName && !(name in Object.prototype);
|
|
973
|
+
}
|
|
974
|
+
function readAttributes(raw) {
|
|
975
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
976
|
+
const out = {};
|
|
977
|
+
let count = 0;
|
|
978
|
+
for (const name of Object.keys(raw)) {
|
|
979
|
+
if (count >= OPTION_LIMITS.attributes) break;
|
|
980
|
+
if (!attributeName(name)) continue;
|
|
981
|
+
const v = raw[name];
|
|
982
|
+
const fits = (x) => typeof x === "string" && x.length <= OPTION_LIMITS.attributeValue;
|
|
983
|
+
if (fits(v)) out[name] = v;
|
|
984
|
+
else if (Array.isArray(v) && v.length <= OPTION_LIMITS.attributeItems && v.every(fits)) out[name] = [...v];
|
|
985
|
+
else continue;
|
|
986
|
+
count++;
|
|
987
|
+
}
|
|
988
|
+
return count ? out : void 0;
|
|
989
|
+
}
|
|
990
|
+
function readOption(raw) {
|
|
991
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
992
|
+
const o = raw;
|
|
993
|
+
if (typeof o.value !== "string") return null;
|
|
994
|
+
const out = { value: o.value };
|
|
995
|
+
if (typeof o.label === "string") out.label = o.label;
|
|
996
|
+
if (typeof o.description === "string" && o.description.trim() && o.description.length <= OPTION_LIMITS.description) {
|
|
997
|
+
out.description = o.description;
|
|
998
|
+
}
|
|
999
|
+
if (isHttpsUrl(o.image)) out.image = o.image;
|
|
1000
|
+
const attributes = readAttributes(o.attributes);
|
|
1001
|
+
if (attributes) out.attributes = attributes;
|
|
1002
|
+
return out;
|
|
1003
|
+
}
|
|
1004
|
+
function optionJson(option) {
|
|
1005
|
+
const out = { value: option.value };
|
|
1006
|
+
if (option.label !== void 0) out.label = option.label;
|
|
1007
|
+
if (option.description !== void 0) out.description = option.description;
|
|
1008
|
+
if (option.image !== void 0) out.image = option.image;
|
|
1009
|
+
if (option.attributes !== void 0) out.attributes = { ...option.attributes };
|
|
1010
|
+
return out;
|
|
1011
|
+
}
|
|
953
1012
|
var OTHER_MAX_LENGTH = 200;
|
|
954
1013
|
function otherOption(field2) {
|
|
955
1014
|
const other = field2.props?.other;
|
|
@@ -967,14 +1026,21 @@ var typedOther = (field2, value) => isOtherValue(field2, value) && value.trim()
|
|
|
967
1026
|
function choiceOptions(field2) {
|
|
968
1027
|
const raw = field2.props?.options;
|
|
969
1028
|
if (!Array.isArray(raw)) return [];
|
|
970
|
-
return raw.flatMap(
|
|
971
|
-
|
|
972
|
-
|
|
1029
|
+
return raw.flatMap((o) => {
|
|
1030
|
+
const option = readOption(o);
|
|
1031
|
+
return option ? [option] : [];
|
|
1032
|
+
});
|
|
973
1033
|
}
|
|
974
1034
|
function optionsSource(field2) {
|
|
975
1035
|
const raw = field2.props?.optionsFrom;
|
|
976
1036
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
977
|
-
|
|
1037
|
+
if (raw.source !== "host" || typeof raw.key !== "string" || !raw.key) return void 0;
|
|
1038
|
+
const out = { source: "host", key: raw.key };
|
|
1039
|
+
const filter = raw.filter;
|
|
1040
|
+
if (filter && typeof filter === "object" && !Array.isArray(filter) && typeof filter.attribute === "string" && filter.attribute && typeof filter.field === "string" && filter.field) {
|
|
1041
|
+
out.filter = { attribute: filter.attribute, field: filter.field };
|
|
1042
|
+
}
|
|
1043
|
+
return out;
|
|
978
1044
|
}
|
|
979
1045
|
function hostList(hostOptions, key) {
|
|
980
1046
|
if (!hostOptions || !Object.prototype.hasOwnProperty.call(hostOptions, key)) return [];
|
|
@@ -983,11 +1049,10 @@ function hostList(hostOptions, key) {
|
|
|
983
1049
|
const seen = /* @__PURE__ */ new Set();
|
|
984
1050
|
const out = [];
|
|
985
1051
|
for (const o of list) {
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
out.push(typeof label === "string" ? { value, label } : { value });
|
|
1052
|
+
const option = readOption(o);
|
|
1053
|
+
if (!option || !option.value || seen.has(option.value)) continue;
|
|
1054
|
+
seen.add(option.value);
|
|
1055
|
+
out.push(option);
|
|
991
1056
|
}
|
|
992
1057
|
return out;
|
|
993
1058
|
}
|
|
@@ -1002,7 +1067,7 @@ function withHostOptions(definition, hostOptions) {
|
|
|
1002
1067
|
const added = hostList(hostOptions, from.key).filter((o) => !taken.has(o.value));
|
|
1003
1068
|
if (!added.length) return block;
|
|
1004
1069
|
changed = true;
|
|
1005
|
-
const options = [...own2, ...added].map(
|
|
1070
|
+
const options = [...own2, ...added].map(optionJson);
|
|
1006
1071
|
return { ...block, props: { ...block.props, options } };
|
|
1007
1072
|
});
|
|
1008
1073
|
return changed ? { ...definition, blocks } : definition;
|
|
@@ -1271,6 +1336,47 @@ function dateLimits(field2) {
|
|
|
1271
1336
|
}
|
|
1272
1337
|
for (const manifest of [...builtins, ...structuredFieldTypes, calculatedFieldType, photoFieldType]) registerFieldType(manifest);
|
|
1273
1338
|
|
|
1339
|
+
// src/hidden.ts
|
|
1340
|
+
var MAX_HIDDEN_STRING_LENGTH = 1e3;
|
|
1341
|
+
var DECIMAL = /^-?\d+(\.\d+)?$/;
|
|
1342
|
+
function coerceHiddenValue(value, type) {
|
|
1343
|
+
if (typeof value === "string" && value.length > MAX_HIDDEN_STRING_LENGTH) return void 0;
|
|
1344
|
+
if (type === "string") {
|
|
1345
|
+
if (typeof value === "string") return value;
|
|
1346
|
+
if (typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
1347
|
+
return void 0;
|
|
1348
|
+
}
|
|
1349
|
+
if (type === "number") {
|
|
1350
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
|
|
1351
|
+
if (typeof value !== "string" || !DECIMAL.test(value)) return void 0;
|
|
1352
|
+
const n = Number(value);
|
|
1353
|
+
return Number.isFinite(n) ? n : void 0;
|
|
1354
|
+
}
|
|
1355
|
+
if (typeof value === "boolean") return value;
|
|
1356
|
+
if (value === "true") return true;
|
|
1357
|
+
if (value === "false") return false;
|
|
1358
|
+
return void 0;
|
|
1359
|
+
}
|
|
1360
|
+
function coerceHidden(definition, raw, options = {}) {
|
|
1361
|
+
const declared = new Map((definition.hidden ?? []).map((h) => [h.name, h]));
|
|
1362
|
+
const values = {};
|
|
1363
|
+
const ignored = [];
|
|
1364
|
+
if (!isPlainObject(raw)) return { values, ignored };
|
|
1365
|
+
for (const name of Object.keys(raw)) {
|
|
1366
|
+
const value = raw[name];
|
|
1367
|
+
if (value === void 0) continue;
|
|
1368
|
+
const spec = declared.get(name);
|
|
1369
|
+
if (!spec || options.sources && !options.sources.includes(spec.source)) {
|
|
1370
|
+
ignored.push(name);
|
|
1371
|
+
continue;
|
|
1372
|
+
}
|
|
1373
|
+
const coerced = coerceHiddenValue(value, spec.type);
|
|
1374
|
+
if (coerced === void 0) ignored.push(name);
|
|
1375
|
+
else Object.defineProperty(values, name, { value: coerced, enumerable: true, writable: true, configurable: true });
|
|
1376
|
+
}
|
|
1377
|
+
return { values, ignored };
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1274
1380
|
// src/logic.ts
|
|
1275
1381
|
function own(record, key) {
|
|
1276
1382
|
return Object.prototype.hasOwnProperty.call(record, key) ? record[key] : void 0;
|
|
@@ -1402,6 +1508,225 @@ function fieldMap(def) {
|
|
|
1402
1508
|
return map;
|
|
1403
1509
|
}
|
|
1404
1510
|
|
|
1511
|
+
// src/options.ts
|
|
1512
|
+
var CHOICE_FIELD_TYPES = /* @__PURE__ */ new Set(["single-choice", "multi-choice", "dropdown"]);
|
|
1513
|
+
var isChoice = (block) => !!block && block.kind === "field" && CHOICE_FIELD_TYPES.has(block.type);
|
|
1514
|
+
function put(record, key, value) {
|
|
1515
|
+
Object.defineProperty(record, key, { value, enumerable: true, writable: true, configurable: true });
|
|
1516
|
+
}
|
|
1517
|
+
function optionFilter(field2) {
|
|
1518
|
+
return optionsSource(field2)?.filter;
|
|
1519
|
+
}
|
|
1520
|
+
function answerValues(answer) {
|
|
1521
|
+
const one = (v) => typeof v === "string" ? [v] : typeof v === "number" || typeof v === "boolean" ? [String(v)] : [];
|
|
1522
|
+
if (answer === void 0 || answer === null) return [];
|
|
1523
|
+
return Array.isArray(answer) ? answer.flatMap(one) : one(answer);
|
|
1524
|
+
}
|
|
1525
|
+
function optionMatches(option, attribute, answer) {
|
|
1526
|
+
const have = option.attributes && Object.prototype.hasOwnProperty.call(option.attributes, attribute) ? option.attributes[attribute] : void 0;
|
|
1527
|
+
if (have === void 0) return false;
|
|
1528
|
+
const wanted = answerValues(answer);
|
|
1529
|
+
return (Array.isArray(have) ? have : [have]).some((v) => wanted.includes(v));
|
|
1530
|
+
}
|
|
1531
|
+
function filterSource(definition, key) {
|
|
1532
|
+
return definition.blocks.find((b) => b.kind === "field" && b.key === key);
|
|
1533
|
+
}
|
|
1534
|
+
function visibleOptions(definition, field2, values) {
|
|
1535
|
+
const options = choiceOptions(field2);
|
|
1536
|
+
const filter = optionFilter(field2);
|
|
1537
|
+
if (!filter) return options;
|
|
1538
|
+
const source = filterSource(definition, filter.field);
|
|
1539
|
+
if (!source || source.id === field2.id) return options;
|
|
1540
|
+
const answer = own(values, source.id);
|
|
1541
|
+
if (isEmptyValue(answer, source)) return options;
|
|
1542
|
+
return options.filter((o) => optionMatches(o, filter.attribute, answer));
|
|
1543
|
+
}
|
|
1544
|
+
function answersOnPath(state) {
|
|
1545
|
+
const out = /* @__PURE__ */ Object.create(null);
|
|
1546
|
+
for (const id of state.path) out[id] = own(state.values, id);
|
|
1547
|
+
return out;
|
|
1548
|
+
}
|
|
1549
|
+
var OUTSIDE_FILTER = "Choose one of the options.";
|
|
1550
|
+
function filteredChoiceError(definition, field2, value, values) {
|
|
1551
|
+
if (!optionFilter(field2) || isEmptyValue(value, field2)) return null;
|
|
1552
|
+
const all = new Set(choiceOptions(field2).map((o) => o.value));
|
|
1553
|
+
const shown2 = new Set(visibleOptions(definition, field2, values).map((o) => o.value));
|
|
1554
|
+
const picked = answerValues(value);
|
|
1555
|
+
return picked.some((v) => all.has(v) && !shown2.has(v)) ? OUTSIDE_FILTER : null;
|
|
1556
|
+
}
|
|
1557
|
+
function hasOptionFilters(definition) {
|
|
1558
|
+
return definition.blocks.some((b) => isChoice(b) && optionFilter(b) !== void 0);
|
|
1559
|
+
}
|
|
1560
|
+
function clearFilteredAnswers(definition, values, changedId) {
|
|
1561
|
+
const changed = definition.blocks.find((b) => b.kind === "field" && b.id === changedId);
|
|
1562
|
+
if (!changed) return values;
|
|
1563
|
+
const keys = /* @__PURE__ */ new Set([changed.key]);
|
|
1564
|
+
let out = values;
|
|
1565
|
+
for (const block of definition.blocks) {
|
|
1566
|
+
if (!isChoice(block)) continue;
|
|
1567
|
+
const filter = optionFilter(block);
|
|
1568
|
+
if (!filter || !keys.has(filter.field)) continue;
|
|
1569
|
+
const value = own(out, block.id);
|
|
1570
|
+
if (value === void 0 || isEmptyValue(value, block)) continue;
|
|
1571
|
+
const all = new Set(choiceOptions(block).map((o) => o.value));
|
|
1572
|
+
const shown2 = new Set(visibleOptions(definition, block, out).map((o) => o.value));
|
|
1573
|
+
const keep = (v) => typeof v !== "string" || !all.has(v) || shown2.has(v);
|
|
1574
|
+
let next = value;
|
|
1575
|
+
if (Array.isArray(value)) {
|
|
1576
|
+
const kept = value.filter(keep);
|
|
1577
|
+
if (kept.length !== value.length) next = kept.length ? kept : void 0;
|
|
1578
|
+
} else if (!keep(value)) next = void 0;
|
|
1579
|
+
if (next === value) continue;
|
|
1580
|
+
if (out === values) out = { ...values };
|
|
1581
|
+
put(out, block.id, next);
|
|
1582
|
+
keys.add(block.key);
|
|
1583
|
+
}
|
|
1584
|
+
return out;
|
|
1585
|
+
}
|
|
1586
|
+
var SEARCHABLE_OPTION_COUNT = 10;
|
|
1587
|
+
function isSearchable(field2, optionCount = choiceOptions(field2).length) {
|
|
1588
|
+
const setting = field2.props?.searchable;
|
|
1589
|
+
if (setting === true || setting === false) return setting;
|
|
1590
|
+
return optionCount > SEARCHABLE_OPTION_COUNT;
|
|
1591
|
+
}
|
|
1592
|
+
function fold(text) {
|
|
1593
|
+
return text.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
|
|
1594
|
+
}
|
|
1595
|
+
function searchOptions(options, query) {
|
|
1596
|
+
const words = fold(query).split(/\s+/).filter(Boolean);
|
|
1597
|
+
if (!words.length) return [...options];
|
|
1598
|
+
return options.filter((o) => {
|
|
1599
|
+
const text = fold([o.label ?? "", o.value, o.description ?? ""].join(" "));
|
|
1600
|
+
return words.every((w) => text.includes(w));
|
|
1601
|
+
});
|
|
1602
|
+
}
|
|
1603
|
+
var MAX_PREFILL_PARAM_LENGTH = 64;
|
|
1604
|
+
function isPrefillParam(param) {
|
|
1605
|
+
return typeof param === "string" && param.length <= MAX_PREFILL_PARAM_LENGTH && /^[A-Za-z0-9_.-]+$/.test(param);
|
|
1606
|
+
}
|
|
1607
|
+
function prefillSetting(field2) {
|
|
1608
|
+
if (!CHOICE_FIELD_TYPES.has(field2.type)) return void 0;
|
|
1609
|
+
const raw = field2.props?.prefill;
|
|
1610
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw) || !isPrefillParam(raw.param)) return void 0;
|
|
1611
|
+
return { param: raw.param, hideWhenPrefilled: raw.hideWhenPrefilled === true };
|
|
1612
|
+
}
|
|
1613
|
+
function paramValues(params, name) {
|
|
1614
|
+
let raw;
|
|
1615
|
+
if (typeof params.getAll === "function") {
|
|
1616
|
+
raw = params.getAll(name);
|
|
1617
|
+
} else if (Object.prototype.hasOwnProperty.call(params, name)) {
|
|
1618
|
+
raw = params[name];
|
|
1619
|
+
}
|
|
1620
|
+
const list = Array.isArray(raw) ? raw : raw === void 0 ? [] : [raw];
|
|
1621
|
+
return list.filter((v) => typeof v === "string" && v !== "" && v.length <= MAX_HIDDEN_STRING_LENGTH);
|
|
1622
|
+
}
|
|
1623
|
+
function prefillFromLink(definition, params, values = {}) {
|
|
1624
|
+
const out = {};
|
|
1625
|
+
if (!params || typeof params !== "object") return out;
|
|
1626
|
+
const seen = {};
|
|
1627
|
+
for (const id of Object.keys(values)) put(seen, id, values[id]);
|
|
1628
|
+
for (const block of definition.blocks) {
|
|
1629
|
+
if (!isChoice(block)) continue;
|
|
1630
|
+
const setting = prefillSetting(block);
|
|
1631
|
+
if (!setting || own(seen, block.id) !== void 0) continue;
|
|
1632
|
+
const raw = paramValues(params, setting.param);
|
|
1633
|
+
if (!raw.length) continue;
|
|
1634
|
+
const shown2 = new Set(visibleOptions(definition, block, seen).map((o) => o.value));
|
|
1635
|
+
let value;
|
|
1636
|
+
if (block.type === "multi-choice") {
|
|
1637
|
+
const picked = [];
|
|
1638
|
+
for (const r of raw) {
|
|
1639
|
+
for (const v of shown2.has(r) ? [r] : r.split(",").map((s) => s.trim())) {
|
|
1640
|
+
if (shown2.has(v) && !picked.includes(v)) picked.push(v);
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
if (picked.length) value = picked;
|
|
1644
|
+
} else value = raw.find((v) => shown2.has(v));
|
|
1645
|
+
if (value === void 0) continue;
|
|
1646
|
+
put(out, block.id, value);
|
|
1647
|
+
put(seen, block.id, value);
|
|
1648
|
+
}
|
|
1649
|
+
return out;
|
|
1650
|
+
}
|
|
1651
|
+
function hiddenByPrefill(definition, state) {
|
|
1652
|
+
const hideable = /* @__PURE__ */ new Set();
|
|
1653
|
+
for (const b of definition.blocks) {
|
|
1654
|
+
if (isChoice(b) && prefillSetting(b)?.hideWhenPrefilled) hideable.add(b.id);
|
|
1655
|
+
}
|
|
1656
|
+
if (!hideable.size) return [];
|
|
1657
|
+
const prefilled = /* @__PURE__ */ new Set();
|
|
1658
|
+
for (const e of state.events) {
|
|
1659
|
+
if (e.type !== "answer" || !hideable.has(e.field)) continue;
|
|
1660
|
+
if (e.source === "prefill") prefilled.add(e.field);
|
|
1661
|
+
else prefilled.delete(e.field);
|
|
1662
|
+
}
|
|
1663
|
+
if (!prefilled.size) return [];
|
|
1664
|
+
const fields = new Map(definition.blocks.map((b) => [b.id, b]));
|
|
1665
|
+
return state.path.filter((id) => {
|
|
1666
|
+
if (!prefilled.has(id) || own(state.errors, id) !== void 0) return false;
|
|
1667
|
+
const field2 = fields.get(id);
|
|
1668
|
+
return !isEmptyValue(own(state.values, id), field2);
|
|
1669
|
+
});
|
|
1670
|
+
}
|
|
1671
|
+
function respondentPath(definition, state) {
|
|
1672
|
+
const hidden = hiddenByPrefill(definition, state);
|
|
1673
|
+
if (!hidden.length) return [...state.path];
|
|
1674
|
+
const skip = new Set(hidden);
|
|
1675
|
+
return state.path.filter((id) => !skip.has(id));
|
|
1676
|
+
}
|
|
1677
|
+
function snapshotOf(byValue, value) {
|
|
1678
|
+
const option = byValue.get(value);
|
|
1679
|
+
if (option) return { value, label: option.label ?? value };
|
|
1680
|
+
return { value, label: value, other: true };
|
|
1681
|
+
}
|
|
1682
|
+
function answerSnapshots(definition, answers) {
|
|
1683
|
+
const out = {};
|
|
1684
|
+
for (const block of definition.blocks) {
|
|
1685
|
+
if (!isChoice(block) || !optionsSource(block)) continue;
|
|
1686
|
+
const value = own(answers, block.id);
|
|
1687
|
+
if (isEmptyValue(value, block)) continue;
|
|
1688
|
+
const byValue = new Map(choiceOptions(block).map((o) => [o.value, o]));
|
|
1689
|
+
let snapshot;
|
|
1690
|
+
if (Array.isArray(value)) {
|
|
1691
|
+
const items = value.filter((v) => typeof v === "string").map((v) => snapshotOf(byValue, v));
|
|
1692
|
+
if (items.length) snapshot = items;
|
|
1693
|
+
} else if (typeof value === "string") snapshot = snapshotOf(byValue, value);
|
|
1694
|
+
if (snapshot) put(out, block.id, snapshot);
|
|
1695
|
+
}
|
|
1696
|
+
return out;
|
|
1697
|
+
}
|
|
1698
|
+
function answersFromSnapshots(definition, snapshots) {
|
|
1699
|
+
const answers = {};
|
|
1700
|
+
const missing = {};
|
|
1701
|
+
for (const block of definition.blocks) {
|
|
1702
|
+
if (!isChoice(block)) continue;
|
|
1703
|
+
const raw = own(snapshots, block.id);
|
|
1704
|
+
const list = (Array.isArray(raw) ? raw : raw === void 0 ? [] : [raw]).flatMap((s) => {
|
|
1705
|
+
const o = readOption(s);
|
|
1706
|
+
if (!o) return [];
|
|
1707
|
+
const label = o.label ?? o.value;
|
|
1708
|
+
return [s.other === true ? { value: o.value, label, other: true } : { value: o.value, label }];
|
|
1709
|
+
});
|
|
1710
|
+
if (!list.length) continue;
|
|
1711
|
+
const options = choiceOptions(block);
|
|
1712
|
+
const byValue = new Set(options.map((o) => o.value));
|
|
1713
|
+
const allowsOther = block.props?.other !== void 0 && block.props?.other !== false;
|
|
1714
|
+
const found = [];
|
|
1715
|
+
const lost = [];
|
|
1716
|
+
for (const s of list) {
|
|
1717
|
+
let value;
|
|
1718
|
+
if (byValue.has(s.value)) value = s.value;
|
|
1719
|
+
else if (s.other) value = allowsOther ? s.value : void 0;
|
|
1720
|
+
else value = options.find((o) => fold(o.label ?? o.value) === fold(s.label))?.value;
|
|
1721
|
+
if (value === void 0) lost.push(s);
|
|
1722
|
+
else if (!found.includes(value)) found.push(value);
|
|
1723
|
+
}
|
|
1724
|
+
if (found.length) put(answers, block.id, block.type === "multi-choice" ? found : found[0]);
|
|
1725
|
+
if (lost.length) put(missing, block.id, lost);
|
|
1726
|
+
}
|
|
1727
|
+
return { answers, missing };
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1405
1730
|
// src/recall.ts
|
|
1406
1731
|
var TOKEN = /\{\{\s*(field|hidden):([A-Za-z0-9_-]+)\s*(?:\|([^}]*))?\}\}/g;
|
|
1407
1732
|
function recall(text, scope) {
|
|
@@ -1481,6 +1806,31 @@ function parseForm(input) {
|
|
|
1481
1806
|
const optionalBoolean = (v, path) => {
|
|
1482
1807
|
if (v !== void 0 && typeof v !== "boolean") issue(path, "Must be true or false.");
|
|
1483
1808
|
};
|
|
1809
|
+
const optionDetails = (o, at) => {
|
|
1810
|
+
if (o.description !== void 0 && (typeof o.description !== "string" || o.description.length > OPTION_LIMITS.description)) {
|
|
1811
|
+
issue(`${at}.description`, `Must be text of at most ${OPTION_LIMITS.description} characters.`);
|
|
1812
|
+
}
|
|
1813
|
+
if (o.image !== void 0 && !isHttpsUrl(o.image)) {
|
|
1814
|
+
issue(`${at}.image`, `Must be an https:// link of at most ${OPTION_LIMITS.image} characters.`);
|
|
1815
|
+
}
|
|
1816
|
+
if (o.attributes === void 0) return;
|
|
1817
|
+
const attributes = o.attributes;
|
|
1818
|
+
if (!isObject2(attributes) || Object.keys(attributes).length > OPTION_LIMITS.attributes) {
|
|
1819
|
+
issue(`${at}.attributes`, `Must be an object of at most ${OPTION_LIMITS.attributes} attributes.`);
|
|
1820
|
+
return;
|
|
1821
|
+
}
|
|
1822
|
+
const fits = (x) => typeof x === "string" && x.length <= OPTION_LIMITS.attributeValue;
|
|
1823
|
+
for (const [name2, v] of Object.entries(attributes)) {
|
|
1824
|
+
if (!name2.trim() || name2.length > OPTION_LIMITS.attributeName || RESERVED.has(name2)) {
|
|
1825
|
+
issue(`${at}.attributes`, `${shown(name2)} isn't a usable attribute name (at most ${OPTION_LIMITS.attributeName} characters).`);
|
|
1826
|
+
} else if (!fits(v) && !(Array.isArray(v) && v.length <= OPTION_LIMITS.attributeItems && v.every(fits))) {
|
|
1827
|
+
issue(
|
|
1828
|
+
`${at}.attributes.${name2}`,
|
|
1829
|
+
`Must be text, or a list of at most ${OPTION_LIMITS.attributeItems} texts, each at most ${OPTION_LIMITS.attributeValue} characters.`
|
|
1830
|
+
);
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
};
|
|
1484
1834
|
const name = (v, path, what) => {
|
|
1485
1835
|
if (typeof v !== "string" || !v) {
|
|
1486
1836
|
issue(path, `${what} must be a non-empty string.`);
|
|
@@ -1653,7 +2003,31 @@ function parseForm(input) {
|
|
|
1653
2003
|
} else if (typeof block.type === "string" && !CHOICE_TYPES.has(block.type)) {
|
|
1654
2004
|
warnings.push({ path: `${path}.props.optionsFrom`, message: "Only single choice, multiple choice and dropdown questions take options from the app." });
|
|
1655
2005
|
}
|
|
2006
|
+
const filter = isObject2(from) ? from.filter : void 0;
|
|
2007
|
+
if (filter !== void 0) {
|
|
2008
|
+
const at = `${path}.props.optionsFrom.filter`;
|
|
2009
|
+
if (!isObject2(filter) || typeof filter.attribute !== "string" || !filter.attribute || filter.attribute.length > OPTION_LIMITS.attributeName || typeof filter.field !== "string" || !filter.field) {
|
|
2010
|
+
issue(at, `Must be { attribute, field }: an attribute name (at most ${OPTION_LIMITS.attributeName} characters) and an earlier question's key.`);
|
|
2011
|
+
} else if (!keys.has(filter.field)) {
|
|
2012
|
+
issue(`${at}.field`, `"${filter.field}" must be the key of an earlier question.`);
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
1656
2015
|
}
|
|
2016
|
+
const prefill = isObject2(block.props) ? block.props.prefill : void 0;
|
|
2017
|
+
if (prefill !== void 0) {
|
|
2018
|
+
if (!isObject2(prefill) || !isPrefillParam(prefill.param)) {
|
|
2019
|
+
issue(
|
|
2020
|
+
`${path}.props.prefill`,
|
|
2021
|
+
`Must be { param, hideWhenPrefilled? }: a link parameter of letters, digits, "_", "-" or "." (at most ${MAX_PREFILL_PARAM_LENGTH} characters).`
|
|
2022
|
+
);
|
|
2023
|
+
} else {
|
|
2024
|
+
optionalBoolean(prefill.hideWhenPrefilled, `${path}.props.prefill.hideWhenPrefilled`);
|
|
2025
|
+
if (typeof block.type === "string" && !CHOICE_TYPES.has(block.type)) {
|
|
2026
|
+
warnings.push({ path: `${path}.props.prefill`, message: "Only single choice, multiple choice and dropdown questions are filled in from a link." });
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
if (isObject2(block.props)) optionalBoolean(block.props.searchable, `${path}.props.searchable`);
|
|
1657
2031
|
if (!isObject2(block.props) || !isJson(block.props)) issue(`${path}.props`, "Must be a JSON object.");
|
|
1658
2032
|
else if (block.props.options !== void 0) {
|
|
1659
2033
|
const options = block.props.options;
|
|
@@ -1662,7 +2036,10 @@ function parseForm(input) {
|
|
|
1662
2036
|
options.forEach((o, j) => {
|
|
1663
2037
|
const at = `${path}.props.options[${j}]`;
|
|
1664
2038
|
if (!isObject2(o) || typeof o.value !== "string") issue(at, "Each option needs a string value.");
|
|
1665
|
-
else
|
|
2039
|
+
else {
|
|
2040
|
+
optionalText(o.label, `${at}.label`);
|
|
2041
|
+
optionDetails(o, at);
|
|
2042
|
+
}
|
|
1666
2043
|
});
|
|
1667
2044
|
if (from === void 0) {
|
|
1668
2045
|
choices.set(
|
|
@@ -1976,9 +2353,24 @@ var props = (all) => Object.fromEntries(Object.entries(all).filter((e) => e[1] !
|
|
|
1976
2353
|
var choiceProps = (o) => {
|
|
1977
2354
|
const out = {};
|
|
1978
2355
|
if (o.options || !o.optionsFrom) {
|
|
1979
|
-
out.options = (o.options ?? []).map(
|
|
2356
|
+
out.options = (o.options ?? []).map(
|
|
2357
|
+
(x) => props({
|
|
2358
|
+
value: x.value,
|
|
2359
|
+
label: x.label || void 0,
|
|
2360
|
+
description: x.description,
|
|
2361
|
+
image: x.image,
|
|
2362
|
+
attributes: x.attributes
|
|
2363
|
+
})
|
|
2364
|
+
);
|
|
1980
2365
|
}
|
|
1981
|
-
if (o.optionsFrom)
|
|
2366
|
+
if (o.optionsFrom) {
|
|
2367
|
+
const { source, key, filter } = o.optionsFrom;
|
|
2368
|
+
out.optionsFrom = filter ? { source, key, filter: { attribute: filter.attribute, field: filter.field } } : { source, key };
|
|
2369
|
+
}
|
|
2370
|
+
if (o.prefill) {
|
|
2371
|
+
out.prefill = o.prefill.hideWhenPrefilled ? { param: o.prefill.param, hideWhenPrefilled: true } : { param: o.prefill.param };
|
|
2372
|
+
}
|
|
2373
|
+
if (o.searchable !== void 0) out.searchable = o.searchable;
|
|
1982
2374
|
if (o.other) out.other = o.other === true ? true : props({ label: o.other.label });
|
|
1983
2375
|
return out;
|
|
1984
2376
|
};
|
|
@@ -2179,47 +2571,6 @@ ${list}`);
|
|
|
2179
2571
|
};
|
|
2180
2572
|
}
|
|
2181
2573
|
|
|
2182
|
-
// src/hidden.ts
|
|
2183
|
-
var MAX_HIDDEN_STRING_LENGTH = 1e3;
|
|
2184
|
-
var DECIMAL = /^-?\d+(\.\d+)?$/;
|
|
2185
|
-
function coerceHiddenValue(value, type) {
|
|
2186
|
-
if (typeof value === "string" && value.length > MAX_HIDDEN_STRING_LENGTH) return void 0;
|
|
2187
|
-
if (type === "string") {
|
|
2188
|
-
if (typeof value === "string") return value;
|
|
2189
|
-
if (typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
2190
|
-
return void 0;
|
|
2191
|
-
}
|
|
2192
|
-
if (type === "number") {
|
|
2193
|
-
if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
|
|
2194
|
-
if (typeof value !== "string" || !DECIMAL.test(value)) return void 0;
|
|
2195
|
-
const n = Number(value);
|
|
2196
|
-
return Number.isFinite(n) ? n : void 0;
|
|
2197
|
-
}
|
|
2198
|
-
if (typeof value === "boolean") return value;
|
|
2199
|
-
if (value === "true") return true;
|
|
2200
|
-
if (value === "false") return false;
|
|
2201
|
-
return void 0;
|
|
2202
|
-
}
|
|
2203
|
-
function coerceHidden(definition, raw, options = {}) {
|
|
2204
|
-
const declared = new Map((definition.hidden ?? []).map((h) => [h.name, h]));
|
|
2205
|
-
const values = {};
|
|
2206
|
-
const ignored = [];
|
|
2207
|
-
if (!isPlainObject(raw)) return { values, ignored };
|
|
2208
|
-
for (const name of Object.keys(raw)) {
|
|
2209
|
-
const value = raw[name];
|
|
2210
|
-
if (value === void 0) continue;
|
|
2211
|
-
const spec = declared.get(name);
|
|
2212
|
-
if (!spec || options.sources && !options.sources.includes(spec.source)) {
|
|
2213
|
-
ignored.push(name);
|
|
2214
|
-
continue;
|
|
2215
|
-
}
|
|
2216
|
-
const coerced = coerceHiddenValue(value, spec.type);
|
|
2217
|
-
if (coerced === void 0) ignored.push(name);
|
|
2218
|
-
else Object.defineProperty(values, name, { value: coerced, enumerable: true, writable: true, configurable: true });
|
|
2219
|
-
}
|
|
2220
|
-
return { values, ignored };
|
|
2221
|
-
}
|
|
2222
|
-
|
|
2223
2574
|
// src/validate.ts
|
|
2224
2575
|
var REQUIRED_MESSAGE = "This question needs an answer.";
|
|
2225
2576
|
function runCustom(validator, value) {
|
|
@@ -2323,16 +2674,34 @@ function build(given, options, replaying = false, budget) {
|
|
|
2323
2674
|
return at === void 0 ? event : { ...event, at };
|
|
2324
2675
|
};
|
|
2325
2676
|
const isVisibleIn = (s, id) => s.path.includes(id);
|
|
2677
|
+
const filters = hasOptionFilters(definition);
|
|
2678
|
+
const clearFiltered = (values, id) => filters ? clearFilteredAnswers(definition, values, id) : values;
|
|
2326
2679
|
const errorsFor = (s, ids) => {
|
|
2327
2680
|
const errors = {};
|
|
2681
|
+
let shown2;
|
|
2328
2682
|
for (const id of ids) {
|
|
2329
2683
|
const field2 = fields.get(id);
|
|
2330
2684
|
if (!field2 || !isVisibleIn(s, id)) continue;
|
|
2331
|
-
const
|
|
2685
|
+
const value = own(s.values, id);
|
|
2686
|
+
let message = validateField(field2, value, { custom: options.validators?.[id] });
|
|
2687
|
+
if (!message && filters) message = filteredChoiceError(definition, field2, value, shown2 ??= answersOnPath(s));
|
|
2332
2688
|
if (message) errors[id] = message;
|
|
2333
2689
|
}
|
|
2334
2690
|
return errors;
|
|
2335
2691
|
};
|
|
2692
|
+
const skipped = (s) => new Set(hiddenByPrefill(definition, s));
|
|
2693
|
+
const shownFrom = (s, from, skip) => {
|
|
2694
|
+
for (let i = from; i < s.path.length; i++) if (!skip.has(s.path[i])) return s.path[i];
|
|
2695
|
+
return void 0;
|
|
2696
|
+
};
|
|
2697
|
+
const showCurrent = () => {
|
|
2698
|
+
if (!state.current) return;
|
|
2699
|
+
const skip = skipped(state);
|
|
2700
|
+
if (!skip.has(state.current)) return;
|
|
2701
|
+
const at = state.path.indexOf(state.current);
|
|
2702
|
+
const shown2 = at < 0 ? void 0 : shownFrom(state, at, skip);
|
|
2703
|
+
if (shown2) state = { ...state, current: shown2, furthest: state.furthest === state.current ? shown2 : state.furthest };
|
|
2704
|
+
};
|
|
2336
2705
|
let unsettled = false;
|
|
2337
2706
|
let formulasStale = false;
|
|
2338
2707
|
const settleNow = (needValues = true) => {
|
|
@@ -2361,13 +2730,13 @@ function build(given, options, replaying = false, budget) {
|
|
|
2361
2730
|
const errors = { ...state.errors };
|
|
2362
2731
|
delete errors[id];
|
|
2363
2732
|
if (batch) {
|
|
2364
|
-
state.values = { ...state.values, [id]: value };
|
|
2733
|
+
state.values = clearFiltered({ ...state.values, [id]: value }, id);
|
|
2365
2734
|
state.errors = errors;
|
|
2366
2735
|
log(event);
|
|
2367
2736
|
unsettled = true;
|
|
2368
2737
|
return;
|
|
2369
2738
|
}
|
|
2370
|
-
const { values, path } = settle({ ...state.values, [id]: value }, state.hidden);
|
|
2739
|
+
const { values, path } = settle(clearFiltered({ ...state.values, [id]: value }, id), state.hidden);
|
|
2371
2740
|
emit({ ...state, values, path, errors, events: log(event) });
|
|
2372
2741
|
};
|
|
2373
2742
|
const engine = {
|
|
@@ -2398,7 +2767,7 @@ function build(given, options, replaying = false, budget) {
|
|
|
2398
2767
|
return false;
|
|
2399
2768
|
}
|
|
2400
2769
|
const at = state.path.indexOf(state.current);
|
|
2401
|
-
const target = state
|
|
2770
|
+
const target = shownFrom(state, at + 1, skipped(state));
|
|
2402
2771
|
if (!target) {
|
|
2403
2772
|
emit({ ...state, events });
|
|
2404
2773
|
return true;
|
|
@@ -2410,8 +2779,9 @@ function build(given, options, replaying = false, budget) {
|
|
|
2410
2779
|
back() {
|
|
2411
2780
|
if (state.status === "completed") return;
|
|
2412
2781
|
const history = [...state.history];
|
|
2782
|
+
const skip = skipped(state);
|
|
2413
2783
|
let previous = history.pop();
|
|
2414
|
-
while (previous && !state.path.includes(previous)) previous = history.pop();
|
|
2784
|
+
while (previous && (!state.path.includes(previous) || skip.has(previous))) previous = history.pop();
|
|
2415
2785
|
if (!previous) return;
|
|
2416
2786
|
emit({ ...state, current: previous, history, events: log(stamp({ type: "back" })) });
|
|
2417
2787
|
},
|
|
@@ -2439,15 +2809,18 @@ function build(given, options, replaying = false, budget) {
|
|
|
2439
2809
|
return out;
|
|
2440
2810
|
}
|
|
2441
2811
|
};
|
|
2442
|
-
|
|
2812
|
+
const fromLink = options.linkParams ? prefillFromLink(definition, options.linkParams, options.initialValues) : {};
|
|
2813
|
+
const initialValues = Object.keys(fromLink).length ? { ...fromLink, ...options.initialValues } : options.initialValues;
|
|
2814
|
+
if (initialValues) {
|
|
2443
2815
|
const wasBatch = batch;
|
|
2444
2816
|
batch = true;
|
|
2445
|
-
for (const [id, value] of Object.entries(
|
|
2817
|
+
for (const [id, value] of Object.entries(initialValues)) {
|
|
2446
2818
|
if (!fields.has(id) || value === void 0) continue;
|
|
2447
2819
|
answer(id, value, stamp({ type: "answer", field: id, value, source: "prefill" }));
|
|
2448
2820
|
}
|
|
2449
2821
|
settleNow();
|
|
2450
2822
|
batch = wasBatch;
|
|
2823
|
+
showCurrent();
|
|
2451
2824
|
}
|
|
2452
2825
|
const resumeAt = options.resumeAt;
|
|
2453
2826
|
if (resumeAt && !replaying && state.path.includes(resumeAt)) {
|
|
@@ -2466,18 +2839,22 @@ function build(given, options, replaying = false, budget) {
|
|
|
2466
2839
|
}
|
|
2467
2840
|
} else if (event.type === "next") {
|
|
2468
2841
|
settleNow(false);
|
|
2842
|
+
showCurrent();
|
|
2469
2843
|
if (formulasStale && isCalculated(fields.get(state.current ?? ""))) settleNow(true);
|
|
2470
2844
|
engine.next();
|
|
2471
2845
|
} else if (event.type === "back") {
|
|
2472
2846
|
settleNow(false);
|
|
2847
|
+
showCurrent();
|
|
2473
2848
|
engine.back();
|
|
2474
2849
|
} else if (event.type === "submit") {
|
|
2475
2850
|
settleNow();
|
|
2851
|
+
showCurrent();
|
|
2476
2852
|
engine.submit();
|
|
2477
2853
|
}
|
|
2478
2854
|
};
|
|
2479
2855
|
const finish = () => {
|
|
2480
2856
|
settleNow();
|
|
2857
|
+
showCurrent();
|
|
2481
2858
|
batch = false;
|
|
2482
2859
|
state = { ...state, events: [...state.events] };
|
|
2483
2860
|
};
|
|
@@ -2488,7 +2865,12 @@ function replay(definition, events, options = {}) {
|
|
|
2488
2865
|
}
|
|
2489
2866
|
function replayWithin(definition, events, options, maxWork) {
|
|
2490
2867
|
const budget = void 0 ;
|
|
2491
|
-
const { engine, apply, finish } = build(
|
|
2868
|
+
const { engine, apply, finish } = build(
|
|
2869
|
+
definition,
|
|
2870
|
+
{ ...options, initialValues: void 0, linkParams: void 0, clock: () => void 0 },
|
|
2871
|
+
true,
|
|
2872
|
+
budget
|
|
2873
|
+
);
|
|
2492
2874
|
try {
|
|
2493
2875
|
for (const event of events) apply(event);
|
|
2494
2876
|
finish();
|
|
@@ -2660,6 +3042,22 @@ function describeCondition(condition, def, fields = fieldMap(def)) {
|
|
|
2660
3042
|
return `${left} ${op} ${right}`;
|
|
2661
3043
|
}
|
|
2662
3044
|
|
|
2663
|
-
|
|
3045
|
+
// src/carry.ts
|
|
3046
|
+
function carryAnswers(from, to, answers, extra = {}) {
|
|
3047
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
3048
|
+
for (const block of from.blocks) {
|
|
3049
|
+
if (block.kind === "field" && answers[block.id] !== void 0) byKey.set(block.key, answers[block.id]);
|
|
3050
|
+
}
|
|
3051
|
+
for (const [key, value] of Object.entries(extra)) {
|
|
3052
|
+
if (value !== null && value !== void 0 && !byKey.has(key)) byKey.set(key, value);
|
|
3053
|
+
}
|
|
3054
|
+
const out = {};
|
|
3055
|
+
for (const block of to.blocks) {
|
|
3056
|
+
if (block.kind === "field" && byKey.has(block.key)) out[block.id] = byKey.get(block.key);
|
|
3057
|
+
}
|
|
3058
|
+
return out;
|
|
3059
|
+
}
|
|
3060
|
+
|
|
3061
|
+
export { CALCULATED_TYPE, CHOICE_FIELD_TYPES, 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_PREFILL_PARAM_LENGTH, MAX_SETTLE_ITEMS, MAX_TABLE_CELL_LENGTH, MAX_TABLE_COLUMNS, MAX_TIMESTAMP_SECONDS, OPTION_LIMITS, OTHER_MAX_LENGTH, PHOTO_FORMATS, PHOTO_TYPE, REQUIRED_MESSAGE, SEARCHABLE_OPTION_COUNT, STRUCTURED_FIELD_TYPES, UPLOAD_FIELD_TYPES, answerSnapshots, answersFromSnapshots, answersOnPath, calculatedProps, calculatedValue, canonicalJson, carryAnswers, choiceOptions, clearFilteredAnswers, coerceHidden, coerceHiddenValue, computePath, createForm, dateLimits, defineForm, describeCondition, evaluate, evaluateFormula, explain, f, filteredChoiceError, fingerprint, formProgress, formatCalculated, formatTimestamp, formulaInput, formulaNumber, formulaRefs, furthestReached, getFieldType, hasOptionFilters, hiddenByPrefill, isEmptyValue, isFormEvent, isHttpsUrl, isIsoDate, isJson, isOtherValue, isPhotoFormat, isPhotoRef, isPrefillParam, isSearchable, isSensitive, listFieldTypes, listLimits, normalizeValue, numberLimits, optionFilter, optionJson, optionMatches, optionsSource, otherOption, parseForm, parseFormula, parseTimestamp, photoCountMessage, photoFormatList, photoLimits, photoRefs, photoSizeMessage, photoTypeMessage, prefillFromLink, prefillSetting, ratingDisplay, readOption, recall, registerFieldType, renameFormulaKey, replay, respondentPath, ruleVisible, scaleLabels, searchOptions, steps, summarizeValue, tableColumns, tableLimits, validateField, visibleOptions, when, withHostOptions };
|
|
2664
3062
|
//# sourceMappingURL=index.js.map
|
|
2665
3063
|
//# sourceMappingURL=index.js.map
|