@veil-runtime/ui 0.4.1 → 0.5.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/CHANGELOG.md +29 -0
- package/README.md +35 -17
- package/dist/build-manifest.json +10 -10
- package/dist/dom.js +280 -24
- package/dist/interface.d.ts +207 -22
- package/dist/interface.js +151 -32
- package/dist/validation-safety.d.ts +10 -0
- package/dist/validation-safety.js +3 -1
- package/docs/API.md +15 -3
- package/docs/ASYNC-PRESENTATION-0.5.0.md +109 -0
- package/docs/INTERACTIVE-COLLECTIONS-0.5.0.md +139 -0
- package/docs/INTERFACE-CAPABILITIES-0.5.0.md +105 -0
- package/docs/RELEASE-0.5.0.md +47 -0
- package/docs/RELEASE-QUALIFICATION-0.5.0.md +157 -0
- package/docs/RICHER-FORMS-0.5.0.md +69 -0
- package/docs/UNIVERSAL-INTERFACE.md +19 -11
- package/docs/V0.5.0-HANDOVER.md +144 -0
- package/examples/universal/async-presentation.mjs +32 -0
- package/examples/universal/collections.mjs +22 -0
- package/examples/universal/forms.mjs +21 -0
- package/package.json +5 -2
package/dist/interface.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export type InterfacePresentationPhase = "loading" | "ready" | "empty" | "error";
|
|
1
2
|
export type InterfaceValue = string | number | boolean | null;
|
|
2
3
|
export interface InterfaceBinding {
|
|
3
4
|
source: "data" | "state";
|
|
@@ -29,15 +30,32 @@ export interface InterfaceOption {
|
|
|
29
30
|
value: string;
|
|
30
31
|
label: string;
|
|
31
32
|
}
|
|
33
|
+
export type InterfaceCellPresentation = "text" | "badge";
|
|
32
34
|
export interface InterfaceColumn {
|
|
33
35
|
key: string;
|
|
34
36
|
label: string;
|
|
37
|
+
presentation?: InterfaceCellPresentation;
|
|
35
38
|
}
|
|
36
|
-
export interface
|
|
39
|
+
export interface InterfaceRowAction {
|
|
40
|
+
action: string;
|
|
41
|
+
label: string;
|
|
42
|
+
}
|
|
43
|
+
export interface InterfaceTableOptions {
|
|
44
|
+
rowKey?: string;
|
|
45
|
+
rowActions?: InterfaceRowAction[];
|
|
46
|
+
}
|
|
47
|
+
export type GridColumns = 1 | 2 | 3 | 4;
|
|
48
|
+
export type GridGap = "none" | "sm" | "md" | "lg";
|
|
49
|
+
export interface GridBreakpoints {
|
|
50
|
+
sm?: GridColumns;
|
|
51
|
+
lg?: GridColumns;
|
|
52
|
+
}
|
|
53
|
+
export interface InterfaceNode extends InterfaceTableOptions {
|
|
37
54
|
key: string;
|
|
38
55
|
component: string;
|
|
39
56
|
children?: InterfaceNode[];
|
|
40
57
|
text?: string | InterfaceBinding;
|
|
58
|
+
phase?: InterfacePresentationPhase | InterfaceBinding;
|
|
41
59
|
binding?: InterfaceBinding;
|
|
42
60
|
visible?: InterfaceConditionExpression;
|
|
43
61
|
disabled?: InterfaceConditionExpression;
|
|
@@ -46,8 +64,12 @@ export interface InterfaceNode {
|
|
|
46
64
|
validate?: boolean;
|
|
47
65
|
action?: string;
|
|
48
66
|
label?: string;
|
|
67
|
+
description?: string;
|
|
68
|
+
readOnly?: boolean;
|
|
49
69
|
inputType?: "text" | "number" | "checkbox";
|
|
50
|
-
columns?: InterfaceColumn[];
|
|
70
|
+
columns?: InterfaceColumn[] | GridColumns;
|
|
71
|
+
columnsAt?: GridBreakpoints;
|
|
72
|
+
gap?: GridGap;
|
|
51
73
|
ariaLabel?: string;
|
|
52
74
|
}
|
|
53
75
|
export interface InterfaceDefinition {
|
|
@@ -58,32 +80,50 @@ export interface InterfaceDefinition {
|
|
|
58
80
|
state?: Record<string, unknown>;
|
|
59
81
|
}
|
|
60
82
|
/** Use `satisfies BuiltinInterfaceDefinition` for compile-time checks on JSON-only built-in screens. */
|
|
83
|
+
type FieldOptions = Pick<InterfaceNode, "description" | "disabled">;
|
|
84
|
+
type InputMode = {
|
|
85
|
+
inputType?: "text" | "number";
|
|
86
|
+
readOnly?: boolean;
|
|
87
|
+
} | {
|
|
88
|
+
inputType: "checkbox";
|
|
89
|
+
readOnly?: never;
|
|
90
|
+
};
|
|
61
91
|
type BuiltinBase = Pick<InterfaceNode, "key" | "visible" | "ariaLabel">;
|
|
62
92
|
export type BuiltinInterfaceNode = (BuiltinBase & {
|
|
63
93
|
component: "Stack" | "Row";
|
|
64
94
|
children?: BuiltinInterfaceNode[];
|
|
65
95
|
}) | (BuiltinBase & {
|
|
66
|
-
component: "
|
|
96
|
+
component: "Grid";
|
|
97
|
+
children?: BuiltinInterfaceNode[];
|
|
98
|
+
columns?: GridColumns;
|
|
99
|
+
columnsAt?: GridBreakpoints;
|
|
100
|
+
gap?: GridGap;
|
|
101
|
+
}) | (BuiltinBase & {
|
|
102
|
+
component: "Text";
|
|
67
103
|
text?: string | InterfaceBinding;
|
|
104
|
+
}) | (BuiltinBase & {
|
|
105
|
+
component: "Status";
|
|
106
|
+
text?: string | InterfaceBinding;
|
|
107
|
+
phase?: InterfacePresentationPhase | InterfaceBinding;
|
|
68
108
|
}) | (BuiltinBase & {
|
|
69
109
|
component: "Heading";
|
|
70
110
|
text: string | InterfaceBinding;
|
|
71
|
-
}) | (BuiltinBase & {
|
|
111
|
+
}) | (BuiltinBase & FieldOptions & {
|
|
72
112
|
component: "Input";
|
|
73
113
|
label: string;
|
|
74
114
|
binding: InterfaceBinding & {
|
|
75
115
|
source: "state";
|
|
76
116
|
};
|
|
77
|
-
inputType?: "text" | "number" | "checkbox";
|
|
78
117
|
validation?: InterfaceValidation;
|
|
79
|
-
}) | (BuiltinBase & {
|
|
118
|
+
} & InputMode) | (BuiltinBase & FieldOptions & {
|
|
80
119
|
component: "Textarea";
|
|
120
|
+
readOnly?: boolean;
|
|
81
121
|
label: string;
|
|
82
122
|
binding: InterfaceBinding & {
|
|
83
123
|
source: "state";
|
|
84
124
|
};
|
|
85
125
|
validation?: InterfaceValidation;
|
|
86
|
-
}) | (BuiltinBase & {
|
|
126
|
+
}) | (BuiltinBase & FieldOptions & {
|
|
87
127
|
component: "Select";
|
|
88
128
|
label: string;
|
|
89
129
|
binding: InterfaceBinding & {
|
|
@@ -101,7 +141,7 @@ export type BuiltinInterfaceNode = (BuiltinBase & {
|
|
|
101
141
|
component: "Table";
|
|
102
142
|
binding: InterfaceBinding;
|
|
103
143
|
columns: InterfaceColumn[];
|
|
104
|
-
}) | (BuiltinBase & {
|
|
144
|
+
} & InterfaceTableOptions) | (BuiltinBase & {
|
|
105
145
|
component: "List";
|
|
106
146
|
binding: InterfaceBinding;
|
|
107
147
|
});
|
|
@@ -109,6 +149,8 @@ export type BuiltinInterfaceDefinition = Omit<InterfaceDefinition, "screen"> & {
|
|
|
109
149
|
screen: BuiltinInterfaceNode;
|
|
110
150
|
};
|
|
111
151
|
export interface InterfaceEvent {
|
|
152
|
+
/** Opaque lookup reference; the host must authorize access to the actual record. */
|
|
153
|
+
rowId?: string;
|
|
112
154
|
action: string;
|
|
113
155
|
source: string;
|
|
114
156
|
state: Record<string, unknown>;
|
|
@@ -126,6 +168,7 @@ export interface InterfaceController {
|
|
|
126
168
|
updateDefinition(definition: InterfaceDefinition, expectedRevision?: number): boolean;
|
|
127
169
|
setState(path: string, value: InterfaceValue): void;
|
|
128
170
|
dispatch(action: string, source: string): void;
|
|
171
|
+
dispatchRow(action: string, source: string, rowId: string, expectedRevision: number): boolean;
|
|
129
172
|
subscribe(listener: (snapshot: InterfaceSnapshot) => void): () => void;
|
|
130
173
|
dispose(): void;
|
|
131
174
|
}
|
|
@@ -145,6 +188,12 @@ export declare function getInterfaceCapabilities(): {
|
|
|
145
188
|
readonly children: true;
|
|
146
189
|
readonly event: null;
|
|
147
190
|
};
|
|
191
|
+
readonly Grid: {
|
|
192
|
+
readonly properties: readonly ["key", "component", "visible", "ariaLabel", "children", "columns", "columnsAt", "gap"];
|
|
193
|
+
readonly required: readonly [];
|
|
194
|
+
readonly children: true;
|
|
195
|
+
readonly event: null;
|
|
196
|
+
};
|
|
148
197
|
readonly Text: {
|
|
149
198
|
readonly properties: readonly ["key", "component", "visible", "ariaLabel", "text"];
|
|
150
199
|
readonly required: readonly [];
|
|
@@ -158,25 +207,25 @@ export declare function getInterfaceCapabilities(): {
|
|
|
158
207
|
readonly event: null;
|
|
159
208
|
};
|
|
160
209
|
readonly Status: {
|
|
161
|
-
readonly properties: readonly ["key", "component", "visible", "ariaLabel", "text"];
|
|
210
|
+
readonly properties: readonly ["key", "component", "visible", "ariaLabel", "text", "phase"];
|
|
162
211
|
readonly required: readonly [];
|
|
163
212
|
readonly children: false;
|
|
164
213
|
readonly event: null;
|
|
165
214
|
};
|
|
166
215
|
readonly Input: {
|
|
167
|
-
readonly properties: readonly ["key", "component", "visible", "ariaLabel", "label", "binding", "inputType", "validation"];
|
|
216
|
+
readonly properties: readonly ["key", "component", "visible", "ariaLabel", "description", "disabled", "readOnly", "label", "binding", "inputType", "validation"];
|
|
168
217
|
readonly required: readonly ["label", "binding"];
|
|
169
218
|
readonly children: false;
|
|
170
219
|
readonly event: "state change";
|
|
171
220
|
};
|
|
172
221
|
readonly Textarea: {
|
|
173
|
-
readonly properties: readonly ["key", "component", "visible", "ariaLabel", "label", "binding", "validation"];
|
|
222
|
+
readonly properties: readonly ["key", "component", "visible", "ariaLabel", "description", "disabled", "readOnly", "label", "binding", "validation"];
|
|
174
223
|
readonly required: readonly ["label", "binding"];
|
|
175
224
|
readonly children: false;
|
|
176
225
|
readonly event: "state change";
|
|
177
226
|
};
|
|
178
227
|
readonly Select: {
|
|
179
|
-
readonly properties: readonly ["key", "component", "visible", "ariaLabel", "label", "binding", "validation", "options"];
|
|
228
|
+
readonly properties: readonly ["key", "component", "visible", "ariaLabel", "description", "disabled", "label", "binding", "validation", "options"];
|
|
180
229
|
readonly required: readonly ["label", "binding", "options"];
|
|
181
230
|
readonly children: false;
|
|
182
231
|
readonly event: "state change";
|
|
@@ -188,10 +237,10 @@ export declare function getInterfaceCapabilities(): {
|
|
|
188
237
|
readonly event: "action";
|
|
189
238
|
};
|
|
190
239
|
readonly Table: {
|
|
191
|
-
readonly properties: readonly ["key", "component", "visible", "ariaLabel", "binding", "columns"];
|
|
240
|
+
readonly properties: readonly ["key", "component", "visible", "ariaLabel", "binding", "columns", "rowKey", "rowActions"];
|
|
192
241
|
readonly required: readonly ["binding", "columns"];
|
|
193
242
|
readonly children: false;
|
|
194
|
-
readonly event:
|
|
243
|
+
readonly event: "row action (opt-in)";
|
|
195
244
|
};
|
|
196
245
|
readonly List: {
|
|
197
246
|
readonly properties: readonly ["key", "component", "visible", "ariaLabel", "binding"];
|
|
@@ -205,8 +254,17 @@ export declare function getInterfaceCapabilities(): {
|
|
|
205
254
|
path: string;
|
|
206
255
|
missing: string;
|
|
207
256
|
visibility: string;
|
|
257
|
+
pathPattern: string;
|
|
258
|
+
separator: string;
|
|
259
|
+
emptyInteriorSegmentsAccepted: boolean;
|
|
260
|
+
forbiddenSegments: string[];
|
|
261
|
+
ownPropertiesOnly: boolean;
|
|
262
|
+
exactProperties: string[];
|
|
208
263
|
};
|
|
209
264
|
propertyTypes: {
|
|
265
|
+
phase: string;
|
|
266
|
+
rowKey: string;
|
|
267
|
+
rowActions: string;
|
|
210
268
|
key: string;
|
|
211
269
|
component: string;
|
|
212
270
|
children: string;
|
|
@@ -214,6 +272,8 @@ export declare function getInterfaceCapabilities(): {
|
|
|
214
272
|
binding: string;
|
|
215
273
|
visible: string;
|
|
216
274
|
disabled: string;
|
|
275
|
+
description: string;
|
|
276
|
+
readOnly: string;
|
|
217
277
|
validation: string;
|
|
218
278
|
validate: string;
|
|
219
279
|
options: string;
|
|
@@ -221,11 +281,14 @@ export declare function getInterfaceCapabilities(): {
|
|
|
221
281
|
label: string;
|
|
222
282
|
inputType: string[];
|
|
223
283
|
columns: string;
|
|
284
|
+
columnsAt: string;
|
|
285
|
+
gap: string[];
|
|
224
286
|
ariaLabel: string;
|
|
225
287
|
};
|
|
226
288
|
events: {
|
|
227
289
|
action: {
|
|
228
290
|
fields: string[];
|
|
291
|
+
optionalFields: string[];
|
|
229
292
|
declaration: string;
|
|
230
293
|
};
|
|
231
294
|
state: {
|
|
@@ -234,13 +297,135 @@ export declare function getInterfaceCapabilities(): {
|
|
|
234
297
|
};
|
|
235
298
|
};
|
|
236
299
|
limits: {
|
|
237
|
-
treeDepth:
|
|
238
|
-
nodes:
|
|
239
|
-
textLength:
|
|
240
|
-
tableRows:
|
|
241
|
-
tableColumns:
|
|
242
|
-
listItems:
|
|
243
|
-
transportBytes:
|
|
300
|
+
treeDepth: 15;
|
|
301
|
+
nodes: 512;
|
|
302
|
+
textLength: 4096;
|
|
303
|
+
tableRows: 100;
|
|
304
|
+
tableColumns: 20;
|
|
305
|
+
listItems: 100;
|
|
306
|
+
transportBytes: 1048576;
|
|
307
|
+
selectOptions: 100;
|
|
308
|
+
conditionDepth: 8;
|
|
309
|
+
conditionNodes: 64;
|
|
310
|
+
conditionTerms: 16;
|
|
311
|
+
rowActions: 8;
|
|
312
|
+
rowIdLength: 128;
|
|
313
|
+
aggregate: {
|
|
314
|
+
readonly depth: 32;
|
|
315
|
+
readonly nodes: 10000;
|
|
316
|
+
readonly keys: 256;
|
|
317
|
+
readonly items: 1000;
|
|
318
|
+
readonly string: 65536;
|
|
319
|
+
readonly bytes: 1048576;
|
|
320
|
+
};
|
|
321
|
+
treeDepthMeaning: string;
|
|
322
|
+
};
|
|
323
|
+
behavior: {
|
|
324
|
+
presentation: {
|
|
325
|
+
component: string;
|
|
326
|
+
phases: string[];
|
|
327
|
+
phaseBinding: string;
|
|
328
|
+
message: string;
|
|
329
|
+
defaults: {
|
|
330
|
+
loading: string;
|
|
331
|
+
ready: string;
|
|
332
|
+
empty: string;
|
|
333
|
+
error: string;
|
|
334
|
+
};
|
|
335
|
+
accessibility: string;
|
|
336
|
+
focus: string;
|
|
337
|
+
retry: string;
|
|
338
|
+
transitions: string;
|
|
339
|
+
orchestration: string;
|
|
340
|
+
};
|
|
341
|
+
collections: {
|
|
342
|
+
component: string;
|
|
343
|
+
rowKey: string;
|
|
344
|
+
rowIdPattern: string;
|
|
345
|
+
rowIdMatching: string;
|
|
346
|
+
duplicateOrMissingIds: string;
|
|
347
|
+
missingBinding: string;
|
|
348
|
+
rowActionsRequire: string[];
|
|
349
|
+
presentations: string[];
|
|
350
|
+
defaultPresentation: string;
|
|
351
|
+
badge: string;
|
|
352
|
+
dispatch: string;
|
|
353
|
+
source: string;
|
|
354
|
+
staleRevisionOrMissingRow: string;
|
|
355
|
+
identityScope: string[];
|
|
356
|
+
reconciliation: string;
|
|
357
|
+
keyboard: string;
|
|
358
|
+
gesture: string;
|
|
359
|
+
authorization: string;
|
|
360
|
+
eventRowData: boolean;
|
|
361
|
+
};
|
|
362
|
+
grid: {
|
|
363
|
+
columns: number[];
|
|
364
|
+
defaultColumns: number;
|
|
365
|
+
breakpoints: {
|
|
366
|
+
sm: number;
|
|
367
|
+
lg: number;
|
|
368
|
+
};
|
|
369
|
+
semantics: string;
|
|
370
|
+
gaps: {
|
|
371
|
+
none: string;
|
|
372
|
+
sm: string;
|
|
373
|
+
md: string;
|
|
374
|
+
lg: string;
|
|
375
|
+
};
|
|
376
|
+
defaultGap: string;
|
|
377
|
+
tracks: string;
|
|
378
|
+
order: string;
|
|
379
|
+
};
|
|
380
|
+
conditions: {
|
|
381
|
+
forms: string[];
|
|
382
|
+
operators: string[];
|
|
383
|
+
orderedValueType: string;
|
|
384
|
+
equality: string;
|
|
385
|
+
minTerms: number;
|
|
386
|
+
maxTerms: 16;
|
|
387
|
+
maxDepth: 8;
|
|
388
|
+
maxNodes: 64;
|
|
389
|
+
missingNumericMatches: boolean;
|
|
390
|
+
};
|
|
391
|
+
validation: {
|
|
392
|
+
fields: string[];
|
|
393
|
+
rules: string[];
|
|
394
|
+
lengthIntegerRange: number[];
|
|
395
|
+
numericRulesRequire: {
|
|
396
|
+
component: string;
|
|
397
|
+
inputType: string;
|
|
398
|
+
};
|
|
399
|
+
lengthExcludedInputTypes: string[];
|
|
400
|
+
reversedBounds: string;
|
|
401
|
+
hiddenFields: string;
|
|
402
|
+
disabledFields: string;
|
|
403
|
+
readOnlyFields: string;
|
|
404
|
+
feedback: string;
|
|
405
|
+
submissionFocus: string;
|
|
406
|
+
trigger: string;
|
|
407
|
+
};
|
|
408
|
+
actions: {
|
|
409
|
+
declaration: string;
|
|
410
|
+
hostAllowlist: string;
|
|
411
|
+
source: string;
|
|
412
|
+
optionalEventFields: string[];
|
|
413
|
+
hiddenOrDisabled: string;
|
|
414
|
+
eventFields: string[];
|
|
415
|
+
stateCopy: boolean;
|
|
416
|
+
authorization: string;
|
|
417
|
+
};
|
|
418
|
+
updates: {
|
|
419
|
+
data: string;
|
|
420
|
+
definition: string;
|
|
421
|
+
expectedRevision: string;
|
|
422
|
+
invalidCandidate: string;
|
|
423
|
+
rendererPreparation: string;
|
|
424
|
+
subscriptions: string;
|
|
425
|
+
listenerFeedbackPasses: number;
|
|
426
|
+
compatibleState: string[];
|
|
427
|
+
disposal: string;
|
|
428
|
+
};
|
|
244
429
|
};
|
|
245
430
|
};
|
|
246
431
|
export declare function defineInterface<const T extends InterfaceDefinition>(definition: T): T;
|
|
@@ -256,6 +441,6 @@ export declare function resolveInterfaceBinding(snapshot: InterfaceSnapshot, bin
|
|
|
256
441
|
/** Evaluate a validated condition without coercion or side effects. Missing numeric values never match. */
|
|
257
442
|
export declare function evaluateInterfaceCondition(condition: InterfaceConditionExpression, snapshot: Pick<InterfaceSnapshot, "data" | "state">): boolean;
|
|
258
443
|
export declare function isInterfaceField(node: Pick<InterfaceNode, "component">): boolean;
|
|
259
|
-
/** Errors are recomputed from accepted state; hidden fields are excluded, including hidden ancestors. */
|
|
444
|
+
/** Errors are recomputed from accepted state; hidden and disabled fields are excluded, including hidden ancestors. */
|
|
260
445
|
export declare function getInterfaceValidation(snapshot: Pick<InterfaceSnapshot, "definition" | "data" | "state">): Record<string, string>;
|
|
261
446
|
export {};
|