@uipath/apollo-wind 0.7.2-pr188.4865fad

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 (254) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +188 -0
  3. package/dist/components/forms/data-fetcher.cjs +250 -0
  4. package/dist/components/forms/data-fetcher.d.ts +173 -0
  5. package/dist/components/forms/data-fetcher.js +207 -0
  6. package/dist/components/forms/demo-mocks.cjs +1031 -0
  7. package/dist/components/forms/demo-mocks.d.ts +10 -0
  8. package/dist/components/forms/demo-mocks.js +997 -0
  9. package/dist/components/forms/field-renderer.cjs +595 -0
  10. package/dist/components/forms/field-renderer.d.ts +14 -0
  11. package/dist/components/forms/field-renderer.js +561 -0
  12. package/dist/components/forms/form-designer.cjs +2314 -0
  13. package/dist/components/forms/form-designer.d.ts +1 -0
  14. package/dist/components/forms/form-designer.js +2280 -0
  15. package/dist/components/forms/form-examples.cjs +962 -0
  16. package/dist/components/forms/form-examples.d.ts +46 -0
  17. package/dist/components/forms/form-examples.js +907 -0
  18. package/dist/components/forms/form-plugins.cjs +225 -0
  19. package/dist/components/forms/form-plugins.d.ts +11 -0
  20. package/dist/components/forms/form-plugins.js +176 -0
  21. package/dist/components/forms/form-schema.cjs +56 -0
  22. package/dist/components/forms/form-schema.d.ts +324 -0
  23. package/dist/components/forms/form-schema.js +13 -0
  24. package/dist/components/forms/form-state-viewer.cjs +498 -0
  25. package/dist/components/forms/form-state-viewer.d.ts +15 -0
  26. package/dist/components/forms/form-state-viewer.js +464 -0
  27. package/dist/components/forms/index.cjs +103 -0
  28. package/dist/components/forms/index.d.ts +13 -0
  29. package/dist/components/forms/index.js +9 -0
  30. package/dist/components/forms/metadata-form.cjs +400 -0
  31. package/dist/components/forms/metadata-form.d.ts +16 -0
  32. package/dist/components/forms/metadata-form.js +366 -0
  33. package/dist/components/forms/rules-engine.cjs +343 -0
  34. package/dist/components/forms/rules-engine.d.ts +99 -0
  35. package/dist/components/forms/rules-engine.js +293 -0
  36. package/dist/components/forms/schema-serializer.cjs +250 -0
  37. package/dist/components/forms/schema-serializer.d.ts +27 -0
  38. package/dist/components/forms/schema-serializer.js +213 -0
  39. package/dist/components/forms/schema-viewer.cjs +157 -0
  40. package/dist/components/forms/schema-viewer.d.ts +29 -0
  41. package/dist/components/forms/schema-viewer.js +117 -0
  42. package/dist/components/forms/validation-converter.cjs +154 -0
  43. package/dist/components/forms/validation-converter.d.ts +42 -0
  44. package/dist/components/forms/validation-converter.js +114 -0
  45. package/dist/components/ui/accordion.cjs +82 -0
  46. package/dist/components/ui/accordion.d.ts +7 -0
  47. package/dist/components/ui/accordion.js +39 -0
  48. package/dist/components/ui/alert-dialog.cjs +126 -0
  49. package/dist/components/ui/alert-dialog.d.ts +20 -0
  50. package/dist/components/ui/alert-dialog.js +62 -0
  51. package/dist/components/ui/alert.cjs +77 -0
  52. package/dist/components/ui/alert.d.ts +8 -0
  53. package/dist/components/ui/alert.js +37 -0
  54. package/dist/components/ui/aspect-ratio.cjs +38 -0
  55. package/dist/components/ui/aspect-ratio.d.ts +3 -0
  56. package/dist/components/ui/aspect-ratio.js +4 -0
  57. package/dist/components/ui/avatar.cjs +63 -0
  58. package/dist/components/ui/avatar.d.ts +6 -0
  59. package/dist/components/ui/avatar.js +23 -0
  60. package/dist/components/ui/badge.cjs +63 -0
  61. package/dist/components/ui/badge.d.ts +9 -0
  62. package/dist/components/ui/badge.js +26 -0
  63. package/dist/components/ui/breadcrumb.cjs +118 -0
  64. package/dist/components/ui/breadcrumb.d.ts +19 -0
  65. package/dist/components/ui/breadcrumb.js +66 -0
  66. package/dist/components/ui/button-group.cjs +68 -0
  67. package/dist/components/ui/button-group.d.ts +14 -0
  68. package/dist/components/ui/button-group.js +28 -0
  69. package/dist/components/ui/button.cjs +78 -0
  70. package/dist/components/ui/button.d.ts +11 -0
  71. package/dist/components/ui/button.js +41 -0
  72. package/dist/components/ui/calendar.cjs +144 -0
  73. package/dist/components/ui/calendar.d.ts +8 -0
  74. package/dist/components/ui/calendar.js +107 -0
  75. package/dist/components/ui/card.cjs +89 -0
  76. package/dist/components/ui/card.d.ts +8 -0
  77. package/dist/components/ui/card.js +40 -0
  78. package/dist/components/ui/checkbox.cjs +52 -0
  79. package/dist/components/ui/checkbox.d.ts +6 -0
  80. package/dist/components/ui/checkbox.js +18 -0
  81. package/dist/components/ui/collapsible.cjs +45 -0
  82. package/dist/components/ui/collapsible.d.ts +5 -0
  83. package/dist/components/ui/collapsible.js +5 -0
  84. package/dist/components/ui/combobox.cjs +102 -0
  85. package/dist/components/ui/combobox.d.ts +15 -0
  86. package/dist/components/ui/combobox.js +68 -0
  87. package/dist/components/ui/command.cjs +131 -0
  88. package/dist/components/ui/command.d.ts +80 -0
  89. package/dist/components/ui/command.js +73 -0
  90. package/dist/components/ui/context-menu.cjs +173 -0
  91. package/dist/components/ui/context-menu.d.ts +27 -0
  92. package/dist/components/ui/context-menu.js +97 -0
  93. package/dist/components/ui/data-table.cjs +292 -0
  94. package/dist/components/ui/data-table.d.ts +23 -0
  95. package/dist/components/ui/data-table.js +252 -0
  96. package/dist/components/ui/date-picker.cjs +118 -0
  97. package/dist/components/ui/date-picker.d.ts +21 -0
  98. package/dist/components/ui/date-picker.js +81 -0
  99. package/dist/components/ui/datetime-picker.cjs +154 -0
  100. package/dist/components/ui/datetime-picker.d.ts +9 -0
  101. package/dist/components/ui/datetime-picker.js +120 -0
  102. package/dist/components/ui/dialog.cjs +159 -0
  103. package/dist/components/ui/dialog.d.ts +15 -0
  104. package/dist/components/ui/dialog.js +98 -0
  105. package/dist/components/ui/drawer.cjs +116 -0
  106. package/dist/components/ui/drawer.d.ts +18 -0
  107. package/dist/components/ui/drawer.js +55 -0
  108. package/dist/components/ui/dropdown-menu.cjs +174 -0
  109. package/dist/components/ui/dropdown-menu.d.ts +27 -0
  110. package/dist/components/ui/dropdown-menu.js +98 -0
  111. package/dist/components/ui/editable-cell.cjs +256 -0
  112. package/dist/components/ui/editable-cell.d.ts +24 -0
  113. package/dist/components/ui/editable-cell.js +219 -0
  114. package/dist/components/ui/empty-state.cjs +73 -0
  115. package/dist/components/ui/empty-state.d.ts +16 -0
  116. package/dist/components/ui/empty-state.js +39 -0
  117. package/dist/components/ui/file-upload.cjs +236 -0
  118. package/dist/components/ui/file-upload.d.ts +10 -0
  119. package/dist/components/ui/file-upload.js +202 -0
  120. package/dist/components/ui/hover-card.cjs +55 -0
  121. package/dist/components/ui/hover-card.d.ts +6 -0
  122. package/dist/components/ui/hover-card.js +15 -0
  123. package/dist/components/ui/index.cjs +546 -0
  124. package/dist/components/ui/index.d.ts +55 -0
  125. package/dist/components/ui/index.js +55 -0
  126. package/dist/components/ui/input.cjs +45 -0
  127. package/dist/components/ui/input.d.ts +5 -0
  128. package/dist/components/ui/input.js +11 -0
  129. package/dist/components/ui/label.cjs +47 -0
  130. package/dist/components/ui/label.d.ts +7 -0
  131. package/dist/components/ui/label.js +13 -0
  132. package/dist/components/ui/layout/column.cjs +84 -0
  133. package/dist/components/ui/layout/column.d.ts +21 -0
  134. package/dist/components/ui/layout/column.js +50 -0
  135. package/dist/components/ui/layout/grid.cjs +101 -0
  136. package/dist/components/ui/layout/grid.d.ts +22 -0
  137. package/dist/components/ui/layout/grid.js +67 -0
  138. package/dist/components/ui/layout/index.cjs +44 -0
  139. package/dist/components/ui/layout/index.d.ts +7 -0
  140. package/dist/components/ui/layout/index.js +4 -0
  141. package/dist/components/ui/layout/row.cjs +84 -0
  142. package/dist/components/ui/layout/row.d.ts +21 -0
  143. package/dist/components/ui/layout/row.js +50 -0
  144. package/dist/components/ui/layout/types.cjs +18 -0
  145. package/dist/components/ui/layout/types.d.ts +149 -0
  146. package/dist/components/ui/layout/types.js +0 -0
  147. package/dist/components/ui/layout/utils.cjs +324 -0
  148. package/dist/components/ui/layout/utils.d.ts +76 -0
  149. package/dist/components/ui/layout/utils.js +239 -0
  150. package/dist/components/ui/menubar.cjs +210 -0
  151. package/dist/components/ui/menubar.d.ts +28 -0
  152. package/dist/components/ui/menubar.js +131 -0
  153. package/dist/components/ui/multi-select.cjs +187 -0
  154. package/dist/components/ui/multi-select.d.ts +18 -0
  155. package/dist/components/ui/multi-select.js +153 -0
  156. package/dist/components/ui/navigation-menu.cjs +122 -0
  157. package/dist/components/ui/navigation-menu.d.ts +12 -0
  158. package/dist/components/ui/navigation-menu.js +64 -0
  159. package/dist/components/ui/pagination.cjs +131 -0
  160. package/dist/components/ui/pagination.d.ts +28 -0
  161. package/dist/components/ui/pagination.js +79 -0
  162. package/dist/components/ui/popover.cjs +61 -0
  163. package/dist/components/ui/popover.d.ts +7 -0
  164. package/dist/components/ui/popover.js +18 -0
  165. package/dist/components/ui/progress.cjs +51 -0
  166. package/dist/components/ui/progress.d.ts +4 -0
  167. package/dist/components/ui/progress.js +17 -0
  168. package/dist/components/ui/radio-group.cjs +61 -0
  169. package/dist/components/ui/radio-group.d.ts +5 -0
  170. package/dist/components/ui/radio-group.js +24 -0
  171. package/dist/components/ui/resizable.cjs +60 -0
  172. package/dist/components/ui/resizable.d.ts +23 -0
  173. package/dist/components/ui/resizable.js +20 -0
  174. package/dist/components/ui/scroll-area.cjs +67 -0
  175. package/dist/components/ui/scroll-area.d.ts +5 -0
  176. package/dist/components/ui/scroll-area.js +30 -0
  177. package/dist/components/ui/search.cjs +153 -0
  178. package/dist/components/ui/search.d.ts +19 -0
  179. package/dist/components/ui/search.js +116 -0
  180. package/dist/components/ui/select.cjs +151 -0
  181. package/dist/components/ui/select.d.ts +13 -0
  182. package/dist/components/ui/select.js +90 -0
  183. package/dist/components/ui/separator.cjs +47 -0
  184. package/dist/components/ui/separator.d.ts +4 -0
  185. package/dist/components/ui/separator.js +13 -0
  186. package/dist/components/ui/sheet.cjs +142 -0
  187. package/dist/components/ui/sheet.d.ts +25 -0
  188. package/dist/components/ui/sheet.js +81 -0
  189. package/dist/components/ui/skeleton.cjs +43 -0
  190. package/dist/components/ui/skeleton.d.ts +2 -0
  191. package/dist/components/ui/skeleton.js +9 -0
  192. package/dist/components/ui/slider.cjs +63 -0
  193. package/dist/components/ui/slider.d.ts +4 -0
  194. package/dist/components/ui/slider.js +29 -0
  195. package/dist/components/ui/sonner.cjs +76 -0
  196. package/dist/components/ui/sonner.d.ts +4 -0
  197. package/dist/components/ui/sonner.js +39 -0
  198. package/dist/components/ui/spinner.cjs +78 -0
  199. package/dist/components/ui/spinner.d.ts +11 -0
  200. package/dist/components/ui/spinner.js +41 -0
  201. package/dist/components/ui/stats-card.cjs +102 -0
  202. package/dist/components/ui/stats-card.d.ts +15 -0
  203. package/dist/components/ui/stats-card.js +68 -0
  204. package/dist/components/ui/stepper.cjs +99 -0
  205. package/dist/components/ui/stepper.d.ts +14 -0
  206. package/dist/components/ui/stepper.js +65 -0
  207. package/dist/components/ui/switch.cjs +48 -0
  208. package/dist/components/ui/switch.d.ts +4 -0
  209. package/dist/components/ui/switch.js +14 -0
  210. package/dist/components/ui/table.cjs +110 -0
  211. package/dist/components/ui/table.d.ts +10 -0
  212. package/dist/components/ui/table.js +55 -0
  213. package/dist/components/ui/tabs.cjs +67 -0
  214. package/dist/components/ui/tabs.d.ts +7 -0
  215. package/dist/components/ui/tabs.js +24 -0
  216. package/dist/components/ui/textarea.cjs +44 -0
  217. package/dist/components/ui/textarea.d.ts +4 -0
  218. package/dist/components/ui/textarea.js +10 -0
  219. package/dist/components/ui/toggle-group.cjs +73 -0
  220. package/dist/components/ui/toggle-group.d.ts +12 -0
  221. package/dist/components/ui/toggle-group.js +36 -0
  222. package/dist/components/ui/toggle.cjs +71 -0
  223. package/dist/components/ui/toggle.d.ts +12 -0
  224. package/dist/components/ui/toggle.js +34 -0
  225. package/dist/components/ui/tooltip.cjs +58 -0
  226. package/dist/components/ui/tooltip.d.ts +7 -0
  227. package/dist/components/ui/tooltip.js +15 -0
  228. package/dist/examples/admin-layout-example.d.ts +92 -0
  229. package/dist/examples/app-shell-example.d.ts +52 -0
  230. package/dist/examples/dashboard-example.d.ts +11 -0
  231. package/dist/examples/data-management-example.d.ts +1 -0
  232. package/dist/examples/flow-editor-layout-example.d.ts +22 -0
  233. package/dist/examples/flow-start-example.d.ts +30 -0
  234. package/dist/examples/form-builder-example.d.ts +1 -0
  235. package/dist/examples/new-project-example.d.ts +30 -0
  236. package/dist/examples/settings-example.d.ts +1 -0
  237. package/dist/examples/vscode-example.d.ts +80 -0
  238. package/dist/index.cjs +830 -0
  239. package/dist/index.d.ts +86 -0
  240. package/dist/index.js +67 -0
  241. package/dist/lib/index.cjs +42 -0
  242. package/dist/lib/index.d.ts +1 -0
  243. package/dist/lib/index.js +2 -0
  244. package/dist/lib/utils.cjs +70 -0
  245. package/dist/lib/utils.d.ts +14 -0
  246. package/dist/lib/utils.js +30 -0
  247. package/dist/postcss.config.export.cjs +43 -0
  248. package/dist/postcss.config.export.js +9 -0
  249. package/dist/styles.css +6868 -0
  250. package/dist/tailwind.css +239 -0
  251. package/dist/tailwind.preset.cjs +77 -0
  252. package/dist/tailwind.preset.js +43 -0
  253. package/package.json +157 -0
  254. package/postcss.config.export.js +9 -0
@@ -0,0 +1,2280 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useState } from "react";
3
+ import { schemaToJson } from "./schema-serializer.js";
4
+ import { MetadataForm } from "./metadata-form.js";
5
+ import { Button } from "../ui/button.js";
6
+ import { Input } from "../ui/input.js";
7
+ import { Label } from "../ui/label.js";
8
+ import { Textarea } from "../ui/textarea.js";
9
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select.js";
10
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card.js";
11
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from "../ui/tabs.js";
12
+ import { Checkbox } from "../ui/checkbox.js";
13
+ import { Switch } from "../ui/switch.js";
14
+ import { AlertTriangle, Asterisk, Ban, ChevronRight, Code, Database, Eye, EyeOff, GitBranch, GripVertical, Layers, MoveDown, MoveUp, Plus, Settings, Trash2, View } from "lucide-react";
15
+ import { Separator } from "../ui/separator.js";
16
+ import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "../ui/accordion.js";
17
+ import { Grid } from "../ui/layout/grid.js";
18
+ const FIELD_TYPE_METADATA = [
19
+ {
20
+ value: 'text',
21
+ label: 'Text',
22
+ category: 'Input',
23
+ description: 'Single-line text input'
24
+ },
25
+ {
26
+ value: 'email',
27
+ label: 'Email',
28
+ category: 'Input',
29
+ description: 'Email with validation'
30
+ },
31
+ {
32
+ value: 'textarea',
33
+ label: 'Textarea',
34
+ category: 'Input',
35
+ description: 'Multi-line text input'
36
+ },
37
+ {
38
+ value: 'number',
39
+ label: 'Number',
40
+ category: 'Input',
41
+ description: 'Numeric input with min/max'
42
+ },
43
+ {
44
+ value: 'date',
45
+ label: 'Date',
46
+ category: 'Input',
47
+ description: 'Date picker'
48
+ },
49
+ {
50
+ value: 'datetime',
51
+ label: 'Date & Time',
52
+ category: 'Input',
53
+ description: 'Date and time picker'
54
+ },
55
+ {
56
+ value: 'file',
57
+ label: 'File Upload',
58
+ category: 'Input',
59
+ description: 'File upload control'
60
+ },
61
+ {
62
+ value: 'select',
63
+ label: 'Select Dropdown',
64
+ category: 'Selection',
65
+ description: 'Single-select dropdown'
66
+ },
67
+ {
68
+ value: 'multiselect',
69
+ label: 'Multi-Select',
70
+ category: 'Selection',
71
+ description: 'Multi-select with search'
72
+ },
73
+ {
74
+ value: 'radio',
75
+ label: 'Radio Group',
76
+ category: 'Selection',
77
+ description: 'Radio button group'
78
+ },
79
+ {
80
+ value: 'checkbox',
81
+ label: 'Checkbox',
82
+ category: 'Boolean',
83
+ description: 'Single checkbox'
84
+ },
85
+ {
86
+ value: 'switch',
87
+ label: 'Switch Toggle',
88
+ category: 'Boolean',
89
+ description: 'Toggle switch'
90
+ },
91
+ {
92
+ value: 'slider',
93
+ label: 'Slider',
94
+ category: 'Input',
95
+ description: 'Range slider'
96
+ },
97
+ {
98
+ value: 'custom',
99
+ label: 'Custom Component',
100
+ category: 'Advanced',
101
+ description: 'Custom field component'
102
+ }
103
+ ];
104
+ function buildValidationConfig(field) {
105
+ const { type, validation, rules } = field;
106
+ const config = {};
107
+ const messages = {};
108
+ const isAlwaysRequired = rules?.some((r)=>true === r.effects.required && 0 === r.conditions.length);
109
+ if (isAlwaysRequired) {
110
+ config.required = true;
111
+ if (validation?.requiredMessage) messages.required = validation.requiredMessage;
112
+ }
113
+ if (!validation && !isAlwaysRequired) return;
114
+ if (validation) {
115
+ if ('text' === type || 'textarea' === type || 'email' === type) {
116
+ const minLen = validation.minLength;
117
+ const maxLen = validation.maxLength;
118
+ const validLengthConstraints = null == minLen || null == maxLen || minLen <= maxLen;
119
+ if (validLengthConstraints) {
120
+ if (null != minLen) {
121
+ config.minLength = minLen;
122
+ if (validation.customMessage) messages.minLength = validation.customMessage;
123
+ }
124
+ if (null != maxLen) {
125
+ config.maxLength = maxLen;
126
+ if (validation.customMessage) messages.maxLength = validation.customMessage;
127
+ }
128
+ }
129
+ if (validation.pattern) try {
130
+ new RegExp(validation.pattern);
131
+ config.pattern = validation.pattern;
132
+ if (validation.patternMessage) messages.pattern = validation.patternMessage;
133
+ else if (validation.customMessage) messages.pattern = validation.customMessage;
134
+ } catch {}
135
+ }
136
+ if ('number' === type || 'slider' === type) {
137
+ if (validation.integer) {
138
+ config.integer = true;
139
+ if (validation.customMessage) messages.integer = validation.customMessage;
140
+ }
141
+ const minVal = field.min;
142
+ const maxVal = field.max;
143
+ const validRangeConstraints = null == minVal || null == maxVal || minVal <= maxVal;
144
+ if (validRangeConstraints) {
145
+ if (null != minVal) {
146
+ config.min = minVal;
147
+ if (validation.customMessage) messages.min = validation.customMessage;
148
+ }
149
+ if (null != maxVal) {
150
+ config.max = maxVal;
151
+ if (validation.customMessage) messages.max = validation.customMessage;
152
+ }
153
+ }
154
+ }
155
+ if ('file' === type) {
156
+ if (null != validation.maxFileSize) config.maxFileSize = validation.maxFileSize;
157
+ if (field.multiple && null != validation.maxFiles) {
158
+ config.maxItems = validation.maxFiles;
159
+ if (validation.customMessage) messages.maxItems = validation.customMessage;
160
+ }
161
+ }
162
+ if (validation.customMessage) messages.custom = validation.customMessage;
163
+ }
164
+ if (Object.keys(messages).length > 0) config.messages = messages;
165
+ return Object.keys(config).length > 0 ? config : void 0;
166
+ }
167
+ const createSectionConfigSchema = (section)=>({
168
+ id: 'section-config',
169
+ title: '',
170
+ sections: [
171
+ {
172
+ id: 'main',
173
+ title: 'Section settings',
174
+ fields: [
175
+ {
176
+ name: 'id',
177
+ type: 'text',
178
+ label: 'Section ID',
179
+ description: 'Unique identifier for this section'
180
+ },
181
+ {
182
+ name: 'title',
183
+ type: 'text',
184
+ label: 'Section title',
185
+ placeholder: 'Enter section title'
186
+ },
187
+ {
188
+ name: "description",
189
+ type: 'textarea',
190
+ label: "Description",
191
+ placeholder: "Optional section description",
192
+ rows: 2
193
+ },
194
+ {
195
+ name: 'collapsible',
196
+ type: 'switch',
197
+ label: 'Collapsible section'
198
+ },
199
+ {
200
+ name: 'defaultExpanded',
201
+ type: 'switch',
202
+ label: 'Expanded by default',
203
+ rules: [
204
+ {
205
+ id: 'show-when-collapsible',
206
+ conditions: [
207
+ {
208
+ when: 'collapsible',
209
+ is: true
210
+ }
211
+ ],
212
+ operator: 'AND',
213
+ effects: {
214
+ visible: true
215
+ }
216
+ }
217
+ ]
218
+ }
219
+ ]
220
+ }
221
+ ],
222
+ initialData: {
223
+ id: section.id,
224
+ title: section.title,
225
+ description: section.description || '',
226
+ collapsible: section.collapsible || false,
227
+ defaultExpanded: false !== section.defaultExpanded
228
+ },
229
+ actions: []
230
+ });
231
+ const createFieldConfigSchema = (field)=>({
232
+ id: 'field-config',
233
+ title: '',
234
+ sections: [
235
+ {
236
+ id: 'basic',
237
+ title: 'Basic settings',
238
+ fields: [
239
+ {
240
+ name: 'name',
241
+ type: 'text',
242
+ label: 'Field name',
243
+ placeholder: 'fieldName',
244
+ description: 'Internal identifier (camelCase recommended)'
245
+ },
246
+ {
247
+ name: 'label',
248
+ type: 'text',
249
+ label: 'Label',
250
+ placeholder: 'Field Label'
251
+ },
252
+ {
253
+ name: 'type',
254
+ type: 'select',
255
+ label: 'Field type',
256
+ options: FIELD_TYPE_METADATA.map((t)=>({
257
+ label: `${t.label} (${t.category})`,
258
+ value: t.value
259
+ }))
260
+ },
261
+ {
262
+ name: 'placeholder',
263
+ type: 'text',
264
+ label: 'Placeholder',
265
+ placeholder: 'Enter placeholder text...'
266
+ },
267
+ {
268
+ name: "description",
269
+ type: 'textarea',
270
+ label: "Description",
271
+ placeholder: 'Help text for this field',
272
+ rows: 2
273
+ }
274
+ ]
275
+ },
276
+ {
277
+ id: 'number-settings',
278
+ title: 'Number settings',
279
+ fields: [
280
+ {
281
+ name: 'min',
282
+ type: 'number',
283
+ label: 'Min'
284
+ },
285
+ {
286
+ name: 'max',
287
+ type: 'number',
288
+ label: 'Max'
289
+ },
290
+ {
291
+ name: 'step',
292
+ type: 'number',
293
+ label: 'Step'
294
+ }
295
+ ],
296
+ conditions: [
297
+ {
298
+ when: 'type',
299
+ in: [
300
+ 'number',
301
+ 'slider'
302
+ ]
303
+ }
304
+ ]
305
+ },
306
+ {
307
+ id: 'file-settings',
308
+ title: 'File settings',
309
+ fields: [
310
+ {
311
+ name: 'accept',
312
+ type: 'text',
313
+ label: 'Accepted file types',
314
+ placeholder: '.pdf,.doc,.docx',
315
+ description: 'Comma-separated file extensions'
316
+ },
317
+ {
318
+ name: 'multiple',
319
+ type: 'checkbox',
320
+ label: 'Allow multiple files'
321
+ }
322
+ ],
323
+ conditions: [
324
+ {
325
+ when: 'type',
326
+ is: 'file'
327
+ }
328
+ ]
329
+ },
330
+ {
331
+ id: 'text-validation',
332
+ title: 'Text validation',
333
+ fields: [
334
+ {
335
+ name: 'validation.minLength',
336
+ type: 'number',
337
+ label: 'Minimum length',
338
+ min: 0,
339
+ placeholder: '0'
340
+ },
341
+ {
342
+ name: 'validation.maxLength',
343
+ type: 'number',
344
+ label: 'Maximum length',
345
+ min: 0,
346
+ placeholder: 'No limit'
347
+ },
348
+ {
349
+ name: 'validation.pattern',
350
+ type: 'text',
351
+ label: 'Pattern (regex)',
352
+ placeholder: '^[A-Za-z]+$',
353
+ description: 'Regular expression pattern'
354
+ },
355
+ {
356
+ name: 'validation.patternMessage',
357
+ type: 'text',
358
+ label: 'Pattern error message',
359
+ placeholder: 'Invalid format',
360
+ rules: [
361
+ {
362
+ id: 'show-when-pattern',
363
+ conditions: [
364
+ {
365
+ when: 'validation.pattern',
366
+ isNot: ''
367
+ }
368
+ ],
369
+ operator: 'AND',
370
+ effects: {
371
+ visible: true
372
+ }
373
+ }
374
+ ]
375
+ }
376
+ ],
377
+ conditions: [
378
+ {
379
+ when: 'type',
380
+ in: [
381
+ 'text',
382
+ 'textarea',
383
+ 'email'
384
+ ]
385
+ }
386
+ ]
387
+ },
388
+ {
389
+ id: 'number-validation',
390
+ title: 'Number validation',
391
+ fields: [
392
+ {
393
+ name: 'validation.integer',
394
+ type: 'switch',
395
+ label: 'Integer only',
396
+ description: 'Only allow whole numbers'
397
+ }
398
+ ],
399
+ conditions: [
400
+ {
401
+ when: 'type',
402
+ in: [
403
+ 'number',
404
+ 'slider'
405
+ ]
406
+ }
407
+ ]
408
+ },
409
+ {
410
+ id: 'file-validation',
411
+ title: 'File validation',
412
+ fields: [
413
+ {
414
+ name: 'validation.maxFileSize',
415
+ type: 'number',
416
+ label: 'Max file size (MB)',
417
+ min: 0,
418
+ step: 0.1,
419
+ placeholder: 'No limit'
420
+ },
421
+ {
422
+ name: 'validation.maxFiles',
423
+ type: 'number',
424
+ label: 'Max number of files',
425
+ min: 1,
426
+ placeholder: 'No limit',
427
+ rules: [
428
+ {
429
+ id: 'show-when-multiple',
430
+ conditions: [
431
+ {
432
+ when: 'multiple',
433
+ is: true
434
+ }
435
+ ],
436
+ operator: 'AND',
437
+ effects: {
438
+ visible: true
439
+ }
440
+ }
441
+ ]
442
+ }
443
+ ],
444
+ conditions: [
445
+ {
446
+ when: 'type',
447
+ is: 'file'
448
+ }
449
+ ]
450
+ }
451
+ ],
452
+ initialData: {
453
+ name: field.name,
454
+ label: field.label,
455
+ type: field.type,
456
+ placeholder: field.placeholder || '',
457
+ description: field.description || '',
458
+ min: field.min,
459
+ max: field.max,
460
+ step: field.step,
461
+ accept: field.accept || '',
462
+ multiple: field.multiple || false,
463
+ validation: {
464
+ minLength: field.validation?.minLength,
465
+ maxLength: field.validation?.maxLength,
466
+ pattern: field.validation?.pattern || '',
467
+ patternMessage: field.validation?.patternMessage || '',
468
+ integer: field.validation?.integer || false,
469
+ maxFileSize: field.validation?.maxFileSize ? field.validation.maxFileSize / 1048576 : void 0,
470
+ maxFiles: field.validation?.maxFiles
471
+ }
472
+ },
473
+ actions: []
474
+ });
475
+ function SectionConfigForm({ section, onUpdate, existingSectionIds }) {
476
+ const [attemptedId, setAttemptedId] = useState(null);
477
+ useEffect(()=>{
478
+ setAttemptedId(null);
479
+ }, [
480
+ section.id
481
+ ]);
482
+ const isDuplicateId = null !== attemptedId && attemptedId !== section.id && existingSectionIds.has(attemptedId);
483
+ const schema = useMemo(()=>createSectionConfigSchema(section), [
484
+ section
485
+ ]);
486
+ const plugins = useMemo(()=>[
487
+ {
488
+ name: 'section-sync',
489
+ onValueChange: (_field, _value, context)=>{
490
+ const values = context.values;
491
+ const newId = values.id;
492
+ setAttemptedId(newId);
493
+ onUpdate({
494
+ id: newId,
495
+ title: values.title,
496
+ description: values.description || void 0,
497
+ collapsible: values.collapsible,
498
+ defaultExpanded: values.defaultExpanded
499
+ });
500
+ }
501
+ }
502
+ ], [
503
+ onUpdate
504
+ ]);
505
+ return /*#__PURE__*/ jsxs("div", {
506
+ className: "space-y-4",
507
+ children: [
508
+ isDuplicateId && /*#__PURE__*/ jsxs("div", {
509
+ className: "flex items-center gap-2 p-2 bg-destructive/10 border border-destructive/20 rounded-md text-destructive text-sm",
510
+ children: [
511
+ /*#__PURE__*/ jsx(AlertTriangle, {
512
+ className: "h-4 w-4 shrink-0"
513
+ }),
514
+ /*#__PURE__*/ jsxs("span", {
515
+ children: [
516
+ 'Section ID "',
517
+ attemptedId,
518
+ '" already exists. Please use a unique ID.'
519
+ ]
520
+ })
521
+ ]
522
+ }),
523
+ /*#__PURE__*/ jsx(MetadataForm, {
524
+ schema: schema,
525
+ plugins: plugins,
526
+ autoComplete: "off"
527
+ }, section.id),
528
+ /*#__PURE__*/ jsx(Separator, {}),
529
+ /*#__PURE__*/ jsxs("div", {
530
+ className: "text-sm text-muted-foreground",
531
+ children: [
532
+ /*#__PURE__*/ jsxs("p", {
533
+ children: [
534
+ "This section contains ",
535
+ section.fields.length,
536
+ " field(s)."
537
+ ]
538
+ }),
539
+ /*#__PURE__*/ jsx("p", {
540
+ className: "mt-1",
541
+ children: "Click on a field in the left panel to configure it."
542
+ })
543
+ ]
544
+ })
545
+ ]
546
+ });
547
+ }
548
+ function FieldConfigForm({ field, onUpdate, allFields, existingFieldNames }) {
549
+ const [attemptedName, setAttemptedName] = useState(null);
550
+ useEffect(()=>{
551
+ setAttemptedName(null);
552
+ }, [
553
+ field.id
554
+ ]);
555
+ const isDuplicateName = null !== attemptedName && attemptedName !== field.name && existingFieldNames.has(attemptedName);
556
+ const schema = useMemo(()=>createFieldConfigSchema(field), [
557
+ field
558
+ ]);
559
+ const currentTypeRef = useMemo(()=>({
560
+ type: field.type
561
+ }), [
562
+ field.type
563
+ ]);
564
+ const plugins = useMemo(()=>[
565
+ {
566
+ name: 'field-sync',
567
+ onValueChange: (_fieldName, _value, context)=>{
568
+ const values = context.values;
569
+ const newType = values.type;
570
+ const newName = values.name;
571
+ const validationValues = values.validation;
572
+ setAttemptedName(newName);
573
+ const updates = {
574
+ name: newName,
575
+ label: values.label,
576
+ type: newType,
577
+ placeholder: values.placeholder || void 0,
578
+ description: values.description || void 0
579
+ };
580
+ const requiredMessage = validationValues?.requiredMessage || void 0;
581
+ if ('number' === newType || 'slider' === newType) {
582
+ updates.min = values.min;
583
+ updates.max = values.max;
584
+ updates.step = values.step;
585
+ updates.validation = {
586
+ integer: validationValues?.integer,
587
+ requiredMessage
588
+ };
589
+ } else if ('file' === newType) {
590
+ updates.accept = values.accept || void 0;
591
+ updates.multiple = values.multiple;
592
+ const maxFileSizeMB = validationValues?.maxFileSize;
593
+ updates.validation = {
594
+ maxFileSize: maxFileSizeMB ? 1024 * maxFileSizeMB * 1024 : void 0,
595
+ maxFiles: validationValues?.maxFiles,
596
+ requiredMessage
597
+ };
598
+ } else if ('text' === newType || 'textarea' === newType || 'email' === newType) updates.validation = {
599
+ minLength: validationValues?.minLength,
600
+ maxLength: validationValues?.maxLength,
601
+ pattern: validationValues?.pattern || void 0,
602
+ patternMessage: validationValues?.patternMessage || void 0,
603
+ requiredMessage
604
+ };
605
+ else if (requiredMessage) updates.validation = {
606
+ requiredMessage
607
+ };
608
+ if (newType !== currentTypeRef.type) {
609
+ const preservedRequiredMessage = field.validation?.requiredMessage;
610
+ updates.options = void 0;
611
+ updates.min = void 0;
612
+ updates.max = void 0;
613
+ updates.step = void 0;
614
+ updates.accept = void 0;
615
+ updates.multiple = void 0;
616
+ updates.validation = void 0;
617
+ if ('number' === newType || 'slider' === newType) {
618
+ updates.min = values.min;
619
+ updates.max = values.max;
620
+ updates.step = values.step;
621
+ updates.validation = {
622
+ integer: validationValues?.integer,
623
+ requiredMessage: preservedRequiredMessage
624
+ };
625
+ } else if ('file' === newType) {
626
+ updates.accept = values.accept || void 0;
627
+ updates.multiple = values.multiple;
628
+ const maxFileSizeMB = validationValues?.maxFileSize;
629
+ updates.validation = {
630
+ maxFileSize: maxFileSizeMB ? 1024 * maxFileSizeMB * 1024 : void 0,
631
+ maxFiles: validationValues?.maxFiles,
632
+ requiredMessage: preservedRequiredMessage
633
+ };
634
+ } else if ('text' === newType || 'textarea' === newType || 'email' === newType) updates.validation = {
635
+ minLength: validationValues?.minLength,
636
+ maxLength: validationValues?.maxLength,
637
+ pattern: validationValues?.pattern || void 0,
638
+ patternMessage: validationValues?.patternMessage || void 0,
639
+ requiredMessage: preservedRequiredMessage
640
+ };
641
+ else if (preservedRequiredMessage) updates.validation = {
642
+ requiredMessage: preservedRequiredMessage
643
+ };
644
+ currentTypeRef.type = newType;
645
+ }
646
+ onUpdate(updates);
647
+ }
648
+ }
649
+ ], [
650
+ onUpdate,
651
+ currentTypeRef,
652
+ field.validation?.requiredMessage
653
+ ]);
654
+ const needsOptions = [
655
+ 'select',
656
+ 'multiselect',
657
+ 'radio'
658
+ ].includes(field.type);
659
+ return /*#__PURE__*/ jsxs("div", {
660
+ className: "space-y-2",
661
+ children: [
662
+ isDuplicateName && /*#__PURE__*/ jsxs("div", {
663
+ className: "flex items-center gap-2 p-2 bg-destructive/10 border border-destructive/20 rounded-md text-destructive text-sm",
664
+ children: [
665
+ /*#__PURE__*/ jsx(AlertTriangle, {
666
+ className: "h-4 w-4 shrink-0"
667
+ }),
668
+ /*#__PURE__*/ jsxs("span", {
669
+ children: [
670
+ 'Field name "',
671
+ attemptedName,
672
+ '" already exists. Please use a unique name.'
673
+ ]
674
+ })
675
+ ]
676
+ }),
677
+ /*#__PURE__*/ jsx(MetadataForm, {
678
+ schema: schema,
679
+ plugins: plugins,
680
+ autoComplete: "off"
681
+ }, field.id),
682
+ needsOptions && /*#__PURE__*/ jsx(Accordion, {
683
+ type: "multiple",
684
+ defaultValue: [
685
+ 'options'
686
+ ],
687
+ children: /*#__PURE__*/ jsxs(AccordionItem, {
688
+ value: "options",
689
+ className: "border rounded-lg px-3",
690
+ children: [
691
+ /*#__PURE__*/ jsx(AccordionTrigger, {
692
+ className: "text-sm font-medium",
693
+ children: /*#__PURE__*/ jsxs("div", {
694
+ className: "flex items-center gap-2",
695
+ children: [
696
+ /*#__PURE__*/ jsx(Database, {
697
+ className: "h-4 w-4"
698
+ }),
699
+ "Options"
700
+ ]
701
+ })
702
+ }),
703
+ /*#__PURE__*/ jsx(AccordionContent, {
704
+ className: "pt-2",
705
+ children: /*#__PURE__*/ jsx(FieldOptionsEditor, {
706
+ options: field.options || [],
707
+ onChange: (options)=>onUpdate({
708
+ options
709
+ })
710
+ })
711
+ })
712
+ ]
713
+ })
714
+ }),
715
+ /*#__PURE__*/ jsx(Accordion, {
716
+ type: "multiple",
717
+ defaultValue: [
718
+ 'data-source'
719
+ ],
720
+ children: /*#__PURE__*/ jsxs(AccordionItem, {
721
+ value: "data-source",
722
+ className: "border rounded-lg px-3",
723
+ children: [
724
+ /*#__PURE__*/ jsx(AccordionTrigger, {
725
+ className: "text-sm font-medium",
726
+ children: /*#__PURE__*/ jsxs("div", {
727
+ className: "flex items-center gap-2",
728
+ children: [
729
+ /*#__PURE__*/ jsx(Database, {
730
+ className: "h-4 w-4"
731
+ }),
732
+ "Data source"
733
+ ]
734
+ })
735
+ }),
736
+ /*#__PURE__*/ jsx(AccordionContent, {
737
+ className: "pt-2",
738
+ children: /*#__PURE__*/ jsx(DataSourceEditor, {
739
+ dataSource: field.dataSource,
740
+ onChange: (dataSource)=>onUpdate({
741
+ dataSource
742
+ })
743
+ })
744
+ })
745
+ ]
746
+ })
747
+ }),
748
+ /*#__PURE__*/ jsx(Accordion, {
749
+ type: "multiple",
750
+ defaultValue: [
751
+ 'rules'
752
+ ],
753
+ children: /*#__PURE__*/ jsxs(AccordionItem, {
754
+ value: "rules",
755
+ className: "border rounded-lg px-3",
756
+ children: [
757
+ /*#__PURE__*/ jsx(AccordionTrigger, {
758
+ className: "text-sm font-medium",
759
+ children: /*#__PURE__*/ jsxs("div", {
760
+ className: "flex items-center gap-2",
761
+ children: [
762
+ /*#__PURE__*/ jsx(GitBranch, {
763
+ className: "h-4 w-4"
764
+ }),
765
+ "Rules & conditions"
766
+ ]
767
+ })
768
+ }),
769
+ /*#__PURE__*/ jsx(AccordionContent, {
770
+ className: "pt-2",
771
+ children: /*#__PURE__*/ jsx(RulesEditor, {
772
+ rules: field.rules,
773
+ onChange: (rules)=>onUpdate({
774
+ rules
775
+ }),
776
+ allFields: allFields,
777
+ requiredMessage: field.validation?.requiredMessage,
778
+ onRequiredMessageChange: (message)=>onUpdate({
779
+ validation: {
780
+ ...field.validation,
781
+ requiredMessage: message
782
+ }
783
+ })
784
+ })
785
+ })
786
+ ]
787
+ })
788
+ })
789
+ ]
790
+ });
791
+ }
792
+ function FormDesigner() {
793
+ const [formTitle, setFormTitle] = useState('My Custom Form');
794
+ const [formDescription, setFormDescription] = useState('');
795
+ const [sections, setSections] = useState([
796
+ {
797
+ id: 'section-1',
798
+ title: 'General Information',
799
+ collapsible: false,
800
+ defaultExpanded: true,
801
+ fields: [
802
+ {
803
+ id: '1',
804
+ name: 'fullName',
805
+ type: 'text',
806
+ label: 'Full Name',
807
+ placeholder: 'Enter your name'
808
+ }
809
+ ]
810
+ }
811
+ ]);
812
+ const [selectedSectionId, setSelectedSectionId] = useState('section-1');
813
+ const [selectedFieldId, setSelectedFieldId] = useState('1');
814
+ const [expandedSections, setExpandedSections] = useState([
815
+ 'section-1'
816
+ ]);
817
+ const [previewDisabled, setPreviewDisabled] = useState(false);
818
+ const allFields = sections.flatMap((s)=>s.fields);
819
+ const selectedSection = sections.find((s)=>s.id === selectedSectionId);
820
+ const selectedField = allFields.find((f)=>f.id === selectedFieldId);
821
+ const generatedSchema = {
822
+ id: 'custom-form',
823
+ title: formTitle,
824
+ description: formDescription || void 0,
825
+ mode: 'onChange',
826
+ reValidateMode: 'onChange',
827
+ sections: sections.map((section)=>({
828
+ id: section.id,
829
+ title: section.title,
830
+ description: section.description,
831
+ collapsible: section.collapsible,
832
+ defaultExpanded: section.defaultExpanded,
833
+ fields: section.fields.map((field)=>{
834
+ const { id: _id, validation: _validationConfig, ...fieldMeta } = field;
835
+ const validationConfig = buildValidationConfig(field);
836
+ return {
837
+ ...fieldMeta,
838
+ validation: validationConfig
839
+ };
840
+ })
841
+ }))
842
+ };
843
+ const addSection = ()=>{
844
+ const newSection = {
845
+ id: `section-${Date.now()}`,
846
+ title: `Section ${sections.length + 1}`,
847
+ collapsible: true,
848
+ defaultExpanded: true,
849
+ fields: []
850
+ };
851
+ setSections([
852
+ ...sections,
853
+ newSection
854
+ ]);
855
+ setSelectedSectionId(newSection.id);
856
+ setSelectedFieldId(null);
857
+ setExpandedSections([
858
+ ...expandedSections,
859
+ newSection.id
860
+ ]);
861
+ };
862
+ const removeSection = (id)=>{
863
+ if (sections.length <= 1) return;
864
+ setSections(sections.filter((s)=>s.id !== id));
865
+ setExpandedSections(expandedSections.filter((sId)=>sId !== id));
866
+ if (selectedSectionId === id) {
867
+ setSelectedSectionId(sections[0]?.id || null);
868
+ setSelectedFieldId(null);
869
+ }
870
+ };
871
+ const updateSection = (id, updates)=>{
872
+ let finalUpdates = updates;
873
+ if (updates.id && updates.id !== id) {
874
+ const idExists = sections.some((s)=>s.id === updates.id);
875
+ if (idExists) {
876
+ const { id: _id, ...rest } = updates;
877
+ finalUpdates = rest;
878
+ }
879
+ }
880
+ setSections(sections.map((s)=>s.id === id ? {
881
+ ...s,
882
+ ...finalUpdates
883
+ } : s));
884
+ if (finalUpdates.id && finalUpdates.id !== id) {
885
+ if (selectedSectionId === id) setSelectedSectionId(finalUpdates.id);
886
+ setExpandedSections(expandedSections.map((sId)=>sId === id ? finalUpdates.id : sId));
887
+ }
888
+ };
889
+ const moveSection = (id, direction)=>{
890
+ const index = sections.findIndex((s)=>s.id === id);
891
+ if (-1 === index) return;
892
+ const newSections = [
893
+ ...sections
894
+ ];
895
+ if ('up' === direction && index > 0) [newSections[index - 1], newSections[index]] = [
896
+ newSections[index],
897
+ newSections[index - 1]
898
+ ];
899
+ else if ('down' === direction && index < sections.length - 1) [newSections[index], newSections[index + 1]] = [
900
+ newSections[index + 1],
901
+ newSections[index]
902
+ ];
903
+ setSections(newSections);
904
+ };
905
+ const addField = (sectionId)=>{
906
+ const section = sections.find((s)=>s.id === sectionId);
907
+ if (!section) return;
908
+ const newField = {
909
+ id: Date.now().toString(),
910
+ name: `field_${allFields.length + 1}`,
911
+ type: 'text',
912
+ label: `Field ${allFields.length + 1}`
913
+ };
914
+ setSections(sections.map((s)=>s.id === sectionId ? {
915
+ ...s,
916
+ fields: [
917
+ ...s.fields,
918
+ newField
919
+ ]
920
+ } : s));
921
+ setSelectedSectionId(sectionId);
922
+ setSelectedFieldId(newField.id);
923
+ };
924
+ const removeField = (sectionId, fieldId)=>{
925
+ setSections(sections.map((s)=>s.id === sectionId ? {
926
+ ...s,
927
+ fields: s.fields.filter((f)=>f.id !== fieldId)
928
+ } : s));
929
+ if (selectedFieldId === fieldId) {
930
+ const section = sections.find((s)=>s.id === sectionId);
931
+ setSelectedFieldId(section?.fields[0]?.id || null);
932
+ }
933
+ };
934
+ const updateField = (fieldId, updates)=>{
935
+ setSections((prevSections)=>{
936
+ const prevAllFields = prevSections.flatMap((s)=>s.fields);
937
+ let finalUpdates = updates;
938
+ if (updates.name) {
939
+ const currentField = prevAllFields.find((f)=>f.id === fieldId);
940
+ if (currentField && updates.name !== currentField.name) {
941
+ const nameExists = prevAllFields.some((f)=>f.id !== fieldId && f.name === updates.name);
942
+ if (nameExists) {
943
+ const { name: _name, ...rest } = updates;
944
+ finalUpdates = rest;
945
+ }
946
+ }
947
+ }
948
+ return prevSections.map((s)=>({
949
+ ...s,
950
+ fields: s.fields.map((f)=>f.id === fieldId ? {
951
+ ...f,
952
+ ...finalUpdates
953
+ } : f)
954
+ }));
955
+ });
956
+ };
957
+ const moveField = (sectionId, fieldId, direction)=>{
958
+ const section = sections.find((s)=>s.id === sectionId);
959
+ if (!section) return;
960
+ const index = section.fields.findIndex((f)=>f.id === fieldId);
961
+ if (-1 === index) return;
962
+ const newFields = [
963
+ ...section.fields
964
+ ];
965
+ if ('up' === direction && index > 0) [newFields[index - 1], newFields[index]] = [
966
+ newFields[index],
967
+ newFields[index - 1]
968
+ ];
969
+ else if ('down' === direction && index < newFields.length - 1) [newFields[index], newFields[index + 1]] = [
970
+ newFields[index + 1],
971
+ newFields[index]
972
+ ];
973
+ setSections(sections.map((s)=>s.id === sectionId ? {
974
+ ...s,
975
+ fields: newFields
976
+ } : s));
977
+ };
978
+ return /*#__PURE__*/ jsxs(Grid, {
979
+ gap: 3,
980
+ h: "screen",
981
+ p: 3,
982
+ className: "lg:grid-cols-[2fr_3fr_3fr]",
983
+ children: [
984
+ /*#__PURE__*/ jsxs(Card, {
985
+ className: "overflow-hidden flex flex-col",
986
+ children: [
987
+ /*#__PURE__*/ jsx(CardHeader, {
988
+ children: /*#__PURE__*/ jsxs("div", {
989
+ className: "flex items-center justify-between",
990
+ children: [
991
+ /*#__PURE__*/ jsxs("div", {
992
+ children: [
993
+ /*#__PURE__*/ jsxs(CardTitle, {
994
+ className: "flex items-center gap-2",
995
+ children: [
996
+ /*#__PURE__*/ jsx(Layers, {
997
+ className: "h-4 w-4"
998
+ }),
999
+ "Sections"
1000
+ ]
1001
+ }),
1002
+ /*#__PURE__*/ jsx(CardDescription, {
1003
+ children: "Organize fields into sections"
1004
+ })
1005
+ ]
1006
+ }),
1007
+ /*#__PURE__*/ jsxs(Button, {
1008
+ onClick: addSection,
1009
+ variant: "outline",
1010
+ size: "sm",
1011
+ children: [
1012
+ /*#__PURE__*/ jsx(Plus, {
1013
+ className: "h-3 w-3 mr-1"
1014
+ }),
1015
+ "Section"
1016
+ ]
1017
+ })
1018
+ ]
1019
+ })
1020
+ }),
1021
+ /*#__PURE__*/ jsx(CardContent, {
1022
+ className: "flex-1 overflow-auto px-2 pb-2",
1023
+ children: /*#__PURE__*/ jsx(Accordion, {
1024
+ type: "multiple",
1025
+ value: expandedSections,
1026
+ onValueChange: setExpandedSections,
1027
+ className: "space-y-1",
1028
+ children: sections.map((section, sectionIndex)=>/*#__PURE__*/ jsxs(AccordionItem, {
1029
+ value: section.id,
1030
+ className: `group/section border rounded-lg ${selectedSectionId === section.id && !selectedFieldId ? 'ring-2 ring-primary' : ''}`,
1031
+ children: [
1032
+ /*#__PURE__*/ jsxs("div", {
1033
+ className: "flex items-center gap-1 px-2 py-1.5",
1034
+ children: [
1035
+ /*#__PURE__*/ jsx(AccordionTrigger, {
1036
+ className: "h-5 w-5 p-0 hover:no-underline hover:bg-accent rounded [&>svg]:hidden flex items-center justify-center shrink-0",
1037
+ children: /*#__PURE__*/ jsx("span", {
1038
+ className: "flex items-center justify-center",
1039
+ children: /*#__PURE__*/ jsx(ChevronRight, {
1040
+ className: "h-3 w-3 shrink-0 transition-transform duration-200 group-data-[state=open]/section:rotate-90"
1041
+ })
1042
+ })
1043
+ }),
1044
+ /*#__PURE__*/ jsxs("div", {
1045
+ className: "flex-1 min-w-0 cursor-pointer flex items-center gap-1",
1046
+ onClick: ()=>{
1047
+ setSelectedSectionId(section.id);
1048
+ setSelectedFieldId(null);
1049
+ },
1050
+ children: [
1051
+ /*#__PURE__*/ jsx("span", {
1052
+ className: "text-sm font-medium truncate",
1053
+ children: section.title
1054
+ }),
1055
+ section.collapsible && /*#__PURE__*/ jsx("span", {
1056
+ className: "text-[10px] text-muted-foreground",
1057
+ children: "(collapsible)"
1058
+ })
1059
+ ]
1060
+ }),
1061
+ /*#__PURE__*/ jsxs("div", {
1062
+ className: "flex gap-0.5 opacity-0 group-hover/section:opacity-100 transition-opacity",
1063
+ children: [
1064
+ /*#__PURE__*/ jsx(Button, {
1065
+ variant: "ghost",
1066
+ size: "sm",
1067
+ className: "h-5 w-5 p-0",
1068
+ onClick: (e)=>{
1069
+ e.stopPropagation();
1070
+ moveSection(section.id, 'up');
1071
+ },
1072
+ disabled: 0 === sectionIndex,
1073
+ children: /*#__PURE__*/ jsx(MoveUp, {
1074
+ className: "h-2.5 w-2.5"
1075
+ })
1076
+ }),
1077
+ /*#__PURE__*/ jsx(Button, {
1078
+ variant: "ghost",
1079
+ size: "sm",
1080
+ className: "h-5 w-5 p-0",
1081
+ onClick: (e)=>{
1082
+ e.stopPropagation();
1083
+ moveSection(section.id, 'down');
1084
+ },
1085
+ disabled: sectionIndex === sections.length - 1,
1086
+ children: /*#__PURE__*/ jsx(MoveDown, {
1087
+ className: "h-2.5 w-2.5"
1088
+ })
1089
+ }),
1090
+ /*#__PURE__*/ jsx(Button, {
1091
+ variant: "ghost",
1092
+ size: "sm",
1093
+ className: "h-5 w-5 p-0",
1094
+ onClick: (e)=>{
1095
+ e.stopPropagation();
1096
+ removeSection(section.id);
1097
+ },
1098
+ disabled: sections.length <= 1,
1099
+ children: /*#__PURE__*/ jsx(Trash2, {
1100
+ className: "h-2.5 w-2.5 text-destructive"
1101
+ })
1102
+ })
1103
+ ]
1104
+ })
1105
+ ]
1106
+ }),
1107
+ /*#__PURE__*/ jsx(AccordionContent, {
1108
+ className: "px-2 pb-2 pt-0",
1109
+ children: /*#__PURE__*/ jsxs("div", {
1110
+ className: "space-y-0.5 ml-3 border-l pl-2",
1111
+ children: [
1112
+ section.fields.map((field, fieldIndex)=>/*#__PURE__*/ jsxs("div", {
1113
+ className: `group/field flex items-center gap-1 px-2 py-1 rounded cursor-pointer hover:bg-accent transition-colors ${selectedFieldId === field.id ? 'bg-accent' : ''}`,
1114
+ onClick: ()=>{
1115
+ setSelectedSectionId(section.id);
1116
+ setSelectedFieldId(field.id);
1117
+ },
1118
+ children: [
1119
+ /*#__PURE__*/ jsx(GripVertical, {
1120
+ className: "h-3 w-3 text-muted-foreground opacity-0 group-hover/field:opacity-50"
1121
+ }),
1122
+ /*#__PURE__*/ jsxs("div", {
1123
+ className: "flex-1 min-w-0",
1124
+ children: [
1125
+ /*#__PURE__*/ jsxs("div", {
1126
+ className: "flex items-center gap-1",
1127
+ children: [
1128
+ /*#__PURE__*/ jsx("span", {
1129
+ className: "text-xs font-medium truncate",
1130
+ children: field.label
1131
+ }),
1132
+ field.rules?.some((r)=>r.effects.required) && /*#__PURE__*/ jsx("span", {
1133
+ className: "text-[10px] text-destructive",
1134
+ children: "*"
1135
+ })
1136
+ ]
1137
+ }),
1138
+ /*#__PURE__*/ jsx("div", {
1139
+ className: "text-[9px] text-muted-foreground",
1140
+ children: field.type
1141
+ })
1142
+ ]
1143
+ }),
1144
+ /*#__PURE__*/ jsxs("div", {
1145
+ className: "flex gap-0.5 opacity-0 group-hover/field:opacity-100 transition-opacity",
1146
+ children: [
1147
+ /*#__PURE__*/ jsx(Button, {
1148
+ variant: "ghost",
1149
+ size: "sm",
1150
+ className: "h-5 w-5 p-0",
1151
+ onClick: (e)=>{
1152
+ e.stopPropagation();
1153
+ moveField(section.id, field.id, 'up');
1154
+ },
1155
+ disabled: 0 === fieldIndex,
1156
+ children: /*#__PURE__*/ jsx(MoveUp, {
1157
+ className: "h-2.5 w-2.5"
1158
+ })
1159
+ }),
1160
+ /*#__PURE__*/ jsx(Button, {
1161
+ variant: "ghost",
1162
+ size: "sm",
1163
+ className: "h-5 w-5 p-0",
1164
+ onClick: (e)=>{
1165
+ e.stopPropagation();
1166
+ moveField(section.id, field.id, 'down');
1167
+ },
1168
+ disabled: fieldIndex === section.fields.length - 1,
1169
+ children: /*#__PURE__*/ jsx(MoveDown, {
1170
+ className: "h-2.5 w-2.5"
1171
+ })
1172
+ }),
1173
+ /*#__PURE__*/ jsx(Button, {
1174
+ variant: "ghost",
1175
+ size: "sm",
1176
+ className: "h-5 w-5 p-0",
1177
+ onClick: (e)=>{
1178
+ e.stopPropagation();
1179
+ removeField(section.id, field.id);
1180
+ },
1181
+ children: /*#__PURE__*/ jsx(Trash2, {
1182
+ className: "h-2.5 w-2.5 text-destructive"
1183
+ })
1184
+ })
1185
+ ]
1186
+ })
1187
+ ]
1188
+ }, field.id)),
1189
+ /*#__PURE__*/ jsxs(Button, {
1190
+ onClick: ()=>addField(section.id),
1191
+ variant: "outline",
1192
+ size: "sm",
1193
+ children: [
1194
+ /*#__PURE__*/ jsx(Plus, {
1195
+ className: "h-3 w-3 mr-1"
1196
+ }),
1197
+ "Field"
1198
+ ]
1199
+ })
1200
+ ]
1201
+ })
1202
+ })
1203
+ ]
1204
+ }, section.id))
1205
+ })
1206
+ })
1207
+ ]
1208
+ }),
1209
+ /*#__PURE__*/ jsxs(Card, {
1210
+ className: "overflow-hidden flex flex-col",
1211
+ children: [
1212
+ /*#__PURE__*/ jsxs(CardHeader, {
1213
+ children: [
1214
+ /*#__PURE__*/ jsxs(CardTitle, {
1215
+ className: "flex items-center gap-2",
1216
+ children: [
1217
+ /*#__PURE__*/ jsx(Settings, {
1218
+ className: "h-4 w-4"
1219
+ }),
1220
+ selectedFieldId ? 'Field configuration' : selectedSectionId ? 'Section configuration' : 'Configuration'
1221
+ ]
1222
+ }),
1223
+ /*#__PURE__*/ jsx(CardDescription, {
1224
+ children: selectedField ? `Configure "${selectedField.label}"` : selectedSection ? `Configure "${selectedSection.title}" section` : 'Select a section or field to configure'
1225
+ })
1226
+ ]
1227
+ }),
1228
+ /*#__PURE__*/ jsx(CardContent, {
1229
+ className: "flex-1 overflow-auto",
1230
+ children: selectedField ? /*#__PURE__*/ jsx(FieldConfigForm, {
1231
+ field: selectedField,
1232
+ onUpdate: (updates)=>updateField(selectedField.id, updates),
1233
+ allFields: allFields,
1234
+ existingFieldNames: new Set(allFields.map((f)=>f.name))
1235
+ }) : selectedSection ? /*#__PURE__*/ jsx(SectionConfigForm, {
1236
+ section: selectedSection,
1237
+ onUpdate: (updates)=>updateSection(selectedSection.id, updates),
1238
+ existingSectionIds: new Set(sections.map((s)=>s.id))
1239
+ }) : /*#__PURE__*/ jsx("div", {
1240
+ className: "flex items-center justify-center h-full text-muted-foreground",
1241
+ children: "Select a section or field to configure"
1242
+ })
1243
+ })
1244
+ ]
1245
+ }),
1246
+ /*#__PURE__*/ jsxs(Card, {
1247
+ className: "overflow-hidden flex flex-col",
1248
+ children: [
1249
+ /*#__PURE__*/ jsx(CardHeader, {
1250
+ children: /*#__PURE__*/ jsxs("div", {
1251
+ className: "space-y-4",
1252
+ children: [
1253
+ /*#__PURE__*/ jsxs("div", {
1254
+ children: [
1255
+ /*#__PURE__*/ jsxs(CardTitle, {
1256
+ className: "flex items-center gap-2",
1257
+ children: [
1258
+ /*#__PURE__*/ jsx(View, {
1259
+ className: "h-4 w-4"
1260
+ }),
1261
+ "Preview & export"
1262
+ ]
1263
+ }),
1264
+ /*#__PURE__*/ jsx(CardDescription, {
1265
+ children: "See how your form looks"
1266
+ })
1267
+ ]
1268
+ }),
1269
+ /*#__PURE__*/ jsxs("div", {
1270
+ className: "space-y-2",
1271
+ children: [
1272
+ /*#__PURE__*/ jsx(Label, {
1273
+ htmlFor: "form-title",
1274
+ children: "Form title"
1275
+ }),
1276
+ /*#__PURE__*/ jsx(Input, {
1277
+ id: "form-title",
1278
+ value: formTitle,
1279
+ onChange: (e)=>setFormTitle(e.target.value)
1280
+ })
1281
+ ]
1282
+ }),
1283
+ /*#__PURE__*/ jsxs("div", {
1284
+ className: "space-y-2",
1285
+ children: [
1286
+ /*#__PURE__*/ jsx(Label, {
1287
+ htmlFor: "form-description",
1288
+ children: "Form description"
1289
+ }),
1290
+ /*#__PURE__*/ jsx(Textarea, {
1291
+ id: "form-description",
1292
+ value: formDescription,
1293
+ onChange: (e)=>setFormDescription(e.target.value),
1294
+ placeholder: "Optional description",
1295
+ rows: 2
1296
+ })
1297
+ ]
1298
+ })
1299
+ ]
1300
+ })
1301
+ }),
1302
+ /*#__PURE__*/ jsx(CardContent, {
1303
+ className: "flex-1 overflow-auto",
1304
+ children: /*#__PURE__*/ jsxs(Tabs, {
1305
+ defaultValue: "preview",
1306
+ className: "h-full flex flex-col",
1307
+ children: [
1308
+ /*#__PURE__*/ jsxs(TabsList, {
1309
+ className: "grid w-full grid-cols-2",
1310
+ children: [
1311
+ /*#__PURE__*/ jsxs(TabsTrigger, {
1312
+ value: "preview",
1313
+ children: [
1314
+ /*#__PURE__*/ jsx(Eye, {
1315
+ className: "h-4 w-4 mr-2"
1316
+ }),
1317
+ "Preview"
1318
+ ]
1319
+ }),
1320
+ /*#__PURE__*/ jsxs(TabsTrigger, {
1321
+ value: "code",
1322
+ children: [
1323
+ /*#__PURE__*/ jsx(Code, {
1324
+ className: "h-4 w-4 mr-2"
1325
+ }),
1326
+ "Schema"
1327
+ ]
1328
+ })
1329
+ ]
1330
+ }),
1331
+ /*#__PURE__*/ jsxs(TabsContent, {
1332
+ value: "preview",
1333
+ className: "flex-1 overflow-auto",
1334
+ children: [
1335
+ /*#__PURE__*/ jsxs("div", {
1336
+ className: "flex items-center justify-end gap-2 mb-4 pb-2 border-b",
1337
+ children: [
1338
+ /*#__PURE__*/ jsx(Label, {
1339
+ htmlFor: "preview-readonly",
1340
+ className: "text-sm text-muted-foreground",
1341
+ children: "Readonly"
1342
+ }),
1343
+ /*#__PURE__*/ jsx(Switch, {
1344
+ id: "preview-readonly",
1345
+ checked: previewDisabled,
1346
+ onCheckedChange: setPreviewDisabled
1347
+ })
1348
+ ]
1349
+ }),
1350
+ /*#__PURE__*/ jsx(MetadataForm, {
1351
+ schema: generatedSchema,
1352
+ onSubmit: (data)=>{
1353
+ console.log('Form submitted:', data);
1354
+ alert('Form submitted! Check console for data.');
1355
+ },
1356
+ disabled: previewDisabled,
1357
+ autoComplete: "off"
1358
+ }, sections.map((s)=>`${s.id}:${s.collapsible}:${s.defaultExpanded}:${s.fields.map((f)=>`${f.id}:${f.type}:${f.name}:${JSON.stringify(f.rules || [])}:${JSON.stringify(f.validation || {})}`).join('-')}`).join(','))
1359
+ ]
1360
+ }),
1361
+ /*#__PURE__*/ jsx(TabsContent, {
1362
+ value: "code",
1363
+ className: "flex-1 overflow-auto",
1364
+ children: /*#__PURE__*/ jsx("pre", {
1365
+ className: "text-xs bg-muted p-4 rounded-lg overflow-auto max-h-full",
1366
+ children: schemaToJson(generatedSchema)
1367
+ })
1368
+ })
1369
+ ]
1370
+ })
1371
+ })
1372
+ ]
1373
+ })
1374
+ ]
1375
+ });
1376
+ }
1377
+ function FieldOptionsEditor({ options, onChange }) {
1378
+ const addOption = ()=>{
1379
+ onChange([
1380
+ ...options,
1381
+ {
1382
+ label: `Option ${options.length + 1}`,
1383
+ value: `option${options.length + 1}`
1384
+ }
1385
+ ]);
1386
+ };
1387
+ const updateOption = (index, updates)=>{
1388
+ const newOptions = [
1389
+ ...options
1390
+ ];
1391
+ newOptions[index] = {
1392
+ ...newOptions[index],
1393
+ ...updates
1394
+ };
1395
+ onChange(newOptions);
1396
+ };
1397
+ const removeOption = (index)=>{
1398
+ onChange(options.filter((_, i)=>i !== index));
1399
+ };
1400
+ return /*#__PURE__*/ jsxs("div", {
1401
+ className: "space-y-3",
1402
+ children: [
1403
+ options.map((option, index)=>/*#__PURE__*/ jsxs("div", {
1404
+ className: "flex gap-2 items-center",
1405
+ children: [
1406
+ /*#__PURE__*/ jsxs("div", {
1407
+ className: "flex-1 grid grid-cols-2 gap-2",
1408
+ children: [
1409
+ /*#__PURE__*/ jsx(Input, {
1410
+ placeholder: "Label",
1411
+ value: option.label,
1412
+ onChange: (e)=>updateOption(index, {
1413
+ label: e.target.value
1414
+ })
1415
+ }),
1416
+ /*#__PURE__*/ jsx(Input, {
1417
+ placeholder: "Value",
1418
+ value: option.value,
1419
+ onChange: (e)=>updateOption(index, {
1420
+ value: e.target.value
1421
+ })
1422
+ })
1423
+ ]
1424
+ }),
1425
+ /*#__PURE__*/ jsx(Button, {
1426
+ variant: "ghost",
1427
+ size: "icon",
1428
+ className: "h-8 w-8 text-muted-foreground hover:text-destructive",
1429
+ onClick: ()=>removeOption(index),
1430
+ children: /*#__PURE__*/ jsx(Trash2, {
1431
+ className: "h-4 w-4"
1432
+ })
1433
+ })
1434
+ ]
1435
+ }, index)),
1436
+ /*#__PURE__*/ jsxs(Button, {
1437
+ onClick: addOption,
1438
+ variant: "outline",
1439
+ size: "sm",
1440
+ className: "w-full",
1441
+ children: [
1442
+ /*#__PURE__*/ jsx(Plus, {
1443
+ className: "h-3 w-3 mr-2"
1444
+ }),
1445
+ "Add option"
1446
+ ]
1447
+ })
1448
+ ]
1449
+ });
1450
+ }
1451
+ function DataSourceEditor({ dataSource, onChange }) {
1452
+ const [sourceType, setSourceType] = useState(dataSource?.type || 'none');
1453
+ return /*#__PURE__*/ jsxs("div", {
1454
+ className: "space-y-4",
1455
+ children: [
1456
+ /*#__PURE__*/ jsxs("div", {
1457
+ className: "space-y-2",
1458
+ children: [
1459
+ /*#__PURE__*/ jsx(Label, {
1460
+ children: "Data source type"
1461
+ }),
1462
+ /*#__PURE__*/ jsxs(Select, {
1463
+ value: sourceType,
1464
+ onValueChange: (value)=>{
1465
+ setSourceType(value);
1466
+ if ('none' === value) onChange(void 0);
1467
+ else if ('static' === value) onChange({
1468
+ type: 'static',
1469
+ options: []
1470
+ });
1471
+ else if ('fetch' === value) onChange({
1472
+ type: 'fetch',
1473
+ url: '',
1474
+ method: 'GET'
1475
+ });
1476
+ else if ('remote' === value) onChange({
1477
+ type: 'remote',
1478
+ endpoint: '',
1479
+ params: {}
1480
+ });
1481
+ else if ('computed' === value) onChange({
1482
+ type: 'computed',
1483
+ dependency: [],
1484
+ compute: ''
1485
+ });
1486
+ },
1487
+ children: [
1488
+ /*#__PURE__*/ jsx(SelectTrigger, {
1489
+ children: /*#__PURE__*/ jsx(SelectValue, {})
1490
+ }),
1491
+ /*#__PURE__*/ jsxs(SelectContent, {
1492
+ children: [
1493
+ /*#__PURE__*/ jsx(SelectItem, {
1494
+ value: "none",
1495
+ children: "None"
1496
+ }),
1497
+ /*#__PURE__*/ jsx(SelectItem, {
1498
+ value: "fetch",
1499
+ children: "Fetch (single request)"
1500
+ }),
1501
+ /*#__PURE__*/ jsx(SelectItem, {
1502
+ value: "remote",
1503
+ children: "Remote (dependent)"
1504
+ }),
1505
+ /*#__PURE__*/ jsx(SelectItem, {
1506
+ value: "computed",
1507
+ children: "Computed"
1508
+ })
1509
+ ]
1510
+ })
1511
+ ]
1512
+ })
1513
+ ]
1514
+ }),
1515
+ 'fetch' === sourceType && dataSource?.type === 'fetch' && /*#__PURE__*/ jsxs("div", {
1516
+ className: "space-y-3",
1517
+ children: [
1518
+ /*#__PURE__*/ jsxs("div", {
1519
+ className: "space-y-2",
1520
+ children: [
1521
+ /*#__PURE__*/ jsx(Label, {
1522
+ children: "API URL"
1523
+ }),
1524
+ /*#__PURE__*/ jsx(Input, {
1525
+ placeholder: "/api/data",
1526
+ value: dataSource.url,
1527
+ onChange: (e)=>onChange({
1528
+ ...dataSource,
1529
+ url: e.target.value
1530
+ })
1531
+ })
1532
+ ]
1533
+ }),
1534
+ /*#__PURE__*/ jsxs("div", {
1535
+ className: "space-y-2",
1536
+ children: [
1537
+ /*#__PURE__*/ jsx(Label, {
1538
+ children: "Transform"
1539
+ }),
1540
+ /*#__PURE__*/ jsx(Textarea, {
1541
+ placeholder: "data.map(item => ({ label: item.name, value: item.id }))",
1542
+ value: dataSource.transform || '',
1543
+ onChange: (e)=>onChange({
1544
+ ...dataSource,
1545
+ transform: e.target.value
1546
+ }),
1547
+ rows: 2
1548
+ })
1549
+ ]
1550
+ })
1551
+ ]
1552
+ }),
1553
+ 'remote' === sourceType && dataSource?.type === 'remote' && /*#__PURE__*/ jsxs("div", {
1554
+ className: "space-y-3",
1555
+ children: [
1556
+ /*#__PURE__*/ jsxs("div", {
1557
+ className: "space-y-2",
1558
+ children: [
1559
+ /*#__PURE__*/ jsx(Label, {
1560
+ children: "Endpoint"
1561
+ }),
1562
+ /*#__PURE__*/ jsx(Input, {
1563
+ placeholder: "/api/data",
1564
+ value: dataSource.endpoint,
1565
+ onChange: (e)=>onChange({
1566
+ ...dataSource,
1567
+ endpoint: e.target.value
1568
+ })
1569
+ })
1570
+ ]
1571
+ }),
1572
+ /*#__PURE__*/ jsxs("div", {
1573
+ className: "space-y-2",
1574
+ children: [
1575
+ /*#__PURE__*/ jsx(Label, {
1576
+ children: "Parameters (JSON)"
1577
+ }),
1578
+ /*#__PURE__*/ jsx(Textarea, {
1579
+ placeholder: '{ "fieldName": "$otherField" }',
1580
+ value: JSON.stringify(dataSource.params || {}, null, 2),
1581
+ onChange: (e)=>{
1582
+ try {
1583
+ const params = JSON.parse(e.target.value);
1584
+ onChange({
1585
+ ...dataSource,
1586
+ params
1587
+ });
1588
+ } catch {}
1589
+ },
1590
+ rows: 3
1591
+ })
1592
+ ]
1593
+ })
1594
+ ]
1595
+ }),
1596
+ 'computed' === sourceType && dataSource?.type === 'computed' && /*#__PURE__*/ jsxs("div", {
1597
+ className: "space-y-3",
1598
+ children: [
1599
+ /*#__PURE__*/ jsxs("div", {
1600
+ className: "space-y-2",
1601
+ children: [
1602
+ /*#__PURE__*/ jsx(Label, {
1603
+ children: "Dependencies (comma-separated)"
1604
+ }),
1605
+ /*#__PURE__*/ jsx(Input, {
1606
+ placeholder: "field1, field2",
1607
+ value: dataSource.dependency.join(', '),
1608
+ onChange: (e)=>onChange({
1609
+ ...dataSource,
1610
+ dependency: e.target.value.split(',').map((s)=>s.trim())
1611
+ })
1612
+ })
1613
+ ]
1614
+ }),
1615
+ /*#__PURE__*/ jsxs("div", {
1616
+ className: "space-y-2",
1617
+ children: [
1618
+ /*#__PURE__*/ jsx(Label, {
1619
+ children: "Compute expression"
1620
+ }),
1621
+ /*#__PURE__*/ jsx(Textarea, {
1622
+ placeholder: "(field1 || 0) * (field2 || 0)",
1623
+ value: dataSource.compute,
1624
+ onChange: (e)=>onChange({
1625
+ ...dataSource,
1626
+ compute: e.target.value
1627
+ }),
1628
+ rows: 2
1629
+ })
1630
+ ]
1631
+ })
1632
+ ]
1633
+ })
1634
+ ]
1635
+ });
1636
+ }
1637
+ const CONDITION_OPERATORS = [
1638
+ {
1639
+ value: 'is',
1640
+ label: 'equals',
1641
+ description: 'Field value equals'
1642
+ },
1643
+ {
1644
+ value: 'isNot',
1645
+ label: 'not equals',
1646
+ description: 'Field value does not equal'
1647
+ },
1648
+ {
1649
+ value: 'in',
1650
+ label: 'is one of',
1651
+ description: 'Field value is one of'
1652
+ },
1653
+ {
1654
+ value: 'notIn',
1655
+ label: 'is not one of',
1656
+ description: 'Field value is not one of'
1657
+ },
1658
+ {
1659
+ value: 'matches',
1660
+ label: 'matches pattern',
1661
+ description: 'Field value matches regex'
1662
+ }
1663
+ ];
1664
+ const RULE_EFFECTS = [
1665
+ {
1666
+ value: 'show',
1667
+ label: 'Show field',
1668
+ description: 'Show this field when conditions are met',
1669
+ Icon: Eye,
1670
+ color: 'text-green-600 bg-green-50 border-green-200'
1671
+ },
1672
+ {
1673
+ value: 'hide',
1674
+ label: 'Hide field',
1675
+ description: 'Hide this field when conditions are met',
1676
+ Icon: EyeOff,
1677
+ color: 'text-orange-600 bg-orange-50 border-orange-200'
1678
+ },
1679
+ {
1680
+ value: 'require',
1681
+ label: 'Make required',
1682
+ description: 'Require this field when conditions are met',
1683
+ Icon: Asterisk,
1684
+ color: 'text-red-600 bg-red-50 border-red-200'
1685
+ },
1686
+ {
1687
+ value: 'disable',
1688
+ label: 'Disable field',
1689
+ description: 'Disable this field when conditions are met',
1690
+ Icon: Ban,
1691
+ color: 'text-gray-600 bg-gray-50 border-gray-200'
1692
+ }
1693
+ ];
1694
+ function RulesEditor({ rules = [], onChange, allFields, requiredMessage, onRequiredMessageChange }) {
1695
+ const [isAddingRule, setIsAddingRule] = useState(false);
1696
+ const [editingRuleIndex, setEditingRuleIndex] = useState(null);
1697
+ const [selectedEffect, setSelectedEffect] = useState('show');
1698
+ const [conditions, setConditions] = useState([
1699
+ {
1700
+ field: '',
1701
+ operator: 'is',
1702
+ value: ''
1703
+ }
1704
+ ]);
1705
+ const [conditionOperator, setConditionOperator] = useState('AND');
1706
+ const isAlwaysRequired = rules.some((r)=>true === r.effects.required && 0 === r.conditions.length);
1707
+ const resetBuilder = ()=>{
1708
+ setSelectedEffect('show');
1709
+ setConditions([
1710
+ {
1711
+ field: '',
1712
+ operator: 'is',
1713
+ value: ''
1714
+ }
1715
+ ]);
1716
+ setConditionOperator('AND');
1717
+ setIsAddingRule(false);
1718
+ setEditingRuleIndex(null);
1719
+ };
1720
+ const addCondition = ()=>{
1721
+ setConditions([
1722
+ ...conditions,
1723
+ {
1724
+ field: '',
1725
+ operator: 'is',
1726
+ value: ''
1727
+ }
1728
+ ]);
1729
+ };
1730
+ const updateCondition = (index, updates)=>{
1731
+ const newConditions = [
1732
+ ...conditions
1733
+ ];
1734
+ newConditions[index] = {
1735
+ ...newConditions[index],
1736
+ ...updates
1737
+ };
1738
+ setConditions(newConditions);
1739
+ };
1740
+ const removeCondition = (index)=>{
1741
+ if (conditions.length > 1) setConditions(conditions.filter((_, i)=>i !== index));
1742
+ };
1743
+ const buildCondition = (cond)=>{
1744
+ const condition = {
1745
+ when: cond.field
1746
+ };
1747
+ const targetField = allFields.find((f)=>f.name === cond.field);
1748
+ const isNumericField = targetField?.type === 'number' || targetField?.type === 'slider';
1749
+ const isBooleanField = targetField?.type === 'checkbox' || targetField?.type === 'switch';
1750
+ const parseValue = (val)=>{
1751
+ if (isBooleanField) {
1752
+ if ('true' === val.toLowerCase()) return true;
1753
+ if ('false' === val.toLowerCase()) return false;
1754
+ }
1755
+ if (isNumericField) {
1756
+ const num = Number(val);
1757
+ if (!isNaN(num)) return num;
1758
+ }
1759
+ if ('true' === val.toLowerCase()) return true;
1760
+ if ('false' === val.toLowerCase()) return false;
1761
+ return val;
1762
+ };
1763
+ switch(cond.operator){
1764
+ case 'is':
1765
+ condition.is = parseValue(cond.value);
1766
+ break;
1767
+ case 'isNot':
1768
+ condition.isNot = parseValue(cond.value);
1769
+ break;
1770
+ case 'in':
1771
+ condition.in = cond.value.split(',').map((v)=>parseValue(v.trim()));
1772
+ break;
1773
+ case 'notIn':
1774
+ condition.notIn = cond.value.split(',').map((v)=>parseValue(v.trim()));
1775
+ break;
1776
+ case 'matches':
1777
+ condition.matches = cond.value;
1778
+ break;
1779
+ }
1780
+ return condition;
1781
+ };
1782
+ const saveRule = ()=>{
1783
+ const validConditions = conditions.filter((c)=>c.field);
1784
+ if (0 === validConditions.length) return;
1785
+ const newRule = {
1786
+ id: `rule-${Date.now()}`,
1787
+ conditions: validConditions.map(buildCondition),
1788
+ operator: conditionOperator,
1789
+ effects: {}
1790
+ };
1791
+ switch(selectedEffect){
1792
+ case 'show':
1793
+ newRule.effects.visible = true;
1794
+ break;
1795
+ case 'hide':
1796
+ newRule.effects.visible = false;
1797
+ break;
1798
+ case 'require':
1799
+ newRule.effects.required = true;
1800
+ break;
1801
+ case 'disable':
1802
+ newRule.effects.disabled = true;
1803
+ break;
1804
+ }
1805
+ if (null !== editingRuleIndex) {
1806
+ const newRules = [
1807
+ ...rules
1808
+ ];
1809
+ newRules[editingRuleIndex] = newRule;
1810
+ onChange(newRules);
1811
+ } else onChange([
1812
+ ...rules,
1813
+ newRule
1814
+ ]);
1815
+ resetBuilder();
1816
+ };
1817
+ const editRule = (index)=>{
1818
+ const rule = rules[index];
1819
+ if (!rule) return;
1820
+ let effect = 'show';
1821
+ if (true === rule.effects.visible) effect = 'show';
1822
+ else if (false === rule.effects.visible) effect = 'hide';
1823
+ else if (true === rule.effects.required) effect = 'require';
1824
+ else if (true === rule.effects.disabled) effect = 'disable';
1825
+ setSelectedEffect(effect);
1826
+ setConditionOperator(rule.operator || 'AND');
1827
+ const editableConditions = rule.conditions.map((cond)=>{
1828
+ let operator = 'is';
1829
+ let value = '';
1830
+ if (void 0 !== cond.is) {
1831
+ operator = 'is';
1832
+ value = String(cond.is);
1833
+ } else if (void 0 !== cond.isNot) {
1834
+ operator = 'isNot';
1835
+ value = String(cond.isNot);
1836
+ } else if (void 0 !== cond.in) {
1837
+ operator = 'in';
1838
+ value = cond.in.map(String).join(', ');
1839
+ } else if (void 0 !== cond.notIn) {
1840
+ operator = 'notIn';
1841
+ value = cond.notIn.map(String).join(', ');
1842
+ } else if (void 0 !== cond.matches) {
1843
+ operator = 'matches';
1844
+ value = cond.matches;
1845
+ }
1846
+ return {
1847
+ field: cond.when,
1848
+ operator,
1849
+ value
1850
+ };
1851
+ });
1852
+ setConditions(editableConditions.length > 0 ? editableConditions : [
1853
+ {
1854
+ field: '',
1855
+ operator: 'is',
1856
+ value: ''
1857
+ }
1858
+ ]);
1859
+ setEditingRuleIndex(index);
1860
+ setIsAddingRule(true);
1861
+ };
1862
+ const deleteRule = (index)=>{
1863
+ onChange(rules.filter((_, i)=>i !== index));
1864
+ };
1865
+ const getFieldLabel = (fieldName)=>{
1866
+ const field = allFields.find((f)=>f.name === fieldName);
1867
+ return field?.label || fieldName;
1868
+ };
1869
+ const describeRule = (rule)=>{
1870
+ if (0 === rule.conditions.length) {
1871
+ if (rule.effects.required) return 'Always required';
1872
+ return 'Always applies';
1873
+ }
1874
+ const conditionDescriptions = rule.conditions.map((cond)=>{
1875
+ const fieldLabel = getFieldLabel(cond.when);
1876
+ if (void 0 !== cond.is) return `"${fieldLabel}" = ${JSON.stringify(cond.is)}`;
1877
+ if (void 0 !== cond.isNot) return `"${fieldLabel}" ≠ ${JSON.stringify(cond.isNot)}`;
1878
+ if (void 0 !== cond.in) return `"${fieldLabel}" in [${cond.in.map((v)=>JSON.stringify(v)).join(', ')}]`;
1879
+ if (void 0 !== cond.notIn) return `"${fieldLabel}" not in [${cond.notIn.map((v)=>JSON.stringify(v)).join(', ')}]`;
1880
+ if (void 0 !== cond.matches) return `"${fieldLabel}" matches /${cond.matches}/`;
1881
+ return `"${fieldLabel}"`;
1882
+ });
1883
+ const operator = 'OR' === rule.operator ? ' OR ' : ' AND ';
1884
+ return conditionDescriptions.join(operator);
1885
+ };
1886
+ const getEffectDescription = (rule)=>{
1887
+ if (true === rule.effects.visible) return {
1888
+ label: 'Show',
1889
+ color: 'text-green-600 bg-green-50'
1890
+ };
1891
+ if (false === rule.effects.visible) return {
1892
+ label: 'Hide',
1893
+ color: 'text-orange-600 bg-orange-50'
1894
+ };
1895
+ if (true === rule.effects.required) return {
1896
+ label: 'Required',
1897
+ color: 'text-red-600 bg-red-50'
1898
+ };
1899
+ if (true === rule.effects.disabled) return {
1900
+ label: 'Disabled',
1901
+ color: 'text-gray-600 bg-gray-50'
1902
+ };
1903
+ return {
1904
+ label: 'Unknown',
1905
+ color: 'text-muted-foreground bg-muted'
1906
+ };
1907
+ };
1908
+ const getFieldOptions = (fieldName)=>{
1909
+ const field = allFields.find((f)=>f.name === fieldName);
1910
+ return field?.options || [];
1911
+ };
1912
+ return /*#__PURE__*/ jsxs("div", {
1913
+ className: "space-y-4",
1914
+ children: [
1915
+ /*#__PURE__*/ jsxs("div", {
1916
+ className: "space-y-3 p-3 border rounded-lg bg-muted/30",
1917
+ children: [
1918
+ /*#__PURE__*/ jsxs("div", {
1919
+ className: "flex items-center justify-between",
1920
+ children: [
1921
+ /*#__PURE__*/ jsxs("div", {
1922
+ className: "flex items-center gap-3",
1923
+ children: [
1924
+ /*#__PURE__*/ jsx(Asterisk, {
1925
+ className: "h-5 w-5 text-red-500"
1926
+ }),
1927
+ /*#__PURE__*/ jsxs("div", {
1928
+ children: [
1929
+ /*#__PURE__*/ jsx(Label, {
1930
+ className: "cursor-pointer font-medium",
1931
+ children: "Always required"
1932
+ }),
1933
+ /*#__PURE__*/ jsx("p", {
1934
+ className: "text-xs text-muted-foreground",
1935
+ children: "Field must always have a value"
1936
+ })
1937
+ ]
1938
+ })
1939
+ ]
1940
+ }),
1941
+ /*#__PURE__*/ jsx(Checkbox, {
1942
+ checked: isAlwaysRequired,
1943
+ onCheckedChange: (checked)=>{
1944
+ if (checked) {
1945
+ const requiredRule = {
1946
+ id: 'always-required',
1947
+ conditions: [],
1948
+ operator: 'AND',
1949
+ effects: {
1950
+ required: true
1951
+ }
1952
+ };
1953
+ onChange([
1954
+ ...rules.filter((r)=>!(r.effects.required && 0 === r.conditions.length)),
1955
+ requiredRule
1956
+ ]);
1957
+ } else {
1958
+ onChange(rules.filter((r)=>!(r.effects.required && 0 === r.conditions.length)));
1959
+ onRequiredMessageChange(void 0);
1960
+ }
1961
+ }
1962
+ })
1963
+ ]
1964
+ }),
1965
+ isAlwaysRequired && /*#__PURE__*/ jsxs("div", {
1966
+ className: "space-y-1.5 pl-8",
1967
+ children: [
1968
+ /*#__PURE__*/ jsx(Label, {
1969
+ htmlFor: "required-message",
1970
+ className: "text-xs text-muted-foreground",
1971
+ children: "Error message"
1972
+ }),
1973
+ /*#__PURE__*/ jsx(Input, {
1974
+ id: "required-message",
1975
+ placeholder: "This field is required",
1976
+ value: requiredMessage || '',
1977
+ onChange: (e)=>onRequiredMessageChange(e.target.value || void 0),
1978
+ className: "h-8 text-sm"
1979
+ })
1980
+ ]
1981
+ })
1982
+ ]
1983
+ }),
1984
+ rules.filter((r)=>r.conditions.length > 0 || !r.effects.required).length > 0 && /*#__PURE__*/ jsxs("div", {
1985
+ className: "space-y-2",
1986
+ children: [
1987
+ /*#__PURE__*/ jsx(Label, {
1988
+ className: "text-xs text-muted-foreground uppercase tracking-wide",
1989
+ children: "Conditional rules"
1990
+ }),
1991
+ rules.map((rule, index)=>({
1992
+ rule,
1993
+ index
1994
+ })).filter(({ rule })=>rule.conditions.length > 0 || !rule.effects.required).map(({ rule, index })=>{
1995
+ const effect = getEffectDescription(rule);
1996
+ return /*#__PURE__*/ jsx("div", {
1997
+ className: "group border rounded-lg p-3 hover:border-primary/50 transition-colors",
1998
+ children: /*#__PURE__*/ jsxs("div", {
1999
+ className: "flex items-start justify-between gap-2",
2000
+ children: [
2001
+ /*#__PURE__*/ jsxs("div", {
2002
+ className: "flex-1 min-w-0",
2003
+ children: [
2004
+ /*#__PURE__*/ jsxs("div", {
2005
+ className: "flex items-center gap-2 mb-1",
2006
+ children: [
2007
+ /*#__PURE__*/ jsx("span", {
2008
+ className: `text-xs font-medium px-2 py-0.5 rounded ${effect.color}`,
2009
+ children: effect.label
2010
+ }),
2011
+ rule.conditions.length > 1 && /*#__PURE__*/ jsxs("span", {
2012
+ className: "text-xs text-muted-foreground",
2013
+ children: [
2014
+ "(",
2015
+ rule.operator,
2016
+ ")"
2017
+ ]
2018
+ })
2019
+ ]
2020
+ }),
2021
+ /*#__PURE__*/ jsx("p", {
2022
+ className: "text-sm text-muted-foreground truncate",
2023
+ children: describeRule(rule)
2024
+ })
2025
+ ]
2026
+ }),
2027
+ /*#__PURE__*/ jsxs("div", {
2028
+ className: "flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity",
2029
+ children: [
2030
+ /*#__PURE__*/ jsx(Button, {
2031
+ variant: "ghost",
2032
+ size: "sm",
2033
+ className: "h-7 w-7 p-0",
2034
+ onClick: ()=>editRule(index),
2035
+ children: /*#__PURE__*/ jsx(Settings, {
2036
+ className: "h-3.5 w-3.5"
2037
+ })
2038
+ }),
2039
+ /*#__PURE__*/ jsx(Button, {
2040
+ variant: "ghost",
2041
+ size: "sm",
2042
+ className: "h-7 w-7 p-0 text-destructive hover:text-destructive",
2043
+ onClick: ()=>deleteRule(index),
2044
+ children: /*#__PURE__*/ jsx(Trash2, {
2045
+ className: "h-3.5 w-3.5"
2046
+ })
2047
+ })
2048
+ ]
2049
+ })
2050
+ ]
2051
+ })
2052
+ }, index);
2053
+ })
2054
+ ]
2055
+ }),
2056
+ isAddingRule ? /*#__PURE__*/ jsxs("div", {
2057
+ className: "border rounded-lg p-4 space-y-4 bg-muted/20",
2058
+ children: [
2059
+ /*#__PURE__*/ jsxs("div", {
2060
+ className: "flex items-center justify-between",
2061
+ children: [
2062
+ /*#__PURE__*/ jsx(Label, {
2063
+ className: "font-medium",
2064
+ children: null !== editingRuleIndex ? 'Edit rule' : 'New rule'
2065
+ }),
2066
+ /*#__PURE__*/ jsx(Button, {
2067
+ variant: "ghost",
2068
+ size: "sm",
2069
+ onClick: resetBuilder,
2070
+ children: "Cancel"
2071
+ })
2072
+ ]
2073
+ }),
2074
+ /*#__PURE__*/ jsxs("div", {
2075
+ className: "space-y-2",
2076
+ children: [
2077
+ /*#__PURE__*/ jsx(Label, {
2078
+ className: "text-xs text-muted-foreground",
2079
+ children: "When conditions are met:"
2080
+ }),
2081
+ /*#__PURE__*/ jsx("div", {
2082
+ className: "grid grid-cols-2 gap-2",
2083
+ children: RULE_EFFECTS.map((effect)=>/*#__PURE__*/ jsxs("button", {
2084
+ type: "button",
2085
+ className: `flex items-center gap-2 p-2 rounded-lg border text-left text-sm transition-all ${selectedEffect === effect.value ? effect.color + ' border-current' : 'hover:bg-muted'}`,
2086
+ onClick: ()=>setSelectedEffect(effect.value),
2087
+ children: [
2088
+ /*#__PURE__*/ jsx(effect.Icon, {
2089
+ className: "h-4 w-4"
2090
+ }),
2091
+ /*#__PURE__*/ jsx("span", {
2092
+ className: "font-medium",
2093
+ children: effect.label
2094
+ })
2095
+ ]
2096
+ }, effect.value))
2097
+ })
2098
+ ]
2099
+ }),
2100
+ /*#__PURE__*/ jsxs("div", {
2101
+ className: "space-y-3",
2102
+ children: [
2103
+ /*#__PURE__*/ jsxs("div", {
2104
+ className: "flex items-center justify-between",
2105
+ children: [
2106
+ /*#__PURE__*/ jsx(Label, {
2107
+ className: "text-xs text-muted-foreground",
2108
+ children: "Conditions:"
2109
+ }),
2110
+ conditions.length > 1 && /*#__PURE__*/ jsxs(Select, {
2111
+ value: conditionOperator,
2112
+ onValueChange: (v)=>setConditionOperator(v),
2113
+ children: [
2114
+ /*#__PURE__*/ jsx(SelectTrigger, {
2115
+ className: "w-24 h-7 text-xs",
2116
+ children: /*#__PURE__*/ jsx(SelectValue, {})
2117
+ }),
2118
+ /*#__PURE__*/ jsxs(SelectContent, {
2119
+ children: [
2120
+ /*#__PURE__*/ jsx(SelectItem, {
2121
+ value: "AND",
2122
+ children: "Match ALL"
2123
+ }),
2124
+ /*#__PURE__*/ jsx(SelectItem, {
2125
+ value: "OR",
2126
+ children: "Match ANY"
2127
+ })
2128
+ ]
2129
+ })
2130
+ ]
2131
+ })
2132
+ ]
2133
+ }),
2134
+ conditions.map((cond, index)=>/*#__PURE__*/ jsxs("div", {
2135
+ className: "space-y-2",
2136
+ children: [
2137
+ index > 0 && /*#__PURE__*/ jsxs("div", {
2138
+ className: "flex items-center gap-2 text-xs text-muted-foreground",
2139
+ children: [
2140
+ /*#__PURE__*/ jsx(Separator, {
2141
+ className: "flex-1"
2142
+ }),
2143
+ /*#__PURE__*/ jsx("span", {
2144
+ children: conditionOperator
2145
+ }),
2146
+ /*#__PURE__*/ jsx(Separator, {
2147
+ className: "flex-1"
2148
+ })
2149
+ ]
2150
+ }),
2151
+ /*#__PURE__*/ jsxs("div", {
2152
+ className: "flex gap-2 items-start",
2153
+ children: [
2154
+ /*#__PURE__*/ jsxs("div", {
2155
+ className: "flex-1 space-y-2",
2156
+ children: [
2157
+ /*#__PURE__*/ jsxs(Select, {
2158
+ value: cond.field,
2159
+ onValueChange: (v)=>updateCondition(index, {
2160
+ field: v
2161
+ }),
2162
+ children: [
2163
+ /*#__PURE__*/ jsx(SelectTrigger, {
2164
+ className: "h-8 text-sm",
2165
+ children: /*#__PURE__*/ jsx(SelectValue, {
2166
+ placeholder: "Select field..."
2167
+ })
2168
+ }),
2169
+ /*#__PURE__*/ jsx(SelectContent, {
2170
+ children: allFields.map((field)=>/*#__PURE__*/ jsx(SelectItem, {
2171
+ value: field.name,
2172
+ children: field.label
2173
+ }, field.id))
2174
+ })
2175
+ ]
2176
+ }),
2177
+ /*#__PURE__*/ jsxs("div", {
2178
+ className: "flex gap-2",
2179
+ children: [
2180
+ /*#__PURE__*/ jsxs(Select, {
2181
+ value: cond.operator,
2182
+ onValueChange: (v)=>updateCondition(index, {
2183
+ operator: v
2184
+ }),
2185
+ children: [
2186
+ /*#__PURE__*/ jsx(SelectTrigger, {
2187
+ className: "w-32 h-8 text-sm",
2188
+ children: /*#__PURE__*/ jsx(SelectValue, {})
2189
+ }),
2190
+ /*#__PURE__*/ jsx(SelectContent, {
2191
+ children: CONDITION_OPERATORS.map((op)=>/*#__PURE__*/ jsx(SelectItem, {
2192
+ value: op.value,
2193
+ children: op.label
2194
+ }, op.value))
2195
+ })
2196
+ ]
2197
+ }),
2198
+ /*#__PURE__*/ jsx("div", {
2199
+ className: "flex-1",
2200
+ children: cond.field && getFieldOptions(cond.field).length > 0 && ('is' === cond.operator || 'isNot' === cond.operator) ? /*#__PURE__*/ jsxs(Select, {
2201
+ value: cond.value,
2202
+ onValueChange: (v)=>updateCondition(index, {
2203
+ value: v
2204
+ }),
2205
+ children: [
2206
+ /*#__PURE__*/ jsx(SelectTrigger, {
2207
+ className: "h-8 text-sm",
2208
+ children: /*#__PURE__*/ jsx(SelectValue, {
2209
+ placeholder: "Select value..."
2210
+ })
2211
+ }),
2212
+ /*#__PURE__*/ jsx(SelectContent, {
2213
+ children: getFieldOptions(cond.field).map((opt)=>/*#__PURE__*/ jsx(SelectItem, {
2214
+ value: String(opt.value),
2215
+ children: opt.label
2216
+ }, String(opt.value)))
2217
+ })
2218
+ ]
2219
+ }) : /*#__PURE__*/ jsx(Input, {
2220
+ className: "h-8 text-sm",
2221
+ placeholder: 'in' === cond.operator || 'notIn' === cond.operator ? 'value1, value2, ...' : 'matches' === cond.operator ? 'regex pattern' : 'value',
2222
+ value: cond.value,
2223
+ onChange: (e)=>updateCondition(index, {
2224
+ value: e.target.value
2225
+ })
2226
+ })
2227
+ })
2228
+ ]
2229
+ })
2230
+ ]
2231
+ }),
2232
+ conditions.length > 1 && /*#__PURE__*/ jsx(Button, {
2233
+ variant: "ghost",
2234
+ size: "sm",
2235
+ className: "h-8 w-8 p-0 text-muted-foreground",
2236
+ onClick: ()=>removeCondition(index),
2237
+ children: /*#__PURE__*/ jsx(Trash2, {
2238
+ className: "h-3.5 w-3.5"
2239
+ })
2240
+ })
2241
+ ]
2242
+ })
2243
+ ]
2244
+ }, index)),
2245
+ /*#__PURE__*/ jsxs(Button, {
2246
+ variant: "outline",
2247
+ size: "sm",
2248
+ className: "w-full",
2249
+ onClick: addCondition,
2250
+ children: [
2251
+ /*#__PURE__*/ jsx(Plus, {
2252
+ className: "h-3 w-3 mr-2"
2253
+ }),
2254
+ "Add condition"
2255
+ ]
2256
+ })
2257
+ ]
2258
+ }),
2259
+ /*#__PURE__*/ jsx(Button, {
2260
+ className: "w-full",
2261
+ onClick: saveRule,
2262
+ disabled: !conditions.some((c)=>c.field),
2263
+ children: null !== editingRuleIndex ? 'Update rule' : 'Add rule'
2264
+ })
2265
+ ]
2266
+ }) : /*#__PURE__*/ jsxs(Button, {
2267
+ variant: "outline",
2268
+ className: "w-full",
2269
+ onClick: ()=>setIsAddingRule(true),
2270
+ children: [
2271
+ /*#__PURE__*/ jsx(Plus, {
2272
+ className: "h-4 w-4 mr-2"
2273
+ }),
2274
+ "Add conditional rule"
2275
+ ]
2276
+ })
2277
+ ]
2278
+ });
2279
+ }
2280
+ export { FormDesigner };