@marktiderman/genesis-forms 0.4.0 → 0.4.2
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 +31 -4
- package/dist/destinations.cjs.map +1 -1
- package/dist/destinations.js.map +1 -1
- package/dist/index.cjs +230 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +229 -46
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +303 -55
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +29 -2
- package/dist/server.d.ts +29 -2
- package/dist/server.js +301 -56
- package/dist/server.js.map +1 -1
- package/dist/testing.cjs +302 -54
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.js +302 -54
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -64,6 +64,7 @@ function tokenize(source) {
|
|
|
64
64
|
i++;
|
|
65
65
|
while (isDigit(source[i] ?? "")) i++;
|
|
66
66
|
}
|
|
67
|
+
if (isIdStart(source[i] ?? "")) throw new FormulaError("Write a number in digits only, like 1000000.", at);
|
|
67
68
|
const v = Number(source.slice(at, i));
|
|
68
69
|
if (!Number.isFinite(v)) throw new FormulaError("This number is too large.", at);
|
|
69
70
|
tokens.push({ t: "num", v, at });
|
|
@@ -293,6 +294,27 @@ function numbersIn(values, out = []) {
|
|
|
293
294
|
}
|
|
294
295
|
return out;
|
|
295
296
|
}
|
|
297
|
+
var listTotals = /* @__PURE__ */ new WeakMap();
|
|
298
|
+
var ownLists = /* @__PURE__ */ new WeakSet();
|
|
299
|
+
function ownFormulaList(list) {
|
|
300
|
+
Object.freeze(list);
|
|
301
|
+
ownLists.add(list);
|
|
302
|
+
return list;
|
|
303
|
+
}
|
|
304
|
+
function totalsOf(list) {
|
|
305
|
+
const own2 = ownLists.has(list);
|
|
306
|
+
let t = own2 ? listTotals.get(list) : void 0;
|
|
307
|
+
if (t) return t;
|
|
308
|
+
const nums = numbersIn(list);
|
|
309
|
+
t = { sum: 0, count: nums.length, min: Infinity, max: -Infinity };
|
|
310
|
+
for (const n of nums) {
|
|
311
|
+
t.sum += n;
|
|
312
|
+
if (n < t.min) t.min = n;
|
|
313
|
+
if (n > t.max) t.max = n;
|
|
314
|
+
}
|
|
315
|
+
if (own2) listTotals.set(list, t);
|
|
316
|
+
return t;
|
|
317
|
+
}
|
|
296
318
|
function compare(op, a, b) {
|
|
297
319
|
const blank2 = (v) => v === null || Array.isArray(v) || typeof v === "string" && v.trim() === "";
|
|
298
320
|
if (blank2(a) || blank2(b)) return op === "!=";
|
|
@@ -317,7 +339,7 @@ function evaluateFormula(ast, read) {
|
|
|
317
339
|
case "text":
|
|
318
340
|
return node.value;
|
|
319
341
|
case "ref":
|
|
320
|
-
return read(node
|
|
342
|
+
return read(node);
|
|
321
343
|
case "unary": {
|
|
322
344
|
const n = formulaNumber(scalar(run(node.arg)));
|
|
323
345
|
return n === null ? null : -n;
|
|
@@ -325,12 +347,31 @@ function evaluateFormula(ast, read) {
|
|
|
325
347
|
case "if":
|
|
326
348
|
return truthy(run(node.test)) ? run(node.then) : run(node.else);
|
|
327
349
|
case "call": {
|
|
328
|
-
|
|
329
|
-
|
|
350
|
+
let total = 0;
|
|
351
|
+
let count = 0;
|
|
352
|
+
let min = Infinity;
|
|
353
|
+
let max = -Infinity;
|
|
354
|
+
for (const arg of node.args) {
|
|
355
|
+
const v = run(arg);
|
|
356
|
+
if (Array.isArray(v)) {
|
|
357
|
+
const t = totalsOf(v);
|
|
358
|
+
total += t.sum;
|
|
359
|
+
count += t.count;
|
|
360
|
+
if (t.min < min) min = t.min;
|
|
361
|
+
if (t.max > max) max = t.max;
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
const n = formulaNumber(v);
|
|
365
|
+
if (n === null) continue;
|
|
366
|
+
total += n;
|
|
367
|
+
count++;
|
|
368
|
+
if (n < min) min = n;
|
|
369
|
+
if (n > max) max = n;
|
|
370
|
+
}
|
|
330
371
|
if (node.fn === "sum") return finite(total);
|
|
331
|
-
if (!
|
|
332
|
-
if (node.fn === "avg") return finite(total /
|
|
333
|
-
return
|
|
372
|
+
if (!count) return null;
|
|
373
|
+
if (node.fn === "avg") return finite(total / count);
|
|
374
|
+
return node.fn === "min" ? min : max;
|
|
334
375
|
}
|
|
335
376
|
case "binary": {
|
|
336
377
|
const a = run(node.left);
|
|
@@ -358,6 +399,7 @@ function evaluateFormula(ast, read) {
|
|
|
358
399
|
// src/calculated.ts
|
|
359
400
|
var CALCULATED_TYPE = "calculated";
|
|
360
401
|
var COMPUTED_FIELD_TYPES = [CALCULATED_TYPE];
|
|
402
|
+
var MAX_FORM_FORMULA_LENGTH = 2e4;
|
|
361
403
|
var MAX_CALCULATED_DECIMALS = 10;
|
|
362
404
|
function calculatedProps(field2) {
|
|
363
405
|
const p = field2.props ?? {};
|
|
@@ -375,7 +417,9 @@ var round = (n, decimals) => {
|
|
|
375
417
|
return Object.is(r, -0) ? 0 : r;
|
|
376
418
|
};
|
|
377
419
|
function calculatedValue(result, field2) {
|
|
378
|
-
|
|
420
|
+
return valueAs(result, calculatedProps(field2));
|
|
421
|
+
}
|
|
422
|
+
function valueAs(result, { format, decimals }) {
|
|
379
423
|
if (result === null || Array.isArray(result)) return void 0;
|
|
380
424
|
if (format === "number" || format === "percent") {
|
|
381
425
|
const n = formulaNumber(result);
|
|
@@ -396,24 +440,43 @@ function formatCalculated(value, field2) {
|
|
|
396
440
|
return typeof value === "string" ? value : "";
|
|
397
441
|
}
|
|
398
442
|
var MAX_FORMULA_ITEMS = 1e4;
|
|
443
|
+
var MAX_SETTLE_ITEMS = 5e4;
|
|
444
|
+
var extract = (value, column) => column !== void 0 ? value.flatMap((row) => {
|
|
445
|
+
if (!row || typeof row !== "object" || Array.isArray(row)) return [];
|
|
446
|
+
const cell = row[column];
|
|
447
|
+
return typeof cell === "string" || typeof cell === "number" ? [cell] : [];
|
|
448
|
+
}) : value.flatMap((v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean" ? [v] : []);
|
|
399
449
|
function formulaInput(value, column) {
|
|
400
450
|
if (value === void 0 || value === null) return null;
|
|
401
451
|
if (Array.isArray(value) && value.length > MAX_FORMULA_ITEMS) return null;
|
|
402
452
|
if (column !== void 0) {
|
|
403
453
|
if (!Array.isArray(value)) return null;
|
|
404
|
-
return value
|
|
405
|
-
if (!row || typeof row !== "object" || Array.isArray(row)) return [];
|
|
406
|
-
const cell = row[column];
|
|
407
|
-
return typeof cell === "string" || typeof cell === "number" ? [cell] : [];
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
if (Array.isArray(value)) {
|
|
411
|
-
return value.flatMap((v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean" ? [v] : []);
|
|
454
|
+
return extract(value, column);
|
|
412
455
|
}
|
|
456
|
+
if (Array.isArray(value)) return extract(value, void 0);
|
|
413
457
|
return typeof value === "object" ? null : value;
|
|
414
458
|
}
|
|
459
|
+
function refNodes(node, out = []) {
|
|
460
|
+
if (node.kind === "ref") out.push(node);
|
|
461
|
+
else if (node.kind === "unary") refNodes(node.arg, out);
|
|
462
|
+
else if (node.kind === "binary") refNodes(node.left, out), refNodes(node.right, out);
|
|
463
|
+
else if (node.kind === "if") refNodes(node.test, out), refNodes(node.then, out), refNodes(node.else, out);
|
|
464
|
+
else if (node.kind === "call") for (const a of node.args) refNodes(a, out);
|
|
465
|
+
return out;
|
|
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
|
+
}
|
|
415
477
|
var UNREAD = /* @__PURE__ */ Symbol("unread");
|
|
416
|
-
|
|
478
|
+
var OVER = /* @__PURE__ */ Symbol("over");
|
|
479
|
+
function calculator(definition, work) {
|
|
417
480
|
const compiled = [];
|
|
418
481
|
const idByKey = /* @__PURE__ */ new Map();
|
|
419
482
|
for (const block of definition.blocks) {
|
|
@@ -422,35 +485,105 @@ function calculator(definition) {
|
|
|
422
485
|
}
|
|
423
486
|
for (const block of definition.blocks) {
|
|
424
487
|
if (block.kind !== "field" || !isCalculated(block)) continue;
|
|
425
|
-
const
|
|
426
|
-
const
|
|
427
|
-
|
|
488
|
+
const props2 = calculatedProps(block);
|
|
489
|
+
const parsed = parseFormula(props2.formula);
|
|
490
|
+
const reads = [];
|
|
491
|
+
const slots = /* @__PURE__ */ new Map();
|
|
492
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
493
|
+
for (const ref of parsed.ok ? refNodes(parsed.ast) : []) {
|
|
494
|
+
const id = idByKey.get(ref.key);
|
|
495
|
+
const key = `${id ?? ""}\0${ref.column ?? ""}`;
|
|
496
|
+
let slot = byKey.get(key);
|
|
497
|
+
if (slot === void 0) {
|
|
498
|
+
slot = reads.push({ id, column: ref.column, key }) - 1;
|
|
499
|
+
byKey.set(key, slot);
|
|
500
|
+
}
|
|
501
|
+
slots.set(ref, slot);
|
|
502
|
+
}
|
|
503
|
+
compiled.push({ field: block, props: props2, ast: parsed.ok ? parsed.ast : null, size: parsed.ok ? formulaSize(parsed.ast) : 0, reads, slots, last: null });
|
|
428
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
|
+
};
|
|
429
525
|
const withCalculated = (values, path) => {
|
|
430
526
|
if (!compiled.length) return values;
|
|
431
527
|
const visible = new Set(path);
|
|
432
528
|
let next = values;
|
|
433
|
-
|
|
529
|
+
let copied = false;
|
|
530
|
+
let budget = MAX_SETTLE_ITEMS;
|
|
531
|
+
const within = /* @__PURE__ */ new Map();
|
|
532
|
+
const input = ({ id }) => {
|
|
533
|
+
if (id === void 0 || !visible.has(id) || !Object.prototype.hasOwnProperty.call(next, id)) return UNREAD;
|
|
534
|
+
const value = next[id];
|
|
535
|
+
if (!Array.isArray(value)) return value;
|
|
536
|
+
let ok = within.get(id);
|
|
537
|
+
if (ok === void 0) {
|
|
538
|
+
ok = value.length <= MAX_FORMULA_ITEMS && value.length <= budget;
|
|
539
|
+
if (ok) budget -= value.length;
|
|
540
|
+
within.set(id, ok);
|
|
541
|
+
}
|
|
542
|
+
return ok ? value : OVER;
|
|
543
|
+
};
|
|
434
544
|
for (const entry of compiled) {
|
|
435
545
|
const { field: field2, ast } = entry;
|
|
436
|
-
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
|
+
}
|
|
437
556
|
let value;
|
|
438
|
-
if (
|
|
557
|
+
if (same) {
|
|
439
558
|
value = entry.last.value;
|
|
440
559
|
} else {
|
|
560
|
+
spend(work, entry.size);
|
|
561
|
+
const resolved = new Array(inputs.length);
|
|
441
562
|
const read = (ref) => {
|
|
442
|
-
const
|
|
443
|
-
|
|
563
|
+
const slot = entry.slots.get(ref);
|
|
564
|
+
if (slot === void 0) return null;
|
|
565
|
+
let v = resolved[slot];
|
|
566
|
+
if (v === void 0) {
|
|
567
|
+
const raw = inputs[slot];
|
|
568
|
+
v = resolved[slot] = raw === UNREAD ? null : readAnswer(raw, reads[slot].column);
|
|
569
|
+
}
|
|
570
|
+
return v;
|
|
444
571
|
};
|
|
445
|
-
value = ast ?
|
|
572
|
+
value = ast && !over ? valueAs(evaluateFormula(ast, read), entry.props) : void 0;
|
|
446
573
|
entry.last = { inputs, value };
|
|
447
574
|
}
|
|
448
575
|
const current = Object.prototype.hasOwnProperty.call(next, field2.id) ? next[field2.id] : void 0;
|
|
449
|
-
if (current !== value)
|
|
576
|
+
if (current !== value) {
|
|
577
|
+
if (!copied) {
|
|
578
|
+
next = { ...next };
|
|
579
|
+
copied = true;
|
|
580
|
+
}
|
|
581
|
+
next[field2.id] = value;
|
|
582
|
+
}
|
|
450
583
|
}
|
|
451
584
|
return next;
|
|
452
585
|
};
|
|
453
|
-
return { active: compiled.length > 0, withCalculated };
|
|
586
|
+
return { active: compiled.length > 0, ids: new Set(compiled.map((c) => c.field.id)), withCalculated, forget };
|
|
454
587
|
}
|
|
455
588
|
var numberOps = ["eq", "neq", "lt", "lte", "gt", "gte", "in", "answered", "empty"];
|
|
456
589
|
var calculatedFieldType = {
|
|
@@ -1085,8 +1218,8 @@ function rulesAllow(def, blockId, scope) {
|
|
|
1085
1218
|
}
|
|
1086
1219
|
function walkPath(def, scope) {
|
|
1087
1220
|
const list = steps(def);
|
|
1088
|
-
|
|
1089
|
-
|
|
1221
|
+
let index;
|
|
1222
|
+
let position;
|
|
1090
1223
|
const jumps = (def.logic ?? []).filter(
|
|
1091
1224
|
(r) => r.effect === "jump"
|
|
1092
1225
|
);
|
|
@@ -1110,6 +1243,7 @@ function walkPath(def, scope) {
|
|
|
1110
1243
|
ending = jump.to.ending;
|
|
1111
1244
|
break;
|
|
1112
1245
|
}
|
|
1246
|
+
index ??= new Map(list.map((b, at) => [b.id, at]));
|
|
1113
1247
|
const target = index.get(jump.to);
|
|
1114
1248
|
if (target !== void 0 && target > i) {
|
|
1115
1249
|
i = nextVisible(target);
|
|
@@ -1119,6 +1253,7 @@ function walkPath(def, scope) {
|
|
|
1119
1253
|
i = nextVisible(i + 1);
|
|
1120
1254
|
}
|
|
1121
1255
|
const scopeAt = (blockId, inclusive = false) => {
|
|
1256
|
+
position ??= new Map(def.blocks.map((b, i2) => [b.id, i2]));
|
|
1122
1257
|
const at = position.get(blockId) ?? -1;
|
|
1123
1258
|
const values = /* @__PURE__ */ Object.create(null);
|
|
1124
1259
|
for (const id of path) {
|
|
@@ -1423,9 +1558,15 @@ function parseForm(input) {
|
|
|
1423
1558
|
issue(`${path}.kind`, "Unknown block kind.");
|
|
1424
1559
|
}
|
|
1425
1560
|
});
|
|
1561
|
+
let formulaChars = 0;
|
|
1426
1562
|
input.blocks.forEach((block, i) => {
|
|
1427
1563
|
if (!isObject2(block) || block.kind !== "field" || block.type !== CALCULATED_TYPE) return;
|
|
1428
1564
|
const path = `blocks[${i}].props.formula`;
|
|
1565
|
+
const source = isObject2(block.props) && typeof block.props.formula === "string" ? block.props.formula : "";
|
|
1566
|
+
formulaChars += source.length;
|
|
1567
|
+
if (formulaChars > MAX_FORM_FORMULA_LENGTH && formulaChars - source.length <= MAX_FORM_FORMULA_LENGTH) {
|
|
1568
|
+
issue(path, `The form's formulas together are over ${MAX_FORM_FORMULA_LENGTH} characters; shorten some, or work part out once in an earlier calculated field.`);
|
|
1569
|
+
}
|
|
1429
1570
|
if (block.required === true) {
|
|
1430
1571
|
warnings.push({ path: `blocks[${i}].required`, message: "A calculated field is worked out, not answered, so it is never required." });
|
|
1431
1572
|
}
|
|
@@ -1924,10 +2065,19 @@ function validateField(field2, value, options = {}) {
|
|
|
1924
2065
|
}
|
|
1925
2066
|
|
|
1926
2067
|
// src/engine.ts
|
|
2068
|
+
function readsAny(node, ids) {
|
|
2069
|
+
if (Array.isArray(node)) return node.some((n) => readsAny(n, ids));
|
|
2070
|
+
if (!node || typeof node !== "object") return false;
|
|
2071
|
+
for (const [k, v] of Object.entries(node)) {
|
|
2072
|
+
if (k === "field" && typeof v === "string" && ids.has(v)) return true;
|
|
2073
|
+
if (typeof v === "object" && readsAny(v, ids)) return true;
|
|
2074
|
+
}
|
|
2075
|
+
return false;
|
|
2076
|
+
}
|
|
1927
2077
|
function createForm(definition, options = {}) {
|
|
1928
2078
|
return build(definition, options).engine;
|
|
1929
2079
|
}
|
|
1930
|
-
function build(definition, options, replaying = false) {
|
|
2080
|
+
function build(definition, options, replaying = false, budget) {
|
|
1931
2081
|
const fields = fieldMap(definition);
|
|
1932
2082
|
const byKey = new Map([...fields.values()].map((f2) => [f2.key, f2]));
|
|
1933
2083
|
const blocks = new Map(definition.blocks.map((b) => [b.id, b]));
|
|
@@ -1945,15 +2095,24 @@ function build(definition, options, replaying = false) {
|
|
|
1945
2095
|
if (!declared.has(name)) initialHidden[name] = value;
|
|
1946
2096
|
}
|
|
1947
2097
|
Object.assign(initialHidden, coerceHidden(definition, options.hidden).values);
|
|
1948
|
-
const calc = calculator(definition);
|
|
2098
|
+
const calc = calculator(definition, budget);
|
|
2099
|
+
const pathOf = (values, hidden) => {
|
|
2100
|
+
spend(budget, definition.blocks.length);
|
|
2101
|
+
return computePath(definition, scopeOf(values, hidden));
|
|
2102
|
+
};
|
|
2103
|
+
const logicReadsCalculated = calc.active && readsAny(definition.logic, calc.ids);
|
|
1949
2104
|
const settle = (values, hidden) => {
|
|
1950
|
-
let { path } =
|
|
2105
|
+
let { path } = pathOf(values, hidden);
|
|
1951
2106
|
if (!calc.active) return { values, path };
|
|
2107
|
+
if (!logicReadsCalculated) return { values: calc.withCalculated(values, path), path };
|
|
1952
2108
|
for (let round2 = 0; round2 < 4; round2++) {
|
|
1953
2109
|
const next = calc.withCalculated(values, path);
|
|
1954
2110
|
if (next === values) break;
|
|
1955
2111
|
values = next;
|
|
1956
|
-
|
|
2112
|
+
const again = pathOf(values, hidden).path;
|
|
2113
|
+
const same = again.length === path.length && again.every((id, i) => id === path[i]);
|
|
2114
|
+
path = again;
|
|
2115
|
+
if (same) break;
|
|
1957
2116
|
}
|
|
1958
2117
|
return { values, path };
|
|
1959
2118
|
};
|
|
@@ -1995,14 +2154,30 @@ function build(definition, options, replaying = false) {
|
|
|
1995
2154
|
return errors;
|
|
1996
2155
|
};
|
|
1997
2156
|
let unsettled = false;
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
unsettled
|
|
2001
|
-
|
|
2002
|
-
|
|
2157
|
+
let formulasStale = false;
|
|
2158
|
+
const settleNow = (needValues = true) => {
|
|
2159
|
+
if (unsettled && calc.active && !logicReadsCalculated && !needValues) {
|
|
2160
|
+
unsettled = false;
|
|
2161
|
+
formulasStale = true;
|
|
2162
|
+
state = { ...state, path: pathOf(state.values, state.hidden).path };
|
|
2163
|
+
return;
|
|
2164
|
+
}
|
|
2165
|
+
if (unsettled) {
|
|
2166
|
+
unsettled = false;
|
|
2167
|
+
formulasStale = false;
|
|
2168
|
+
const { values, path } = settle(state.values, state.hidden);
|
|
2169
|
+
state = { ...state, values, path };
|
|
2170
|
+
} else if (formulasStale && needValues) {
|
|
2171
|
+
formulasStale = false;
|
|
2172
|
+
state = { ...state, values: calc.withCalculated(state.values, state.path) };
|
|
2173
|
+
}
|
|
2003
2174
|
};
|
|
2004
2175
|
const answer = (id, value, event) => {
|
|
2005
|
-
if (state.status === "completed" ||
|
|
2176
|
+
if (state.status === "completed" || isCalculated(fields.get(id))) return;
|
|
2177
|
+
if (own(state.values, id) === value) {
|
|
2178
|
+
if (value === null || typeof value !== "object") return;
|
|
2179
|
+
calc.forget(value);
|
|
2180
|
+
}
|
|
2006
2181
|
const errors = { ...state.errors };
|
|
2007
2182
|
delete errors[id];
|
|
2008
2183
|
if (batch) {
|
|
@@ -2068,7 +2243,7 @@ function build(definition, options, replaying = false) {
|
|
|
2068
2243
|
emit({ ...state, errors, current: firstError, events });
|
|
2069
2244
|
return false;
|
|
2070
2245
|
}
|
|
2071
|
-
const { ending } =
|
|
2246
|
+
const { ending } = pathOf(state.values, state.hidden);
|
|
2072
2247
|
emit({ ...state, errors: {}, status: "completed", ending, events });
|
|
2073
2248
|
return true;
|
|
2074
2249
|
},
|
|
@@ -2100,10 +2275,11 @@ function build(definition, options, replaying = false) {
|
|
|
2100
2275
|
answer(event.field, event.value, logged);
|
|
2101
2276
|
}
|
|
2102
2277
|
} else if (event.type === "next") {
|
|
2103
|
-
settleNow();
|
|
2278
|
+
settleNow(false);
|
|
2279
|
+
if (formulasStale && isCalculated(fields.get(state.current ?? ""))) settleNow(true);
|
|
2104
2280
|
engine.next();
|
|
2105
2281
|
} else if (event.type === "back") {
|
|
2106
|
-
settleNow();
|
|
2282
|
+
settleNow(false);
|
|
2107
2283
|
engine.back();
|
|
2108
2284
|
} else if (event.type === "submit") {
|
|
2109
2285
|
settleNow();
|
|
@@ -2118,9 +2294,16 @@ function build(definition, options, replaying = false) {
|
|
|
2118
2294
|
return { engine, apply, finish };
|
|
2119
2295
|
}
|
|
2120
2296
|
function replay(definition, events, options = {}) {
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2297
|
+
return replayWithin(definition, events, options);
|
|
2298
|
+
}
|
|
2299
|
+
function replayWithin(definition, events, options, maxWork) {
|
|
2300
|
+
const budget = void 0 ;
|
|
2301
|
+
const { engine, apply, finish } = build(definition, { ...options, initialValues: void 0, clock: () => void 0 }, true, budget);
|
|
2302
|
+
try {
|
|
2303
|
+
for (const event of events) apply(event);
|
|
2304
|
+
finish();
|
|
2305
|
+
} finally {
|
|
2306
|
+
}
|
|
2124
2307
|
return engine;
|
|
2125
2308
|
}
|
|
2126
2309
|
|
|
@@ -2267,9 +2450,11 @@ exports.HIGHLIGHT_NOTE_MESSAGE = HIGHLIGHT_NOTE_MESSAGE;
|
|
|
2267
2450
|
exports.MAX_CALCULATED_DECIMALS = MAX_CALCULATED_DECIMALS;
|
|
2268
2451
|
exports.MAX_FORMULA_ITEMS = MAX_FORMULA_ITEMS;
|
|
2269
2452
|
exports.MAX_FORMULA_LENGTH = MAX_FORMULA_LENGTH;
|
|
2453
|
+
exports.MAX_FORM_FORMULA_LENGTH = MAX_FORM_FORMULA_LENGTH;
|
|
2270
2454
|
exports.MAX_HIDDEN_STRING_LENGTH = MAX_HIDDEN_STRING_LENGTH;
|
|
2271
2455
|
exports.MAX_HIGHLIGHT_NOTE_LENGTH = MAX_HIGHLIGHT_NOTE_LENGTH;
|
|
2272
2456
|
exports.MAX_HIGHLIGHT_QUOTE_LENGTH = MAX_HIGHLIGHT_QUOTE_LENGTH;
|
|
2457
|
+
exports.MAX_SETTLE_ITEMS = MAX_SETTLE_ITEMS;
|
|
2273
2458
|
exports.MAX_TABLE_CELL_LENGTH = MAX_TABLE_CELL_LENGTH;
|
|
2274
2459
|
exports.MAX_TABLE_COLUMNS = MAX_TABLE_COLUMNS;
|
|
2275
2460
|
exports.MAX_TIMESTAMP_SECONDS = MAX_TIMESTAMP_SECONDS;
|