@burgantech/pseudo-ui 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 +336 -0
- package/dist/_virtual/_plugin-vue_export-helper.js +9 -0
- package/dist/adapters/vue/DynamicRenderer.vue.d.ts +8 -0
- package/dist/adapters/vue/DynamicRenderer.vue.js +7 -0
- package/dist/adapters/vue/DynamicRenderer.vue2.js +1302 -0
- package/dist/adapters/vue/ErrorBoundary.vue.d.ts +16 -0
- package/dist/adapters/vue/ErrorBoundary.vue.js +7 -0
- package/dist/adapters/vue/ErrorBoundary.vue2.js +27 -0
- package/dist/adapters/vue/NestedComponentWrapper.vue.d.ts +15 -0
- package/dist/adapters/vue/NestedComponentWrapper.vue.js +96 -0
- package/dist/adapters/vue/NestedComponentWrapper.vue2.js +4 -0
- package/dist/adapters/vue/PseudoView.vue.d.ts +18 -0
- package/dist/adapters/vue/PseudoView.vue.js +59 -0
- package/dist/adapters/vue/PseudoView.vue2.js +4 -0
- package/dist/adapters/vue/index.d.ts +6 -0
- package/dist/adapters/vue/index.js +17 -0
- package/dist/adapters/vue/injection.d.ts +3 -0
- package/dist/adapters/vue/injection.js +14 -0
- package/dist/adapters/vue/useFormContext.d.ts +4 -0
- package/dist/adapters/vue/useFormContext.js +35 -0
- package/dist/adapters/vue/useLookups.d.ts +4 -0
- package/dist/adapters/vue/useLookups.js +38 -0
- package/dist/engine/conditionalEngine.d.ts +6 -0
- package/dist/engine/conditionalEngine.js +56 -0
- package/dist/engine/dataClient.d.ts +5 -0
- package/dist/engine/dataClient.js +39 -0
- package/dist/engine/expressionResolver.d.ts +13 -0
- package/dist/engine/expressionResolver.js +136 -0
- package/dist/engine/index.d.ts +7 -0
- package/dist/engine/schemaResolver.d.ts +14 -0
- package/dist/engine/schemaResolver.js +97 -0
- package/dist/engine/types.d.ts +155 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +23 -0
- package/dist/pseudo-ui.css +1 -0
- package/package.json +57 -0
- package/vocabularies/view-model-vocabulary.json +474 -0
- package/vocabularies/view-vocabulary.json +1104 -0
|
@@ -0,0 +1,1104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://amorphie.io/meta/view-vocabulary/1.0",
|
|
4
|
+
"title": "Amorphie View Vocabulary",
|
|
5
|
+
"description": "Platform-agnostic, Material Design 3 based component tree specification. Defines the structure of view JSON files that are rendered by platform-specific engines (Vue/PrimeVue, Flutter/material.io). Contains no styling - only structural component definitions, data binding, and semantic variants.",
|
|
6
|
+
|
|
7
|
+
"type": "object",
|
|
8
|
+
"required": ["$schema", "dataSchema", "view"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"$schema": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"const": "https://amorphie.io/meta/view-vocabulary/1.0",
|
|
13
|
+
"description": "View vocabulary schema reference"
|
|
14
|
+
},
|
|
15
|
+
"dataSchema": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"format": "uri",
|
|
18
|
+
"description": "Reference to the JSON Schema $id that defines the data contract for this view. The renderer uses this to resolve bind targets, labels, validation rules, LOV sources, and conditional logic."
|
|
19
|
+
},
|
|
20
|
+
"lookups": {
|
|
21
|
+
"type": "array",
|
|
22
|
+
"items": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"minLength": 1
|
|
25
|
+
},
|
|
26
|
+
"description": "List of schema property names whose x-lookup definitions should be activated for this view. The renderer watches filter dependencies and lazily fetches lookup data when required parameters are available. Results are stored in lookupData and accessible via $lookup.{propertyName}.{field} expressions.",
|
|
27
|
+
"examples": [
|
|
28
|
+
["branchDetail"],
|
|
29
|
+
["accountInfo", "customerAddressLookup"]
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"uiState": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"additionalProperties": true,
|
|
35
|
+
"description": "Initial values for the $ui namespace — transient UI state that is NOT included in form submission. Used for overlay visibility toggles, active tab tracking, accordion expansion state, etc. Keys are freely defined (no schema required). Access via $ui.key expressions and set via ActionDescriptor with bind: '$ui.key'.",
|
|
36
|
+
"examples": [
|
|
37
|
+
{ "showConfirmDialog": false, "activeTab": "home", "filterPanelOpen": true }
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"view": {
|
|
41
|
+
"$ref": "#/$defs/componentNode",
|
|
42
|
+
"description": "Root component node - the entry point of the component tree"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"additionalProperties": false,
|
|
46
|
+
|
|
47
|
+
"$defs": {
|
|
48
|
+
|
|
49
|
+
"componentNode": {
|
|
50
|
+
"description": "A single node in the component tree. Discriminated by the 'type' field.",
|
|
51
|
+
"oneOf": [
|
|
52
|
+
{ "$ref": "#/$defs/columnComponent" },
|
|
53
|
+
{ "$ref": "#/$defs/rowComponent" },
|
|
54
|
+
{ "$ref": "#/$defs/wrapComponent" },
|
|
55
|
+
{ "$ref": "#/$defs/stackComponent" },
|
|
56
|
+
{ "$ref": "#/$defs/gridComponent" },
|
|
57
|
+
{ "$ref": "#/$defs/expandedComponent" },
|
|
58
|
+
{ "$ref": "#/$defs/spacerComponent" },
|
|
59
|
+
{ "$ref": "#/$defs/centerComponent" },
|
|
60
|
+
{ "$ref": "#/$defs/scrollViewComponent" },
|
|
61
|
+
|
|
62
|
+
{ "$ref": "#/$defs/cardComponent" },
|
|
63
|
+
{ "$ref": "#/$defs/expansionPanelComponent" },
|
|
64
|
+
{ "$ref": "#/$defs/stepperComponent" },
|
|
65
|
+
{ "$ref": "#/$defs/tabViewComponent" },
|
|
66
|
+
{ "$ref": "#/$defs/dividerComponent" },
|
|
67
|
+
|
|
68
|
+
{ "$ref": "#/$defs/textFieldComponent" },
|
|
69
|
+
{ "$ref": "#/$defs/textAreaComponent" },
|
|
70
|
+
{ "$ref": "#/$defs/numberFieldComponent" },
|
|
71
|
+
{ "$ref": "#/$defs/dropdownComponent" },
|
|
72
|
+
{ "$ref": "#/$defs/checkboxComponent" },
|
|
73
|
+
{ "$ref": "#/$defs/radioGroupComponent" },
|
|
74
|
+
{ "$ref": "#/$defs/switchComponent" },
|
|
75
|
+
{ "$ref": "#/$defs/datePickerComponent" },
|
|
76
|
+
{ "$ref": "#/$defs/sliderComponent" },
|
|
77
|
+
|
|
78
|
+
{ "$ref": "#/$defs/textComponent" },
|
|
79
|
+
{ "$ref": "#/$defs/iconComponent" },
|
|
80
|
+
{ "$ref": "#/$defs/imageComponent" },
|
|
81
|
+
{ "$ref": "#/$defs/chipComponent" },
|
|
82
|
+
{ "$ref": "#/$defs/badgeComponent" },
|
|
83
|
+
{ "$ref": "#/$defs/progressIndicatorComponent" },
|
|
84
|
+
|
|
85
|
+
{ "$ref": "#/$defs/buttonComponent" },
|
|
86
|
+
{ "$ref": "#/$defs/iconButtonComponent" },
|
|
87
|
+
{ "$ref": "#/$defs/fabComponent" },
|
|
88
|
+
|
|
89
|
+
{ "$ref": "#/$defs/forEachComponent" },
|
|
90
|
+
{ "$ref": "#/$defs/nestedComponent" },
|
|
91
|
+
|
|
92
|
+
{ "$ref": "#/$defs/timePickerComponent" },
|
|
93
|
+
{ "$ref": "#/$defs/segmentedButtonComponent" },
|
|
94
|
+
{ "$ref": "#/$defs/searchFieldComponent" },
|
|
95
|
+
{ "$ref": "#/$defs/autoCompleteComponent" },
|
|
96
|
+
|
|
97
|
+
{ "$ref": "#/$defs/listTileComponent" },
|
|
98
|
+
{ "$ref": "#/$defs/avatarComponent" },
|
|
99
|
+
{ "$ref": "#/$defs/richTextComponent" },
|
|
100
|
+
{ "$ref": "#/$defs/loadingIndicatorComponent" },
|
|
101
|
+
|
|
102
|
+
{ "$ref": "#/$defs/dialogComponent" },
|
|
103
|
+
{ "$ref": "#/$defs/bottomSheetComponent" },
|
|
104
|
+
{ "$ref": "#/$defs/sideSheetComponent" },
|
|
105
|
+
{ "$ref": "#/$defs/snackbarComponent" },
|
|
106
|
+
{ "$ref": "#/$defs/tooltipComponent" },
|
|
107
|
+
|
|
108
|
+
{ "$ref": "#/$defs/appBarComponent" },
|
|
109
|
+
{ "$ref": "#/$defs/navigationBarComponent" },
|
|
110
|
+
{ "$ref": "#/$defs/navigationDrawerComponent" },
|
|
111
|
+
|
|
112
|
+
{ "$ref": "#/$defs/menuComponent" },
|
|
113
|
+
{ "$ref": "#/$defs/toolbarComponent" },
|
|
114
|
+
{ "$ref": "#/$defs/carouselComponent" }
|
|
115
|
+
]
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
"spacingToken": {
|
|
119
|
+
"type": "string",
|
|
120
|
+
"enum": ["xs", "sm", "md", "lg", "xl"],
|
|
121
|
+
"description": "Semantic spacing token. Resolved to platform-specific pixel values by the theme. xs=4, sm=8, md=16, lg=24, xl=32 are typical defaults."
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
"mainAxisAlignment": {
|
|
125
|
+
"type": "string",
|
|
126
|
+
"enum": ["start", "center", "end", "spaceBetween", "spaceAround", "spaceEvenly"],
|
|
127
|
+
"description": "Alignment along the main axis (vertical for Column, horizontal for Row)"
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
"crossAxisAlignment": {
|
|
131
|
+
"type": "string",
|
|
132
|
+
"enum": ["start", "center", "end", "stretch"],
|
|
133
|
+
"description": "Alignment along the cross axis (horizontal for Column, vertical for Row)"
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
"typographyVariant": {
|
|
137
|
+
"type": "string",
|
|
138
|
+
"enum": [
|
|
139
|
+
"displayLarge", "displayMedium", "displaySmall",
|
|
140
|
+
"headlineLarge", "headlineMedium", "headlineSmall",
|
|
141
|
+
"titleLarge", "titleMedium", "titleSmall",
|
|
142
|
+
"bodyLarge", "bodyMedium", "bodySmall",
|
|
143
|
+
"labelLarge", "labelMedium", "labelSmall"
|
|
144
|
+
],
|
|
145
|
+
"description": "Material Design 3 Type Scale variant"
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
"buttonVariant": {
|
|
149
|
+
"type": "string",
|
|
150
|
+
"enum": ["filled", "outlined", "text", "elevated", "tonal"],
|
|
151
|
+
"description": "Material Design 3 button style variant"
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
"inputVariant": {
|
|
155
|
+
"type": "string",
|
|
156
|
+
"enum": ["filled", "outlined"],
|
|
157
|
+
"description": "Material Design 3 input field style variant"
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
"buttonAction": {
|
|
161
|
+
"type": "string",
|
|
162
|
+
"enum": ["submit", "cancel", "back"],
|
|
163
|
+
"description": "Semantic button action. submit: validates then dispatches, cancel/back: dispatches immediately. The optional 'command' property carries the opaque reference (URN, URL, etc.) for the delegate."
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
"sheetVariant": {
|
|
167
|
+
"type": "string",
|
|
168
|
+
"enum": ["standard", "modal"],
|
|
169
|
+
"description": "Sheet presentation mode. standard: non-blocking, co-exists with main content. modal: blocks interaction with content behind."
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
"appBarVariant": {
|
|
173
|
+
"type": "string",
|
|
174
|
+
"enum": ["center", "small", "medium", "large"],
|
|
175
|
+
"description": "Material Design 3 top app bar variant."
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
"chipVariant": {
|
|
179
|
+
"type": "string",
|
|
180
|
+
"enum": ["assist", "filter", "input", "suggestion"],
|
|
181
|
+
"description": "Material Design 3 chip type. assist: action shortcut, filter: toggleable filter, input: user-entered info, suggestion: contextual hint."
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
"avatarShape": {
|
|
185
|
+
"type": "string",
|
|
186
|
+
"enum": ["circle", "square"],
|
|
187
|
+
"description": "Avatar shape variant."
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
"multiLangText": {
|
|
191
|
+
"type": "object",
|
|
192
|
+
"description": "Multi-language text object. Keys are ISO 639-1 language codes.",
|
|
193
|
+
"patternProperties": {
|
|
194
|
+
"^[a-z]{2}(-[A-Z]{2})?$": {
|
|
195
|
+
"type": "string",
|
|
196
|
+
"minLength": 1
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
"additionalProperties": false,
|
|
200
|
+
"examples": [
|
|
201
|
+
{ "tr": "Kaydet", "en": "Save", "ar": "حفظ" }
|
|
202
|
+
]
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
"textContent": {
|
|
206
|
+
"description": "Text content - either a static/expression string or a multi-language object. Expressions start with $ (e.g. $schema.firstName.label, $form.firstName, $instance.selectedBranchCode, $param.city, $ui.activeTab, $lov.city.display, $lookup.branchDetail.address, $item.name, $context.lang)",
|
|
207
|
+
"oneOf": [
|
|
208
|
+
{ "type": "string", "minLength": 1 },
|
|
209
|
+
{ "$ref": "#/$defs/multiLangText" }
|
|
210
|
+
]
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
"expression": {
|
|
214
|
+
"type": "string",
|
|
215
|
+
"pattern": "^\\$",
|
|
216
|
+
"description": "Runtime expression. $form.fieldName = user input data, $instance.fieldName = backend-persisted data, $param.fieldName = parent-bound data (sub-components only), $ui.key = transient UI state (not submitted), $schema.fieldName.label = field label from x-labels, $context.key = runtime context (lang, etc.), $item.field = current iteration item, $lov.fieldName = LOV items array, $lov.fieldName.display = localized display name for current value, $lookup.propName.field = enrichment data"
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
"actionDescriptor": {
|
|
220
|
+
"description": "Action triggered by user interaction. Can be a simple action name string, a detailed action object, or an array of action objects (to set multiple fields in one tap).",
|
|
221
|
+
"oneOf": [
|
|
222
|
+
{
|
|
223
|
+
"type": "string",
|
|
224
|
+
"description": "Simple action name: 'submit', 'cancel', 'back', 'next', etc."
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"type": "object",
|
|
228
|
+
"required": ["action"],
|
|
229
|
+
"properties": {
|
|
230
|
+
"action": {
|
|
231
|
+
"type": "string",
|
|
232
|
+
"description": "Action identifier"
|
|
233
|
+
},
|
|
234
|
+
"bind": {
|
|
235
|
+
"type": "string",
|
|
236
|
+
"description": "Schema property to update"
|
|
237
|
+
},
|
|
238
|
+
"value": {
|
|
239
|
+
"description": "Value to set (static or expression)"
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
"additionalProperties": false
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"type": "array",
|
|
246
|
+
"description": "Array of action objects. Executed sequentially in one interaction (e.g. set branchCode and branchName on card tap).",
|
|
247
|
+
"items": {
|
|
248
|
+
"type": "object",
|
|
249
|
+
"required": ["action"],
|
|
250
|
+
"properties": {
|
|
251
|
+
"action": { "type": "string" },
|
|
252
|
+
"bind": { "type": "string" },
|
|
253
|
+
"value": {}
|
|
254
|
+
},
|
|
255
|
+
"additionalProperties": false
|
|
256
|
+
},
|
|
257
|
+
"minItems": 1
|
|
258
|
+
}
|
|
259
|
+
]
|
|
260
|
+
},
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
"columnComponent": {
|
|
264
|
+
"type": "object",
|
|
265
|
+
"required": ["type", "children"],
|
|
266
|
+
"properties": {
|
|
267
|
+
"type": { "const": "Column" },
|
|
268
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1 },
|
|
269
|
+
"gap": { "$ref": "#/$defs/spacingToken" },
|
|
270
|
+
"mainAxisAlignment": { "$ref": "#/$defs/mainAxisAlignment" },
|
|
271
|
+
"crossAxisAlignment": { "$ref": "#/$defs/crossAxisAlignment" }
|
|
272
|
+
},
|
|
273
|
+
"additionalProperties": false,
|
|
274
|
+
"description": "Vertical layout container. Flutter: Column, Vue: flex-direction column."
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
"rowComponent": {
|
|
278
|
+
"type": "object",
|
|
279
|
+
"required": ["type", "children"],
|
|
280
|
+
"properties": {
|
|
281
|
+
"type": { "const": "Row" },
|
|
282
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1 },
|
|
283
|
+
"gap": { "$ref": "#/$defs/spacingToken" },
|
|
284
|
+
"mainAxisAlignment": { "$ref": "#/$defs/mainAxisAlignment" },
|
|
285
|
+
"crossAxisAlignment": { "$ref": "#/$defs/crossAxisAlignment" }
|
|
286
|
+
},
|
|
287
|
+
"additionalProperties": false,
|
|
288
|
+
"description": "Horizontal layout container. Flutter: Row, Vue: flex-direction row."
|
|
289
|
+
},
|
|
290
|
+
|
|
291
|
+
"wrapComponent": {
|
|
292
|
+
"type": "object",
|
|
293
|
+
"required": ["type", "children"],
|
|
294
|
+
"properties": {
|
|
295
|
+
"type": { "const": "Wrap" },
|
|
296
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1 },
|
|
297
|
+
"gap": { "$ref": "#/$defs/spacingToken" }
|
|
298
|
+
},
|
|
299
|
+
"additionalProperties": false,
|
|
300
|
+
"description": "Flow layout that wraps children to next line. Flutter: Wrap, Vue: flex-wrap."
|
|
301
|
+
},
|
|
302
|
+
|
|
303
|
+
"stackComponent": {
|
|
304
|
+
"type": "object",
|
|
305
|
+
"required": ["type", "children"],
|
|
306
|
+
"properties": {
|
|
307
|
+
"type": { "const": "Stack" },
|
|
308
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1 }
|
|
309
|
+
},
|
|
310
|
+
"additionalProperties": false,
|
|
311
|
+
"description": "Overlay layout where children are stacked on top of each other. Flutter: Stack, Vue: position relative container."
|
|
312
|
+
},
|
|
313
|
+
|
|
314
|
+
"gridComponent": {
|
|
315
|
+
"type": "object",
|
|
316
|
+
"required": ["type", "children", "columns"],
|
|
317
|
+
"properties": {
|
|
318
|
+
"type": { "const": "Grid" },
|
|
319
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1 },
|
|
320
|
+
"columns": { "type": "integer", "minimum": 1, "maximum": 12, "description": "Number of grid columns" },
|
|
321
|
+
"gap": { "$ref": "#/$defs/spacingToken" }
|
|
322
|
+
},
|
|
323
|
+
"additionalProperties": false,
|
|
324
|
+
"description": "Grid layout. Flutter: GridView, Vue: CSS Grid."
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
"expandedComponent": {
|
|
328
|
+
"type": "object",
|
|
329
|
+
"required": ["type", "children"],
|
|
330
|
+
"properties": {
|
|
331
|
+
"type": { "const": "Expanded" },
|
|
332
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1, "maxItems": 1 },
|
|
333
|
+
"flex": { "type": "integer", "minimum": 1, "default": 1 }
|
|
334
|
+
},
|
|
335
|
+
"additionalProperties": false,
|
|
336
|
+
"description": "Fills remaining space in a Row or Column. Flutter: Expanded, Vue: flex 1."
|
|
337
|
+
},
|
|
338
|
+
|
|
339
|
+
"spacerComponent": {
|
|
340
|
+
"type": "object",
|
|
341
|
+
"required": ["type"],
|
|
342
|
+
"properties": {
|
|
343
|
+
"type": { "const": "Spacer" },
|
|
344
|
+
"flex": { "type": "integer", "minimum": 1, "default": 1 }
|
|
345
|
+
},
|
|
346
|
+
"additionalProperties": false,
|
|
347
|
+
"description": "Flexible empty space. Flutter: Spacer, Vue: flex spacer div."
|
|
348
|
+
},
|
|
349
|
+
|
|
350
|
+
"centerComponent": {
|
|
351
|
+
"type": "object",
|
|
352
|
+
"required": ["type", "children"],
|
|
353
|
+
"properties": {
|
|
354
|
+
"type": { "const": "Center" },
|
|
355
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1, "maxItems": 1 }
|
|
356
|
+
},
|
|
357
|
+
"additionalProperties": false,
|
|
358
|
+
"description": "Centers its child. Flutter: Center, Vue: centered flex container."
|
|
359
|
+
},
|
|
360
|
+
|
|
361
|
+
"scrollViewComponent": {
|
|
362
|
+
"type": "object",
|
|
363
|
+
"required": ["type", "children"],
|
|
364
|
+
"properties": {
|
|
365
|
+
"type": { "const": "ScrollView" },
|
|
366
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1 }
|
|
367
|
+
},
|
|
368
|
+
"additionalProperties": false,
|
|
369
|
+
"description": "Scrollable container. Flutter: SingleChildScrollView, Vue: overflow-auto."
|
|
370
|
+
},
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
"cardComponent": {
|
|
374
|
+
"type": "object",
|
|
375
|
+
"required": ["type", "children"],
|
|
376
|
+
"properties": {
|
|
377
|
+
"type": { "const": "Card" },
|
|
378
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1 },
|
|
379
|
+
"variant": { "type": "string", "enum": ["elevated", "filled", "outlined"], "default": "elevated" },
|
|
380
|
+
"onTap": { "$ref": "#/$defs/actionDescriptor" }
|
|
381
|
+
},
|
|
382
|
+
"additionalProperties": false,
|
|
383
|
+
"description": "Material card container. Flutter: Card, Vue/PrimeVue: Card."
|
|
384
|
+
},
|
|
385
|
+
|
|
386
|
+
"expansionPanelComponent": {
|
|
387
|
+
"type": "object",
|
|
388
|
+
"required": ["type", "title", "children"],
|
|
389
|
+
"properties": {
|
|
390
|
+
"type": { "const": "ExpansionPanel" },
|
|
391
|
+
"title": { "$ref": "#/$defs/textContent" },
|
|
392
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1 },
|
|
393
|
+
"initiallyExpanded": { "type": "boolean", "default": false }
|
|
394
|
+
},
|
|
395
|
+
"additionalProperties": false,
|
|
396
|
+
"description": "Expandable/collapsible panel. Flutter: ExpansionTile, Vue/PrimeVue: Accordion."
|
|
397
|
+
},
|
|
398
|
+
|
|
399
|
+
"stepperComponent": {
|
|
400
|
+
"type": "object",
|
|
401
|
+
"required": ["type", "steps"],
|
|
402
|
+
"properties": {
|
|
403
|
+
"type": { "const": "Stepper" },
|
|
404
|
+
"steps": {
|
|
405
|
+
"type": "array",
|
|
406
|
+
"minItems": 2,
|
|
407
|
+
"items": {
|
|
408
|
+
"type": "object",
|
|
409
|
+
"required": ["title", "content"],
|
|
410
|
+
"properties": {
|
|
411
|
+
"title": { "$ref": "#/$defs/textContent" },
|
|
412
|
+
"subtitle": { "$ref": "#/$defs/textContent" },
|
|
413
|
+
"content": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1 }
|
|
414
|
+
},
|
|
415
|
+
"additionalProperties": false
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
},
|
|
419
|
+
"additionalProperties": false,
|
|
420
|
+
"description": "Multi-step wizard. Flutter: Stepper, Vue/PrimeVue: Steps."
|
|
421
|
+
},
|
|
422
|
+
|
|
423
|
+
"dividerComponent": {
|
|
424
|
+
"type": "object",
|
|
425
|
+
"required": ["type"],
|
|
426
|
+
"properties": {
|
|
427
|
+
"type": { "const": "Divider" }
|
|
428
|
+
},
|
|
429
|
+
"additionalProperties": false,
|
|
430
|
+
"description": "Horizontal divider line. Flutter: Divider, Vue/PrimeVue: Divider."
|
|
431
|
+
},
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
"textFieldComponent": {
|
|
435
|
+
"type": "object",
|
|
436
|
+
"required": ["type", "bind"],
|
|
437
|
+
"properties": {
|
|
438
|
+
"type": { "const": "TextField" },
|
|
439
|
+
"bind": { "type": "string", "minLength": 1, "description": "JSON Schema property name to bind to. Renderer resolves label, validation, conditional visibility from the schema." },
|
|
440
|
+
"variant": { "$ref": "#/$defs/inputVariant" }
|
|
441
|
+
},
|
|
442
|
+
"additionalProperties": false,
|
|
443
|
+
"description": "Single-line text input. All metadata (label, placeholder, validation, error messages, conditional) comes from the bound JSON Schema property via x-labels, x-errorMessages, x-conditional, etc."
|
|
444
|
+
},
|
|
445
|
+
|
|
446
|
+
"textAreaComponent": {
|
|
447
|
+
"type": "object",
|
|
448
|
+
"required": ["type", "bind"],
|
|
449
|
+
"properties": {
|
|
450
|
+
"type": { "const": "TextArea" },
|
|
451
|
+
"bind": { "type": "string", "minLength": 1 },
|
|
452
|
+
"variant": { "$ref": "#/$defs/inputVariant" }
|
|
453
|
+
},
|
|
454
|
+
"additionalProperties": false,
|
|
455
|
+
"description": "Multi-line text input. Flutter: TextField(maxLines), Vue/PrimeVue: Textarea."
|
|
456
|
+
},
|
|
457
|
+
|
|
458
|
+
"numberFieldComponent": {
|
|
459
|
+
"type": "object",
|
|
460
|
+
"required": ["type", "bind"],
|
|
461
|
+
"properties": {
|
|
462
|
+
"type": { "const": "NumberField" },
|
|
463
|
+
"bind": { "type": "string", "minLength": 1 },
|
|
464
|
+
"variant": { "$ref": "#/$defs/inputVariant" }
|
|
465
|
+
},
|
|
466
|
+
"additionalProperties": false,
|
|
467
|
+
"description": "Numeric input. Flutter: TextField(keyboardType: number), Vue/PrimeVue: InputNumber."
|
|
468
|
+
},
|
|
469
|
+
|
|
470
|
+
"dropdownComponent": {
|
|
471
|
+
"type": "object",
|
|
472
|
+
"required": ["type", "bind"],
|
|
473
|
+
"properties": {
|
|
474
|
+
"type": { "const": "Dropdown" },
|
|
475
|
+
"bind": { "type": "string", "minLength": 1 },
|
|
476
|
+
"variant": { "$ref": "#/$defs/inputVariant" }
|
|
477
|
+
},
|
|
478
|
+
"additionalProperties": false,
|
|
479
|
+
"description": "Selection dropdown. Options come from the bound schema property's 'enum' + 'x-enum' (static) or 'x-lov' (dynamic from backend). Cascade filtering handled via x-lov.filter."
|
|
480
|
+
},
|
|
481
|
+
|
|
482
|
+
"checkboxComponent": {
|
|
483
|
+
"type": "object",
|
|
484
|
+
"required": ["type", "bind"],
|
|
485
|
+
"properties": {
|
|
486
|
+
"type": { "const": "Checkbox" },
|
|
487
|
+
"bind": { "type": "string", "minLength": 1 }
|
|
488
|
+
},
|
|
489
|
+
"additionalProperties": false,
|
|
490
|
+
"description": "Boolean checkbox. Label comes from x-labels of the bound schema property."
|
|
491
|
+
},
|
|
492
|
+
|
|
493
|
+
"radioGroupComponent": {
|
|
494
|
+
"type": "object",
|
|
495
|
+
"required": ["type", "bind"],
|
|
496
|
+
"properties": {
|
|
497
|
+
"type": { "const": "RadioGroup" },
|
|
498
|
+
"bind": { "type": "string", "minLength": 1 }
|
|
499
|
+
},
|
|
500
|
+
"additionalProperties": false,
|
|
501
|
+
"description": "Radio button group. Options come from the bound schema property's 'enum' + 'x-enum'."
|
|
502
|
+
},
|
|
503
|
+
|
|
504
|
+
"switchComponent": {
|
|
505
|
+
"type": "object",
|
|
506
|
+
"required": ["type", "bind"],
|
|
507
|
+
"properties": {
|
|
508
|
+
"type": { "const": "Switch" },
|
|
509
|
+
"bind": { "type": "string", "minLength": 1 }
|
|
510
|
+
},
|
|
511
|
+
"additionalProperties": false,
|
|
512
|
+
"description": "Boolean toggle switch. Flutter: Switch, Vue/PrimeVue: ToggleSwitch."
|
|
513
|
+
},
|
|
514
|
+
|
|
515
|
+
"datePickerComponent": {
|
|
516
|
+
"type": "object",
|
|
517
|
+
"required": ["type", "bind"],
|
|
518
|
+
"properties": {
|
|
519
|
+
"type": { "const": "DatePicker" },
|
|
520
|
+
"bind": { "type": "string", "minLength": 1 }
|
|
521
|
+
},
|
|
522
|
+
"additionalProperties": false,
|
|
523
|
+
"description": "Date selection input. Flutter: showDatePicker, Vue/PrimeVue: DatePicker."
|
|
524
|
+
},
|
|
525
|
+
|
|
526
|
+
"sliderComponent": {
|
|
527
|
+
"type": "object",
|
|
528
|
+
"required": ["type", "bind"],
|
|
529
|
+
"properties": {
|
|
530
|
+
"type": { "const": "Slider" },
|
|
531
|
+
"bind": { "type": "string", "minLength": 1 }
|
|
532
|
+
},
|
|
533
|
+
"additionalProperties": false,
|
|
534
|
+
"description": "Numeric slider. Min/max come from the bound schema property's minimum/maximum."
|
|
535
|
+
},
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
"textComponent": {
|
|
539
|
+
"type": "object",
|
|
540
|
+
"required": ["type", "content"],
|
|
541
|
+
"properties": {
|
|
542
|
+
"type": { "const": "Text" },
|
|
543
|
+
"content": { "$ref": "#/$defs/textContent" },
|
|
544
|
+
"variant": { "$ref": "#/$defs/typographyVariant" }
|
|
545
|
+
},
|
|
546
|
+
"additionalProperties": false,
|
|
547
|
+
"description": "Text display. Supports static text, multi-language text, and expressions ($schema.fieldName.label, $form.fieldName, $instance.fieldName, $param.fieldName, $lov.fieldName.display, $lookup.propName.field, $item.name)."
|
|
548
|
+
},
|
|
549
|
+
|
|
550
|
+
"iconComponent": {
|
|
551
|
+
"type": "object",
|
|
552
|
+
"required": ["type", "name"],
|
|
553
|
+
"properties": {
|
|
554
|
+
"type": { "const": "Icon" },
|
|
555
|
+
"name": { "type": "string", "minLength": 1, "description": "Material icon name (e.g. 'business', 'person', 'check_circle')" },
|
|
556
|
+
"size": { "type": "string", "enum": ["sm", "md", "lg"], "default": "md" }
|
|
557
|
+
},
|
|
558
|
+
"additionalProperties": false,
|
|
559
|
+
"description": "Material icon. Flutter: Icon(Icons.name), Vue: Material Icons / PrimeIcons."
|
|
560
|
+
},
|
|
561
|
+
|
|
562
|
+
"imageComponent": {
|
|
563
|
+
"type": "object",
|
|
564
|
+
"required": ["type", "source"],
|
|
565
|
+
"properties": {
|
|
566
|
+
"type": { "const": "Image" },
|
|
567
|
+
"source": { "type": "string", "minLength": 1, "description": "Image URL or expression" },
|
|
568
|
+
"fit": { "type": "string", "enum": ["cover", "contain", "fill"], "default": "cover" }
|
|
569
|
+
},
|
|
570
|
+
"additionalProperties": false,
|
|
571
|
+
"description": "Image display. Flutter: Image, Vue: img element."
|
|
572
|
+
},
|
|
573
|
+
|
|
574
|
+
"chipComponent": {
|
|
575
|
+
"type": "object",
|
|
576
|
+
"required": ["type", "label"],
|
|
577
|
+
"properties": {
|
|
578
|
+
"type": { "const": "Chip" },
|
|
579
|
+
"label": { "$ref": "#/$defs/textContent" },
|
|
580
|
+
"icon": { "type": "string" },
|
|
581
|
+
"variant": { "type": "string", "enum": ["filled", "outlined"], "default": "filled" }
|
|
582
|
+
},
|
|
583
|
+
"additionalProperties": false,
|
|
584
|
+
"description": "Compact element for tags or status. Flutter: Chip, Vue/PrimeVue: Chip."
|
|
585
|
+
},
|
|
586
|
+
|
|
587
|
+
"badgeComponent": {
|
|
588
|
+
"type": "object",
|
|
589
|
+
"required": ["type", "content", "children"],
|
|
590
|
+
"properties": {
|
|
591
|
+
"type": { "const": "Badge" },
|
|
592
|
+
"content": { "$ref": "#/$defs/textContent" },
|
|
593
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1, "maxItems": 1 }
|
|
594
|
+
},
|
|
595
|
+
"additionalProperties": false,
|
|
596
|
+
"description": "Badge overlay on a child widget. Flutter: Badge, Vue/PrimeVue: Badge."
|
|
597
|
+
},
|
|
598
|
+
|
|
599
|
+
"progressIndicatorComponent": {
|
|
600
|
+
"type": "object",
|
|
601
|
+
"required": ["type"],
|
|
602
|
+
"properties": {
|
|
603
|
+
"type": { "const": "ProgressIndicator" },
|
|
604
|
+
"variant": { "type": "string", "enum": ["circular", "linear"], "default": "circular" }
|
|
605
|
+
},
|
|
606
|
+
"additionalProperties": false,
|
|
607
|
+
"description": "Loading indicator. Flutter: CircularProgressIndicator/LinearProgressIndicator, Vue/PrimeVue: ProgressSpinner/ProgressBar."
|
|
608
|
+
},
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
"buttonComponent": {
|
|
612
|
+
"type": "object",
|
|
613
|
+
"required": ["type", "label", "action"],
|
|
614
|
+
"properties": {
|
|
615
|
+
"type": { "const": "Button" },
|
|
616
|
+
"label": { "$ref": "#/$defs/textContent" },
|
|
617
|
+
"variant": { "$ref": "#/$defs/buttonVariant" },
|
|
618
|
+
"icon": { "type": "string", "description": "Optional leading Material icon name" },
|
|
619
|
+
"action": {
|
|
620
|
+
"oneOf": [
|
|
621
|
+
{ "$ref": "#/$defs/buttonAction" },
|
|
622
|
+
{ "$ref": "#/$defs/actionDescriptor" }
|
|
623
|
+
],
|
|
624
|
+
"description": "ButtonAction string (submit/cancel/back) or a full ActionDescriptor."
|
|
625
|
+
},
|
|
626
|
+
"command": { "type": "string", "description": "Opaque reference (URN, URL, short code) passed to the onAction delegate. SDK does not interpret this value." }
|
|
627
|
+
},
|
|
628
|
+
"additionalProperties": false,
|
|
629
|
+
"description": "Material button. Flutter: ElevatedButton/OutlinedButton/TextButton, Vue/PrimeVue: Button."
|
|
630
|
+
},
|
|
631
|
+
|
|
632
|
+
"iconButtonComponent": {
|
|
633
|
+
"type": "object",
|
|
634
|
+
"required": ["type", "icon", "action"],
|
|
635
|
+
"properties": {
|
|
636
|
+
"type": { "const": "IconButton" },
|
|
637
|
+
"icon": { "type": "string", "minLength": 1 },
|
|
638
|
+
"action": { "$ref": "#/$defs/actionDescriptor" }
|
|
639
|
+
},
|
|
640
|
+
"additionalProperties": false,
|
|
641
|
+
"description": "Icon-only button. Flutter: IconButton, Vue/PrimeVue: Button(icon)."
|
|
642
|
+
},
|
|
643
|
+
|
|
644
|
+
"fabComponent": {
|
|
645
|
+
"type": "object",
|
|
646
|
+
"required": ["type", "icon", "action"],
|
|
647
|
+
"properties": {
|
|
648
|
+
"type": { "const": "FAB" },
|
|
649
|
+
"icon": { "type": "string", "minLength": 1 },
|
|
650
|
+
"label": { "$ref": "#/$defs/textContent" },
|
|
651
|
+
"action": { "$ref": "#/$defs/actionDescriptor" },
|
|
652
|
+
"variant": { "type": "string", "enum": ["small", "regular", "large"], "default": "regular" }
|
|
653
|
+
},
|
|
654
|
+
"additionalProperties": false,
|
|
655
|
+
"description": "Floating action button. If label is provided, renders as extended FAB. Flutter: FloatingActionButton, Vue/PrimeVue: SpeedDial."
|
|
656
|
+
},
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
"tabViewComponent": {
|
|
660
|
+
"type": "object",
|
|
661
|
+
"required": ["type", "tabs"],
|
|
662
|
+
"properties": {
|
|
663
|
+
"type": { "const": "TabView" },
|
|
664
|
+
"tabs": {
|
|
665
|
+
"type": "array",
|
|
666
|
+
"items": {
|
|
667
|
+
"type": "object",
|
|
668
|
+
"required": ["title", "content"],
|
|
669
|
+
"properties": {
|
|
670
|
+
"title": {
|
|
671
|
+
"oneOf": [
|
|
672
|
+
{ "type": "string" },
|
|
673
|
+
{ "$ref": "#/$defs/multiLangText" }
|
|
674
|
+
],
|
|
675
|
+
"description": "Tab header text. Can be a simple string or a multi-language object."
|
|
676
|
+
},
|
|
677
|
+
"icon": {
|
|
678
|
+
"type": "string",
|
|
679
|
+
"description": "Optional PrimeIcons icon name (without 'pi pi-' prefix). Flutter: Icons.* equivalent."
|
|
680
|
+
},
|
|
681
|
+
"content": {
|
|
682
|
+
"type": "array",
|
|
683
|
+
"items": { "$ref": "#/$defs/componentNode" },
|
|
684
|
+
"description": "Child components rendered when this tab is active."
|
|
685
|
+
}
|
|
686
|
+
},
|
|
687
|
+
"additionalProperties": false
|
|
688
|
+
},
|
|
689
|
+
"minItems": 1,
|
|
690
|
+
"description": "Array of tab definitions. Each tab has a title, optional icon, and content components."
|
|
691
|
+
}
|
|
692
|
+
},
|
|
693
|
+
"additionalProperties": false,
|
|
694
|
+
"description": "Tabbed navigation container. Renders content in switchable tab panels. Flutter: TabBar + TabBarView, Vue/PrimeVue: Tabs."
|
|
695
|
+
},
|
|
696
|
+
|
|
697
|
+
"forEachComponent": {
|
|
698
|
+
"type": "object",
|
|
699
|
+
"required": ["type", "source", "as", "template"],
|
|
700
|
+
"properties": {
|
|
701
|
+
"type": { "const": "ForEach" },
|
|
702
|
+
"source": {
|
|
703
|
+
"type": "string",
|
|
704
|
+
"pattern": "^\\$",
|
|
705
|
+
"description": "Expression pointing to an array data source. Examples: $form.addresses, $instance.items, $lov.branchCode (LOV data for a field)"
|
|
706
|
+
},
|
|
707
|
+
"as": {
|
|
708
|
+
"type": "string",
|
|
709
|
+
"minLength": 1,
|
|
710
|
+
"description": "Iterator variable name. Children access current item via $item.fieldName"
|
|
711
|
+
},
|
|
712
|
+
"template": {
|
|
713
|
+
"$ref": "#/$defs/componentNode",
|
|
714
|
+
"description": "Component template to render for each item in the source array"
|
|
715
|
+
}
|
|
716
|
+
},
|
|
717
|
+
"additionalProperties": false,
|
|
718
|
+
"description": "Iteration component. Repeats the template for each item in the source array. Inside the template, $item references the current iteration item."
|
|
719
|
+
},
|
|
720
|
+
|
|
721
|
+
"nestedComponent": {
|
|
722
|
+
"type": "object",
|
|
723
|
+
"required": ["type", "ref"],
|
|
724
|
+
"properties": {
|
|
725
|
+
"type": { "const": "Component" },
|
|
726
|
+
"ref": {
|
|
727
|
+
"type": "string",
|
|
728
|
+
"pattern": "^[a-z0-9-]+$",
|
|
729
|
+
"description": "Component identifier. Resolved via naming convention: components/{ref}/schema.json + components/{ref}/view.json"
|
|
730
|
+
},
|
|
731
|
+
"bind": {
|
|
732
|
+
"oneOf": [
|
|
733
|
+
{
|
|
734
|
+
"type": "string",
|
|
735
|
+
"minLength": 1,
|
|
736
|
+
"description": "Compact object bind: pass an entire namespace to the child. '$instance' spreads all instanceData fields, '$form' spreads all formData fields. Inside the child, all received fields are accessible via $param.fieldName. '$ui' is NOT supported in compact form."
|
|
737
|
+
},
|
|
738
|
+
{
|
|
739
|
+
"type": "object",
|
|
740
|
+
"additionalProperties": { "type": "string" },
|
|
741
|
+
"description": "Multi-bind: each key is a child property name, each value is a parent expression ($form.fieldName, $instance.fieldName, or $ui.key). Example: { \"cityCode\": \"$form.city\", \"showMap\": \"$ui.showHomeMap\" }. Both input (parent->child) and output (child->parent) flow through the same mapping. $ui.* values allow passing transient UI state to child components."
|
|
742
|
+
}
|
|
743
|
+
],
|
|
744
|
+
"description": "Data binding between parent and child components. All bound values are merged into the child's $param namespace. String form ('$instance' or '$form') passes an entire object. Object form maps individual fields with explicit source prefixes ($form.*, $instance.*, or $ui.*). $ui.* bindings enable passing transient UI state (e.g. dialog visibility) to child components -- child changes write back to parent's uiState. Properties marked x-binding in the child schema declare which bindings are expected from the parent."
|
|
745
|
+
}
|
|
746
|
+
},
|
|
747
|
+
"additionalProperties": false,
|
|
748
|
+
"description": "Embeds another component by reference. Each nested component has its own schema.json (data contract) and view.json (pseudo UI). The renderer fetches and recursively renders the referenced component. The component manages its own isolated data store. Input and output flow through bind: parent properties mapped to child properties bidirectionally. Properties marked with x-binding in the child schema declare the input contract."
|
|
749
|
+
},
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
"timePickerComponent": {
|
|
753
|
+
"type": "object",
|
|
754
|
+
"required": ["type", "bind"],
|
|
755
|
+
"properties": {
|
|
756
|
+
"type": { "const": "TimePicker" },
|
|
757
|
+
"bind": { "type": "string", "minLength": 1 },
|
|
758
|
+
"variant": { "$ref": "#/$defs/inputVariant" },
|
|
759
|
+
"hourFormat": { "type": "string", "enum": ["12", "24"], "default": "24", "description": "12-hour or 24-hour display." }
|
|
760
|
+
},
|
|
761
|
+
"additionalProperties": false,
|
|
762
|
+
"description": "Time selection input. Flutter: showTimePicker, Vue/PrimeVue: DatePicker(timeOnly)."
|
|
763
|
+
},
|
|
764
|
+
|
|
765
|
+
"segmentedButtonComponent": {
|
|
766
|
+
"type": "object",
|
|
767
|
+
"required": ["type", "bind"],
|
|
768
|
+
"properties": {
|
|
769
|
+
"type": { "const": "SegmentedButton" },
|
|
770
|
+
"bind": { "type": "string", "minLength": 1 },
|
|
771
|
+
"multiSelect": { "type": "boolean", "default": false, "description": "Allow selecting multiple segments." }
|
|
772
|
+
},
|
|
773
|
+
"additionalProperties": false,
|
|
774
|
+
"description": "2-5 option toggle group. Options come from the bound schema property's enum + x-enum. Flutter: SegmentedButton, Vue/PrimeVue: SelectButton."
|
|
775
|
+
},
|
|
776
|
+
|
|
777
|
+
"searchFieldComponent": {
|
|
778
|
+
"type": "object",
|
|
779
|
+
"required": ["type", "bind"],
|
|
780
|
+
"properties": {
|
|
781
|
+
"type": { "const": "SearchField" },
|
|
782
|
+
"bind": { "type": "string", "minLength": 1 },
|
|
783
|
+
"variant": { "$ref": "#/$defs/inputVariant" }
|
|
784
|
+
},
|
|
785
|
+
"additionalProperties": false,
|
|
786
|
+
"description": "Search text input with search icon and clear button. Flutter: SearchBar, Vue/PrimeVue: IconField + InputText."
|
|
787
|
+
},
|
|
788
|
+
|
|
789
|
+
"autoCompleteComponent": {
|
|
790
|
+
"type": "object",
|
|
791
|
+
"required": ["type", "bind"],
|
|
792
|
+
"properties": {
|
|
793
|
+
"type": { "const": "AutoComplete" },
|
|
794
|
+
"bind": { "type": "string", "minLength": 1 },
|
|
795
|
+
"variant": { "$ref": "#/$defs/inputVariant" },
|
|
796
|
+
"minLength": { "type": "integer", "minimum": 0, "default": 1, "description": "Minimum characters before suggestions appear." }
|
|
797
|
+
},
|
|
798
|
+
"additionalProperties": false,
|
|
799
|
+
"description": "Text input with typeahead suggestions from x-lov. Flutter: Autocomplete, Vue/PrimeVue: AutoComplete."
|
|
800
|
+
},
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
"listTileComponent": {
|
|
804
|
+
"type": "object",
|
|
805
|
+
"required": ["type", "title"],
|
|
806
|
+
"properties": {
|
|
807
|
+
"type": { "const": "ListTile" },
|
|
808
|
+
"title": { "$ref": "#/$defs/textContent" },
|
|
809
|
+
"subtitle": { "$ref": "#/$defs/textContent" },
|
|
810
|
+
"leading": { "$ref": "#/$defs/componentNode", "description": "Widget before the title (typically Icon or Avatar)." },
|
|
811
|
+
"trailing": { "$ref": "#/$defs/componentNode", "description": "Widget after the title (typically Icon, Switch, or Checkbox)." },
|
|
812
|
+
"onTap": { "$ref": "#/$defs/actionDescriptor" }
|
|
813
|
+
},
|
|
814
|
+
"additionalProperties": false,
|
|
815
|
+
"description": "Structured list row with title, optional subtitle, and leading/trailing slots. Flutter: ListTile, Vue/PrimeVue: custom flex row."
|
|
816
|
+
},
|
|
817
|
+
|
|
818
|
+
"avatarComponent": {
|
|
819
|
+
"type": "object",
|
|
820
|
+
"required": ["type"],
|
|
821
|
+
"properties": {
|
|
822
|
+
"type": { "const": "Avatar" },
|
|
823
|
+
"source": { "type": "string", "description": "Image URL or expression for the avatar photo." },
|
|
824
|
+
"label": { "$ref": "#/$defs/textContent", "description": "Initials or text shown when no image is available." },
|
|
825
|
+
"icon": { "type": "string", "description": "Fallback Material icon name when no image or label." },
|
|
826
|
+
"shape": { "$ref": "#/$defs/avatarShape" },
|
|
827
|
+
"size": { "type": "string", "enum": ["sm", "md", "lg", "xl"], "default": "md" }
|
|
828
|
+
},
|
|
829
|
+
"additionalProperties": false,
|
|
830
|
+
"description": "User or entity avatar. Shows image, initials, or icon fallback. Flutter: CircleAvatar, Vue/PrimeVue: Avatar."
|
|
831
|
+
},
|
|
832
|
+
|
|
833
|
+
"richTextComponent": {
|
|
834
|
+
"type": "object",
|
|
835
|
+
"required": ["type", "spans"],
|
|
836
|
+
"properties": {
|
|
837
|
+
"type": { "const": "RichText" },
|
|
838
|
+
"spans": {
|
|
839
|
+
"type": "array",
|
|
840
|
+
"items": {
|
|
841
|
+
"type": "object",
|
|
842
|
+
"required": ["text"],
|
|
843
|
+
"properties": {
|
|
844
|
+
"text": { "$ref": "#/$defs/textContent" },
|
|
845
|
+
"variant": { "$ref": "#/$defs/typographyVariant" },
|
|
846
|
+
"bold": { "type": "boolean" },
|
|
847
|
+
"italic": { "type": "boolean" },
|
|
848
|
+
"link": { "type": "string", "description": "URL to open when tapped." }
|
|
849
|
+
},
|
|
850
|
+
"additionalProperties": false
|
|
851
|
+
},
|
|
852
|
+
"minItems": 1
|
|
853
|
+
}
|
|
854
|
+
},
|
|
855
|
+
"additionalProperties": false,
|
|
856
|
+
"description": "Formatted text with inline styled spans. Flutter: RichText/TextSpan, Vue/PrimeVue: inline HTML spans."
|
|
857
|
+
},
|
|
858
|
+
|
|
859
|
+
"loadingIndicatorComponent": {
|
|
860
|
+
"type": "object",
|
|
861
|
+
"required": ["type"],
|
|
862
|
+
"properties": {
|
|
863
|
+
"type": { "const": "LoadingIndicator" }
|
|
864
|
+
},
|
|
865
|
+
"additionalProperties": false,
|
|
866
|
+
"description": "M3 loading indicator (animated dots). For determinate progress use ProgressIndicator instead. Flutter: CircularProgressIndicator.adaptive, Vue/PrimeVue: ProgressSpinner."
|
|
867
|
+
},
|
|
868
|
+
|
|
869
|
+
|
|
870
|
+
"dialogComponent": {
|
|
871
|
+
"type": "object",
|
|
872
|
+
"required": ["type", "title"],
|
|
873
|
+
"properties": {
|
|
874
|
+
"type": { "const": "Dialog" },
|
|
875
|
+
"title": { "$ref": "#/$defs/textContent" },
|
|
876
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "description": "Dialog body content." },
|
|
877
|
+
"actions": {
|
|
878
|
+
"type": "array",
|
|
879
|
+
"items": { "$ref": "#/$defs/componentNode" },
|
|
880
|
+
"description": "Action buttons displayed at the bottom of the dialog."
|
|
881
|
+
},
|
|
882
|
+
"dismissible": { "type": "boolean", "default": true, "description": "Whether tapping outside closes the dialog." },
|
|
883
|
+
"icon": { "type": "string", "description": "Optional hero icon displayed above the title." },
|
|
884
|
+
"visible": { "$ref": "#/$defs/expression", "description": "Expression controlling dialog visibility (e.g. $form.showConfirmDialog)." }
|
|
885
|
+
},
|
|
886
|
+
"additionalProperties": false,
|
|
887
|
+
"description": "Modal dialog with title, content, and action buttons. Flutter: AlertDialog/SimpleDialog, Vue/PrimeVue: Dialog."
|
|
888
|
+
},
|
|
889
|
+
|
|
890
|
+
"bottomSheetComponent": {
|
|
891
|
+
"type": "object",
|
|
892
|
+
"required": ["type", "children"],
|
|
893
|
+
"properties": {
|
|
894
|
+
"type": { "const": "BottomSheet" },
|
|
895
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1 },
|
|
896
|
+
"variant": { "$ref": "#/$defs/sheetVariant" },
|
|
897
|
+
"visible": { "$ref": "#/$defs/expression", "description": "Expression controlling sheet visibility." },
|
|
898
|
+
"dragHandle": { "type": "boolean", "default": true, "description": "Show drag handle indicator at top." }
|
|
899
|
+
},
|
|
900
|
+
"additionalProperties": false,
|
|
901
|
+
"description": "Bottom-anchored surface for secondary content. Flutter: BottomSheet/DraggableScrollableSheet, Vue/PrimeVue: Drawer(position: bottom)."
|
|
902
|
+
},
|
|
903
|
+
|
|
904
|
+
"sideSheetComponent": {
|
|
905
|
+
"type": "object",
|
|
906
|
+
"required": ["type", "children"],
|
|
907
|
+
"properties": {
|
|
908
|
+
"type": { "const": "SideSheet" },
|
|
909
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1 },
|
|
910
|
+
"variant": { "$ref": "#/$defs/sheetVariant" },
|
|
911
|
+
"visible": { "$ref": "#/$defs/expression", "description": "Expression controlling sheet visibility." },
|
|
912
|
+
"title": { "$ref": "#/$defs/textContent" }
|
|
913
|
+
},
|
|
914
|
+
"additionalProperties": false,
|
|
915
|
+
"description": "Side-anchored surface for detail or filter panels. Flutter: end Drawer, Vue/PrimeVue: Drawer(position: right)."
|
|
916
|
+
},
|
|
917
|
+
|
|
918
|
+
"snackbarComponent": {
|
|
919
|
+
"type": "object",
|
|
920
|
+
"required": ["type", "content"],
|
|
921
|
+
"properties": {
|
|
922
|
+
"type": { "const": "Snackbar" },
|
|
923
|
+
"content": { "$ref": "#/$defs/textContent" },
|
|
924
|
+
"action": { "$ref": "#/$defs/actionDescriptor", "description": "Optional action button in the snackbar." },
|
|
925
|
+
"duration": { "type": "integer", "default": 4000, "description": "Auto-dismiss duration in milliseconds." },
|
|
926
|
+
"variant": { "type": "string", "enum": ["standard", "success", "error", "warning", "info"], "default": "standard" }
|
|
927
|
+
},
|
|
928
|
+
"additionalProperties": false,
|
|
929
|
+
"description": "Brief message bar at bottom of screen. Flutter: SnackBar, Vue/PrimeVue: Toast."
|
|
930
|
+
},
|
|
931
|
+
|
|
932
|
+
"tooltipComponent": {
|
|
933
|
+
"type": "object",
|
|
934
|
+
"required": ["type", "content", "children"],
|
|
935
|
+
"properties": {
|
|
936
|
+
"type": { "const": "Tooltip" },
|
|
937
|
+
"content": { "$ref": "#/$defs/textContent", "description": "Tooltip message text." },
|
|
938
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1, "maxItems": 1 },
|
|
939
|
+
"variant": { "type": "string", "enum": ["plain", "rich"], "default": "plain", "description": "plain: single-line text. rich: supports title and longer content." }
|
|
940
|
+
},
|
|
941
|
+
"additionalProperties": false,
|
|
942
|
+
"description": "Hover/tap help text wrapping a child widget. Flutter: Tooltip, Vue/PrimeVue: v-tooltip directive."
|
|
943
|
+
},
|
|
944
|
+
|
|
945
|
+
|
|
946
|
+
"appBarComponent": {
|
|
947
|
+
"type": "object",
|
|
948
|
+
"required": ["type", "title"],
|
|
949
|
+
"properties": {
|
|
950
|
+
"type": { "const": "AppBar" },
|
|
951
|
+
"title": { "$ref": "#/$defs/textContent" },
|
|
952
|
+
"variant": { "$ref": "#/$defs/appBarVariant" },
|
|
953
|
+
"leading": { "$ref": "#/$defs/componentNode", "description": "Widget on the left (typically IconButton for menu or back)." },
|
|
954
|
+
"actions": {
|
|
955
|
+
"type": "array",
|
|
956
|
+
"items": { "$ref": "#/$defs/componentNode" },
|
|
957
|
+
"description": "Trailing action widgets (typically IconButtons)."
|
|
958
|
+
}
|
|
959
|
+
},
|
|
960
|
+
"additionalProperties": false,
|
|
961
|
+
"description": "Top app bar with title and actions. Flutter: AppBar/SliverAppBar, Vue/PrimeVue: Toolbar."
|
|
962
|
+
},
|
|
963
|
+
|
|
964
|
+
"navigationBarComponent": {
|
|
965
|
+
"type": "object",
|
|
966
|
+
"required": ["type", "destinations", "bind"],
|
|
967
|
+
"properties": {
|
|
968
|
+
"type": { "const": "NavigationBar" },
|
|
969
|
+
"bind": { "type": "string", "minLength": 1, "description": "Schema property to store the selected destination index/value." },
|
|
970
|
+
"destinations": {
|
|
971
|
+
"type": "array",
|
|
972
|
+
"items": {
|
|
973
|
+
"type": "object",
|
|
974
|
+
"required": ["icon", "label"],
|
|
975
|
+
"properties": {
|
|
976
|
+
"icon": { "type": "string", "description": "Material icon name." },
|
|
977
|
+
"selectedIcon": { "type": "string", "description": "Icon when selected (optional, defaults to filled variant)." },
|
|
978
|
+
"label": { "$ref": "#/$defs/textContent" },
|
|
979
|
+
"value": { "type": "string", "description": "Value written to bound property when selected." }
|
|
980
|
+
},
|
|
981
|
+
"additionalProperties": false
|
|
982
|
+
},
|
|
983
|
+
"minItems": 3,
|
|
984
|
+
"maxItems": 5,
|
|
985
|
+
"description": "Navigation destinations (3-5 items per M3 spec)."
|
|
986
|
+
}
|
|
987
|
+
},
|
|
988
|
+
"additionalProperties": false,
|
|
989
|
+
"description": "Bottom navigation bar. Flutter: NavigationBar, Vue/PrimeVue: TabMenu."
|
|
990
|
+
},
|
|
991
|
+
|
|
992
|
+
"navigationDrawerComponent": {
|
|
993
|
+
"type": "object",
|
|
994
|
+
"required": ["type", "items"],
|
|
995
|
+
"properties": {
|
|
996
|
+
"type": { "const": "NavigationDrawer" },
|
|
997
|
+
"items": {
|
|
998
|
+
"type": "array",
|
|
999
|
+
"items": {
|
|
1000
|
+
"oneOf": [
|
|
1001
|
+
{
|
|
1002
|
+
"type": "object",
|
|
1003
|
+
"required": ["label"],
|
|
1004
|
+
"properties": {
|
|
1005
|
+
"icon": { "type": "string" },
|
|
1006
|
+
"label": { "$ref": "#/$defs/textContent" },
|
|
1007
|
+
"action": { "$ref": "#/$defs/actionDescriptor" },
|
|
1008
|
+
"badge": { "$ref": "#/$defs/textContent" }
|
|
1009
|
+
},
|
|
1010
|
+
"additionalProperties": false
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
"type": "object",
|
|
1014
|
+
"required": ["divider"],
|
|
1015
|
+
"properties": {
|
|
1016
|
+
"divider": { "const": true }
|
|
1017
|
+
},
|
|
1018
|
+
"additionalProperties": false
|
|
1019
|
+
},
|
|
1020
|
+
{
|
|
1021
|
+
"type": "object",
|
|
1022
|
+
"required": ["header"],
|
|
1023
|
+
"properties": {
|
|
1024
|
+
"header": { "$ref": "#/$defs/textContent" }
|
|
1025
|
+
},
|
|
1026
|
+
"additionalProperties": false
|
|
1027
|
+
}
|
|
1028
|
+
]
|
|
1029
|
+
},
|
|
1030
|
+
"minItems": 1
|
|
1031
|
+
},
|
|
1032
|
+
"header": { "$ref": "#/$defs/componentNode", "description": "Optional header widget above the item list." },
|
|
1033
|
+
"variant": { "type": "string", "enum": ["standard", "modal"], "default": "modal" },
|
|
1034
|
+
"visible": { "$ref": "#/$defs/expression" }
|
|
1035
|
+
},
|
|
1036
|
+
"additionalProperties": false,
|
|
1037
|
+
"description": "Side navigation drawer with menu items, dividers, and section headers. Flutter: NavigationDrawer/Drawer, Vue/PrimeVue: Drawer + Menu."
|
|
1038
|
+
},
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
"menuComponent": {
|
|
1042
|
+
"type": "object",
|
|
1043
|
+
"required": ["type", "items"],
|
|
1044
|
+
"properties": {
|
|
1045
|
+
"type": { "const": "Menu" },
|
|
1046
|
+
"items": {
|
|
1047
|
+
"type": "array",
|
|
1048
|
+
"items": {
|
|
1049
|
+
"oneOf": [
|
|
1050
|
+
{
|
|
1051
|
+
"type": "object",
|
|
1052
|
+
"required": ["label"],
|
|
1053
|
+
"properties": {
|
|
1054
|
+
"icon": { "type": "string" },
|
|
1055
|
+
"label": { "$ref": "#/$defs/textContent" },
|
|
1056
|
+
"action": { "$ref": "#/$defs/actionDescriptor" },
|
|
1057
|
+
"disabled": { "type": "boolean", "default": false }
|
|
1058
|
+
},
|
|
1059
|
+
"additionalProperties": false
|
|
1060
|
+
},
|
|
1061
|
+
{
|
|
1062
|
+
"type": "object",
|
|
1063
|
+
"required": ["divider"],
|
|
1064
|
+
"properties": {
|
|
1065
|
+
"divider": { "const": true }
|
|
1066
|
+
},
|
|
1067
|
+
"additionalProperties": false
|
|
1068
|
+
}
|
|
1069
|
+
]
|
|
1070
|
+
},
|
|
1071
|
+
"minItems": 1
|
|
1072
|
+
},
|
|
1073
|
+
"anchor": { "$ref": "#/$defs/componentNode", "description": "The widget that triggers menu open (typically an IconButton)." }
|
|
1074
|
+
},
|
|
1075
|
+
"additionalProperties": false,
|
|
1076
|
+
"description": "Popup/context menu showing a list of actions. Flutter: PopupMenuButton/DropdownMenu, Vue/PrimeVue: Menu/TieredMenu."
|
|
1077
|
+
},
|
|
1078
|
+
|
|
1079
|
+
"toolbarComponent": {
|
|
1080
|
+
"type": "object",
|
|
1081
|
+
"required": ["type", "children"],
|
|
1082
|
+
"properties": {
|
|
1083
|
+
"type": { "const": "Toolbar" },
|
|
1084
|
+
"children": { "type": "array", "items": { "$ref": "#/$defs/componentNode" }, "minItems": 1, "description": "Action widgets (Buttons, IconButtons, etc.)." }
|
|
1085
|
+
},
|
|
1086
|
+
"additionalProperties": false,
|
|
1087
|
+
"description": "Horizontal bar of frequently used actions. Flutter: BottomAppBar, Vue/PrimeVue: Toolbar."
|
|
1088
|
+
},
|
|
1089
|
+
|
|
1090
|
+
"carouselComponent": {
|
|
1091
|
+
"type": "object",
|
|
1092
|
+
"required": ["type", "source", "template"],
|
|
1093
|
+
"properties": {
|
|
1094
|
+
"type": { "const": "Carousel" },
|
|
1095
|
+
"source": { "$ref": "#/$defs/expression", "description": "Expression pointing to an array data source." },
|
|
1096
|
+
"template": { "$ref": "#/$defs/componentNode", "description": "Component template for each carousel item." },
|
|
1097
|
+
"autoPlay": { "type": "boolean", "default": false },
|
|
1098
|
+
"showIndicators": { "type": "boolean", "default": true, "description": "Show page/dot indicators." }
|
|
1099
|
+
},
|
|
1100
|
+
"additionalProperties": false,
|
|
1101
|
+
"description": "Horizontal scrolling content carousel. Flutter: PageView/CarouselView, Vue/PrimeVue: Carousel."
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
}
|