bank20baht-ui 0.0.10 → 0.0.11
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-workflow.d.ts +5 -1
- package/dist/components/primitives/baht-file.d.ts +14 -1
- 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 +13 -0
- package/dist/core/i18n.d.ts +5 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/types.d.ts +30 -0
- package/dist/custom-elements.json +195 -2
- package/dist/engine.js +195 -132
- package/dist/index.js +945 -830
- package/dist/react.d.ts +5 -0
- package/dist/tokens.css +51 -0
- package/dist/vscode.html-custom-data.json +19 -2
- package/dist/web-types.json +45 -2
- package/package.json +1 -1
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:
|
|
@@ -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;
|
|
@@ -1,9 +1,22 @@
|
|
|
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
|
+
private get refs();
|
|
18
|
+
private emitRefs;
|
|
19
|
+
private uploadAll;
|
|
20
|
+
private onPick;
|
|
8
21
|
protected renderControl(): TemplateResult;
|
|
9
22
|
}
|
|
@@ -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,13 @@
|
|
|
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.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveNext(workflow: WorkflowDefinition, current: string, data: NestedData): string | 'end';
|
|
8
|
+
/**
|
|
9
|
+
* The full path a submission takes from the start form to 'end' under this
|
|
10
|
+
* data — what the server validates against (off-path forms are as good as
|
|
11
|
+
* skipped). Back-edges that revisit a form stop the walk instead of looping.
|
|
12
|
+
*/
|
|
13
|
+
export declare function walkPath(workflow: WorkflowDefinition, data: NestedData): string[];
|
package/dist/core/i18n.d.ts
CHANGED
|
@@ -12,6 +12,11 @@ export interface MessageCatalog {
|
|
|
12
12
|
compareGte: string;
|
|
13
13
|
compareLt: string;
|
|
14
14
|
compareLte: string;
|
|
15
|
+
fileTooLarge: string;
|
|
16
|
+
fileTypeNotAllowed: string;
|
|
17
|
+
uploading: string;
|
|
18
|
+
uploadFailed: string;
|
|
19
|
+
removeFile: string;
|
|
15
20
|
addRow: string;
|
|
16
21
|
removeRow: string;
|
|
17
22
|
minRows: string;
|
package/dist/core/index.d.ts
CHANGED
|
@@ -7,5 +7,6 @@ export { applyFlags, flagEnabled } from './flags.js';
|
|
|
7
7
|
export { 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;
|
|
@@ -438,6 +438,16 @@
|
|
|
438
438
|
"default": "{}",
|
|
439
439
|
"description": "Feature-flag values (spec 01 §12): flag-off steps/fields/rules vanish."
|
|
440
440
|
},
|
|
441
|
+
{
|
|
442
|
+
"kind": "field",
|
|
443
|
+
"name": "showSteps",
|
|
444
|
+
"type": {
|
|
445
|
+
"text": "boolean"
|
|
446
|
+
},
|
|
447
|
+
"default": "false",
|
|
448
|
+
"description": "Render a <baht-steps> progress indicator above the current form.",
|
|
449
|
+
"attribute": "show-steps"
|
|
450
|
+
},
|
|
441
451
|
{
|
|
442
452
|
"kind": "field",
|
|
443
453
|
"name": "data",
|
|
@@ -539,6 +549,16 @@
|
|
|
539
549
|
"privacy": "private",
|
|
540
550
|
"readonly": true
|
|
541
551
|
},
|
|
552
|
+
{
|
|
553
|
+
"kind": "field",
|
|
554
|
+
"name": "navTarget",
|
|
555
|
+
"type": {
|
|
556
|
+
"text": "string | 'end'"
|
|
557
|
+
},
|
|
558
|
+
"privacy": "private",
|
|
559
|
+
"description": "Where next() would go from here: a formName or 'end' (spec 03 §6).",
|
|
560
|
+
"readonly": true
|
|
561
|
+
},
|
|
542
562
|
{
|
|
543
563
|
"kind": "field",
|
|
544
564
|
"name": "isLast",
|
|
@@ -635,7 +655,7 @@
|
|
|
635
655
|
}
|
|
636
656
|
}
|
|
637
657
|
],
|
|
638
|
-
"description": "Advance past the current form: submit+complete
|
|
658
|
+
"description": "Advance past the current form: submit+complete at 'end', else step to navTarget."
|
|
639
659
|
},
|
|
640
660
|
{
|
|
641
661
|
"kind": "method",
|
|
@@ -887,6 +907,15 @@
|
|
|
887
907
|
},
|
|
888
908
|
"default": "true",
|
|
889
909
|
"fieldName": "showBack"
|
|
910
|
+
},
|
|
911
|
+
{
|
|
912
|
+
"name": "show-steps",
|
|
913
|
+
"type": {
|
|
914
|
+
"text": "boolean"
|
|
915
|
+
},
|
|
916
|
+
"default": "false",
|
|
917
|
+
"description": "Render a <baht-steps> progress indicator above the current form.",
|
|
918
|
+
"fieldName": "showSteps"
|
|
890
919
|
}
|
|
891
920
|
],
|
|
892
921
|
"superclass": {
|
|
@@ -3078,9 +3107,98 @@
|
|
|
3078
3107
|
"declarations": [
|
|
3079
3108
|
{
|
|
3080
3109
|
"kind": "class",
|
|
3081
|
-
"description": "
|
|
3110
|
+
"description": "File field (spec 01 §2 + §13). Two modes:\n- capture (default): value = File handle(s); the lib never uploads.\n- upload (`field.uploader` + host `uploader` fn from the registry):\n picking uploads immediately, value becomes serializable UploadedFile\n ref(s), and the control shows chips with remove buttons.\nmaxSize (bytes) is enforced here as a soft filter — oversize files rejected.",
|
|
3082
3111
|
"name": "BahtFile",
|
|
3083
3112
|
"members": [
|
|
3113
|
+
{
|
|
3114
|
+
"kind": "field",
|
|
3115
|
+
"name": "uploader",
|
|
3116
|
+
"type": {
|
|
3117
|
+
"text": "(file: File) => Promise<UploadedFile> | undefined"
|
|
3118
|
+
},
|
|
3119
|
+
"description": "Resolved registry uploader — <baht-form> injects it when `field.uploader` is set."
|
|
3120
|
+
},
|
|
3121
|
+
{
|
|
3122
|
+
"kind": "field",
|
|
3123
|
+
"name": "uploadingCount",
|
|
3124
|
+
"type": {
|
|
3125
|
+
"text": "number"
|
|
3126
|
+
},
|
|
3127
|
+
"privacy": "private",
|
|
3128
|
+
"default": "0"
|
|
3129
|
+
},
|
|
3130
|
+
{
|
|
3131
|
+
"kind": "field",
|
|
3132
|
+
"name": "uploadError",
|
|
3133
|
+
"type": {
|
|
3134
|
+
"text": "string | null"
|
|
3135
|
+
},
|
|
3136
|
+
"privacy": "private",
|
|
3137
|
+
"default": "null"
|
|
3138
|
+
},
|
|
3139
|
+
{
|
|
3140
|
+
"kind": "field",
|
|
3141
|
+
"name": "refs",
|
|
3142
|
+
"type": {
|
|
3143
|
+
"text": "UploadedFile[]"
|
|
3144
|
+
},
|
|
3145
|
+
"privacy": "private",
|
|
3146
|
+
"readonly": true
|
|
3147
|
+
},
|
|
3148
|
+
{
|
|
3149
|
+
"kind": "method",
|
|
3150
|
+
"name": "emitRefs",
|
|
3151
|
+
"privacy": "private",
|
|
3152
|
+
"return": {
|
|
3153
|
+
"type": {
|
|
3154
|
+
"text": "void"
|
|
3155
|
+
}
|
|
3156
|
+
},
|
|
3157
|
+
"parameters": [
|
|
3158
|
+
{
|
|
3159
|
+
"name": "refs",
|
|
3160
|
+
"type": {
|
|
3161
|
+
"text": "UploadedFile[]"
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
]
|
|
3165
|
+
},
|
|
3166
|
+
{
|
|
3167
|
+
"kind": "method",
|
|
3168
|
+
"name": "uploadAll",
|
|
3169
|
+
"privacy": "private",
|
|
3170
|
+
"return": {
|
|
3171
|
+
"type": {
|
|
3172
|
+
"text": "Promise<void>"
|
|
3173
|
+
}
|
|
3174
|
+
},
|
|
3175
|
+
"parameters": [
|
|
3176
|
+
{
|
|
3177
|
+
"name": "files",
|
|
3178
|
+
"type": {
|
|
3179
|
+
"text": "File[]"
|
|
3180
|
+
}
|
|
3181
|
+
}
|
|
3182
|
+
]
|
|
3183
|
+
},
|
|
3184
|
+
{
|
|
3185
|
+
"kind": "method",
|
|
3186
|
+
"name": "onPick",
|
|
3187
|
+
"privacy": "private",
|
|
3188
|
+
"return": {
|
|
3189
|
+
"type": {
|
|
3190
|
+
"text": "void"
|
|
3191
|
+
}
|
|
3192
|
+
},
|
|
3193
|
+
"parameters": [
|
|
3194
|
+
{
|
|
3195
|
+
"name": "e",
|
|
3196
|
+
"type": {
|
|
3197
|
+
"text": "Event"
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
]
|
|
3201
|
+
},
|
|
3084
3202
|
{
|
|
3085
3203
|
"kind": "method",
|
|
3086
3204
|
"name": "renderControl",
|
|
@@ -7762,6 +7880,73 @@
|
|
|
7762
7880
|
}
|
|
7763
7881
|
]
|
|
7764
7882
|
},
|
|
7883
|
+
{
|
|
7884
|
+
"kind": "javascript-module",
|
|
7885
|
+
"path": "src/components/primitives/baht-steps.ts",
|
|
7886
|
+
"declarations": [
|
|
7887
|
+
{
|
|
7888
|
+
"kind": "class",
|
|
7889
|
+
"description": "<baht-steps> — wizard progress indicator (spec 03). Standalone display\nprimitive: numbered markers + labels, the current one highlighted, done\nones checked. <baht-workflow show-steps> renders it automatically from its\nvisible forms.",
|
|
7890
|
+
"name": "BahtSteps",
|
|
7891
|
+
"members": [
|
|
7892
|
+
{
|
|
7893
|
+
"kind": "field",
|
|
7894
|
+
"name": "steps",
|
|
7895
|
+
"type": {
|
|
7896
|
+
"text": "string[]"
|
|
7897
|
+
},
|
|
7898
|
+
"default": "[]",
|
|
7899
|
+
"description": "Step labels in order."
|
|
7900
|
+
},
|
|
7901
|
+
{
|
|
7902
|
+
"kind": "field",
|
|
7903
|
+
"name": "current",
|
|
7904
|
+
"type": {
|
|
7905
|
+
"text": "number"
|
|
7906
|
+
},
|
|
7907
|
+
"default": "0",
|
|
7908
|
+
"description": "0-based index of the current step.",
|
|
7909
|
+
"attribute": "current"
|
|
7910
|
+
}
|
|
7911
|
+
],
|
|
7912
|
+
"attributes": [
|
|
7913
|
+
{
|
|
7914
|
+
"name": "current",
|
|
7915
|
+
"type": {
|
|
7916
|
+
"text": "number"
|
|
7917
|
+
},
|
|
7918
|
+
"default": "0",
|
|
7919
|
+
"description": "0-based index of the current step.",
|
|
7920
|
+
"fieldName": "current"
|
|
7921
|
+
}
|
|
7922
|
+
],
|
|
7923
|
+
"superclass": {
|
|
7924
|
+
"name": "BahtElement",
|
|
7925
|
+
"module": "/src/components/base.js"
|
|
7926
|
+
},
|
|
7927
|
+
"tagName": "baht-steps",
|
|
7928
|
+
"customElement": true
|
|
7929
|
+
}
|
|
7930
|
+
],
|
|
7931
|
+
"exports": [
|
|
7932
|
+
{
|
|
7933
|
+
"kind": "js",
|
|
7934
|
+
"name": "BahtSteps",
|
|
7935
|
+
"declaration": {
|
|
7936
|
+
"name": "BahtSteps",
|
|
7937
|
+
"module": "src/components/primitives/baht-steps.ts"
|
|
7938
|
+
}
|
|
7939
|
+
},
|
|
7940
|
+
{
|
|
7941
|
+
"kind": "custom-element-definition",
|
|
7942
|
+
"name": "baht-steps",
|
|
7943
|
+
"declaration": {
|
|
7944
|
+
"name": "BahtSteps",
|
|
7945
|
+
"module": "src/components/primitives/baht-steps.ts"
|
|
7946
|
+
}
|
|
7947
|
+
}
|
|
7948
|
+
]
|
|
7949
|
+
},
|
|
7765
7950
|
{
|
|
7766
7951
|
"kind": "javascript-module",
|
|
7767
7952
|
"path": "src/components/primitives/baht-table.ts",
|
|
@@ -9587,6 +9772,14 @@
|
|
|
9587
9772
|
"module": "./baht-repeater.js"
|
|
9588
9773
|
}
|
|
9589
9774
|
},
|
|
9775
|
+
{
|
|
9776
|
+
"kind": "js",
|
|
9777
|
+
"name": "BahtSteps",
|
|
9778
|
+
"declaration": {
|
|
9779
|
+
"name": "BahtSteps",
|
|
9780
|
+
"module": "./baht-steps.js"
|
|
9781
|
+
}
|
|
9782
|
+
},
|
|
9590
9783
|
{
|
|
9591
9784
|
"kind": "js",
|
|
9592
9785
|
"name": "TAG_FOR_TYPE",
|