bank20baht-ui 0.12.0 → 0.12.1
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/dist/components/baht-form.d.ts +2 -0
- package/dist/components/baht-form.js +34 -24
- package/dist/components/primitives/baht-repeater.d.ts +6 -1
- package/dist/components/primitives/baht-repeater.js +62 -55
- package/dist/core/engine/conditions.d.ts +21 -3
- package/dist/core/engine/conditions.js +62 -44
- package/dist/core/engine/evaluate.js +203 -111
- package/dist/core/index.d.ts +2 -1
- package/dist/core/validators.d.ts +7 -2
- package/dist/core/validators.js +82 -74
- package/dist/custom-elements.json +28 -0
- package/dist/engine.js +25 -23
- package/dist/index.js +169 -167
- package/dist/web-types.json +6 -1
- package/package.json +1 -1
|
@@ -88,6 +88,8 @@ export declare class BahtForm extends BahtElement {
|
|
|
88
88
|
private nextVisible;
|
|
89
89
|
private revealClass;
|
|
90
90
|
private stateFor;
|
|
91
|
+
/** The row sub-field states of one repeater: `fieldStates` keys starting `key[`. */
|
|
92
|
+
private rowStatesFor;
|
|
91
93
|
private valueFor;
|
|
92
94
|
/** Debounced keystrokes still in a control land in `edits` before anyone reads them. */
|
|
93
95
|
private flushTyped;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { nothing as g, html as p } from "lit";
|
|
2
|
-
import { property as d, state as m, customElement as
|
|
3
|
-
import { repeat as
|
|
2
|
+
import { property as d, state as m, customElement as E } from "lit/decorators.js";
|
|
3
|
+
import { repeat as P } from "lit/directives/repeat.js";
|
|
4
4
|
import { html as $ } from "lit/static-html.js";
|
|
5
|
-
import { BahtElement as
|
|
6
|
-
import { TAG_FOR_TYPE as
|
|
5
|
+
import { BahtElement as T, hasDom as O } from "./base.js";
|
|
6
|
+
import { TAG_FOR_TYPE as B, WIDTH_CLASS as I, staticTag as j } from "./primitives/tag-map.js";
|
|
7
7
|
import { defaultValue as C } from "../core/defaults.js";
|
|
8
8
|
import { t as D } from "../core/i18n.js";
|
|
9
9
|
import { validateField as _ } from "../core/validators.js";
|
|
10
10
|
import { resolveViewFields as M } from "../core/views.js";
|
|
11
|
-
import { applyFlags as
|
|
12
|
-
import { hasScripts as w, runScripts as F, createScriptContext as
|
|
13
|
-
import { displayValue as
|
|
11
|
+
import { applyFlags as L } from "../core/flags.js";
|
|
12
|
+
import { hasScripts as w, runScripts as F, createScriptContext as A, MAX_SCRIPT_DEPTH as x } from "../core/engine/scripts.js";
|
|
13
|
+
import { displayValue as R } from "../core/display.js";
|
|
14
14
|
import "./primitives/baht-input.js";
|
|
15
15
|
import "./primitives/baht-textarea.js";
|
|
16
16
|
import "./primitives/baht-number.js";
|
|
@@ -26,12 +26,12 @@ import "./primitives/baht-file.js";
|
|
|
26
26
|
import "./primitives/baht-text.js";
|
|
27
27
|
import "./primitives/baht-section.js";
|
|
28
28
|
import "./primitives/baht-repeater.js";
|
|
29
|
-
var
|
|
30
|
-
for (var r = i > 1 ? void 0 : i ?
|
|
29
|
+
var U = Object.defineProperty, W = Object.getOwnPropertyDescriptor, h = (t, s, e, i) => {
|
|
30
|
+
for (var r = i > 1 ? void 0 : i ? W(s, e) : s, o = t.length - 1, a; o >= 0; o--)
|
|
31
31
|
(a = t[o]) && (r = (i ? a(s, e, r) : a(r)) || r);
|
|
32
|
-
return i && r &&
|
|
32
|
+
return i && r && U(s, e, r), r;
|
|
33
33
|
};
|
|
34
|
-
let n = class extends
|
|
34
|
+
let n = class extends T {
|
|
35
35
|
constructor() {
|
|
36
36
|
super(...arguments), this.value = {}, this.registry = {}, this.showOptional = !1, this.options = {}, this.fieldStates = {}, this.flags = {}, this.readonly = !1, this.edits = {}, this.errors = [], this.scriptStates = {}, this.fieldMessages = {}, this.formMessages = [], this.scriptContext = null, this.scriptContextForm = null, this.scriptDepth = 0, this.loadedForm = null, this.dynamicOptions = /* @__PURE__ */ new Map(), this.optionsSnapshots = /* @__PURE__ */ new Map(), this.optionsEpoch = /* @__PURE__ */ new Map(), this.warnedViews = /* @__PURE__ */ new Set(), this.flagCache = {}, this.lastVisible = {}, this.nextVisible = {};
|
|
37
37
|
}
|
|
@@ -45,7 +45,7 @@ let n = class extends P {
|
|
|
45
45
|
get effectiveForm() {
|
|
46
46
|
const t = this.assignedForm;
|
|
47
47
|
if (t)
|
|
48
|
-
return (this.flagCache.form !== t || this.flagCache.flags !== this.flags) && (this.flagCache = { form: t, flags: this.flags, out:
|
|
48
|
+
return (this.flagCache.form !== t || this.flagCache.flags !== this.flags) && (this.flagCache = { form: t, flags: this.flags, out: L(t, this.flags) }), this.flagCache.out;
|
|
49
49
|
}
|
|
50
50
|
willUpdate(t) {
|
|
51
51
|
t.has("value") && (this.edits = {}), (t.has("form") || t.has("flags")) && (this.dynamicOptions.clear(), this.optionsSnapshots.clear(), this.optionsEpoch.clear()), t.has("form") && (this.scriptStates = {}, this.fieldMessages = {}, this.formMessages = [], this.scriptContext = null), (t.has("form") || t.has("flags") || t.has("value") || t.has("registry")) && this.syncDynamicOptions();
|
|
@@ -111,6 +111,13 @@ let n = class extends P {
|
|
|
111
111
|
}, e = this.scriptStates[t.key];
|
|
112
112
|
return e ? { ...s, ...e } : s;
|
|
113
113
|
}
|
|
114
|
+
/** The row sub-field states of one repeater: `fieldStates` keys starting `key[`. */
|
|
115
|
+
rowStatesFor(t) {
|
|
116
|
+
const s = `${t}[`, e = {};
|
|
117
|
+
for (const [i, r] of Object.entries(this.fieldStates))
|
|
118
|
+
i.startsWith(s) && (e[i] = r);
|
|
119
|
+
return e;
|
|
120
|
+
}
|
|
114
121
|
valueFor(t) {
|
|
115
122
|
return Object.hasOwn(this.edits, t.key) ? this.edits[t.key] : Object.hasOwn(this.value, t.key) ? this.value[t.key] : C(t);
|
|
116
123
|
}
|
|
@@ -149,7 +156,9 @@ let n = class extends P {
|
|
|
149
156
|
const i = this.stateFor(e);
|
|
150
157
|
if (!i.visible) continue;
|
|
151
158
|
const r = i.required === !!e.required ? e : { ...e, required: i.required };
|
|
152
|
-
t.push(
|
|
159
|
+
t.push(
|
|
160
|
+
..._(r, this.valueFor(e), this.registry, s, this.fieldStates)
|
|
161
|
+
);
|
|
153
162
|
}
|
|
154
163
|
return t;
|
|
155
164
|
}
|
|
@@ -183,7 +192,7 @@ let n = class extends P {
|
|
|
183
192
|
// ---- client scripts (spec 01 §14) ----
|
|
184
193
|
/** The `g` (g_form) for the current form — built lazily over this component's state. */
|
|
185
194
|
g(t) {
|
|
186
|
-
return this.scriptContext && this.scriptContextForm === t ? this.scriptContext : (this.scriptContextForm = t, this.scriptContext =
|
|
195
|
+
return this.scriptContext && this.scriptContextForm === t ? this.scriptContext : (this.scriptContextForm = t, this.scriptContext = A(t, {
|
|
187
196
|
getData: () => this.getData(),
|
|
188
197
|
setValue: (s, e) => {
|
|
189
198
|
this.applyScriptValue(s, e);
|
|
@@ -228,9 +237,9 @@ let n = class extends P {
|
|
|
228
237
|
runChangeScripts(t, s, e, i) {
|
|
229
238
|
const r = this.effectiveForm;
|
|
230
239
|
if (!(!r || !w(r, "change", t))) {
|
|
231
|
-
if (this.scriptDepth >=
|
|
240
|
+
if (this.scriptDepth >= x) {
|
|
232
241
|
console.warn(
|
|
233
|
-
`[bahtui] script cascade on "${r.form_name}.${t}" exceeded ${
|
|
242
|
+
`[bahtui] script cascade on "${r.form_name}.${t}" exceeded ${x} levels — stopped (setValue ping-pong between change scripts?)`
|
|
234
243
|
);
|
|
235
244
|
return;
|
|
236
245
|
}
|
|
@@ -295,7 +304,7 @@ let n = class extends P {
|
|
|
295
304
|
const s = this.stateFor(t);
|
|
296
305
|
if (!s.visible) return [];
|
|
297
306
|
const e = this.getData(), i = s.required === !!t.required ? t : { ...t, required: s.required };
|
|
298
|
-
return _(i, this.valueFor(t), this.registry, e);
|
|
307
|
+
return _(i, this.valueFor(t), this.registry, e, this.fieldStates);
|
|
299
308
|
}
|
|
300
309
|
/** `validateOn: 'blur'` — validate just the field the user left, same as
|
|
301
310
|
* how errors are shown elsewhere (merged into `this.errors`, painted by
|
|
@@ -307,18 +316,18 @@ let n = class extends P {
|
|
|
307
316
|
}
|
|
308
317
|
renderField(t) {
|
|
309
318
|
var S;
|
|
310
|
-
const s =
|
|
319
|
+
const s = B[t.type];
|
|
311
320
|
if (!s)
|
|
312
321
|
return console.warn(`[bahtui] unknown field type "${t.type}" — skipped`), g;
|
|
313
|
-
const e = this.stateFor(t), i =
|
|
322
|
+
const e = this.stateFor(t), i = I[t.width ?? "full"] ?? "baht-field--w-full", r = ((S = this.errors.find((u) => u.key === t.key)) == null ? void 0 : S.message) ?? null;
|
|
314
323
|
if (this.readonly && t.type !== "label" && t.type !== "section")
|
|
315
324
|
return this.renderReadonlyField(t, i, e.visible);
|
|
316
325
|
const o = t.options_from ? { ...t, options: this.dynamicOptions.get(t.key) ?? t.options ?? [] } : t, a = this.valueFor(t), l = !e.enabled, c = this.readonly || e.readonly, b = this.options.inputDebounce, v = (u) => {
|
|
317
326
|
this.onControlInput(t.key, u);
|
|
318
|
-
}, f =
|
|
327
|
+
}, f = j(s);
|
|
319
328
|
let y;
|
|
320
329
|
if (t.type === "repeater") {
|
|
321
|
-
const u = this.errors.filter((q) => q.key.startsWith(`${t.key}[`));
|
|
330
|
+
const u = this.errors.filter((q) => q.key.startsWith(`${t.key}[`)), V = this.rowStatesFor(t.key);
|
|
322
331
|
y = $`<${f}
|
|
323
332
|
.field=${o}
|
|
324
333
|
.value=${a}
|
|
@@ -329,6 +338,7 @@ let n = class extends P {
|
|
|
329
338
|
.error=${r}
|
|
330
339
|
.debounce=${b}
|
|
331
340
|
.rowErrors=${u}
|
|
341
|
+
.rowStates=${V}
|
|
332
342
|
@baht-input=${v}
|
|
333
343
|
></${f}>`;
|
|
334
344
|
} else if (t.type === "file") {
|
|
@@ -395,7 +405,7 @@ let n = class extends P {
|
|
|
395
405
|
e && this.onFieldInput(e, s);
|
|
396
406
|
}
|
|
397
407
|
renderReadonlyField(t, s, e) {
|
|
398
|
-
const i = t.options_from ? this.dynamicOptions.get(t.key) ?? t.options ?? [] : t.options, r =
|
|
408
|
+
const i = t.options_from ? this.dynamicOptions.get(t.key) ?? t.options ?? [] : t.options, r = R(t, this.valueFor(t), i), o = r.kind === "empty" ? p`<span class="baht-readonly-value baht-readonly-value--empty">${D("emptyValue")}</span>` : r.kind === "text" ? p`<span class="baht-readonly-value">${r.text}</span>` : r.kind === "chips" ? p`<span class="baht-readonly-value baht-readonly-chips"
|
|
399
409
|
>${r.items.map((a) => p`<span class="baht-readonly-chip">${a}</span>`)}</span
|
|
400
410
|
>` : p`<div class="baht-readonly-rows">
|
|
401
411
|
${r.rows.map(
|
|
@@ -431,7 +441,7 @@ let n = class extends P {
|
|
|
431
441
|
</div>`
|
|
432
442
|
)}
|
|
433
443
|
</div>` : g}
|
|
434
|
-
${
|
|
444
|
+
${P(
|
|
435
445
|
this.sortedFields,
|
|
436
446
|
(t) => t.key,
|
|
437
447
|
(t) => this.renderField(t)
|
|
@@ -482,7 +492,7 @@ h([
|
|
|
482
492
|
m()
|
|
483
493
|
], n.prototype, "formMessages", 2);
|
|
484
494
|
n = h([
|
|
485
|
-
|
|
495
|
+
E("baht-form")
|
|
486
496
|
], n);
|
|
487
497
|
export {
|
|
488
498
|
n as BahtForm
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TemplateResult } from 'lit';
|
|
2
2
|
import { BahtFieldBase } from '../field-base.js';
|
|
3
|
-
import { ValidationError } from '../../core/types.js';
|
|
3
|
+
import { DerivedFieldState, ValidationError } from '../../core/types.js';
|
|
4
4
|
/**
|
|
5
5
|
* <baht-repeater> — array-of-rows control (spec 01 §10). `value` is an array
|
|
6
6
|
* of row objects; every row renders the same `field.fields` sub-descriptors
|
|
@@ -10,6 +10,11 @@ import { ValidationError } from '../../core/types.js';
|
|
|
10
10
|
export declare class BahtRepeater extends BahtFieldBase {
|
|
11
11
|
/** Row-scoped errors from the host form, keyed `key[i].subKey`. */
|
|
12
12
|
rowErrors: ValidationError[];
|
|
13
|
+
/**
|
|
14
|
+
* Rule-derived states of the row sub-fields, keyed `key[i].sub` (spec 02
|
|
15
|
+
* §2a). Absent = every sub-field visible with its descriptor defaults.
|
|
16
|
+
*/
|
|
17
|
+
rowStates: Record<string, DerivedFieldState>;
|
|
13
18
|
private get rows();
|
|
14
19
|
private subFieldsSource;
|
|
15
20
|
private subFieldsCache;
|
|
@@ -1,86 +1,90 @@
|
|
|
1
1
|
import { nothing as d, html as l } from "lit";
|
|
2
|
-
import { property as
|
|
3
|
-
import { repeat as
|
|
4
|
-
import { html as
|
|
5
|
-
import { hasDom as
|
|
6
|
-
import { BahtFieldBase as
|
|
7
|
-
import { TAG_FOR_TYPE as
|
|
8
|
-
import { defaultValue as
|
|
2
|
+
import { property as b, customElement as w } from "lit/decorators.js";
|
|
3
|
+
import { repeat as c } from "lit/directives/repeat.js";
|
|
4
|
+
import { html as v } from "lit/static-html.js";
|
|
5
|
+
import { hasDom as _ } from "../base.js";
|
|
6
|
+
import { BahtFieldBase as F } from "../field-base.js";
|
|
7
|
+
import { TAG_FOR_TYPE as g, staticTag as R, WIDTH_CLASS as S } from "./tag-map.js";
|
|
8
|
+
import { defaultValue as f } from "../../core/defaults.js";
|
|
9
9
|
import { t as h } from "../../core/i18n.js";
|
|
10
|
-
var
|
|
11
|
-
for (var s = o > 1 ? void 0 : o ? T(e,
|
|
12
|
-
(
|
|
13
|
-
return o && s &&
|
|
10
|
+
var k = Object.defineProperty, T = Object.getOwnPropertyDescriptor, p = (r, e, t, o) => {
|
|
11
|
+
for (var s = o > 1 ? void 0 : o ? T(e, t) : e, a = r.length - 1, i; a >= 0; a--)
|
|
12
|
+
(i = r[a]) && (s = (o ? i(e, t, s) : i(s)) || s);
|
|
13
|
+
return o && s && k(e, t, s), s;
|
|
14
14
|
};
|
|
15
|
-
let n = class extends
|
|
15
|
+
let n = class extends F {
|
|
16
16
|
constructor() {
|
|
17
|
-
super(...arguments), this.rowErrors = [], this.subFieldsCache = [];
|
|
17
|
+
super(...arguments), this.rowErrors = [], this.rowStates = {}, this.subFieldsCache = [];
|
|
18
18
|
}
|
|
19
19
|
get rows() {
|
|
20
20
|
return Array.isArray(this.value) ? this.value : [];
|
|
21
21
|
}
|
|
22
22
|
/** Ordered sub-descriptors, cached per identity (read per row per render). */
|
|
23
23
|
get subFields() {
|
|
24
|
-
const
|
|
25
|
-
return
|
|
24
|
+
const r = this.field.fields;
|
|
25
|
+
return r !== this.subFieldsSource && (this.subFieldsSource = r, this.subFieldsCache = [...r ?? []].sort((e, t) => e.order - t.order).filter((e) => e.type !== "repeater")), this.subFieldsCache;
|
|
26
26
|
}
|
|
27
|
-
patchRow(
|
|
27
|
+
patchRow(r, e, t) {
|
|
28
28
|
const o = [...this.rows];
|
|
29
|
-
o[
|
|
29
|
+
o[r] = { ...o[r], [e]: t }, this.emitInput(o);
|
|
30
30
|
}
|
|
31
31
|
addRow() {
|
|
32
|
-
const
|
|
32
|
+
const r = {};
|
|
33
33
|
for (const e of this.subFields)
|
|
34
|
-
e.type === "label" || e.type === "section" || (
|
|
35
|
-
this.emitInput([...this.rows,
|
|
34
|
+
e.type === "label" || e.type === "section" || (r[e.key] = f(e));
|
|
35
|
+
this.emitInput([...this.rows, r]);
|
|
36
36
|
}
|
|
37
|
-
removeRow(
|
|
38
|
-
this.emitInput(this.rows.filter((e,
|
|
37
|
+
removeRow(r) {
|
|
38
|
+
this.emitInput(this.rows.filter((e, t) => t !== r));
|
|
39
39
|
}
|
|
40
40
|
/** Pending keystrokes in any row land in the array before the host reads it. */
|
|
41
41
|
flushTyped() {
|
|
42
|
-
var
|
|
43
|
-
if (!
|
|
42
|
+
var r;
|
|
43
|
+
if (!_()) {
|
|
44
44
|
super.flushTyped();
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
for (const e of this.querySelectorAll(".baht-repeater-row > .baht-field > *"))
|
|
48
|
-
(
|
|
48
|
+
(r = e.flushTyped) == null || r.call(e);
|
|
49
49
|
super.flushTyped();
|
|
50
50
|
}
|
|
51
|
-
errorFor(
|
|
51
|
+
errorFor(r, e) {
|
|
52
52
|
var o;
|
|
53
|
-
const
|
|
54
|
-
return ((o = this.rowErrors.find((s) => s.key ===
|
|
53
|
+
const t = `${this.field.key}[${r}].${e}`;
|
|
54
|
+
return ((o = this.rowErrors.find((s) => s.key === t)) == null ? void 0 : o.message) ?? null;
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
57
57
|
* Sub-controls render declaratively (one static-tag template per primitive, rows
|
|
58
58
|
* keyed by index) so Lit reuses the same node across re-renders — typing keeps
|
|
59
59
|
* focus, same as <baht-form> — and the whole thing renders on the server.
|
|
60
60
|
*/
|
|
61
|
-
renderSub(
|
|
62
|
-
const o =
|
|
61
|
+
renderSub(r, e, t) {
|
|
62
|
+
const o = g[t.type];
|
|
63
63
|
if (!o) return d;
|
|
64
|
-
const s =
|
|
65
|
-
|
|
66
|
-
const { value:
|
|
67
|
-
this.patchRow(e,
|
|
68
|
-
};
|
|
69
|
-
return l`<div
|
|
70
|
-
${
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
.
|
|
76
|
-
.
|
|
64
|
+
const s = R(o), a = S[t.width ?? "full"] ?? "baht-field--w-full", i = this.rowStates[`${this.field.key}[${e}].${t.key}`], y = (u) => {
|
|
65
|
+
u.stopPropagation();
|
|
66
|
+
const { value: m } = u.detail;
|
|
67
|
+
this.patchRow(e, t.key, m);
|
|
68
|
+
}, $ = i !== void 0 && !i.visible;
|
|
69
|
+
return l`<div
|
|
70
|
+
class="baht-field ${a}${$ ? " baht-field--hidden" : ""}"
|
|
71
|
+
data-key=${t.key}
|
|
72
|
+
data-type=${t.type}
|
|
73
|
+
>
|
|
74
|
+
${v`<${s}
|
|
75
|
+
.field=${t}
|
|
76
|
+
.value=${Object.hasOwn(r, t.key) ? r[t.key] : f(t)}
|
|
77
|
+
.disabled=${this.disabled || i !== void 0 && !i.enabled}
|
|
78
|
+
.readonly=${this.readonly || ((i == null ? void 0 : i.readonly) ?? !1)}
|
|
79
|
+
.required=${i ? i.required : !!t.required}
|
|
80
|
+
.error=${this.errorFor(e, t.key)}
|
|
77
81
|
.debounce=${this.debounce}
|
|
78
|
-
@baht-input=${
|
|
82
|
+
@baht-input=${y}
|
|
79
83
|
></${s}>`}
|
|
80
84
|
</div>`;
|
|
81
85
|
}
|
|
82
86
|
renderControl() {
|
|
83
|
-
const
|
|
87
|
+
const r = this.rows, e = !this.disabled && !this.readonly, t = this.field.max_rows !== void 0 && r.length >= this.field.max_rows;
|
|
84
88
|
return l`<div
|
|
85
89
|
class="baht-repeater"
|
|
86
90
|
id=${this.controlId}
|
|
@@ -88,8 +92,8 @@ let n = class extends v {
|
|
|
88
92
|
aria-labelledby=${this.field.label ? this.labelId : d}
|
|
89
93
|
aria-describedby=${this.describedBy}
|
|
90
94
|
>
|
|
91
|
-
${
|
|
92
|
-
|
|
95
|
+
${c(
|
|
96
|
+
r,
|
|
93
97
|
(o, s) => s,
|
|
94
98
|
(o, s) => l`<div
|
|
95
99
|
class="baht-repeater-row"
|
|
@@ -97,10 +101,10 @@ let n = class extends v {
|
|
|
97
101
|
role="group"
|
|
98
102
|
aria-label=${h("row", { n: s + 1 })}
|
|
99
103
|
>
|
|
100
|
-
${
|
|
104
|
+
${c(
|
|
101
105
|
this.subFields,
|
|
102
|
-
(
|
|
103
|
-
(
|
|
106
|
+
(a) => a.key,
|
|
107
|
+
(a) => this.renderSub(o, s, a)
|
|
104
108
|
)}
|
|
105
109
|
${e ? l`<button
|
|
106
110
|
type="button"
|
|
@@ -118,7 +122,7 @@ let n = class extends v {
|
|
|
118
122
|
${this.readonly ? d : l`<button
|
|
119
123
|
type="button"
|
|
120
124
|
class="baht-repeater-add"
|
|
121
|
-
?disabled=${this.disabled ||
|
|
125
|
+
?disabled=${this.disabled || t}
|
|
122
126
|
@click=${() => {
|
|
123
127
|
this.addRow();
|
|
124
128
|
}}
|
|
@@ -128,11 +132,14 @@ let n = class extends v {
|
|
|
128
132
|
</div>`;
|
|
129
133
|
}
|
|
130
134
|
};
|
|
131
|
-
|
|
132
|
-
|
|
135
|
+
p([
|
|
136
|
+
b({ attribute: !1 })
|
|
133
137
|
], n.prototype, "rowErrors", 2);
|
|
134
|
-
|
|
135
|
-
|
|
138
|
+
p([
|
|
139
|
+
b({ attribute: !1 })
|
|
140
|
+
], n.prototype, "rowStates", 2);
|
|
141
|
+
n = p([
|
|
142
|
+
w("baht-repeater")
|
|
136
143
|
], n);
|
|
137
144
|
export {
|
|
138
145
|
n as BahtRepeater
|
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
import { Condition, NestedData } from '../types.js';
|
|
2
|
-
/**
|
|
3
|
-
export
|
|
2
|
+
/** The repeater row a rule is being evaluated for (spec 02 §2a). */
|
|
3
|
+
export interface RowScope {
|
|
4
|
+
form: string;
|
|
5
|
+
repeater: string;
|
|
6
|
+
index: number;
|
|
7
|
+
}
|
|
8
|
+
export interface RowRef {
|
|
9
|
+
form: string;
|
|
10
|
+
repeater: string;
|
|
11
|
+
sub: string;
|
|
12
|
+
}
|
|
13
|
+
/** Split a row-scoped ref, or `null` when it is a plain `Form.key` reference. */
|
|
14
|
+
export declare function parseRowRef(ref: string): RowRef | null;
|
|
15
|
+
/**
|
|
16
|
+
* Read a "formName.fieldKey" reference out of nested data. With a `scope`, a
|
|
17
|
+
* row-scoped ref (`Form.repeater[].sub`) reads that sub-field of the scoped row.
|
|
18
|
+
*/
|
|
19
|
+
export declare function readRef(data: NestedData, ref: string, scope?: RowScope): unknown;
|
|
4
20
|
/**
|
|
5
21
|
* Ordering used by rule conditions AND the `compare` validator: numeric when
|
|
6
22
|
* both sides coerce, date-aware, else lexicographic. Null = not comparable.
|
|
7
23
|
*/
|
|
8
24
|
export declare function compareValues(a: unknown, b: unknown): number | null;
|
|
9
|
-
export declare function evalCondition(cond: Condition | undefined, data: NestedData): boolean;
|
|
25
|
+
export declare function evalCondition(cond: Condition | undefined, data: NestedData, scope?: RowScope): boolean;
|
|
26
|
+
/** Every row-scoped ref a condition mentions (`field` and `value_field`). */
|
|
27
|
+
export declare function conditionRowRefs(cond: Condition | undefined): RowRef[];
|
|
@@ -1,69 +1,87 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
return (t = e[n.slice(0, r)]) == null ? void 0 : t[n.slice(r + 1)];
|
|
1
|
+
const g = /^([^.[\]]+)\.([^.[\]]+)\[\]\.([^.[\]]+)$/;
|
|
2
|
+
function l(r) {
|
|
3
|
+
const t = g.exec(r);
|
|
4
|
+
return t ? { form: t[1], repeater: t[2], sub: t[3] } : null;
|
|
6
5
|
}
|
|
7
|
-
function
|
|
8
|
-
|
|
6
|
+
function y(r, t, n) {
|
|
7
|
+
var u, c;
|
|
8
|
+
const e = l(t);
|
|
9
|
+
if (e) {
|
|
10
|
+
if ((n == null ? void 0 : n.form) !== e.form || n.repeater !== e.repeater) return;
|
|
11
|
+
const m = (u = r[e.form]) == null ? void 0 : u[e.repeater], s = Array.isArray(m) ? m[n.index] : void 0;
|
|
12
|
+
return s !== null && typeof s == "object" && Object.hasOwn(s, e.sub) ? s[e.sub] : void 0;
|
|
13
|
+
}
|
|
14
|
+
const i = t.indexOf(".");
|
|
15
|
+
if (i !== -1)
|
|
16
|
+
return (c = r[t.slice(0, i)]) == null ? void 0 : c[t.slice(i + 1)];
|
|
17
|
+
}
|
|
18
|
+
function N(r) {
|
|
19
|
+
return r == null ? !0 : typeof r == "string" ? r === "" : Array.isArray(r) ? r.length === 0 : !1;
|
|
9
20
|
}
|
|
10
|
-
function
|
|
11
|
-
const
|
|
12
|
-
return Number.isNaN(
|
|
21
|
+
function p(r, t) {
|
|
22
|
+
const n = new Date(r).getTime(), e = new Date(t).getTime();
|
|
23
|
+
return Number.isNaN(n) || Number.isNaN(e) ? null : n - e;
|
|
13
24
|
}
|
|
14
|
-
function
|
|
15
|
-
const
|
|
16
|
-
return
|
|
25
|
+
function A(r, t) {
|
|
26
|
+
const n = Number(r), e = Number(t);
|
|
27
|
+
return r !== "" && t !== "" && !Number.isNaN(n) && !Number.isNaN(e) ? n - e : r < t ? -1 : r > t ? 1 : 0;
|
|
17
28
|
}
|
|
18
|
-
function
|
|
19
|
-
if (typeof
|
|
20
|
-
if (
|
|
21
|
-
if (typeof
|
|
22
|
-
const
|
|
23
|
-
return Number.isNaN(
|
|
29
|
+
function b(r, t) {
|
|
30
|
+
if (typeof r == "number" && typeof t == "number") return r - t;
|
|
31
|
+
if (r instanceof Date || t instanceof Date) return p(r, t);
|
|
32
|
+
if (typeof r == "string" && typeof t == "string") return A(r, t);
|
|
33
|
+
const n = Number(r), e = Number(t);
|
|
34
|
+
return Number.isNaN(n) || Number.isNaN(e) ? null : n - e;
|
|
24
35
|
}
|
|
25
|
-
function
|
|
26
|
-
const
|
|
27
|
-
return
|
|
36
|
+
function f(r, t, n) {
|
|
37
|
+
const e = b(r, t);
|
|
38
|
+
return e !== null && n(e);
|
|
28
39
|
}
|
|
29
|
-
function
|
|
30
|
-
const
|
|
31
|
-
switch (
|
|
40
|
+
function v(r, t, n) {
|
|
41
|
+
const e = y(t, r.field, n), i = r.value_field !== void 0 ? y(t, r.value_field, n) : r.value;
|
|
42
|
+
switch (r.op) {
|
|
32
43
|
case "eq":
|
|
33
|
-
return
|
|
44
|
+
return e === i;
|
|
34
45
|
case "ne":
|
|
35
|
-
return
|
|
46
|
+
return e !== i;
|
|
36
47
|
case "gt":
|
|
37
|
-
return
|
|
48
|
+
return f(e, i, (u) => u > 0);
|
|
38
49
|
case "gte":
|
|
39
|
-
return
|
|
50
|
+
return f(e, i, (u) => u >= 0);
|
|
40
51
|
case "lt":
|
|
41
|
-
return
|
|
52
|
+
return f(e, i, (u) => u < 0);
|
|
42
53
|
case "lte":
|
|
43
|
-
return
|
|
54
|
+
return f(e, i, (u) => u <= 0);
|
|
44
55
|
case "in":
|
|
45
|
-
return Array.isArray(
|
|
56
|
+
return Array.isArray(i) && i.includes(e);
|
|
46
57
|
case "notIn":
|
|
47
|
-
return Array.isArray(
|
|
58
|
+
return Array.isArray(i) && !i.includes(e);
|
|
48
59
|
case "contains":
|
|
49
|
-
return Array.isArray(
|
|
60
|
+
return Array.isArray(e) ? e.includes(i) : typeof e == "string" && e.includes(String(i));
|
|
50
61
|
case "notContains":
|
|
51
|
-
return Array.isArray(
|
|
62
|
+
return Array.isArray(e) ? !e.includes(i) : typeof e == "string" && !e.includes(String(i));
|
|
52
63
|
case "startsWith":
|
|
53
|
-
return typeof
|
|
64
|
+
return typeof e == "string" && e.startsWith(String(i));
|
|
54
65
|
case "endsWith":
|
|
55
|
-
return typeof
|
|
66
|
+
return typeof e == "string" && e.endsWith(String(i));
|
|
56
67
|
case "isEmpty":
|
|
57
|
-
return
|
|
68
|
+
return N(e);
|
|
58
69
|
case "isNotEmpty":
|
|
59
|
-
return !
|
|
70
|
+
return !N(e);
|
|
60
71
|
}
|
|
61
72
|
}
|
|
62
|
-
function
|
|
63
|
-
return
|
|
73
|
+
function a(r, t, n) {
|
|
74
|
+
return r === void 0 ? !0 : "and" in r ? r.and.every((e) => a(e, t, n)) : "or" in r ? r.or.some((e) => a(e, t, n)) : "not" in r ? !a(r.not, t, n) : v(r, t, n);
|
|
75
|
+
}
|
|
76
|
+
function o(r) {
|
|
77
|
+
return r === void 0 ? [] : "and" in r ? r.and.flatMap(o) : "or" in r ? r.or.flatMap(o) : "not" in r ? o(r.not) : [l(r.field), r.value_field ? l(r.value_field) : null].filter(
|
|
78
|
+
(t) => t !== null
|
|
79
|
+
);
|
|
64
80
|
}
|
|
65
81
|
export {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
a as
|
|
82
|
+
b as compareValues,
|
|
83
|
+
o as conditionRowRefs,
|
|
84
|
+
a as evalCondition,
|
|
85
|
+
l as parseRowRef,
|
|
86
|
+
y as readRef
|
|
69
87
|
};
|