bank20baht-ui 0.0.6 → 0.0.8
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 +88 -0
- package/dist/components/baht-form.d.ts +23 -0
- package/dist/components/baht-workflow.d.ts +4 -3
- package/dist/components/primitives/baht-repeater.d.ts +33 -0
- package/dist/components/primitives/index.d.ts +2 -3
- package/dist/components/primitives/tag-map.d.ts +7 -0
- package/dist/core/engine/conditions.d.ts +5 -0
- package/dist/core/i18n.d.ts +48 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/types.d.ts +40 -3
- package/dist/core/validators.d.ts +5 -1
- package/dist/core/views.d.ts +12 -0
- package/dist/custom-elements.json +549 -24
- package/dist/engine.js +289 -174
- package/dist/index.js +816 -667
- package/dist/react.d.ts +2 -0
- package/dist/tokens.css +38 -0
- package/dist/vscode.html-custom-data.json +22 -2
- package/dist/web-types.json +60 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,6 +35,94 @@ npm i bank20baht-ui
|
|
|
35
35
|
`<baht-form>` is a **dumb controlled component**: props in → UI → `baht-change` out. No buttons, no
|
|
36
36
|
cross-field logic, no fetch. Your app owns the state (mutate the JSON, feed it back).
|
|
37
37
|
|
|
38
|
+
### Views — show a subset of one form
|
|
39
|
+
|
|
40
|
+
Define named display projections on the schema (e.g. per user role); select one with the
|
|
41
|
+
`view` attribute:
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
el.form = {
|
|
45
|
+
...form,
|
|
46
|
+
views: [{ name: 'summary', fields: ['age', 'firstName'] }], // view order = display order
|
|
47
|
+
};
|
|
48
|
+
el.view = 'summary'; // or <baht-form view="summary">; unset = full form
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Views are **client-side display only**: the view picks which fields render (and validate —
|
|
52
|
+
the user can only fix what they see), but `getData()` still returns the full form and the
|
|
53
|
+
server (`bank20baht-validator`) always validates the complete schema. In a workflow, set
|
|
54
|
+
`view: 'summary'` on a step's form to pin the view that step renders.
|
|
55
|
+
|
|
56
|
+
### Repeater — line items / repeating rows
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
{ order: 5, type: 'repeater', key: 'items', label: 'Line items', minRows: 1,
|
|
60
|
+
fields: [
|
|
61
|
+
{ order: 1, type: 'text', key: 'name', width: '1/2', required: true },
|
|
62
|
+
{ order: 2, type: 'number', key: 'qty', width: '1/4', min: 1 },
|
|
63
|
+
] }
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Value is an array of row objects (`getData().items → [{ name, qty }, …]`). Rows add/remove in
|
|
67
|
+
the UI (`minRows`/`maxRows` bound the count), each row validates its sub-fields — errors come
|
|
68
|
+
back as `items[0].name`, on both the client and `bank20baht-validator`. One level deep only.
|
|
69
|
+
|
|
70
|
+
### Dependent / async dropdowns
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
// schema — functions never live in JSON, only registry names:
|
|
74
|
+
{ order: 2, type: 'dropdown', key: 'amphoe', optionsFrom: 'amphoeFor', optionsDeps: ['province'] }
|
|
75
|
+
|
|
76
|
+
// registry:
|
|
77
|
+
el.registry = {
|
|
78
|
+
options: { amphoeFor: (data) => fetch(`/api/amphoe?p=${data.province}`).then(r => r.json()) },
|
|
79
|
+
};
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Options resolve from the registry with the form's current data (sync or Promise). When a
|
|
83
|
+
dep changes, options refetch and the dependent value clears — cascading down chains
|
|
84
|
+
(จังหวัด → อำเภอ → ตำบล).
|
|
85
|
+
|
|
86
|
+
### Cross-field validation
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
{ order: 2, type: 'date', key: 'end',
|
|
90
|
+
validators: [{ type: 'compare', op: 'gte', field: 'start' }] }
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`compare` checks against a sibling field (confirm email = `op: 'eq'`), numeric/date-aware,
|
|
94
|
+
skips while either side is empty. Works inside repeater rows and on the server.
|
|
95
|
+
|
|
96
|
+
### Drafts / autosave (host pattern)
|
|
97
|
+
|
|
98
|
+
The library is controlled — autosave is three lines in your app:
|
|
99
|
+
|
|
100
|
+
```js
|
|
101
|
+
el.addEventListener('baht-change', (e) => localStorage.setItem(key, JSON.stringify(e.detail.data)));
|
|
102
|
+
// (workflow: listen to baht-data-change instead)
|
|
103
|
+
el.value = JSON.parse(localStorage.getItem(key) ?? '{}'); // restore on mount
|
|
104
|
+
// clear the key after the server accepts the submission
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
See `apps/web`'s render page for a working restore/discard/clear-on-submit flow.
|
|
108
|
+
|
|
109
|
+
### i18n — Thai (or any) built-in strings
|
|
110
|
+
|
|
111
|
+
All built-in strings — validation messages, Next/Submit/Back, the approval step —
|
|
112
|
+
come from one catalog:
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
import { setLocale } from 'bank20baht-ui';
|
|
116
|
+
|
|
117
|
+
setLocale('th'); // built-ins: 'en' (default), 'th'
|
|
118
|
+
setLocale('th', { required: 'ห้ามว่าง' }); // locale + your own overrides
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Call it once before mounting. Per-field `message` and label attributes
|
|
122
|
+
(`next-label`, `approval.approveLabel`, …) still win over the catalog. The server can
|
|
123
|
+
localize too: `bank20baht-validator` re-exports `setLocale`, so validation issues come
|
|
124
|
+
back in the same language the client shows.
|
|
125
|
+
|
|
38
126
|
## Quick start — wizard with rules (Level 2)
|
|
39
127
|
|
|
40
128
|
```js
|
|
@@ -16,6 +16,13 @@ export declare class BahtForm extends BahtElement {
|
|
|
16
16
|
options: BahtFormOptions;
|
|
17
17
|
/** L2 (workflow) derived per-field UI state, keyed by field key. Optional. */
|
|
18
18
|
fieldStates: Record<string, DerivedFieldState>;
|
|
19
|
+
/**
|
|
20
|
+
* Name of a view from `form.views`. Display-only: when set, only that view's
|
|
21
|
+
* fields are rendered and validated (the user can only fix what they see),
|
|
22
|
+
* but getData() still returns the FULL form — the server always validates
|
|
23
|
+
* the complete schema, views never change the submit payload.
|
|
24
|
+
*/
|
|
25
|
+
view?: string;
|
|
19
26
|
/** Edits the user made since the host last set `value` (controlled overlay). */
|
|
20
27
|
private edits;
|
|
21
28
|
private errors;
|
|
@@ -25,7 +32,23 @@ export declare class BahtForm extends BahtElement {
|
|
|
25
32
|
* which drops focus and makes continuous typing impossible.
|
|
26
33
|
*/
|
|
27
34
|
private controls;
|
|
35
|
+
/** Resolved dynamic options + the dep snapshot / fetch epoch they belong to. */
|
|
36
|
+
private dynamicOptions;
|
|
37
|
+
private optionsSnapshots;
|
|
38
|
+
private optionsEpoch;
|
|
28
39
|
protected willUpdate(changed: Map<PropertyKey, unknown>): void;
|
|
40
|
+
/**
|
|
41
|
+
* Refetch `optionsFrom` options whose dep snapshot changed. Sync fetchers
|
|
42
|
+
* land immediately; async ones re-render on resolve (stale responses are
|
|
43
|
+
* dropped by epoch).
|
|
44
|
+
*/
|
|
45
|
+
private syncDynamicOptions;
|
|
46
|
+
/**
|
|
47
|
+
* A user edit invalidates every field whose optionsDeps include the edited
|
|
48
|
+
* key — their values reset to defaults, cascading down chains
|
|
49
|
+
* (province -> district -> subdistrict).
|
|
50
|
+
*/
|
|
51
|
+
private clearDependents;
|
|
29
52
|
private get sortedFields();
|
|
30
53
|
private stateFor;
|
|
31
54
|
private valueFor;
|
|
@@ -16,9 +16,10 @@ export declare class BahtWorkflow extends BahtElement {
|
|
|
16
16
|
value: NestedData;
|
|
17
17
|
registry: Registry;
|
|
18
18
|
validateGate: boolean;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
/** Label attributes beat the i18n catalog; unset = t('next')/t('submit')/t('back'). */
|
|
20
|
+
nextLabel?: string;
|
|
21
|
+
submitLabel?: string;
|
|
22
|
+
backLabel?: string;
|
|
22
23
|
showBack: boolean;
|
|
23
24
|
private data;
|
|
24
25
|
private derived;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { TemplateResult } from 'lit';
|
|
2
|
+
import { BahtFieldBase } from '../base.js';
|
|
3
|
+
import { ValidationError } from '../../core/types.js';
|
|
4
|
+
/**
|
|
5
|
+
* <baht-repeater> — array-of-rows control (spec 01 §10). `value` is an array
|
|
6
|
+
* of row objects; every row renders the same `field.fields` sub-descriptors
|
|
7
|
+
* (one level deep — nested repeaters are skipped). Controlled like every
|
|
8
|
+
* primitive: edits emit the WHOLE array via `baht-input`; the host re-feeds.
|
|
9
|
+
*/
|
|
10
|
+
export declare class BahtRepeater extends BahtFieldBase {
|
|
11
|
+
/** Row-scoped errors from the host form, keyed `key[i].subKey`. */
|
|
12
|
+
rowErrors: ValidationError[];
|
|
13
|
+
/**
|
|
14
|
+
* One control per `${rowIndex}:${subKey}`, reused across renders so typing
|
|
15
|
+
* doesn't drop focus (same trick as <baht-form>, NOTES round 27). Cleared
|
|
16
|
+
* when the descriptor changes or row indexes shift (remove).
|
|
17
|
+
*/
|
|
18
|
+
private controls;
|
|
19
|
+
protected willUpdate(changed: Map<PropertyKey, unknown>): void;
|
|
20
|
+
private get rows();
|
|
21
|
+
private get subFields();
|
|
22
|
+
private patchRow;
|
|
23
|
+
private addRow;
|
|
24
|
+
private removeRow;
|
|
25
|
+
private errorFor;
|
|
26
|
+
private renderSub;
|
|
27
|
+
protected renderControl(): TemplateResult;
|
|
28
|
+
}
|
|
29
|
+
declare global {
|
|
30
|
+
interface HTMLElementTagNameMap {
|
|
31
|
+
'baht-repeater': BahtRepeater;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { FieldType } from '../../core/types.js';
|
|
2
1
|
export { BahtButton, type ButtonVariant, type ButtonSize } from './baht-button.js';
|
|
3
2
|
export { renderIcon, isIconName, type IconName } from './icons.js';
|
|
4
3
|
export { BahtBadge, type BadgeTone } from './baht-badge.js';
|
|
@@ -42,5 +41,5 @@ export { BahtEmptyState } from './baht-empty-state.js';
|
|
|
42
41
|
export { BahtErrorState } from './baht-error-state.js';
|
|
43
42
|
export { BahtKeyvalueEditor } from './baht-keyvalue-editor.js';
|
|
44
43
|
export { BahtReferencePicker, type ReferenceOption } from './baht-reference-picker.js';
|
|
45
|
-
|
|
46
|
-
export
|
|
44
|
+
export { BahtRepeater } from './baht-repeater.js';
|
|
45
|
+
export { TAG_FOR_TYPE } from './tag-map.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { FieldType } from '../../core/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* field descriptor `type` -> primitive tag (used by <baht-form>, <baht-repeater>
|
|
4
|
+
* and the builder). Lives in its own module so baht-repeater can read it
|
|
5
|
+
* without importing the primitives barrel (which would be circular).
|
|
6
|
+
*/
|
|
7
|
+
export declare const TAG_FOR_TYPE: Record<FieldType, string>;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { Condition, NestedData } from '../types.js';
|
|
2
2
|
/** Read a "formName.fieldKey" reference out of nested data. */
|
|
3
3
|
export declare function readRef(data: NestedData, ref: string): unknown;
|
|
4
|
+
/**
|
|
5
|
+
* Ordering used by rule conditions AND the `compare` validator: numeric when
|
|
6
|
+
* both sides coerce, date-aware, else lexicographic. Null = not comparable.
|
|
7
|
+
*/
|
|
8
|
+
export declare function compareValues(a: unknown, b: unknown): number | null;
|
|
4
9
|
export declare function evalCondition(cond: Condition | undefined, data: NestedData): boolean;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface MessageCatalog {
|
|
2
|
+
required: string;
|
|
3
|
+
minLength: string;
|
|
4
|
+
maxLength: string;
|
|
5
|
+
min: string;
|
|
6
|
+
max: string;
|
|
7
|
+
pattern: string;
|
|
8
|
+
email: string;
|
|
9
|
+
compareEq: string;
|
|
10
|
+
compareNe: string;
|
|
11
|
+
compareGt: string;
|
|
12
|
+
compareGte: string;
|
|
13
|
+
compareLt: string;
|
|
14
|
+
compareLte: string;
|
|
15
|
+
addRow: string;
|
|
16
|
+
removeRow: string;
|
|
17
|
+
minRows: string;
|
|
18
|
+
maxRows: string;
|
|
19
|
+
next: string;
|
|
20
|
+
submit: string;
|
|
21
|
+
back: string;
|
|
22
|
+
step: string;
|
|
23
|
+
approve: string;
|
|
24
|
+
reject: string;
|
|
25
|
+
decision: string;
|
|
26
|
+
comment: string;
|
|
27
|
+
commentRequiredSuffix: string;
|
|
28
|
+
decisionRequired: string;
|
|
29
|
+
commentRequired: string;
|
|
30
|
+
nothingToReview: string;
|
|
31
|
+
yes: string;
|
|
32
|
+
no: string;
|
|
33
|
+
emptyValue: string;
|
|
34
|
+
}
|
|
35
|
+
export type MessageKey = keyof MessageCatalog;
|
|
36
|
+
export type Locale = 'en' | 'th';
|
|
37
|
+
/**
|
|
38
|
+
* Switch every built-in string to a locale, optionally patching single keys:
|
|
39
|
+
*
|
|
40
|
+
* setLocale('th') // all Thai
|
|
41
|
+
* setLocale('th', { required: 'ห้ามว่าง' }) // Thai + one custom message
|
|
42
|
+
*
|
|
43
|
+
* Global and synchronous — set it before mounting (or before validating on
|
|
44
|
+
* the server). Components read the catalog at render time.
|
|
45
|
+
*/
|
|
46
|
+
export declare function setLocale(locale: Locale, overrides?: Partial<MessageCatalog>): void;
|
|
47
|
+
/** Resolve one catalog string, interpolating `{param}` placeholders. */
|
|
48
|
+
export declare function t(key: MessageKey, params?: Record<string, unknown>): string;
|
package/dist/core/index.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ export * from './types.js';
|
|
|
2
2
|
export { defaultValue } from './defaults.js';
|
|
3
3
|
export { approvalFields } from './approval.js';
|
|
4
4
|
export { validateField } from './validators.js';
|
|
5
|
+
export { resolveViewFields } from './views.js';
|
|
6
|
+
export { setLocale, t } from './i18n.js';
|
|
7
|
+
export type { Locale, MessageCatalog, MessageKey } from './i18n.js';
|
|
5
8
|
export { evaluate } from './engine/evaluate.js';
|
|
6
9
|
export { evalCondition, readRef } from './engine/conditions.js';
|
|
7
10
|
export { evalValueExpr } from './engine/expressions.js';
|
package/dist/core/types.d.ts
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
/** Control types supported by v1 (spec 01 §2). */
|
|
2
|
-
export type FieldType = 'text' | 'textarea' | 'number' | 'email' | 'dropdown' | 'multiselect' | 'checkbox' | 'radio' | 'toggle' | 'date' | 'file' | 'label';
|
|
2
|
+
export type FieldType = 'text' | 'textarea' | 'number' | 'email' | 'dropdown' | 'multiselect' | 'checkbox' | 'radio' | 'toggle' | 'date' | 'file' | 'label' | 'repeater';
|
|
3
3
|
export type FieldWidth = '1/4' | '1/2' | '3/4' | 'full';
|
|
4
4
|
export interface FieldOption {
|
|
5
5
|
key: string;
|
|
6
6
|
label: string;
|
|
7
7
|
}
|
|
8
|
-
/**
|
|
8
|
+
/** Ordering/equality ops available to the `compare` validator. */
|
|
9
|
+
export type CompareOp = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte';
|
|
10
|
+
/**
|
|
11
|
+
* Declarative validator (spec 01 §4). `custom` resolves `fn` from the
|
|
12
|
+
* registry; `compare` checks this value against a sibling field's value
|
|
13
|
+
* (same form — or same row inside a repeater) and skips while the sibling
|
|
14
|
+
* is empty or unknown.
|
|
15
|
+
*/
|
|
9
16
|
export interface ValidatorSpec {
|
|
10
|
-
type: 'required' | 'minLength' | 'maxLength' | 'min' | 'max' | 'pattern' | 'email' | 'custom';
|
|
17
|
+
type: 'required' | 'minLength' | 'maxLength' | 'min' | 'max' | 'pattern' | 'email' | 'compare' | 'custom';
|
|
11
18
|
value?: unknown;
|
|
12
19
|
fn?: string;
|
|
20
|
+
op?: CompareOp;
|
|
21
|
+
field?: string;
|
|
13
22
|
message?: string;
|
|
14
23
|
}
|
|
15
24
|
/** One item of `field_data[]` (spec 01 §1). */
|
|
@@ -26,6 +35,14 @@ export interface FieldDescriptor {
|
|
|
26
35
|
disabled?: boolean;
|
|
27
36
|
required?: boolean;
|
|
28
37
|
options?: FieldOption[];
|
|
38
|
+
/** Registry name resolving this field's options from current form data. */
|
|
39
|
+
optionsFrom?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Same-form field keys this field's options depend on. When one changes
|
|
42
|
+
* (user edit), the options refetch and this field's value clears —
|
|
43
|
+
* cascading through chained dependents (province -> district -> …).
|
|
44
|
+
*/
|
|
45
|
+
optionsDeps?: string[];
|
|
29
46
|
maxLength?: number;
|
|
30
47
|
minLength?: number;
|
|
31
48
|
min?: number | string;
|
|
@@ -37,14 +54,30 @@ export interface FieldDescriptor {
|
|
|
37
54
|
maxSize?: number;
|
|
38
55
|
text?: string;
|
|
39
56
|
variant?: string;
|
|
57
|
+
fields?: FieldDescriptor[];
|
|
58
|
+
minRows?: number;
|
|
59
|
+
maxRows?: number;
|
|
60
|
+
addLabel?: string;
|
|
40
61
|
validators?: ValidatorSpec[];
|
|
41
62
|
formatter?: string;
|
|
42
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* A named, client-side-only projection of a form: which fields to show, in
|
|
66
|
+
* what order (e.g. per user role). Display sugar only — the submit payload is
|
|
67
|
+
* always the full form and the server always validates the complete schema.
|
|
68
|
+
*/
|
|
69
|
+
export interface FormViewSpec {
|
|
70
|
+
name: string;
|
|
71
|
+
/** field keys included, in display order; keys absent from field_data are ignored */
|
|
72
|
+
fields: string[];
|
|
73
|
+
}
|
|
43
74
|
/** A Form definition — consumed standalone by <baht-form> (spec 00 §4.1). */
|
|
44
75
|
export interface FormDefinition {
|
|
45
76
|
formId: string;
|
|
46
77
|
formName: string;
|
|
47
78
|
field_data: FieldDescriptor[];
|
|
79
|
+
/** Optional named display subsets; select one via <baht-form view="...">. */
|
|
80
|
+
views?: FormViewSpec[];
|
|
48
81
|
}
|
|
49
82
|
export type ApprovalDecision = 'approved' | 'rejected';
|
|
50
83
|
/** Comment box policy on an approval step. */
|
|
@@ -73,6 +106,8 @@ export interface WorkflowForm extends FormDefinition {
|
|
|
73
106
|
*/
|
|
74
107
|
kind?: 'form' | 'approval';
|
|
75
108
|
approval?: ApprovalConfig;
|
|
109
|
+
/** Name of one of this form's `views` to render for this step (display only). */
|
|
110
|
+
view?: string;
|
|
76
111
|
}
|
|
77
112
|
export type ConditionOp = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'notIn' | 'contains' | 'notContains' | 'startsWith' | 'endsWith' | 'isEmpty' | 'isNotEmpty';
|
|
78
113
|
/** Leaf: compare `formName.fieldKey` against a constant or another field. */
|
|
@@ -136,6 +171,8 @@ export interface Registry {
|
|
|
136
171
|
formatters?: Record<string, (value: unknown) => unknown>;
|
|
137
172
|
/** Return null when valid, or an error message string. */
|
|
138
173
|
validators?: Record<string, (value: unknown) => string | null>;
|
|
174
|
+
/** Option fetchers for `optionsFrom` — receive the form's current flat data. */
|
|
175
|
+
options?: Record<string, (data: Record<string, unknown>) => FieldOption[] | Promise<FieldOption[]>>;
|
|
139
176
|
}
|
|
140
177
|
export interface DerivedFieldState {
|
|
141
178
|
visible: boolean;
|
|
@@ -2,5 +2,9 @@ import { FieldDescriptor, Registry, ValidationError } from './types.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Validate one field's value against its declarative validators (spec 01 §4).
|
|
4
4
|
* Empty + not required = valid (other validators only run on non-empty values).
|
|
5
|
+
* `data` is the surrounding flat form data — only `compare` validators read
|
|
6
|
+
* it; omitting it skips them. Repeaters (spec 01 §10) additionally check row
|
|
7
|
+
* bounds and recurse into each row's sub-fields, prefixing keys as
|
|
8
|
+
* `key[i].subKey` (each row is its own compare context).
|
|
5
9
|
*/
|
|
6
|
-
export declare function validateField(field: FieldDescriptor, value: unknown, registry?: Registry): ValidationError[];
|
|
10
|
+
export declare function validateField(field: FieldDescriptor, value: unknown, registry?: Registry, data?: Record<string, unknown>): ValidationError[];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FieldDescriptor, FormDefinition } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the fields a consumer of `form` should DISPLAY. Views are
|
|
4
|
+
* client-side projections only — data and server validation always cover the
|
|
5
|
+
* full form.
|
|
6
|
+
*
|
|
7
|
+
* - No `view` → every field, sorted by `order` (the full form).
|
|
8
|
+
* - A known view → only its fields, in the order the view lists them.
|
|
9
|
+
* - An unknown view → `null`; the caller decides the fallback (<baht-form>
|
|
10
|
+
* warns and shows the full form).
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveViewFields(form: FormDefinition, view?: string): FieldDescriptor[] | null;
|