@btst/components 0.0.0-stage → 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/LICENSE.md +17 -0
  2. package/dist/_private/ui/styles/markdown-editor.css +31 -0
  3. package/dist/auto-form/index.cjs +8 -0
  4. package/dist/auto-form/index.d.cts +26 -0
  5. package/dist/auto-form/index.d.mts +26 -0
  6. package/dist/auto-form/index.d.ts +26 -0
  7. package/dist/auto-form/index.mjs +1 -0
  8. package/dist/empty/index.cjs +12 -0
  9. package/dist/empty/index.d.cts +15 -0
  10. package/dist/empty/index.d.mts +15 -0
  11. package/dist/empty/index.d.ts +15 -0
  12. package/dist/empty/index.mjs +1 -0
  13. package/dist/form-builder/index.cjs +16 -0
  14. package/dist/form-builder/index.d.cts +395 -0
  15. package/dist/form-builder/index.d.mts +395 -0
  16. package/dist/form-builder/index.d.ts +395 -0
  17. package/dist/form-builder/index.mjs +4 -0
  18. package/dist/markdown/index.cjs +9 -0
  19. package/dist/markdown/index.d.cts +46 -0
  20. package/dist/markdown/index.d.mts +46 -0
  21. package/dist/markdown/index.d.ts +46 -0
  22. package/dist/markdown/index.mjs +2 -0
  23. package/dist/multi-select/index.cjs +7 -0
  24. package/dist/multi-select/index.d.cts +78 -0
  25. package/dist/multi-select/index.d.mts +78 -0
  26. package/dist/multi-select/index.d.ts +78 -0
  27. package/dist/multi-select/index.mjs +1 -0
  28. package/dist/search-select/index.cjs +7 -0
  29. package/dist/search-select/index.d.cts +16 -0
  30. package/dist/search-select/index.d.mts +16 -0
  31. package/dist/search-select/index.d.ts +16 -0
  32. package/dist/search-select/index.mjs +1 -0
  33. package/dist/shared/components.BdvBiegH.d.cts +291 -0
  34. package/dist/shared/components.BdvBiegH.d.mts +291 -0
  35. package/dist/shared/components.BdvBiegH.d.ts +291 -0
  36. package/dist/shared/components.CZMWR72v.d.cts +10 -0
  37. package/dist/shared/components.CZMWR72v.d.mts +10 -0
  38. package/dist/shared/components.CZMWR72v.d.ts +10 -0
  39. package/dist/stepped-auto-form/index.cjs +7 -0
  40. package/dist/stepped-auto-form/index.d.cts +37 -0
  41. package/dist/stepped-auto-form/index.d.mts +37 -0
  42. package/dist/stepped-auto-form/index.d.ts +37 -0
  43. package/dist/stepped-auto-form/index.mjs +1 -0
  44. package/dist/style.css +440 -0
  45. package/dist/ui/src/components/accordion.cjs +81 -0
  46. package/dist/ui/src/components/accordion.mjs +62 -0
  47. package/dist/ui/src/components/auto-form/common/label.cjs +18 -0
  48. package/dist/ui/src/components/auto-form/common/label.mjs +16 -0
  49. package/dist/ui/src/components/auto-form/common/tooltip.cjs +9 -0
  50. package/dist/ui/src/components/auto-form/common/tooltip.mjs +7 -0
  51. package/dist/ui/src/components/auto-form/config.cjs +40 -0
  52. package/dist/ui/src/components/auto-form/config.mjs +37 -0
  53. package/dist/ui/src/components/auto-form/dependencies.cjs +48 -0
  54. package/dist/ui/src/components/auto-form/dependencies.mjs +46 -0
  55. package/dist/ui/src/components/auto-form/fields/array.cjs +266 -0
  56. package/dist/ui/src/components/auto-form/fields/array.mjs +264 -0
  57. package/dist/ui/src/components/auto-form/fields/checkbox.cjs +38 -0
  58. package/dist/ui/src/components/auto-form/fields/checkbox.mjs +36 -0
  59. package/dist/ui/src/components/auto-form/fields/date.cjs +67 -0
  60. package/dist/ui/src/components/auto-form/fields/date.mjs +65 -0
  61. package/dist/ui/src/components/auto-form/fields/enum.cjs +73 -0
  62. package/dist/ui/src/components/auto-form/fields/enum.mjs +71 -0
  63. package/dist/ui/src/components/auto-form/fields/input.cjs +32 -0
  64. package/dist/ui/src/components/auto-form/fields/input.mjs +30 -0
  65. package/dist/ui/src/components/auto-form/fields/number.cjs +31 -0
  66. package/dist/ui/src/components/auto-form/fields/number.mjs +29 -0
  67. package/dist/ui/src/components/auto-form/fields/object.cjs +233 -0
  68. package/dist/ui/src/components/auto-form/fields/object.mjs +217 -0
  69. package/dist/ui/src/components/auto-form/fields/radio-group.cjs +67 -0
  70. package/dist/ui/src/components/auto-form/fields/radio-group.mjs +65 -0
  71. package/dist/ui/src/components/auto-form/fields/switch.cjs +38 -0
  72. package/dist/ui/src/components/auto-form/fields/switch.mjs +36 -0
  73. package/dist/ui/src/components/auto-form/fields/textarea.cjs +31 -0
  74. package/dist/ui/src/components/auto-form/fields/textarea.mjs +29 -0
  75. package/dist/ui/src/components/auto-form/helpers.cjs +270 -0
  76. package/dist/ui/src/components/auto-form/helpers.mjs +259 -0
  77. package/dist/ui/src/components/auto-form/index.cjs +102 -0
  78. package/dist/ui/src/components/auto-form/index.mjs +93 -0
  79. package/dist/ui/src/components/auto-form/stepped-auto-form.cjs +374 -0
  80. package/dist/ui/src/components/auto-form/stepped-auto-form.mjs +368 -0
  81. package/dist/ui/src/components/auto-form/types.cjs +11 -0
  82. package/dist/ui/src/components/auto-form/types.mjs +9 -0
  83. package/dist/ui/src/components/badge.cjs +42 -0
  84. package/dist/ui/src/components/badge.mjs +39 -0
  85. package/dist/ui/src/components/button.cjs +56 -0
  86. package/dist/ui/src/components/button.mjs +53 -0
  87. package/dist/ui/src/components/calendar.cjs +207 -0
  88. package/dist/ui/src/components/calendar.mjs +190 -0
  89. package/dist/ui/src/components/checkbox.cjs +48 -0
  90. package/dist/ui/src/components/checkbox.mjs +32 -0
  91. package/dist/ui/src/components/command.cjs +118 -0
  92. package/dist/ui/src/components/command.mjs +111 -0
  93. package/dist/ui/src/components/date-picker.cjs +41 -0
  94. package/dist/ui/src/components/date-picker.mjs +39 -0
  95. package/dist/ui/src/components/dialog.cjs +141 -0
  96. package/dist/ui/src/components/dialog.mjs +118 -0
  97. package/dist/ui/src/components/empty.cjs +104 -0
  98. package/dist/ui/src/components/empty.mjs +97 -0
  99. package/dist/ui/src/components/form-builder/canvas.cjs +111 -0
  100. package/dist/ui/src/components/form-builder/canvas.mjs +109 -0
  101. package/dist/ui/src/components/form-builder/components/index.cjs +571 -0
  102. package/dist/ui/src/components/form-builder/components/index.mjs +554 -0
  103. package/dist/ui/src/components/form-builder/edit-field-dialog.cjs +131 -0
  104. package/dist/ui/src/components/form-builder/edit-field-dialog.mjs +129 -0
  105. package/dist/ui/src/components/form-builder/form-preview.cjs +73 -0
  106. package/dist/ui/src/components/form-builder/form-preview.mjs +71 -0
  107. package/dist/ui/src/components/form-builder/index.cjs +350 -0
  108. package/dist/ui/src/components/form-builder/index.mjs +344 -0
  109. package/dist/ui/src/components/form-builder/nested-field-editor-dialog.cjs +263 -0
  110. package/dist/ui/src/components/form-builder/nested-field-editor-dialog.mjs +261 -0
  111. package/dist/ui/src/components/form-builder/palette.cjs +52 -0
  112. package/dist/ui/src/components/form-builder/palette.mjs +49 -0
  113. package/dist/ui/src/components/form-builder/schema-utils.cjs +128 -0
  114. package/dist/ui/src/components/form-builder/schema-utils.mjs +122 -0
  115. package/dist/ui/src/components/form-builder/sortable-field.cjs +151 -0
  116. package/dist/ui/src/components/form-builder/sortable-field.mjs +148 -0
  117. package/dist/ui/src/components/form-builder/step-tabs.cjs +180 -0
  118. package/dist/ui/src/components/form-builder/step-tabs.mjs +178 -0
  119. package/dist/ui/src/components/form-builder/types.cjs +7 -0
  120. package/dist/ui/src/components/form-builder/types.mjs +5 -0
  121. package/dist/ui/src/components/form-builder/validation-schemas.cjs +67 -0
  122. package/dist/ui/src/components/form-builder/validation-schemas.mjs +56 -0
  123. package/dist/ui/src/components/form.cjs +120 -0
  124. package/dist/ui/src/components/form.mjs +98 -0
  125. package/dist/ui/src/components/input.cjs +23 -0
  126. package/dist/ui/src/components/input.mjs +21 -0
  127. package/dist/ui/src/components/label.cjs +39 -0
  128. package/dist/ui/src/components/label.mjs +23 -0
  129. package/dist/ui/src/components/markdown-content.cjs +334 -0
  130. package/dist/ui/src/components/markdown-content.mjs +325 -0
  131. package/dist/ui/src/components/markdown-editor.cjs +180 -0
  132. package/dist/ui/src/components/markdown-editor.mjs +178 -0
  133. package/dist/ui/src/components/multi-select.cjs +555 -0
  134. package/dist/ui/src/components/multi-select.mjs +540 -0
  135. package/dist/ui/src/components/popover.cjs +60 -0
  136. package/dist/ui/src/components/popover.mjs +42 -0
  137. package/dist/ui/src/components/radio-group.cjs +62 -0
  138. package/dist/ui/src/components/radio-group.mjs +45 -0
  139. package/dist/ui/src/components/search-select.cjs +99 -0
  140. package/dist/ui/src/components/search-select.mjs +83 -0
  141. package/dist/ui/src/components/select.cjs +161 -0
  142. package/dist/ui/src/components/select.mjs +139 -0
  143. package/dist/ui/src/components/separator.cjs +43 -0
  144. package/dist/ui/src/components/separator.mjs +27 -0
  145. package/dist/ui/src/components/switch.cjs +48 -0
  146. package/dist/ui/src/components/switch.mjs +32 -0
  147. package/dist/ui/src/components/tabs.cjs +84 -0
  148. package/dist/ui/src/components/tabs.mjs +65 -0
  149. package/dist/ui/src/components/textarea.cjs +20 -0
  150. package/dist/ui/src/components/textarea.mjs +18 -0
  151. package/dist/ui/src/hooks/use-debounce.cjs +16 -0
  152. package/dist/ui/src/hooks/use-debounce.mjs +14 -0
  153. package/dist/ui/src/lib/schema-converter.cjs +94 -0
  154. package/dist/ui/src/lib/schema-converter.mjs +92 -0
  155. package/dist/ui/src/lib/throttle.cjs +56 -0
  156. package/dist/ui/src/lib/throttle.mjs +54 -0
  157. package/dist/ui/src/lib/utils.cjs +10 -0
  158. package/dist/ui/src/lib/utils.mjs +8 -0
  159. package/dist/ui.css +131 -0
  160. package/package.json +176 -3
  161. package/README.md +0 -3
@@ -0,0 +1,554 @@
1
+ import { List, FolderOpen, Mail, Lock, Globe, Phone, Calendar, AlignLeft, ToggleLeft, Circle, ChevronDown, CheckSquare, Hash, Type } from 'lucide-react';
2
+ import { z } from 'zod';
3
+ import { defineComponent } from '../types.mjs';
4
+ import { baseMetaSchemaWithPlaceholder, stringValidationSchema, DEFAULT_VALUE_SCHEMAS, numberValidationSchema, baseMetaSchema, booleanValidationSchema, enumOptionsSchema, dateValidationSchema, objectValidationSchema, arrayValidationSchema } from '../validation-schemas.mjs';
5
+ import { beautifyObjectName } from '../../auto-form/helpers.mjs';
6
+
7
+ function toNumber(value) {
8
+ if (value == null || value === "") return void 0;
9
+ const num = Number(value);
10
+ return isNaN(num) ? void 0 : num;
11
+ }
12
+ function buildInputProps(placeholder, inputType) {
13
+ const props = {};
14
+ if (placeholder) props.placeholder = placeholder;
15
+ if (inputType) props.type = inputType;
16
+ return Object.keys(props).length > 0 ? props : void 0;
17
+ }
18
+ function getPlaceholder(prop) {
19
+ return prop.inputProps?.placeholder || prop.placeholder;
20
+ }
21
+ function getLabel(prop, key) {
22
+ return prop.label || prop.title || beautifyObjectName(key);
23
+ }
24
+ const textFieldDefinition = defineComponent({
25
+ type: "text",
26
+ backingType: "string",
27
+ label: "Text Input",
28
+ icon: Type,
29
+ defaultProps: {
30
+ label: "Text Field",
31
+ placeholder: "",
32
+ required: false
33
+ },
34
+ propertiesSchema: baseMetaSchemaWithPlaceholder.merge(stringValidationSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.string })),
35
+ toJSONSchema: (props) => ({
36
+ type: "string",
37
+ label: props.label,
38
+ description: props.description,
39
+ inputProps: buildInputProps(props.placeholder),
40
+ default: props.defaultValue,
41
+ minLength: toNumber(props.minLength),
42
+ maxLength: toNumber(props.maxLength)
43
+ }),
44
+ fromJSONSchema: (prop, key, isRequired) => {
45
+ if (prop.type !== "string" || prop.enum || prop.fieldType || prop.inputType || prop.format || prop.inputProps?.type) {
46
+ return null;
47
+ }
48
+ return {
49
+ id: key,
50
+ type: "text",
51
+ props: {
52
+ label: getLabel(prop, key),
53
+ placeholder: getPlaceholder(prop),
54
+ description: prop.description,
55
+ required: isRequired,
56
+ defaultValue: prop.default,
57
+ minLength: prop.minLength,
58
+ maxLength: prop.maxLength
59
+ }
60
+ };
61
+ }
62
+ });
63
+ const emailFieldDefinition = defineComponent({
64
+ type: "email",
65
+ backingType: "string",
66
+ label: "Email",
67
+ icon: Mail,
68
+ defaultProps: {
69
+ label: "Email",
70
+ placeholder: "email@example.com",
71
+ required: false
72
+ },
73
+ propertiesSchema: baseMetaSchemaWithPlaceholder.merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.string })),
74
+ toJSONSchema: (props) => ({
75
+ type: "string",
76
+ label: props.label,
77
+ description: props.description,
78
+ inputProps: buildInputProps(props.placeholder, "email"),
79
+ default: props.defaultValue,
80
+ format: "email"
81
+ }),
82
+ fromJSONSchema: (prop, key, isRequired) => {
83
+ if (prop.type !== "string" || prop.format !== "email" && prop.inputType !== "email" && prop.inputProps?.type !== "email") {
84
+ return null;
85
+ }
86
+ return {
87
+ id: key,
88
+ type: "email",
89
+ props: {
90
+ label: getLabel(prop, key),
91
+ placeholder: getPlaceholder(prop),
92
+ description: prop.description,
93
+ required: isRequired,
94
+ defaultValue: prop.default
95
+ }
96
+ };
97
+ }
98
+ });
99
+ const numberFieldDefinition = defineComponent({
100
+ type: "number",
101
+ backingType: "number",
102
+ label: "Number",
103
+ icon: Hash,
104
+ defaultProps: {
105
+ label: "Number",
106
+ required: false
107
+ },
108
+ propertiesSchema: baseMetaSchemaWithPlaceholder.merge(numberValidationSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.number })),
109
+ toJSONSchema: (props) => ({
110
+ type: "number",
111
+ label: props.label,
112
+ description: props.description,
113
+ inputProps: buildInputProps(props.placeholder),
114
+ default: props.defaultValue,
115
+ // toNumber handles form input which may come as strings
116
+ minimum: toNumber(props.min),
117
+ maximum: toNumber(props.max)
118
+ }),
119
+ fromJSONSchema: (prop, key, isRequired) => {
120
+ if (prop.type !== "number" && prop.type !== "integer") {
121
+ return null;
122
+ }
123
+ return {
124
+ id: key,
125
+ type: "number",
126
+ props: {
127
+ label: getLabel(prop, key),
128
+ placeholder: getPlaceholder(prop),
129
+ description: prop.description,
130
+ required: isRequired,
131
+ defaultValue: prop.default,
132
+ min: prop.minimum,
133
+ max: prop.maximum
134
+ }
135
+ };
136
+ }
137
+ });
138
+ const textareaFieldDefinition = defineComponent({
139
+ type: "textarea",
140
+ backingType: "string",
141
+ label: "Text Area",
142
+ icon: AlignLeft,
143
+ defaultProps: {
144
+ label: "Text Area",
145
+ placeholder: "",
146
+ required: false
147
+ },
148
+ propertiesSchema: baseMetaSchemaWithPlaceholder.merge(stringValidationSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.string })),
149
+ toJSONSchema: (props) => ({
150
+ type: "string",
151
+ label: props.label,
152
+ description: props.description,
153
+ fieldType: "textarea",
154
+ inputProps: buildInputProps(props.placeholder),
155
+ default: props.defaultValue,
156
+ minLength: toNumber(props.minLength),
157
+ maxLength: toNumber(props.maxLength)
158
+ }),
159
+ fromJSONSchema: (prop, key, isRequired) => {
160
+ if (prop.type !== "string" || prop.fieldType !== "textarea") {
161
+ return null;
162
+ }
163
+ return {
164
+ id: key,
165
+ type: "textarea",
166
+ props: {
167
+ label: getLabel(prop, key),
168
+ placeholder: getPlaceholder(prop),
169
+ description: prop.description,
170
+ required: isRequired,
171
+ defaultValue: prop.default,
172
+ minLength: prop.minLength,
173
+ maxLength: prop.maxLength
174
+ }
175
+ };
176
+ }
177
+ });
178
+ const checkboxFieldDefinition = defineComponent({
179
+ type: "checkbox",
180
+ backingType: "boolean",
181
+ label: "Checkbox",
182
+ icon: CheckSquare,
183
+ defaultProps: {
184
+ label: "Checkbox",
185
+ required: false
186
+ },
187
+ propertiesSchema: baseMetaSchema.merge(booleanValidationSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.boolean })),
188
+ toJSONSchema: (props) => ({
189
+ type: "boolean",
190
+ label: props.label,
191
+ description: props.description,
192
+ default: props.defaultValue
193
+ }),
194
+ fromJSONSchema: (prop, key, isRequired) => {
195
+ if (prop.type !== "boolean" || prop.fieldType === "switch") {
196
+ return null;
197
+ }
198
+ return {
199
+ id: key,
200
+ type: "checkbox",
201
+ props: {
202
+ label: getLabel(prop, key),
203
+ description: prop.description,
204
+ required: isRequired,
205
+ defaultValue: prop.default
206
+ }
207
+ };
208
+ }
209
+ });
210
+ const switchFieldDefinition = defineComponent({
211
+ type: "switch",
212
+ backingType: "boolean",
213
+ label: "Switch",
214
+ icon: ToggleLeft,
215
+ defaultProps: {
216
+ label: "Switch",
217
+ required: false
218
+ },
219
+ propertiesSchema: baseMetaSchema.merge(booleanValidationSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.boolean })),
220
+ toJSONSchema: (props) => ({
221
+ type: "boolean",
222
+ label: props.label,
223
+ description: props.description,
224
+ fieldType: "switch",
225
+ default: props.defaultValue
226
+ }),
227
+ fromJSONSchema: (prop, key, isRequired) => {
228
+ if (prop.type !== "boolean" || prop.fieldType !== "switch") {
229
+ return null;
230
+ }
231
+ return {
232
+ id: key,
233
+ type: "switch",
234
+ props: {
235
+ label: getLabel(prop, key),
236
+ description: prop.description,
237
+ required: isRequired,
238
+ defaultValue: prop.default
239
+ }
240
+ };
241
+ }
242
+ });
243
+ const selectFieldDefinition = defineComponent({
244
+ type: "select",
245
+ backingType: "enum",
246
+ label: "Select",
247
+ icon: ChevronDown,
248
+ defaultProps: {
249
+ label: "Select Field",
250
+ required: false,
251
+ options: ["Option 1", "Option 2", "Option 3"]
252
+ },
253
+ propertiesSchema: baseMetaSchemaWithPlaceholder.merge(enumOptionsSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.enum })),
254
+ toJSONSchema: (props) => ({
255
+ type: "string",
256
+ label: props.label,
257
+ description: props.description,
258
+ inputProps: buildInputProps(props.placeholder),
259
+ default: props.defaultValue,
260
+ enum: props.options
261
+ }),
262
+ fromJSONSchema: (prop, key, isRequired) => {
263
+ if (prop.type !== "string" || !prop.enum || prop.fieldType === "radio") {
264
+ return null;
265
+ }
266
+ return {
267
+ id: key,
268
+ type: "select",
269
+ props: {
270
+ label: getLabel(prop, key),
271
+ placeholder: getPlaceholder(prop),
272
+ description: prop.description,
273
+ required: isRequired,
274
+ defaultValue: prop.default,
275
+ options: prop.enum
276
+ }
277
+ };
278
+ }
279
+ });
280
+ const radioFieldDefinition = defineComponent({
281
+ type: "radio",
282
+ backingType: "enum",
283
+ label: "Radio Group",
284
+ icon: Circle,
285
+ defaultProps: {
286
+ label: "Radio Group",
287
+ required: false,
288
+ options: ["Option 1", "Option 2", "Option 3"]
289
+ },
290
+ propertiesSchema: baseMetaSchema.merge(enumOptionsSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.enum })),
291
+ toJSONSchema: (props) => ({
292
+ type: "string",
293
+ label: props.label,
294
+ description: props.description,
295
+ fieldType: "radio",
296
+ default: props.defaultValue,
297
+ enum: props.options
298
+ }),
299
+ fromJSONSchema: (prop, key, isRequired) => {
300
+ if (prop.type !== "string" || !prop.enum || prop.fieldType !== "radio") {
301
+ return null;
302
+ }
303
+ return {
304
+ id: key,
305
+ type: "radio",
306
+ props: {
307
+ label: getLabel(prop, key),
308
+ description: prop.description,
309
+ required: isRequired,
310
+ defaultValue: prop.default,
311
+ options: prop.enum
312
+ }
313
+ };
314
+ }
315
+ });
316
+ const passwordFieldDefinition = defineComponent({
317
+ type: "password",
318
+ backingType: "string",
319
+ label: "Password",
320
+ icon: Lock,
321
+ defaultProps: {
322
+ label: "Password",
323
+ placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
324
+ required: false
325
+ },
326
+ propertiesSchema: baseMetaSchemaWithPlaceholder.merge(stringValidationSchema).merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.string })),
327
+ toJSONSchema: (props) => ({
328
+ type: "string",
329
+ label: props.label,
330
+ description: props.description,
331
+ inputProps: buildInputProps(props.placeholder, "password"),
332
+ default: props.defaultValue,
333
+ minLength: toNumber(props.minLength),
334
+ maxLength: toNumber(props.maxLength)
335
+ }),
336
+ fromJSONSchema: (prop, key, isRequired) => {
337
+ if (prop.type !== "string" || prop.inputType !== "password" && prop.inputProps?.type !== "password") {
338
+ return null;
339
+ }
340
+ return {
341
+ id: key,
342
+ type: "password",
343
+ props: {
344
+ label: getLabel(prop, key),
345
+ placeholder: getPlaceholder(prop),
346
+ description: prop.description,
347
+ required: isRequired,
348
+ defaultValue: prop.default,
349
+ minLength: prop.minLength,
350
+ maxLength: prop.maxLength
351
+ }
352
+ };
353
+ }
354
+ });
355
+ const urlFieldDefinition = defineComponent({
356
+ type: "url",
357
+ backingType: "string",
358
+ label: "Website URL",
359
+ icon: Globe,
360
+ defaultProps: {
361
+ label: "Website",
362
+ placeholder: "https://example.com",
363
+ required: false
364
+ },
365
+ propertiesSchema: baseMetaSchemaWithPlaceholder.merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.string })),
366
+ toJSONSchema: (props) => ({
367
+ type: "string",
368
+ label: props.label,
369
+ description: props.description,
370
+ inputProps: buildInputProps(props.placeholder),
371
+ default: props.defaultValue,
372
+ format: "uri"
373
+ }),
374
+ fromJSONSchema: (prop, key, isRequired) => {
375
+ if (prop.type !== "string" || prop.format !== "uri") {
376
+ return null;
377
+ }
378
+ return {
379
+ id: key,
380
+ type: "url",
381
+ props: {
382
+ label: getLabel(prop, key),
383
+ placeholder: getPlaceholder(prop),
384
+ description: prop.description,
385
+ required: isRequired,
386
+ defaultValue: prop.default
387
+ }
388
+ };
389
+ }
390
+ });
391
+ const phoneFieldDefinition = defineComponent({
392
+ type: "phone",
393
+ backingType: "string",
394
+ label: "Phone Number",
395
+ icon: Phone,
396
+ defaultProps: {
397
+ label: "Phone Number",
398
+ placeholder: "+1 (555) 123-4567",
399
+ required: false
400
+ },
401
+ propertiesSchema: baseMetaSchemaWithPlaceholder.merge(z.object({ defaultValue: DEFAULT_VALUE_SCHEMAS.string })),
402
+ toJSONSchema: (props) => ({
403
+ type: "string",
404
+ label: props.label,
405
+ description: props.description,
406
+ inputProps: buildInputProps(props.placeholder, "tel"),
407
+ default: props.defaultValue
408
+ }),
409
+ fromJSONSchema: (prop, key, isRequired) => {
410
+ if (prop.type !== "string" || prop.inputType !== "tel" && prop.inputProps?.type !== "tel") {
411
+ return null;
412
+ }
413
+ return {
414
+ id: key,
415
+ type: "phone",
416
+ props: {
417
+ label: getLabel(prop, key),
418
+ placeholder: getPlaceholder(prop),
419
+ description: prop.description,
420
+ required: isRequired,
421
+ defaultValue: prop.default
422
+ }
423
+ };
424
+ }
425
+ });
426
+ const dateFieldDefinition = defineComponent({
427
+ type: "date",
428
+ backingType: "date",
429
+ label: "Date Picker",
430
+ icon: Calendar,
431
+ defaultProps: {
432
+ label: "Date",
433
+ required: false
434
+ },
435
+ propertiesSchema: baseMetaSchema.merge(dateValidationSchema),
436
+ toJSONSchema: (props) => ({
437
+ type: "string",
438
+ format: "date-time",
439
+ fieldType: "date",
440
+ label: props.label,
441
+ description: props.description
442
+ }),
443
+ fromJSONSchema: (prop, key, isRequired) => {
444
+ if (prop.type !== "string" || prop.format !== "date-time" && prop.fieldType !== "date") {
445
+ return null;
446
+ }
447
+ return {
448
+ id: key,
449
+ type: "date",
450
+ props: {
451
+ label: getLabel(prop, key),
452
+ description: prop.description,
453
+ required: isRequired
454
+ }
455
+ };
456
+ }
457
+ });
458
+ const objectFieldDefinition = {
459
+ type: "object",
460
+ label: "Field Group",
461
+ icon: FolderOpen,
462
+ defaultProps: {
463
+ label: "Field Group",
464
+ required: false
465
+ },
466
+ propertiesSchema: baseMetaSchema.extend(objectValidationSchema.shape),
467
+ toJSONSchema: (props) => ({
468
+ type: "object",
469
+ label: props.label,
470
+ description: props.description,
471
+ // properties will be filled in by schema-utils from field.children
472
+ properties: {}
473
+ }),
474
+ fromJSONSchema: (prop, key, isRequired) => {
475
+ if (prop.type !== "object" || !prop.properties) {
476
+ return null;
477
+ }
478
+ return {
479
+ id: key,
480
+ type: "object",
481
+ props: {
482
+ label: getLabel(prop, key),
483
+ description: prop.description,
484
+ required: isRequired
485
+ },
486
+ // children will be filled in by schema-utils
487
+ children: []
488
+ };
489
+ }
490
+ };
491
+ const arrayFieldDefinition = {
492
+ type: "array",
493
+ label: "Repeating Group",
494
+ icon: List,
495
+ defaultProps: {
496
+ label: "Items",
497
+ required: false
498
+ },
499
+ propertiesSchema: baseMetaSchema.extend(arrayValidationSchema.shape),
500
+ toJSONSchema: (props) => ({
501
+ type: "array",
502
+ label: props.label,
503
+ description: props.description,
504
+ minItems: props.minItems,
505
+ maxItems: props.maxItems,
506
+ // items will be filled in by schema-utils from field.itemTemplate
507
+ items: {
508
+ type: "object",
509
+ properties: {}
510
+ }
511
+ }),
512
+ fromJSONSchema: (prop, key, isRequired) => {
513
+ if (prop.type !== "array" || !prop.items) {
514
+ return null;
515
+ }
516
+ return {
517
+ id: key,
518
+ type: "array",
519
+ props: {
520
+ label: getLabel(prop, key),
521
+ description: prop.description,
522
+ required: isRequired,
523
+ minItems: prop.minItems,
524
+ maxItems: prop.maxItems
525
+ },
526
+ // itemTemplate will be filled in by schema-utils
527
+ itemTemplate: []
528
+ };
529
+ }
530
+ };
531
+ const defaultComponents = [
532
+ // Container types (must be before primitives to match object/array JSON Schema)
533
+ objectFieldDefinition,
534
+ arrayFieldDefinition,
535
+ // Specific types first
536
+ emailFieldDefinition,
537
+ passwordFieldDefinition,
538
+ urlFieldDefinition,
539
+ phoneFieldDefinition,
540
+ dateFieldDefinition,
541
+ textareaFieldDefinition,
542
+ switchFieldDefinition,
543
+ radioFieldDefinition,
544
+ selectFieldDefinition,
545
+ checkboxFieldDefinition,
546
+ numberFieldDefinition,
547
+ // Generic fallback last
548
+ textFieldDefinition
549
+ ];
550
+ function getComponentByType(type, components = defaultComponents) {
551
+ return components.find((c) => c.type === type);
552
+ }
553
+
554
+ export { arrayFieldDefinition, checkboxFieldDefinition, dateFieldDefinition, defaultComponents, emailFieldDefinition, getComponentByType, numberFieldDefinition, objectFieldDefinition, passwordFieldDefinition, phoneFieldDefinition, radioFieldDefinition, selectFieldDefinition, switchFieldDefinition, textFieldDefinition, textareaFieldDefinition, urlFieldDefinition };
@@ -0,0 +1,131 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ const jsxRuntime = require('react/jsx-runtime');
5
+ const React = require('react');
6
+ const index = require('../auto-form/index.cjs');
7
+ const helpers = require('../auto-form/helpers.cjs');
8
+ const input = require('../input.cjs');
9
+ const label = require('../label.cjs');
10
+ const button = require('../button.cjs');
11
+ const dialog = require('../dialog.cjs');
12
+ const select = require('../select.cjs');
13
+
14
+ function EditFieldDialog({
15
+ open,
16
+ onOpenChange,
17
+ field,
18
+ component,
19
+ onUpdate,
20
+ steps = [],
21
+ allFieldIds = []
22
+ }) {
23
+ const initialValues = React.useMemo(() => {
24
+ if (!field) return { fieldName: "", props: {}, key: "" };
25
+ const values = { ...field.props };
26
+ if (Array.isArray(values.options)) {
27
+ values.options = values.options.join("\n");
28
+ }
29
+ return { fieldName: field.id, props: values, key: `${field.id}-${open}` };
30
+ }, [field, open]);
31
+ const [fieldNameOverride, setFieldNameOverride] = React.useState(null);
32
+ const [localPropsOverride, setLocalPropsOverride] = React.useState(null);
33
+ const [stepGroupOverride, setStepGroupOverride] = React.useState(null);
34
+ const fieldName = fieldNameOverride ?? initialValues.fieldName;
35
+ const localProps = localPropsOverride ?? initialValues.props;
36
+ const localStepGroup = stepGroupOverride ?? field?.stepGroup ?? 0;
37
+ const isDuplicateId = React.useMemo(() => {
38
+ if (!field || fieldName === field.id) return false;
39
+ return allFieldIds.some((id) => id === fieldName && id !== field.id);
40
+ }, [fieldName, field, allFieldIds]);
41
+ const [prevInitial, setPrevInitial] = React.useState(initialValues);
42
+ if (prevInitial !== initialValues) {
43
+ setPrevInitial(initialValues);
44
+ setFieldNameOverride(null);
45
+ setLocalPropsOverride(null);
46
+ setStepGroupOverride(null);
47
+ }
48
+ const formKey = initialValues.key;
49
+ const handleValuesChange = React.useCallback(
50
+ (values) => {
51
+ setLocalPropsOverride(values);
52
+ },
53
+ []
54
+ );
55
+ const handleSave = React.useCallback(() => {
56
+ if (!field) return;
57
+ const props = { ...localProps };
58
+ if (typeof props.options === "string") {
59
+ props.options = props.options.split("\n").map((s) => s.trim()).filter(Boolean);
60
+ }
61
+ const newId = fieldName !== field.id ? fieldName : void 0;
62
+ const stepGroup = stepGroupOverride !== null && stepGroupOverride !== field.stepGroup ? stepGroupOverride : void 0;
63
+ onUpdate(field.id, props, newId, stepGroup);
64
+ onOpenChange(false);
65
+ }, [field, localProps, fieldName, onUpdate, onOpenChange, stepGroupOverride]);
66
+ if (!field || !component) {
67
+ return null;
68
+ }
69
+ const Icon = component.icon;
70
+ const jsonSchema = component.propertiesSchema.toJSONSchema();
71
+ const fieldConfig = helpers.buildFieldConfigFromJsonSchema(jsonSchema);
72
+ return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { className: "max-w-md max-h-[90vh] overflow-y-auto", children: [
73
+ /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogHeader, { children: [
74
+ /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogTitle, { className: "flex items-center gap-2", children: [
75
+ Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-5 w-5 text-muted-foreground" }),
76
+ "Edit ",
77
+ component.label
78
+ ] }),
79
+ /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogDescription, { children: "Configure the properties for this field" })
80
+ ] }),
81
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 py-4", children: [
82
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
83
+ /* @__PURE__ */ jsxRuntime.jsx(label.Label, { htmlFor: "field-name", children: "Field Name" }),
84
+ /* @__PURE__ */ jsxRuntime.jsx(
85
+ input.Input,
86
+ {
87
+ id: "field-name",
88
+ value: fieldName,
89
+ onChange: (e) => setFieldNameOverride(e.target.value),
90
+ placeholder: "Enter field name",
91
+ className: isDuplicateId ? "border-destructive focus-visible:ring-destructive" : "",
92
+ "aria-invalid": isDuplicateId
93
+ }
94
+ ),
95
+ isDuplicateId ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-destructive", children: "A field with this name already exists. Please choose a different name." }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "This is the key used in the form data and JSON schema" })
96
+ ] }),
97
+ steps.length > 1 && field && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
98
+ /* @__PURE__ */ jsxRuntime.jsx(label.Label, { htmlFor: "field-step", children: "Step" }),
99
+ /* @__PURE__ */ jsxRuntime.jsxs(
100
+ select.Select,
101
+ {
102
+ value: String(localStepGroup),
103
+ onValueChange: (value) => setStepGroupOverride(parseInt(value, 10)),
104
+ children: [
105
+ /* @__PURE__ */ jsxRuntime.jsx(select.SelectTrigger, { id: "field-step", children: /* @__PURE__ */ jsxRuntime.jsx(select.SelectValue, { placeholder: "Select step" }) }),
106
+ /* @__PURE__ */ jsxRuntime.jsx(select.SelectContent, { children: steps.map((step, index) => /* @__PURE__ */ jsxRuntime.jsx(select.SelectItem, { value: String(index), children: step.title }, step.id)) })
107
+ ]
108
+ }
109
+ ),
110
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Which step this field belongs to" })
111
+ ] }),
112
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t pt-4", children: /* @__PURE__ */ jsxRuntime.jsx(
113
+ index.default,
114
+ {
115
+ formSchema: component.propertiesSchema,
116
+ values: localProps,
117
+ onValuesChange: handleValuesChange,
118
+ fieldConfig,
119
+ className: "space-y-4"
120
+ },
121
+ formKey
122
+ ) })
123
+ ] }),
124
+ /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogFooter, { children: [
125
+ /* @__PURE__ */ jsxRuntime.jsx(button.Button, { variant: "outline", onClick: () => onOpenChange(false), children: "Cancel" }),
126
+ /* @__PURE__ */ jsxRuntime.jsx(button.Button, { onClick: handleSave, disabled: isDuplicateId, children: "Save Changes" })
127
+ ] })
128
+ ] }) });
129
+ }
130
+
131
+ exports.EditFieldDialog = EditFieldDialog;