bank20baht-ui 0.0.10 → 0.1.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 +19 -0
- package/dist/components/baht-form.d.ts +8 -0
- package/dist/components/baht-workflow.d.ts +5 -1
- package/dist/components/base.d.ts +6 -0
- package/dist/components/primitives/baht-accordion.d.ts +4 -0
- package/dist/components/primitives/baht-alert.d.ts +2 -1
- package/dist/components/primitives/baht-file.d.ts +16 -1
- package/dist/components/primitives/baht-otp.d.ts +24 -3
- package/dist/components/primitives/baht-steps.d.ts +20 -0
- package/dist/components/primitives/index.d.ts +1 -0
- package/dist/core/engine/graph.d.ts +15 -0
- package/dist/core/i18n.d.ts +16 -0
- package/dist/core/index.d.ts +2 -1
- package/dist/core/types.d.ts +36 -0
- package/dist/custom-elements.json +504 -22
- package/dist/engine.js +332 -219
- package/dist/index.js +1248 -762
- package/dist/overlay.js +12 -13
- package/dist/react.d.ts +5 -0
- package/dist/tokens.css +51 -0
- package/dist/vscode.html-custom-data.json +21 -5
- package/dist/web-types.json +49 -11
- package/package.json +15 -11
- package/dist/chunks/baht-toast-1frNyH2A.js +0 -325
package/README.md
CHANGED
|
@@ -108,6 +108,25 @@ block), nothing in the payload. Missing keys count as off, so new features stay
|
|
|
108
108
|
the file turns them on. Server side: `validateSubmission(applyFlags(schema, flags), data)`
|
|
109
109
|
with the same JSON — `bank20baht-validator` re-exports `applyFlags`.
|
|
110
110
|
|
|
111
|
+
### File upload
|
|
112
|
+
|
|
113
|
+
```js
|
|
114
|
+
// schema:
|
|
115
|
+
{ order: 6, type: 'file', key: 'doc', uploader: 'default', accept: '.pdf,image/*', maxSize: 10_485_760 }
|
|
116
|
+
|
|
117
|
+
// registry — File in, serializable ref out:
|
|
118
|
+
el.registry = {
|
|
119
|
+
uploaders: { default: async (file) => {
|
|
120
|
+
const fd = new FormData(); fd.append('file', file);
|
|
121
|
+
return (await fetch('/api/uploads', { method: 'POST', body: fd })).json();
|
|
122
|
+
} },
|
|
123
|
+
};
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Picking a file uploads immediately; the value becomes `{ name, size, type, url }` — plain
|
|
127
|
+
JSON, chips with remove buttons in the UI, `maxSize`/`accept` validated on both client and
|
|
128
|
+
server. Omit `uploader` for the old capture-only mode.
|
|
129
|
+
|
|
111
130
|
### Drafts / autosave (host pattern)
|
|
112
131
|
|
|
113
132
|
The library is controlled — autosave is three lines in your app:
|
|
@@ -41,6 +41,8 @@ export declare class BahtForm extends BahtElement {
|
|
|
41
41
|
private dynamicOptions;
|
|
42
42
|
private optionsSnapshots;
|
|
43
43
|
private optionsEpoch;
|
|
44
|
+
/** Unknown `view` values already warned about — avoid re-warning on every render. */
|
|
45
|
+
private warnedViews;
|
|
44
46
|
/** applyFlags result, memoized on (form, flags) identity. */
|
|
45
47
|
private flagCache;
|
|
46
48
|
private get effectiveForm();
|
|
@@ -68,6 +70,12 @@ export declare class BahtForm extends BahtElement {
|
|
|
68
70
|
};
|
|
69
71
|
reset(): void;
|
|
70
72
|
private onFieldInput;
|
|
73
|
+
/** Validate a single field against current form data (siblings included). */
|
|
74
|
+
private validateOneField;
|
|
75
|
+
/** `validateOn: 'blur'` — validate just the field the user left, same as
|
|
76
|
+
* how errors are shown elsewhere (merged into `this.errors`, painted by
|
|
77
|
+
* `renderField`/`.baht-error`). No-op for 'change'/'submit' modes. */
|
|
78
|
+
private onFieldBlur;
|
|
71
79
|
private renderField;
|
|
72
80
|
protected render(): TemplateResult;
|
|
73
81
|
}
|
|
@@ -23,6 +23,8 @@ export declare class BahtWorkflow extends BahtElement {
|
|
|
23
23
|
showBack: boolean;
|
|
24
24
|
/** Feature-flag values (spec 01 §12): flag-off steps/fields/rules vanish. */
|
|
25
25
|
flags: FeatureFlags;
|
|
26
|
+
/** Render a <baht-steps> progress indicator above the current form. */
|
|
27
|
+
showSteps: boolean;
|
|
26
28
|
private data;
|
|
27
29
|
private derived;
|
|
28
30
|
private current;
|
|
@@ -37,6 +39,8 @@ export declare class BahtWorkflow extends BahtElement {
|
|
|
37
39
|
/** Forms in ascending order whose derived visibility is true. */
|
|
38
40
|
private get visibleForms();
|
|
39
41
|
private get currentForm();
|
|
42
|
+
/** Where next() would go from here: a formName or 'end' (spec 03 §6). */
|
|
43
|
+
private get navTarget();
|
|
40
44
|
private get isLast();
|
|
41
45
|
private fieldStatesFor;
|
|
42
46
|
private get formEl();
|
|
@@ -48,7 +52,7 @@ export declare class BahtWorkflow extends BahtElement {
|
|
|
48
52
|
*/
|
|
49
53
|
setValue(formName: string, patch: Record<string, unknown>): void;
|
|
50
54
|
next(): void;
|
|
51
|
-
/** Advance past the current form: submit+complete
|
|
55
|
+
/** Advance past the current form: submit+complete at 'end', else step to navTarget. */
|
|
52
56
|
private advance;
|
|
53
57
|
/** Approve the current approval step (same as pressing its Approve button). */
|
|
54
58
|
approve(): void;
|
|
@@ -16,6 +16,12 @@ export declare function adoptLightChildren(host: HTMLElement, slot: HTMLElement)
|
|
|
16
16
|
* Dumb and controlled — never mutates its own `value` prop; the host re-feeds it.
|
|
17
17
|
*/
|
|
18
18
|
export declare abstract class BahtFieldBase extends BahtElement {
|
|
19
|
+
/**
|
|
20
|
+
* Per-instance suffix for controlId: the same field key renders once per
|
|
21
|
+
* repeater row (and can repeat across forms on one page), so key-only ids
|
|
22
|
+
* collide — worst for radios, whose shared native `name` merges groups.
|
|
23
|
+
*/
|
|
24
|
+
private readonly uid;
|
|
19
25
|
field: FieldDescriptor;
|
|
20
26
|
value: unknown;
|
|
21
27
|
disabled: boolean;
|
|
@@ -20,6 +20,10 @@ export declare class BahtAccordion extends BahtElement {
|
|
|
20
20
|
private openSet;
|
|
21
21
|
private static instances;
|
|
22
22
|
private uid;
|
|
23
|
+
/** Fingerprint of the panel content — identity-independent, so an equal
|
|
24
|
+
* re-fed array doesn't look like a "new" set of items. */
|
|
25
|
+
private itemsFingerprint;
|
|
26
|
+
private static fingerprint;
|
|
23
27
|
protected willUpdate(changed: Map<PropertyKey, unknown>): void;
|
|
24
28
|
toggle(index: number): void;
|
|
25
29
|
protected render(): TemplateResult;
|
|
@@ -11,7 +11,8 @@ export declare class BahtAlert extends BahtElement {
|
|
|
11
11
|
heading: string;
|
|
12
12
|
message: string;
|
|
13
13
|
dismissible: boolean;
|
|
14
|
-
|
|
14
|
+
private dismissed;
|
|
15
|
+
protected willUpdate(changed: Map<PropertyKey, unknown>): void;
|
|
15
16
|
private dismiss;
|
|
16
17
|
protected render(): TemplateResult | typeof nothing;
|
|
17
18
|
}
|
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
import { TemplateResult } from 'lit';
|
|
2
2
|
import { BahtFieldBase } from '../base.js';
|
|
3
|
+
import { UploadedFile } from '../../core/types.js';
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
+
* File field (spec 01 §2 + §13). Two modes:
|
|
6
|
+
* - capture (default): value = File handle(s); the lib never uploads.
|
|
7
|
+
* - upload (`field.uploader` + host `uploader` fn from the registry):
|
|
8
|
+
* picking uploads immediately, value becomes serializable UploadedFile
|
|
9
|
+
* ref(s), and the control shows chips with remove buttons.
|
|
5
10
|
* maxSize (bytes) is enforced here as a soft filter — oversize files rejected.
|
|
6
11
|
*/
|
|
7
12
|
export declare class BahtFile extends BahtFieldBase {
|
|
13
|
+
/** Resolved registry uploader — <baht-form> injects it when `field.uploader` is set. */
|
|
14
|
+
uploader?: (file: File) => Promise<UploadedFile>;
|
|
15
|
+
private uploadingCount;
|
|
16
|
+
private uploadError;
|
|
17
|
+
/** Names of files the last pick rejected for being over `field.maxSize`. */
|
|
18
|
+
private rejectedNames;
|
|
19
|
+
private get refs();
|
|
20
|
+
private emitRefs;
|
|
21
|
+
private uploadAll;
|
|
22
|
+
private onPick;
|
|
8
23
|
protected renderControl(): TemplateResult;
|
|
9
24
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { TemplateResult } from 'lit';
|
|
1
|
+
import { PropertyValues, TemplateResult } from 'lit';
|
|
2
2
|
import { BahtElement } from '../base.js';
|
|
3
3
|
/**
|
|
4
4
|
* One-time-code input: N boxes, auto-advance, backspace steps back, paste
|
|
5
|
-
* distributes. Emits `baht-change { value }` per edit and `baht-complete { value }`
|
|
5
|
+
* distributes. Emits `baht-change { value }` per edit and `baht-otp-complete { value }`
|
|
6
6
|
* when every box is filled.
|
|
7
7
|
*
|
|
8
8
|
* <baht-otp length="6"></baht-otp>
|
|
@@ -15,9 +15,30 @@ export declare class BahtOtp extends BahtElement {
|
|
|
15
15
|
mode: 'numeric' | 'text';
|
|
16
16
|
/** Accessible name for the group of boxes. */
|
|
17
17
|
label: string;
|
|
18
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Per-box state, index-aligned; '' marks an empty box. This is the source
|
|
20
|
+
* of truth for rendering so that clearing box N never shifts box N+1's
|
|
21
|
+
* character into its place. `value` stays a derived, compacted (gap-free)
|
|
22
|
+
* string — the existing external contract (docs: a plain "controlled"
|
|
23
|
+
* string of the digits typed so far, in order).
|
|
24
|
+
*/
|
|
25
|
+
private _chars;
|
|
26
|
+
/**
|
|
27
|
+
* The compacted string `_chars` currently represents. Lets willUpdate tell
|
|
28
|
+
* an external `el.value = …` write (e.g. the docs' reset-on-failure
|
|
29
|
+
* example) apart from `commit()` echoing its own assignment, without a
|
|
30
|
+
* boolean flag that could get stuck across a no-op property set.
|
|
31
|
+
*/
|
|
32
|
+
private _lastValue;
|
|
33
|
+
/** Previous "every box filled" state, so `baht-otp-complete` fires only on the
|
|
34
|
+
* not-full → full transition, not on every edit while already full. */
|
|
35
|
+
private _wasFull;
|
|
19
36
|
private inputs;
|
|
20
37
|
private clean;
|
|
38
|
+
protected willUpdate(changed: PropertyValues<this>): void;
|
|
39
|
+
/** Writes `text` into `_chars` starting at `start`. Returns the index just
|
|
40
|
+
* past the last box written (may equal `this.length`). */
|
|
41
|
+
private fill;
|
|
21
42
|
private commit;
|
|
22
43
|
private onInput;
|
|
23
44
|
private onKeydown;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { TemplateResult } from 'lit';
|
|
2
|
+
import { BahtElement } from '../base.js';
|
|
3
|
+
/**
|
|
4
|
+
* <baht-steps> — wizard progress indicator (spec 03). Standalone display
|
|
5
|
+
* primitive: numbered markers + labels, the current one highlighted, done
|
|
6
|
+
* ones checked. <baht-workflow show-steps> renders it automatically from its
|
|
7
|
+
* visible forms.
|
|
8
|
+
*/
|
|
9
|
+
export declare class BahtSteps extends BahtElement {
|
|
10
|
+
/** Step labels in order. */
|
|
11
|
+
steps: string[];
|
|
12
|
+
/** 0-based index of the current step. */
|
|
13
|
+
current: number;
|
|
14
|
+
protected render(): TemplateResult;
|
|
15
|
+
}
|
|
16
|
+
declare global {
|
|
17
|
+
interface HTMLElementTagNameMap {
|
|
18
|
+
'baht-steps': BahtSteps;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -42,4 +42,5 @@ export { BahtErrorState } from './baht-error-state.js';
|
|
|
42
42
|
export { BahtKeyvalueEditor } from './baht-keyvalue-editor.js';
|
|
43
43
|
export { BahtReferencePicker, type ReferenceOption } from './baht-reference-picker.js';
|
|
44
44
|
export { BahtRepeater } from './baht-repeater.js';
|
|
45
|
+
export { BahtSteps } from './baht-steps.js';
|
|
45
46
|
export { TAG_FOR_TYPE } from './tag-map.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { NestedData, WorkflowDefinition } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The step after `current` given the data: a formName or 'end'. Rules run
|
|
4
|
+
* (via evaluate) to decide visibility; hidden targets pass through, cycles
|
|
5
|
+
* of invisible forms end the walk. `visibility` lets a caller that already
|
|
6
|
+
* ran the rules (walkPath — data never changes during a walk) skip the
|
|
7
|
+
* per-hop evaluate() fixpoint.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveNext(workflow: WorkflowDefinition, current: string, data: NestedData, visibility?: ReadonlySet<string>): string | 'end';
|
|
10
|
+
/**
|
|
11
|
+
* The full path a submission takes from the start form to 'end' under this
|
|
12
|
+
* data — what the server validates against (off-path forms are as good as
|
|
13
|
+
* skipped). Back-edges that revisit a form stop the walk instead of looping.
|
|
14
|
+
*/
|
|
15
|
+
export declare function walkPath(workflow: WorkflowDefinition, data: NestedData): string[];
|
package/dist/core/i18n.d.ts
CHANGED
|
@@ -12,6 +12,12 @@ export interface MessageCatalog {
|
|
|
12
12
|
compareGte: string;
|
|
13
13
|
compareLt: string;
|
|
14
14
|
compareLte: string;
|
|
15
|
+
fileTooLarge: string;
|
|
16
|
+
fileTypeNotAllowed: string;
|
|
17
|
+
fileRejectedTooLarge: string;
|
|
18
|
+
uploading: string;
|
|
19
|
+
uploadFailed: string;
|
|
20
|
+
removeFile: string;
|
|
15
21
|
addRow: string;
|
|
16
22
|
removeRow: string;
|
|
17
23
|
minRows: string;
|
|
@@ -31,6 +37,7 @@ export interface MessageCatalog {
|
|
|
31
37
|
yes: string;
|
|
32
38
|
no: string;
|
|
33
39
|
emptyValue: string;
|
|
40
|
+
rowCount: string;
|
|
34
41
|
}
|
|
35
42
|
export type MessageKey = keyof MessageCatalog;
|
|
36
43
|
export type Locale = 'en' | 'th';
|
|
@@ -44,5 +51,14 @@ export type Locale = 'en' | 'th';
|
|
|
44
51
|
* the server). Components read the catalog at render time.
|
|
45
52
|
*/
|
|
46
53
|
export declare function setLocale(locale: Locale, overrides?: Partial<MessageCatalog>): void;
|
|
54
|
+
/**
|
|
55
|
+
* Snapshot of the active catalog. The catalog is module-global — on a server
|
|
56
|
+
* handling concurrent requests with different locales, wrap the locale switch:
|
|
57
|
+
* snapshot, setLocale, do the synchronous work, then setCatalog the snapshot
|
|
58
|
+
* back (bank20baht-validator's `locale` option does exactly this).
|
|
59
|
+
*/
|
|
60
|
+
export declare function getCatalog(): MessageCatalog;
|
|
61
|
+
/** Restore a catalog snapshot taken with getCatalog(). */
|
|
62
|
+
export declare function setCatalog(catalog: MessageCatalog): void;
|
|
47
63
|
/** Resolve one catalog string, interpolating `{param}` placeholders. */
|
|
48
64
|
export declare function t(key: MessageKey, params?: Record<string, unknown>): string;
|
package/dist/core/index.d.ts
CHANGED
|
@@ -4,8 +4,9 @@ export { approvalFields } from './approval.js';
|
|
|
4
4
|
export { validateField } from './validators.js';
|
|
5
5
|
export { resolveViewFields } from './views.js';
|
|
6
6
|
export { applyFlags, flagEnabled } from './flags.js';
|
|
7
|
-
export { setLocale, t } from './i18n.js';
|
|
7
|
+
export { getCatalog, setCatalog, setLocale, t } from './i18n.js';
|
|
8
8
|
export type { Locale, MessageCatalog, MessageKey } from './i18n.js';
|
|
9
9
|
export { evaluate } from './engine/evaluate.js';
|
|
10
|
+
export { resolveNext, walkPath } from './engine/graph.js';
|
|
10
11
|
export { evalCondition, readRef } from './engine/conditions.js';
|
|
11
12
|
export { evalValueExpr } from './engine/expressions.js';
|
package/dist/core/types.d.ts
CHANGED
|
@@ -52,6 +52,12 @@ export interface FieldDescriptor {
|
|
|
52
52
|
accept?: string;
|
|
53
53
|
multiple?: boolean;
|
|
54
54
|
maxSize?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Registry uploader name (spec 01 §13). With it, picking a file uploads
|
|
57
|
+
* immediately and the VALUE becomes a serializable UploadedFile ref
|
|
58
|
+
* (arrays when `multiple`) — without it, capture-only File handles (v1).
|
|
59
|
+
*/
|
|
60
|
+
uploader?: string;
|
|
55
61
|
text?: string;
|
|
56
62
|
variant?: string;
|
|
57
63
|
/**
|
|
@@ -173,11 +179,33 @@ export interface Rule {
|
|
|
173
179
|
}
|
|
174
180
|
/** Flag values — typically fetched from one static JSON file (spec 01 §12). */
|
|
175
181
|
export type FeatureFlags = Record<string, boolean>;
|
|
182
|
+
/**
|
|
183
|
+
* A conditional edge between steps (spec 03 §6). With `transitions` present
|
|
184
|
+
* the wizard routes as a graph: from a form, the first edge whose `when`
|
|
185
|
+
* matches wins; `to: 'end'` submits. Forms with no outgoing edges (and
|
|
186
|
+
* non-matching edge sets) fall back to the next visible form in `order`, so
|
|
187
|
+
* linear authoring keeps working and branches are added only where needed.
|
|
188
|
+
*/
|
|
189
|
+
export interface Transition {
|
|
190
|
+
from: string;
|
|
191
|
+
to: string | 'end';
|
|
192
|
+
when?: Condition;
|
|
193
|
+
flag?: string;
|
|
194
|
+
}
|
|
176
195
|
/** A Workflow definition — consumed by <baht-workflow> (spec 00 §4.2). */
|
|
177
196
|
export interface WorkflowDefinition {
|
|
178
197
|
workflowId: string;
|
|
179
198
|
forms: WorkflowForm[];
|
|
180
199
|
rules: Rule[];
|
|
200
|
+
/** Optional graph routing (spec 03 §6); absent = linear by `order`. */
|
|
201
|
+
transitions?: Transition[];
|
|
202
|
+
}
|
|
203
|
+
/** Serializable result of a registry uploader (spec 01 §13). */
|
|
204
|
+
export interface UploadedFile {
|
|
205
|
+
name: string;
|
|
206
|
+
size: number;
|
|
207
|
+
type?: string;
|
|
208
|
+
url: string;
|
|
181
209
|
}
|
|
182
210
|
export interface Registry {
|
|
183
211
|
formatters?: Record<string, (value: unknown) => unknown>;
|
|
@@ -185,6 +213,8 @@ export interface Registry {
|
|
|
185
213
|
validators?: Record<string, (value: unknown) => string | null>;
|
|
186
214
|
/** Option fetchers for `optionsFrom` — receive the form's current flat data. */
|
|
187
215
|
options?: Record<string, (data: Record<string, unknown>) => FieldOption[] | Promise<FieldOption[]>>;
|
|
216
|
+
/** File uploaders for `uploader` — take the picked File, return its ref. */
|
|
217
|
+
uploaders?: Record<string, (file: File) => Promise<UploadedFile>>;
|
|
188
218
|
}
|
|
189
219
|
export interface DerivedFieldState {
|
|
190
220
|
visible: boolean;
|
|
@@ -204,9 +234,15 @@ export interface Derived {
|
|
|
204
234
|
forms: Record<string, {
|
|
205
235
|
visible: boolean;
|
|
206
236
|
}>;
|
|
237
|
+
/**
|
|
238
|
+
* 'schema' = authoring defect (unknown rule target) — belongs at store
|
|
239
|
+
* time, not on a submission; 'data' = depends on the submitted values
|
|
240
|
+
* (non-convergence). Absent kind = 'schema' (pre-0.0.12 engines).
|
|
241
|
+
*/
|
|
207
242
|
errors: Array<{
|
|
208
243
|
ref: string;
|
|
209
244
|
message: string;
|
|
245
|
+
kind?: 'schema' | 'data';
|
|
210
246
|
}>;
|
|
211
247
|
}
|
|
212
248
|
export interface ValidationError {
|