cxtms 1.9.13

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.
Files changed (215) hide show
  1. package/README.md +384 -0
  2. package/dist/cli.d.ts +6 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +4784 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/extractUtils.d.ts +11 -0
  7. package/dist/extractUtils.d.ts.map +1 -0
  8. package/dist/extractUtils.js +19 -0
  9. package/dist/extractUtils.js.map +1 -0
  10. package/dist/index.d.ts +7 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +11 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/types.d.ts +129 -0
  15. package/dist/types.d.ts.map +1 -0
  16. package/dist/types.js +6 -0
  17. package/dist/types.js.map +1 -0
  18. package/dist/utils/schemaLoader.d.ts +17 -0
  19. package/dist/utils/schemaLoader.d.ts.map +1 -0
  20. package/dist/utils/schemaLoader.js +134 -0
  21. package/dist/utils/schemaLoader.js.map +1 -0
  22. package/dist/validator.d.ts +72 -0
  23. package/dist/validator.d.ts.map +1 -0
  24. package/dist/validator.js +432 -0
  25. package/dist/validator.js.map +1 -0
  26. package/dist/workflowValidator.d.ts +103 -0
  27. package/dist/workflowValidator.d.ts.map +1 -0
  28. package/dist/workflowValidator.js +753 -0
  29. package/dist/workflowValidator.js.map +1 -0
  30. package/package.json +51 -0
  31. package/schemas/actions/all.json +27 -0
  32. package/schemas/actions/clipboard.json +46 -0
  33. package/schemas/actions/confirm.json +21 -0
  34. package/schemas/actions/consoleLog.json +16 -0
  35. package/schemas/actions/dialog.json +25 -0
  36. package/schemas/actions/fileDownload.json +16 -0
  37. package/schemas/actions/forEach.json +31 -0
  38. package/schemas/actions/if.json +12 -0
  39. package/schemas/actions/mutation.json +25 -0
  40. package/schemas/actions/navigate.json +18 -0
  41. package/schemas/actions/navigateBack.json +22 -0
  42. package/schemas/actions/navigateBackOrClose.json +21 -0
  43. package/schemas/actions/notification.json +19 -0
  44. package/schemas/actions/openBarcodeScanner.json +104 -0
  45. package/schemas/actions/query.json +32 -0
  46. package/schemas/actions/refresh.json +13 -0
  47. package/schemas/actions/resetDirtyState.json +22 -0
  48. package/schemas/actions/setFields.json +21 -0
  49. package/schemas/actions/setStore.json +13 -0
  50. package/schemas/actions/validateForm.json +15 -0
  51. package/schemas/actions/workflow.json +24 -0
  52. package/schemas/components/README.md +147 -0
  53. package/schemas/components/appComponent.json +58 -0
  54. package/schemas/components/barcodeScanner.json +69 -0
  55. package/schemas/components/button.json +123 -0
  56. package/schemas/components/calendar.json +489 -0
  57. package/schemas/components/card.json +176 -0
  58. package/schemas/components/collection.json +54 -0
  59. package/schemas/components/dataGrid.json +119 -0
  60. package/schemas/components/datasource.json +151 -0
  61. package/schemas/components/dropdown.json +57 -0
  62. package/schemas/components/field-collection.json +618 -0
  63. package/schemas/components/field.json +265 -0
  64. package/schemas/components/form.json +234 -0
  65. package/schemas/components/index.json +71 -0
  66. package/schemas/components/layout.json +69 -0
  67. package/schemas/components/module.json +167 -0
  68. package/schemas/components/navDropdown.json +36 -0
  69. package/schemas/components/navbar.json +78 -0
  70. package/schemas/components/navbarItem.json +28 -0
  71. package/schemas/components/navbarLink.json +36 -0
  72. package/schemas/components/row.json +31 -0
  73. package/schemas/components/slot.json +30 -0
  74. package/schemas/components/tab.json +34 -0
  75. package/schemas/components/tabs.json +35 -0
  76. package/schemas/components/timeline.json +172 -0
  77. package/schemas/components/timelineGrid.json +328 -0
  78. package/schemas/fields/README.md +66 -0
  79. package/schemas/fields/attachment.json +156 -0
  80. package/schemas/fields/autocomplete-googleplaces.json +130 -0
  81. package/schemas/fields/checkbox.json +82 -0
  82. package/schemas/fields/date.json +88 -0
  83. package/schemas/fields/datetime.json +75 -0
  84. package/schemas/fields/email.json +75 -0
  85. package/schemas/fields/index.json +53 -0
  86. package/schemas/fields/number.json +91 -0
  87. package/schemas/fields/password.json +70 -0
  88. package/schemas/fields/radio.json +94 -0
  89. package/schemas/fields/rangedatetime.json +56 -0
  90. package/schemas/fields/select-async.json +334 -0
  91. package/schemas/fields/select.json +115 -0
  92. package/schemas/fields/tel.json +79 -0
  93. package/schemas/fields/text.json +86 -0
  94. package/schemas/fields/textarea.json +95 -0
  95. package/schemas/fields/time.json +91 -0
  96. package/schemas/fields/url.json +74 -0
  97. package/schemas/schema.graphql +12248 -0
  98. package/schemas/schemas.json +610 -0
  99. package/schemas/workflows/activity.json +96 -0
  100. package/schemas/workflows/common/condition.json +48 -0
  101. package/schemas/workflows/common/expression.json +76 -0
  102. package/schemas/workflows/common/mapping.json +173 -0
  103. package/schemas/workflows/common/step.json +38 -0
  104. package/schemas/workflows/flow/aggregation.json +44 -0
  105. package/schemas/workflows/flow/entity.json +129 -0
  106. package/schemas/workflows/flow/state.json +105 -0
  107. package/schemas/workflows/flow/transition.json +143 -0
  108. package/schemas/workflows/input.json +122 -0
  109. package/schemas/workflows/output.json +61 -0
  110. package/schemas/workflows/schedule.json +26 -0
  111. package/schemas/workflows/tasks/accounting-transaction.json +95 -0
  112. package/schemas/workflows/tasks/action-event.json +65 -0
  113. package/schemas/workflows/tasks/all.json +152 -0
  114. package/schemas/workflows/tasks/appmodule.json +56 -0
  115. package/schemas/workflows/tasks/attachment.json +97 -0
  116. package/schemas/workflows/tasks/authentication.json +86 -0
  117. package/schemas/workflows/tasks/caching.json +68 -0
  118. package/schemas/workflows/tasks/charge.json +92 -0
  119. package/schemas/workflows/tasks/commodity.json +92 -0
  120. package/schemas/workflows/tasks/contact-address.json +72 -0
  121. package/schemas/workflows/tasks/contact-payment-method.json +72 -0
  122. package/schemas/workflows/tasks/contact.json +82 -0
  123. package/schemas/workflows/tasks/csv.json +81 -0
  124. package/schemas/workflows/tasks/document-render.json +105 -0
  125. package/schemas/workflows/tasks/document-send.json +84 -0
  126. package/schemas/workflows/tasks/edi.json +157 -0
  127. package/schemas/workflows/tasks/email-send.json +110 -0
  128. package/schemas/workflows/tasks/error.json +72 -0
  129. package/schemas/workflows/tasks/export.json +90 -0
  130. package/schemas/workflows/tasks/filetransfer.json +102 -0
  131. package/schemas/workflows/tasks/flow-transition.json +68 -0
  132. package/schemas/workflows/tasks/foreach.json +69 -0
  133. package/schemas/workflows/tasks/generic.json +47 -0
  134. package/schemas/workflows/tasks/graphql.json +78 -0
  135. package/schemas/workflows/tasks/httpRequest.json +161 -0
  136. package/schemas/workflows/tasks/import.json +64 -0
  137. package/schemas/workflows/tasks/inventory.json +67 -0
  138. package/schemas/workflows/tasks/job.json +88 -0
  139. package/schemas/workflows/tasks/log.json +73 -0
  140. package/schemas/workflows/tasks/map.json +58 -0
  141. package/schemas/workflows/tasks/movement.json +54 -0
  142. package/schemas/workflows/tasks/note.json +59 -0
  143. package/schemas/workflows/tasks/number.json +65 -0
  144. package/schemas/workflows/tasks/order-tracking-event.json +109 -0
  145. package/schemas/workflows/tasks/order.json +139 -0
  146. package/schemas/workflows/tasks/payment.json +85 -0
  147. package/schemas/workflows/tasks/pdf-document.json +60 -0
  148. package/schemas/workflows/tasks/postal-codes.json +92 -0
  149. package/schemas/workflows/tasks/resolve-timezone.json +65 -0
  150. package/schemas/workflows/tasks/setVariable.json +76 -0
  151. package/schemas/workflows/tasks/switch.json +75 -0
  152. package/schemas/workflows/tasks/template.json +73 -0
  153. package/schemas/workflows/tasks/tracking-event.json +137 -0
  154. package/schemas/workflows/tasks/transmission.json +185 -0
  155. package/schemas/workflows/tasks/unzip-file.json +68 -0
  156. package/schemas/workflows/tasks/user.json +70 -0
  157. package/schemas/workflows/tasks/validation.json +99 -0
  158. package/schemas/workflows/tasks/while.json +53 -0
  159. package/schemas/workflows/tasks/workflow-execute.json +82 -0
  160. package/schemas/workflows/trigger.json +90 -0
  161. package/schemas/workflows/variable.json +46 -0
  162. package/schemas/workflows/workflow.json +335 -0
  163. package/scripts/postinstall.js +291 -0
  164. package/scripts/setup-vscode.js +80 -0
  165. package/skills/cxtms-developer/SKILL.md +118 -0
  166. package/skills/cxtms-developer/ref-cli-auth.md +120 -0
  167. package/skills/cxtms-developer/ref-entity-accounting.md +180 -0
  168. package/skills/cxtms-developer/ref-entity-commodity.md +239 -0
  169. package/skills/cxtms-developer/ref-entity-contact.md +163 -0
  170. package/skills/cxtms-developer/ref-entity-geography.md +154 -0
  171. package/skills/cxtms-developer/ref-entity-job.md +77 -0
  172. package/skills/cxtms-developer/ref-entity-notification.md +85 -0
  173. package/skills/cxtms-developer/ref-entity-order-sub.md +160 -0
  174. package/skills/cxtms-developer/ref-entity-order.md +183 -0
  175. package/skills/cxtms-developer/ref-entity-organization.md +41 -0
  176. package/skills/cxtms-developer/ref-entity-rate.md +182 -0
  177. package/skills/cxtms-developer/ref-entity-shared.md +176 -0
  178. package/skills/cxtms-developer/ref-entity-warehouse.md +115 -0
  179. package/skills/cxtms-developer/ref-graphql-query.md +309 -0
  180. package/skills/cxtms-module-builder/SKILL.md +477 -0
  181. package/skills/cxtms-module-builder/ref-components-data.md +293 -0
  182. package/skills/cxtms-module-builder/ref-components-display.md +411 -0
  183. package/skills/cxtms-module-builder/ref-components-forms.md +369 -0
  184. package/skills/cxtms-module-builder/ref-components-interactive.md +317 -0
  185. package/skills/cxtms-module-builder/ref-components-layout.md +390 -0
  186. package/skills/cxtms-module-builder/ref-components-specialized.md +477 -0
  187. package/skills/cxtms-workflow-builder/SKILL.md +438 -0
  188. package/skills/cxtms-workflow-builder/ref-accounting.md +66 -0
  189. package/skills/cxtms-workflow-builder/ref-communication.md +169 -0
  190. package/skills/cxtms-workflow-builder/ref-entity.md +342 -0
  191. package/skills/cxtms-workflow-builder/ref-expressions-ncalc.md +128 -0
  192. package/skills/cxtms-workflow-builder/ref-expressions-template.md +161 -0
  193. package/skills/cxtms-workflow-builder/ref-filetransfer.md +80 -0
  194. package/skills/cxtms-workflow-builder/ref-flow.md +210 -0
  195. package/skills/cxtms-workflow-builder/ref-other.md +157 -0
  196. package/skills/cxtms-workflow-builder/ref-query.md +105 -0
  197. package/skills/cxtms-workflow-builder/ref-utilities.md +417 -0
  198. package/templates/module-configuration.yaml +44 -0
  199. package/templates/module-form.yaml +152 -0
  200. package/templates/module-grid.yaml +229 -0
  201. package/templates/module-select.yaml +139 -0
  202. package/templates/module.yaml +84 -0
  203. package/templates/workflow-api-tracking.yaml +189 -0
  204. package/templates/workflow-basic.yaml +76 -0
  205. package/templates/workflow-document.yaml +155 -0
  206. package/templates/workflow-entity-trigger.yaml +90 -0
  207. package/templates/workflow-ftp-edi.yaml +158 -0
  208. package/templates/workflow-ftp-tracking.yaml +161 -0
  209. package/templates/workflow-mcp-tool.yaml +112 -0
  210. package/templates/workflow-public-api.yaml +135 -0
  211. package/templates/workflow-scheduled-execute.yaml +75 -0
  212. package/templates/workflow-scheduled.yaml +125 -0
  213. package/templates/workflow-utility.yaml +96 -0
  214. package/templates/workflow-webhook.yaml +128 -0
  215. package/templates/workflow.yaml +140 -0
@@ -0,0 +1,369 @@
1
+ # Form & Input Components
2
+
3
+ ## Contents
4
+ - Form component
5
+ - Field component
6
+ - FieldCollection component
7
+ - BarcodeScanner component
8
+
9
+ ## form
10
+
11
+ Data entry form with validation, queries, and submission. Wraps React Hook Form's FormProvider.
12
+
13
+ **Props:**
14
+ | Prop | Type | Description |
15
+ |------|------|-------------|
16
+ | `title` | `ILocalizeString` | Form title |
17
+ | `initialValues` | `object \| query config` | Initial data — static object, template, or query config |
18
+ | `initialValues.fromQuery` | `{name, path}` | Load initial values from a named query |
19
+ | `initialValues.append` | `Record<string, any>` | Merge additional defaults after query load |
20
+ | `validationSchema` | `Record<string, {type, required?, ...}>` | Yup-based validation rules |
21
+ | `queries` | `QueryDef[]` | GraphQL queries for data loading |
22
+ | `prefix` | `string` | Field name namespace prefix |
23
+ | `refreshHandler` | `string` | Remount on refresh event |
24
+ | `dirtyGuard` | `DirtyGuardProps` | Unsaved changes protection |
25
+ | `dirtyGuard.enabled` | `boolean` | Enable guard |
26
+ | `dirtyGuard.title` | `ILocalizeString` | Dialog title |
27
+ | `dirtyGuard.message` | `ILocalizeString` | Dialog message |
28
+ | `dirtyGuard.confirmLabel` | `ILocalizeString` | Confirm button text |
29
+ | `dirtyGuard.cancelLabel` | `ILocalizeString` | Cancel button text |
30
+ | `autoSave` | `boolean` | Auto-save on field change |
31
+ | `resetOnSubmit` | `boolean` | Reset form after submit |
32
+ | `preventDefault` | `boolean` | Prevent default form submit |
33
+ | `toolbar` | `component[]` | Toolbar components |
34
+ | `cols` | `number` | Column layout for children |
35
+ | `orientation` | `string` | Layout orientation |
36
+
37
+ **Events:**
38
+ | Event | Description |
39
+ |-------|-------------|
40
+ | `onSubmit` | Action chain on form submission |
41
+ | `onChange` | Action chain on any field change |
42
+ | `onLoad` | Action chain when form data loads |
43
+ | `onReset` | Action chain on form reset |
44
+ | `onValidate` | Action chain on validation |
45
+ | `onError` | Action chain on error |
46
+
47
+ **Children:** Yes — typically `field` components. Provides `formName` and `createMode` in variables.
48
+
49
+ ```yaml
50
+ component: form
51
+ name: orderForm
52
+ props:
53
+ title: { en-US: "Order Details" }
54
+ toolbar:
55
+ - component: button
56
+ name: saveBtn
57
+ props:
58
+ label: { en-US: "Save" }
59
+ icon: check
60
+ options: { type: submit, variant: primary }
61
+ queries:
62
+ - name: getOrder
63
+ query:
64
+ command: |
65
+ query GetOrder($id: Int!) {
66
+ order(id: $id) { id orderNumber status }
67
+ }
68
+ variables:
69
+ id: "{{ number id }}"
70
+ initialValues:
71
+ fromQuery:
72
+ name: getOrder
73
+ path: order
74
+ append:
75
+ status: "Draft"
76
+ validationSchema:
77
+ orderNumber:
78
+ type: string
79
+ required: true
80
+ status:
81
+ type: string
82
+ required: true
83
+ dirtyGuard:
84
+ enabled: true
85
+ title: { en-US: "Unsaved Changes" }
86
+ message: { en-US: "You have unsaved changes. Leave?" }
87
+ confirmLabel: { en-US: "Leave" }
88
+ cancelLabel: { en-US: "Stay" }
89
+ onSubmit:
90
+ - mutation:
91
+ command: |
92
+ mutation SaveOrder($input: OrderInput!) {
93
+ saveOrder(input: $input) { id }
94
+ }
95
+ variables:
96
+ input: "{{ form }}"
97
+ onSuccess:
98
+ - notification: { message: { en-US: "Saved!" }, type: success }
99
+ - navigateBack: { fallback: "/orders" }
100
+ children:
101
+ - component: field
102
+ name: orderNumber
103
+ props: { type: text, label: { en-US: "Order Number" }, required: true }
104
+ - component: field
105
+ name: status
106
+ props:
107
+ type: select
108
+ label: { en-US: "Status" }
109
+ items:
110
+ - { label: "Draft", value: "Draft" }
111
+ - { label: "Active", value: "Active" }
112
+ ```
113
+
114
+ ---
115
+
116
+ ## field
117
+
118
+ Polymorphic form field — renders different input types based on `type` prop.
119
+
120
+ **Props:**
121
+ | Prop | Type | Description |
122
+ |------|------|-------------|
123
+ | `type` | `string` | **Required.** Field type (see table below) |
124
+ | `label` | `ILocalizeString` | Localized label |
125
+ | `placeholder` | `string` | Placeholder text (template-parsed) |
126
+ | `disabled` | `string \| boolean` | Disable state (template expression) |
127
+ | `readonly` | `boolean` | Read-only mode |
128
+ | `required` | `boolean` | Required field |
129
+ | `prefix` | `string` | Field name prefix for nested paths |
130
+ | `transformValue` | `{onEdit?, onLoad?}` | Template expressions to transform values |
131
+ | `multiple` | `boolean` | Multi-value mode (for `text`) |
132
+ | `autoComplete` | `string` | HTML autocomplete attribute |
133
+ | `rows` | `number` | Rows for textarea (default 2) |
134
+ | `defaultCountry` | `string` | Default country for phone type |
135
+ | `isClearable` | `boolean` | Allow clearing the value |
136
+ | `InputProps` | `object` | Passed to underlying MUI TextField |
137
+
138
+ **Field Types:**
139
+ | Type | Description |
140
+ |------|-------------|
141
+ | `text` | Standard text input. `multiple: true` → multi-value tags |
142
+ | `number` | Numeric input |
143
+ | `email` | Email input |
144
+ | `password` | Password input |
145
+ | `tel` / `phone` | Phone number with country selector |
146
+ | `textarea` | Multi-line text with `rows` prop |
147
+ | `checkbox` | Boolean checkbox |
148
+ | `radio` | Radio button (use `value` prop) |
149
+ | `date` | Date picker |
150
+ | `datetime` | Date + time picker |
151
+ | `rangedatetime` | Date range picker |
152
+ | `enhanced-rangedatetime` | Enhanced date range picker |
153
+ | `time` | Time picker |
154
+ | `select` | Dropdown select from `items[]` |
155
+ | `select-async` | Async search select (GraphQL-backed) |
156
+ | `autocomplete` | Autocomplete from `items[]` |
157
+ | `autocomplete-async` | Async autocomplete (GraphQL-backed) |
158
+ | `autocomplete-googleplaces` | Google Places autocomplete |
159
+ | `file` | File upload (converts to byte array) |
160
+ | `attachment` | File attachment |
161
+ | `hidden` | Hidden input |
162
+ | `quill` | Rich text editor (Quill) |
163
+ | `object` | JSON object editor |
164
+ | `yaml` | YAML editor |
165
+ | `secret` | Encrypted secret input — stores `${secret:qualifiedName}` reference. Requires `secretPath` prop for naming. |
166
+
167
+ **Select/Async options (under `options`):**
168
+ | Prop | Type | Description |
169
+ |------|------|-------------|
170
+ | `items` | `{label, value}[]` | Static select items |
171
+ | `allowMultiple` | `boolean` | Multi-select mode |
172
+ | `allowClear` | `boolean` | Show clear button |
173
+ | `allowSearch` | `boolean` | Searchable dropdown |
174
+ | `valueFieldName` | `string` | Result field holding the value |
175
+ | `itemLabelTemplate` | `string` | Handlebars template for labels |
176
+ | `itemValueTemplate` | `string` | Handlebars template for values |
177
+ | `navigateActionPermission` | `string` | Permission for edit icon |
178
+ | `searchQuery` | `{name, path, params}` | Paginated search query ref |
179
+ | `valueQuery` | `{name, path, params}` | Single-value lookup query ref |
180
+ | `variant` | `string` | Select variant |
181
+
182
+ **Events:**
183
+ | Event | Description |
184
+ |-------|-------------|
185
+ | `onClick` | Fires on click |
186
+ | `onChange` | Fires on value change (data: `changedValues`, `checked`) |
187
+ | `onBlur` | Fires on blur |
188
+ | `onFocus` | Fires on focus |
189
+ | `onKeyPress` | Fires on keypress (data: `key`, `keyCode`) |
190
+ | `onSelectValue` | Fires on select-async value selection |
191
+ | `onEditClick` | Fires when edit icon clicked. Supported on text and select-async fields. Passes current form values (with optional `valueFieldName`) to the action context |
192
+
193
+ ```yaml
194
+ # Text field
195
+ - component: field
196
+ name: companyName
197
+ props:
198
+ type: text
199
+ label: { en-US: "Company Name" }
200
+ required: true
201
+ placeholder: "Enter company name"
202
+
203
+ # Select field
204
+ - component: field
205
+ name: status
206
+ props:
207
+ type: select
208
+ label: { en-US: "Status" }
209
+ items:
210
+ - { label: "Active", value: "active" }
211
+ - { label: "Inactive", value: "inactive" }
212
+
213
+ # Async select with search
214
+ - component: field
215
+ name: customerId
216
+ props:
217
+ type: select-async
218
+ label: { en-US: "Customer" }
219
+ options:
220
+ valueFieldName: contactId
221
+ itemLabelTemplate: "{{contactName}}"
222
+ itemValueTemplate: "{{contactId}}"
223
+ allowSearch: true
224
+ allowClear: true
225
+ searchQuery:
226
+ name: getContacts
227
+ path: contacts.items
228
+ params:
229
+ search: "{{ string search }}"
230
+ take: "{{ number pageSize }}"
231
+ skip: "{{ number skip }}"
232
+ valueQuery:
233
+ name: getContact
234
+ path: contact
235
+ params:
236
+ contactId: "{{ contactId }}"
237
+ queries:
238
+ - name: getContacts
239
+ query:
240
+ command: >-
241
+ query($search: String!, $take: Int!, $skip: Int!) {
242
+ contacts(search: $search, take: $take, skip: $skip) {
243
+ items { contactId contactName } totalCount
244
+ }
245
+ }
246
+ - name: getContact
247
+ query:
248
+ command: >-
249
+ query($contactId: Int!) {
250
+ contact(contactId: $contactId) { contactId contactName }
251
+ }
252
+ variables:
253
+ contactId: "{{ number contactId }}"
254
+
255
+ # Date field with transform
256
+ - component: field
257
+ name: effectiveDate
258
+ props:
259
+ type: date
260
+ label: { en-US: "Effective Date" }
261
+ transformValue:
262
+ onLoad: "{{ format effectiveDate YYYY-MM-DD }}"
263
+
264
+ # Conditional visibility
265
+ - component: field
266
+ name: notes
267
+ props:
268
+ type: textarea
269
+ label: { en-US: "Notes" }
270
+ rows: 4
271
+ disabled: "{{ eval !canEdit }}"
272
+ ```
273
+
274
+ ---
275
+
276
+ ## field-collection
277
+
278
+ Dynamic array/list editor for repeating field groups. Supports add/remove/reorder with drag-and-drop.
279
+
280
+ **Props:**
281
+ | Prop | Type | Default | Description |
282
+ |------|------|---------|-------------|
283
+ | `fieldName` | `string` | — | **Required.** Form array field binding |
284
+ | `itemTemplate` | `ComponentProps` | — | Template for each item |
285
+ | `itemType` | `object \| string \| number \| boolean` | `object` | Item type |
286
+ | `options.allowAdd` | `boolean` | `true` | Show add button |
287
+ | `options.allowRemove` | `boolean` | `true` | Show remove buttons |
288
+ | `options.allowRemoveAll` | `boolean` | `false` | Show remove all button |
289
+ | `options.allowReorder` | `boolean` | `true` | Enable drag-and-drop |
290
+ | `options.minItems` | `number` | `0` | Minimum items (auto-created) |
291
+ | `options.maxItems` | `number` | `∞` | Maximum items |
292
+ | `addButton.label` | `ILocalizeString` | `Add Item` | Add button label |
293
+ | `addButton.icon` | `string` | `plus` | Add button icon |
294
+ | `addButton.position` | `top \| bottom \| both` | `bottom` | Add button placement |
295
+ | `defaultItem` | `any` | — | Template for new items |
296
+ | `layout` | `list \| grid \| accordion` | `list` | Layout mode |
297
+ | `cols` | `number` | `1` | Grid columns |
298
+ | `groupMode` | `boolean` | `false` | Enable grouping |
299
+ | `groupBy` | `string` | — | Field path to group by |
300
+ | `groups` | `{key, label, icon?}[]` | — | Group definitions |
301
+ | `showIndex` | `boolean` | `false` | Show item index |
302
+ | `showDragHandle` | `boolean` | `false` | Show drag handles |
303
+
304
+ **Children:** Uses `itemTemplate` (not `children`). Each item gets `item`, `index`, `collection` variables.
305
+
306
+ ```yaml
307
+ component: field-collection
308
+ name: lineItems
309
+ props:
310
+ fieldName: lineItems
311
+ options:
312
+ allowAdd: true
313
+ allowRemove: true
314
+ allowReorder: true
315
+ minItems: 1
316
+ maxItems: 50
317
+ addButton:
318
+ label: { en-US: "Add Line Item" }
319
+ icon: plus
320
+ position: bottom
321
+ defaultItem:
322
+ description: ""
323
+ quantity: 1
324
+ unitPrice: 0
325
+ layout: list
326
+ itemTemplate:
327
+ component: row
328
+ name: lineItemRow
329
+ props: { spacing: 2 }
330
+ children:
331
+ - component: field
332
+ name: description
333
+ props: { type: text, label: { en-US: "Description" } }
334
+ - component: field
335
+ name: quantity
336
+ props: { type: number, label: { en-US: "Qty" } }
337
+ - component: field
338
+ name: unitPrice
339
+ props: { type: number, label: { en-US: "Unit Price" } }
340
+ ```
341
+
342
+ ---
343
+
344
+ ## barcodeScanner
345
+
346
+ Headless barcode/keyboard scanner listener. Captures rapid keystrokes and fires on scan.
347
+
348
+ **Props:**
349
+ | Prop | Type | Default | Description |
350
+ |------|------|---------|-------------|
351
+ | `minBarcodeLength` | `number` | `4` | Min chars to qualify as scan |
352
+ | `onScan` | `action[]` | — | **Required.** Action on scan detection |
353
+
354
+ **Renders:** Nothing (empty fragment). Listens on `document` keypress.
355
+
356
+ **Scan data:** `result: { data: string, format: 'input' }`
357
+
358
+ ```yaml
359
+ component: barcodeScanner
360
+ name: scanner
361
+ props:
362
+ minBarcodeLength: 6
363
+ onScan:
364
+ - setFields:
365
+ barcode: "{{ result.data }}"
366
+ - notification:
367
+ message: { en-US: "Scanned: {{ result.data }}" }
368
+ type: info
369
+ ```
@@ -0,0 +1,317 @@
1
+ # Interactive & Navigation Components
2
+
3
+ ## Contents
4
+ - Button component
5
+ - Dropdown component
6
+ - MenuButton component
7
+ - Link component
8
+ - Redirect component
9
+ - Navbar component
10
+ - NavbarItem component
11
+ - NavbarLink component
12
+ - NavDropdown component
13
+
14
+ ## button
15
+
16
+ MUI Button with icon, label, loading state, and action dispatch.
17
+
18
+ **Props:**
19
+ | Prop | Type | Description |
20
+ |------|------|-------------|
21
+ | `label` | `ILocalizeString` | Button text (localized, template-parsed) |
22
+ | `icon` | `string` | Icon name (template-parsed) |
23
+ | `stopPropagation` | `boolean` | Stop click event propagation |
24
+ | `options.variant` | `string` | Visual variant (see mapping below) |
25
+ | `options.disabled` | `boolean \| string` | Disable state (template expression) |
26
+ | `options.type` | `submit \| reset \| button` | Button type |
27
+ | `options.sx` | `SxProps` | MUI sx styles |
28
+ | `options.className` | `string` | CSS class |
29
+
30
+ **Variant mapping:**
31
+ | YAML Value | MUI Rendered |
32
+ |------------|-------------|
33
+ | `primary` | `contained` + primary color |
34
+ | `secondary` | `outlined` + secondary color |
35
+ | `outline-primary` | `outlined` + primary color |
36
+ | `outline-secondary` | `outlined` + secondary color |
37
+ | `danger` | `contained` + error color |
38
+ | `success` | `contained` + success color |
39
+ | `warning` | `contained` + warning color |
40
+ | `info` | `contained` + info color |
41
+ | `link` / `text` | `text` variant |
42
+ | `contained-primary` | compound format supported |
43
+
44
+ **Events:** `onClick` — dispatches action chain with loading spinner while executing.
45
+
46
+ ```yaml
47
+ # Primary submit button
48
+ - component: button
49
+ name: saveBtn
50
+ props:
51
+ label: { en-US: "Save" }
52
+ icon: check
53
+ options:
54
+ type: submit
55
+ variant: primary
56
+
57
+ # Danger button with confirmation
58
+ - component: button
59
+ name: deleteBtn
60
+ props:
61
+ label: { en-US: "Delete" }
62
+ icon: trash
63
+ options:
64
+ variant: danger
65
+ onClick:
66
+ - confirm:
67
+ title: { en-US: "Delete Item?" }
68
+ message: { en-US: "This action cannot be undone." }
69
+ - mutation:
70
+ command: "mutation($id: Int!) { deleteItem(id: $id) { success } }"
71
+ variables: { id: "{{ number id }}" }
72
+ onSuccess:
73
+ - notification: { message: { en-US: "Deleted" }, type: success }
74
+ - navigateBack: { fallback: "/items" }
75
+
76
+ # Conditional disabled state
77
+ - component: button
78
+ name: approveBtn
79
+ props:
80
+ label: { en-US: "Approve" }
81
+ icon: check-circle
82
+ options:
83
+ variant: success
84
+ disabled: "{{ eval status !== 'Pending' }}"
85
+ onClick:
86
+ - mutation:
87
+ command: "mutation($id: Int!) { approveOrder(id: $id) { success } }"
88
+ variables: { id: "{{ number id }}" }
89
+ ```
90
+
91
+ ---
92
+
93
+ ## dropdown
94
+
95
+ Action dropdown menu (not a form select). MUI Button + Menu with permission-gated items.
96
+
97
+ **Props:**
98
+ | Prop | Type | Description |
99
+ |------|------|-------------|
100
+ | `label` | `ILocalizeString` | Trigger button label |
101
+ | `icon` | `string` | Trigger button icon |
102
+ | `name` | `string` | Component name |
103
+ | `items` | `MenuItem[]` | Menu items |
104
+ | `items[].label` | `ILocalizeString` | Item label |
105
+ | `items[].value` | `any` | Item key |
106
+ | `items[].disabled` | `string \| boolean` | Disable (template expression) |
107
+ | `items[].permission` | `string` | Permission gate — hidden if not granted |
108
+ | `items[].onClick` | `action[]` | Per-item action |
109
+ | `options.size` | `string` | Button size (default: `medium`) |
110
+ | `options.variant` | `string` | Button variant (default: `outlined`) |
111
+
112
+ **Events:** `onClick` (button level), `items[].onClick` (per item)
113
+
114
+ ```yaml
115
+ component: dropdown
116
+ name: actionsDropdown
117
+ props:
118
+ label: { en-US: "Actions" }
119
+ icon: activity
120
+ options:
121
+ variant: secondary
122
+ items:
123
+ - label: { en-US: "Export CSV" }
124
+ onClick:
125
+ - notification: { message: { en-US: "Exporting..." }, type: info }
126
+ - label: { en-US: "Import" }
127
+ permission: "Module/Import"
128
+ onClick:
129
+ - dialog:
130
+ component: Module/ImportDialog
131
+ - label: { en-US: "Archive All" }
132
+ disabled: "{{ eval selectedItems.length === 0 }}"
133
+ onClick:
134
+ - confirm: { title: { en-US: "Archive?" }, message: { en-US: "Archive selected items?" } }
135
+ ```
136
+
137
+ ---
138
+
139
+ ## menuButton
140
+
141
+ Collapsible menu with custom component children. Paper container with click toggle.
142
+
143
+ **Props:**
144
+ | Prop | Type | Description |
145
+ |------|------|-------------|
146
+ | `label` | `ILocalizeString` | Trigger element text |
147
+ | `options` | `object` | HTML attributes on trigger div |
148
+ | `options.allowCreate` | `boolean` | Show children with `create` in name |
149
+
150
+ **Children:** Yes — each child rendered as a MenuItem via ComponentRender. Children with `create` in name are gated by `allowCreate`.
151
+
152
+ ```yaml
153
+ component: menuButton
154
+ name: quickActions
155
+ props:
156
+ label: { en-US: "Quick Actions" }
157
+ options:
158
+ allowCreate: true
159
+ children:
160
+ - component: button
161
+ name: createOrder
162
+ props: { label: { en-US: "Create Order" }, icon: plus }
163
+ - component: button
164
+ name: viewReports
165
+ props: { label: { en-US: "View Reports" }, icon: bar-chart }
166
+ ```
167
+
168
+ ---
169
+
170
+ ## link
171
+
172
+ HTML anchor link with template-parsed URL and label.
173
+
174
+ **Props:**
175
+ | Prop | Type | Description |
176
+ |------|------|-------------|
177
+ | `label` | `string` | Display text (template-parsed, localized) |
178
+ | `to` | `string` | URL href (template-parsed) |
179
+ | `options` | `object` | Additional `<a>` attributes (target, rel, etc.) |
180
+
181
+ ```yaml
182
+ component: link
183
+ name: externalLink
184
+ props:
185
+ label: "View on External System"
186
+ to: "https://external.com/entity/{{ entityId }}"
187
+ options:
188
+ target: _blank
189
+ rel: noopener noreferrer
190
+ ```
191
+
192
+ ---
193
+
194
+ ## redirect
195
+
196
+ Programmatic navigation — renders nothing (or spinner with delay).
197
+
198
+ **Props:**
199
+ | Prop | Type | Default | Description |
200
+ |------|------|---------|-------------|
201
+ | `path` | `string` | — | **Required.** Destination (template-parsed) |
202
+ | `params` | `Record<string, any>` | — | Query parameters |
203
+ | `delay` | `number` | `0` | Delay in ms before redirect |
204
+ | `replace` | `boolean` | `false` | Use replace instead of push |
205
+ | `condition` | `any` | — | Template expression; skip redirect if falsy |
206
+
207
+ **Path types:**
208
+ - `http://...` / `https://...` — External redirect
209
+ - `~path` — System path (bypasses org prefix)
210
+ - `/path` — Org-relative path (prepends `/org/{orgId}/v2/`)
211
+
212
+ ```yaml
213
+ # Conditional redirect
214
+ component: redirect
215
+ name: createRedirect
216
+ props:
217
+ condition: "{{ eval !id }}"
218
+ path: "/orders/create"
219
+
220
+ # External redirect with delay
221
+ component: redirect
222
+ name: externalRedirect
223
+ props:
224
+ path: "https://external.com/order/{{ externalId }}"
225
+ delay: 2000
226
+ ```
227
+
228
+ ---
229
+
230
+ ## navbar
231
+
232
+ Vertical navigation menu with accordion submenus. Uses `@menu/vertical-menu`.
233
+
234
+ **Props:**
235
+ | Prop | Type | Description |
236
+ |------|------|-------------|
237
+ | `items` | `component[]` | Primary nav items (navbarItem, navbarLink, navDropdown) |
238
+ | `contextItems` | `component[]` | Additional nav items (bottom section) |
239
+
240
+ **Children:** No — uses `items` and `contextItems` props.
241
+
242
+ ---
243
+
244
+ ## navbarItem
245
+
246
+ Nav section with optional label header. Child of `navbar`.
247
+
248
+ **Props:**
249
+ | Prop | Type | Description |
250
+ |------|------|-------------|
251
+ | `label` | `ILocalizeString` | Section header label |
252
+
253
+ **Children:** Yes — rendered as section content.
254
+
255
+ ---
256
+
257
+ ## navbarLink
258
+
259
+ Single navigation link. Child of `navbarItem` or `navDropdown`.
260
+
261
+ **Props:**
262
+ | Prop | Type | Description |
263
+ |------|------|-------------|
264
+ | `to` | `string` | Target path (template-parsed, locale-prefixed) |
265
+ | `label` | `ILocalizeString` | Link display text |
266
+ | `icon` | `string` | Menu item icon |
267
+
268
+ **Events:** `onClick`
269
+
270
+ ---
271
+
272
+ ## navDropdown
273
+
274
+ Collapsible submenu. Child of `navbarItem`. Auto-expands if child path matches current URL.
275
+
276
+ **Props:**
277
+ | Prop | Type | Description |
278
+ |------|------|-------------|
279
+ | `label` | `ILocalizeString` | Submenu label |
280
+ | `icon` | `string` | Submenu icon |
281
+
282
+ **Children:** Yes — typically `navbarLink` items.
283
+
284
+ ```yaml
285
+ # Full navbar example
286
+ component: navbar
287
+ name: mainNav
288
+ props:
289
+ items:
290
+ - component: navbarItem
291
+ name: mainSection
292
+ props:
293
+ label: { en-US: "Main" }
294
+ children:
295
+ - component: navbarLink
296
+ name: dashboard
297
+ props:
298
+ to: "/dashboard"
299
+ label: { en-US: "Dashboard" }
300
+ icon: home
301
+ - component: navDropdown
302
+ name: ordersMenu
303
+ props:
304
+ label: { en-US: "Orders" }
305
+ icon: package
306
+ children:
307
+ - component: navbarLink
308
+ name: allOrders
309
+ props:
310
+ to: "/orders"
311
+ label: { en-US: "All Orders" }
312
+ - component: navbarLink
313
+ name: createOrder
314
+ props:
315
+ to: "/orders/create"
316
+ label: { en-US: "Create Order" }
317
+ ```