@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,129 @@
1
+ 'use client';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { useMemo, useState, useCallback } from 'react';
4
+ import AutoForm from '../auto-form/index.mjs';
5
+ import { buildFieldConfigFromJsonSchema } from '../auto-form/helpers.mjs';
6
+ import { Input } from '../input.mjs';
7
+ import { Label } from '../label.mjs';
8
+ import { Button } from '../button.mjs';
9
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '../dialog.mjs';
10
+ import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '../select.mjs';
11
+
12
+ function EditFieldDialog({
13
+ open,
14
+ onOpenChange,
15
+ field,
16
+ component,
17
+ onUpdate,
18
+ steps = [],
19
+ allFieldIds = []
20
+ }) {
21
+ const initialValues = useMemo(() => {
22
+ if (!field) return { fieldName: "", props: {}, key: "" };
23
+ const values = { ...field.props };
24
+ if (Array.isArray(values.options)) {
25
+ values.options = values.options.join("\n");
26
+ }
27
+ return { fieldName: field.id, props: values, key: `${field.id}-${open}` };
28
+ }, [field, open]);
29
+ const [fieldNameOverride, setFieldNameOverride] = useState(null);
30
+ const [localPropsOverride, setLocalPropsOverride] = useState(null);
31
+ const [stepGroupOverride, setStepGroupOverride] = useState(null);
32
+ const fieldName = fieldNameOverride ?? initialValues.fieldName;
33
+ const localProps = localPropsOverride ?? initialValues.props;
34
+ const localStepGroup = stepGroupOverride ?? field?.stepGroup ?? 0;
35
+ const isDuplicateId = useMemo(() => {
36
+ if (!field || fieldName === field.id) return false;
37
+ return allFieldIds.some((id) => id === fieldName && id !== field.id);
38
+ }, [fieldName, field, allFieldIds]);
39
+ const [prevInitial, setPrevInitial] = useState(initialValues);
40
+ if (prevInitial !== initialValues) {
41
+ setPrevInitial(initialValues);
42
+ setFieldNameOverride(null);
43
+ setLocalPropsOverride(null);
44
+ setStepGroupOverride(null);
45
+ }
46
+ const formKey = initialValues.key;
47
+ const handleValuesChange = useCallback(
48
+ (values) => {
49
+ setLocalPropsOverride(values);
50
+ },
51
+ []
52
+ );
53
+ const handleSave = useCallback(() => {
54
+ if (!field) return;
55
+ const props = { ...localProps };
56
+ if (typeof props.options === "string") {
57
+ props.options = props.options.split("\n").map((s) => s.trim()).filter(Boolean);
58
+ }
59
+ const newId = fieldName !== field.id ? fieldName : void 0;
60
+ const stepGroup = stepGroupOverride !== null && stepGroupOverride !== field.stepGroup ? stepGroupOverride : void 0;
61
+ onUpdate(field.id, props, newId, stepGroup);
62
+ onOpenChange(false);
63
+ }, [field, localProps, fieldName, onUpdate, onOpenChange, stepGroupOverride]);
64
+ if (!field || !component) {
65
+ return null;
66
+ }
67
+ const Icon = component.icon;
68
+ const jsonSchema = component.propertiesSchema.toJSONSchema();
69
+ const fieldConfig = buildFieldConfigFromJsonSchema(jsonSchema);
70
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-md max-h-[90vh] overflow-y-auto", children: [
71
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
72
+ /* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
73
+ Icon && /* @__PURE__ */ jsx(Icon, { className: "h-5 w-5 text-muted-foreground" }),
74
+ "Edit ",
75
+ component.label
76
+ ] }),
77
+ /* @__PURE__ */ jsx(DialogDescription, { children: "Configure the properties for this field" })
78
+ ] }),
79
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4 py-4", children: [
80
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
81
+ /* @__PURE__ */ jsx(Label, { htmlFor: "field-name", children: "Field Name" }),
82
+ /* @__PURE__ */ jsx(
83
+ Input,
84
+ {
85
+ id: "field-name",
86
+ value: fieldName,
87
+ onChange: (e) => setFieldNameOverride(e.target.value),
88
+ placeholder: "Enter field name",
89
+ className: isDuplicateId ? "border-destructive focus-visible:ring-destructive" : "",
90
+ "aria-invalid": isDuplicateId
91
+ }
92
+ ),
93
+ isDuplicateId ? /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: "A field with this name already exists. Please choose a different name." }) : /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "This is the key used in the form data and JSON schema" })
94
+ ] }),
95
+ steps.length > 1 && field && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
96
+ /* @__PURE__ */ jsx(Label, { htmlFor: "field-step", children: "Step" }),
97
+ /* @__PURE__ */ jsxs(
98
+ Select,
99
+ {
100
+ value: String(localStepGroup),
101
+ onValueChange: (value) => setStepGroupOverride(parseInt(value, 10)),
102
+ children: [
103
+ /* @__PURE__ */ jsx(SelectTrigger, { id: "field-step", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select step" }) }),
104
+ /* @__PURE__ */ jsx(SelectContent, { children: steps.map((step, index) => /* @__PURE__ */ jsx(SelectItem, { value: String(index), children: step.title }, step.id)) })
105
+ ]
106
+ }
107
+ ),
108
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Which step this field belongs to" })
109
+ ] }),
110
+ /* @__PURE__ */ jsx("div", { className: "border-t pt-4", children: /* @__PURE__ */ jsx(
111
+ AutoForm,
112
+ {
113
+ formSchema: component.propertiesSchema,
114
+ values: localProps,
115
+ onValuesChange: handleValuesChange,
116
+ fieldConfig,
117
+ className: "space-y-4"
118
+ },
119
+ formKey
120
+ ) })
121
+ ] }),
122
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
123
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), children: "Cancel" }),
124
+ /* @__PURE__ */ jsx(Button, { onClick: handleSave, disabled: isDuplicateId, children: "Save Changes" })
125
+ ] })
126
+ ] }) });
127
+ }
128
+
129
+ export { EditFieldDialog };
@@ -0,0 +1,73 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ const jsxRuntime = require('react/jsx-runtime');
5
+ const React = require('react');
6
+ const steppedAutoForm = require('../auto-form/stepped-auto-form.cjs');
7
+ const helpers = require('../auto-form/helpers.cjs');
8
+ const button = require('../button.cjs');
9
+ const utils = require('../../lib/utils.cjs');
10
+ const schemaConverter = require('../../lib/schema-converter.cjs');
11
+
12
+ function FormPreview({ schema, className, fieldComponents, defaultValues }) {
13
+ const [submittedValues, setSubmittedValues] = React.useState(null);
14
+ const zodSchema = React.useMemo(() => {
15
+ try {
16
+ if (!schema.properties || Object.keys(schema.properties).length === 0) {
17
+ return null;
18
+ }
19
+ return schemaConverter.formSchemaToZod(schema);
20
+ } catch (error) {
21
+ console.error("Failed to parse JSON Schema:", error);
22
+ return null;
23
+ }
24
+ }, [schema]);
25
+ const mergedFieldComponents = React.useMemo(() => fieldComponents ?? {}, [fieldComponents]);
26
+ const fieldConfig = React.useMemo(() => {
27
+ try {
28
+ return helpers.buildFieldConfigFromJsonSchema(
29
+ schema,
30
+ mergedFieldComponents
31
+ );
32
+ } catch (error) {
33
+ console.error("Failed to build field config:", error);
34
+ return {};
35
+ }
36
+ }, [schema, mergedFieldComponents]);
37
+ const handleSubmit = (values) => {
38
+ setSubmittedValues(values);
39
+ };
40
+ const handleReset = () => {
41
+ setSubmittedValues(null);
42
+ };
43
+ if (!zodSchema) {
44
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("p-8 text-center text-muted-foreground", className), children: [
45
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg font-medium mb-2", children: "No fields to preview" }),
46
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "Add some fields to your form to see a preview" })
47
+ ] });
48
+ }
49
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: utils.cn("p-4 md:p-6", className), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-2xl mx-auto", children: submittedValues ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
50
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
51
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold", children: "Submitted Values" }),
52
+ /* @__PURE__ */ jsxRuntime.jsx(button.Button, { variant: "outline", onClick: handleReset, children: "Try Again" })
53
+ ] }),
54
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border bg-muted/50 p-4", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-sm overflow-auto whitespace-pre-wrap", children: JSON.stringify(submittedValues, null, 2) }) })
55
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
56
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center mb-6", children: [
57
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold", children: "Form Preview" }),
58
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Test your form and see the submitted values" })
59
+ ] }),
60
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border bg-card p-6", children: /* @__PURE__ */ jsxRuntime.jsx(
61
+ steppedAutoForm.SteppedAutoForm,
62
+ {
63
+ formSchema: zodSchema,
64
+ onSubmit: handleSubmit,
65
+ fieldConfig,
66
+ values: defaultValues,
67
+ submitButtonText: "Submit"
68
+ }
69
+ ) })
70
+ ] }) }) });
71
+ }
72
+
73
+ exports.FormPreview = FormPreview;
@@ -0,0 +1,71 @@
1
+ 'use client';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { useState, useMemo } from 'react';
4
+ import { SteppedAutoForm } from '../auto-form/stepped-auto-form.mjs';
5
+ import { buildFieldConfigFromJsonSchema } from '../auto-form/helpers.mjs';
6
+ import { Button } from '../button.mjs';
7
+ import { cn } from '../../lib/utils.mjs';
8
+ import { formSchemaToZod } from '../../lib/schema-converter.mjs';
9
+
10
+ function FormPreview({ schema, className, fieldComponents, defaultValues }) {
11
+ const [submittedValues, setSubmittedValues] = useState(null);
12
+ const zodSchema = useMemo(() => {
13
+ try {
14
+ if (!schema.properties || Object.keys(schema.properties).length === 0) {
15
+ return null;
16
+ }
17
+ return formSchemaToZod(schema);
18
+ } catch (error) {
19
+ console.error("Failed to parse JSON Schema:", error);
20
+ return null;
21
+ }
22
+ }, [schema]);
23
+ const mergedFieldComponents = useMemo(() => fieldComponents ?? {}, [fieldComponents]);
24
+ const fieldConfig = useMemo(() => {
25
+ try {
26
+ return buildFieldConfigFromJsonSchema(
27
+ schema,
28
+ mergedFieldComponents
29
+ );
30
+ } catch (error) {
31
+ console.error("Failed to build field config:", error);
32
+ return {};
33
+ }
34
+ }, [schema, mergedFieldComponents]);
35
+ const handleSubmit = (values) => {
36
+ setSubmittedValues(values);
37
+ };
38
+ const handleReset = () => {
39
+ setSubmittedValues(null);
40
+ };
41
+ if (!zodSchema) {
42
+ return /* @__PURE__ */ jsxs("div", { className: cn("p-8 text-center text-muted-foreground", className), children: [
43
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-medium mb-2", children: "No fields to preview" }),
44
+ /* @__PURE__ */ jsx("p", { className: "text-sm", children: "Add some fields to your form to see a preview" })
45
+ ] });
46
+ }
47
+ return /* @__PURE__ */ jsx("div", { className: cn("p-4 md:p-6", className), children: /* @__PURE__ */ jsx("div", { className: "max-w-2xl mx-auto", children: submittedValues ? /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
48
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
49
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: "Submitted Values" }),
50
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleReset, children: "Try Again" })
51
+ ] }),
52
+ /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-muted/50 p-4", children: /* @__PURE__ */ jsx("pre", { className: "text-sm overflow-auto whitespace-pre-wrap", children: JSON.stringify(submittedValues, null, 2) }) })
53
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
54
+ /* @__PURE__ */ jsxs("div", { className: "text-center mb-6", children: [
55
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: "Form Preview" }),
56
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Test your form and see the submitted values" })
57
+ ] }),
58
+ /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card p-6", children: /* @__PURE__ */ jsx(
59
+ SteppedAutoForm,
60
+ {
61
+ formSchema: zodSchema,
62
+ onSubmit: handleSubmit,
63
+ fieldConfig,
64
+ values: defaultValues,
65
+ submitButtonText: "Submit"
66
+ }
67
+ ) })
68
+ ] }) }) });
69
+ }
70
+
71
+ export { FormPreview };
@@ -0,0 +1,350 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ const jsxRuntime = require('react/jsx-runtime');
5
+ const React = require('react');
6
+ const core = require('@dnd-kit/core');
7
+ const sortable = require('@dnd-kit/sortable');
8
+ const utils = require('../../lib/utils.cjs');
9
+ const tabs = require('../tabs.cjs');
10
+ const palette = require('./palette.cjs');
11
+ const canvas = require('./canvas.cjs');
12
+ const editFieldDialog = require('./edit-field-dialog.cjs');
13
+ const nestedFieldEditorDialog = require('./nested-field-editor-dialog.cjs');
14
+ const formPreview = require('./form-preview.cjs');
15
+ const sortableField = require('./sortable-field.cjs');
16
+ const index = require('./components/index.cjs');
17
+ const schemaUtils = require('./schema-utils.cjs');
18
+ const validationSchemas = require('./validation-schemas.cjs');
19
+
20
+ function FormBuilder({
21
+ components = index.defaultComponents,
22
+ value,
23
+ onChange,
24
+ className,
25
+ fieldComponents,
26
+ defaultValues
27
+ }) {
28
+ const dndContextId = React.useId();
29
+ const [fields, setFields] = React.useState(() => {
30
+ if (!value) return [];
31
+ const { fields: parsedFields } = schemaUtils.jsonSchemaToFieldsAndSteps(value, components);
32
+ return parsedFields;
33
+ });
34
+ const [steps, setSteps] = React.useState(() => {
35
+ if (!value) return [];
36
+ const { steps: parsedSteps } = schemaUtils.jsonSchemaToFieldsAndSteps(value, components);
37
+ return parsedSteps;
38
+ });
39
+ const [activeStepIndex, setActiveStepIndex] = React.useState(0);
40
+ const [editDialogFieldId, setEditDialogFieldId] = React.useState(null);
41
+ const [nestedEditorFieldId, setNestedEditorFieldId] = React.useState(null);
42
+ const [activeId, setActiveId] = React.useState(null);
43
+ const notifyChange = React.useCallback(
44
+ (newFields, newSteps) => {
45
+ if (onChange) {
46
+ const schema = schemaUtils.fieldsToJSONSchema(newFields, components, newSteps ?? steps);
47
+ onChange(schema);
48
+ }
49
+ },
50
+ [onChange, components, steps]
51
+ );
52
+ const currentSchema = React.useMemo(
53
+ () => schemaUtils.fieldsToJSONSchema(fields, components, steps),
54
+ [fields, components, steps]
55
+ );
56
+ const sensors = core.useSensors(
57
+ core.useSensor(core.PointerSensor, {
58
+ activationConstraint: {
59
+ distance: 8
60
+ }
61
+ }),
62
+ core.useSensor(core.TouchSensor, {
63
+ activationConstraint: {
64
+ // Use distance instead of delay for better compatibility with
65
+ // automated testing tools and faster touch interactions
66
+ distance: 8
67
+ }
68
+ }),
69
+ core.useSensor(core.KeyboardSensor, {
70
+ coordinateGetter: sortable.sortableKeyboardCoordinates
71
+ })
72
+ );
73
+ const activeDragData = React.useMemo(() => {
74
+ if (!activeId) return null;
75
+ const idStr = String(activeId);
76
+ if (idStr.startsWith("palette-")) {
77
+ const componentType = idStr.replace("palette-", "");
78
+ return {
79
+ type: "palette",
80
+ componentType,
81
+ component: index.getComponentByType(componentType, components)
82
+ };
83
+ }
84
+ const field = fields.find((f) => f.id === idStr);
85
+ if (field) {
86
+ return {
87
+ type: "field",
88
+ field,
89
+ component: index.getComponentByType(field.type, components)
90
+ };
91
+ }
92
+ return null;
93
+ }, [activeId, fields, components]);
94
+ const handleDragStart = (event) => {
95
+ setActiveId(event.active.id);
96
+ };
97
+ const handleDragEnd = (event) => {
98
+ const { active, over } = event;
99
+ setActiveId(null);
100
+ if (!over) return;
101
+ const activeData = active.data.current;
102
+ if (activeData?.type === "palette") {
103
+ const { componentType } = activeData;
104
+ const component = index.getComponentByType(componentType, components);
105
+ if (component) {
106
+ const newField = {
107
+ id: schemaUtils.generateFieldId(componentType),
108
+ type: componentType,
109
+ props: {
110
+ label: component.defaultProps.label || component.label,
111
+ ...component.defaultProps
112
+ },
113
+ // Assign to active step when in multi-step mode
114
+ ...steps.length > 1 ? { stepGroup: activeStepIndex } : {}
115
+ };
116
+ let insertIndex = fields.length;
117
+ const overId = String(over.id);
118
+ if (overId === "drop-zone-start") {
119
+ insertIndex = 0;
120
+ } else if (overId.startsWith("drop-zone-")) {
121
+ const fieldId = overId.replace("drop-zone-", "");
122
+ const overIndex = fields.findIndex((f) => f.id === fieldId);
123
+ if (overIndex !== -1) {
124
+ insertIndex = overIndex + 1;
125
+ }
126
+ } else if (overId !== "canvas") {
127
+ const overIndex = fields.findIndex((f) => f.id === overId);
128
+ if (overIndex !== -1) {
129
+ insertIndex = overIndex + 1;
130
+ }
131
+ }
132
+ const newFields = [...fields];
133
+ newFields.splice(insertIndex, 0, newField);
134
+ setFields(newFields);
135
+ notifyChange(newFields);
136
+ }
137
+ return;
138
+ }
139
+ if (activeData?.type === "field" && active.id !== over.id) {
140
+ const oldIndex = fields.findIndex((f) => f.id === active.id);
141
+ const newIndex = fields.findIndex((f) => f.id === over.id);
142
+ if (oldIndex !== -1 && newIndex !== -1) {
143
+ const newFields = sortable.arrayMove(fields, oldIndex, newIndex);
144
+ setFields(newFields);
145
+ notifyChange(newFields);
146
+ }
147
+ }
148
+ };
149
+ const handleUpdateField = React.useCallback(
150
+ (id, props, newId, stepGroup) => {
151
+ if (newId && newId !== id) {
152
+ const idExists = fields.some((f) => f.id === newId && f.id !== id);
153
+ if (idExists) {
154
+ console.warn(`Cannot rename field "${id}" to "${newId}": a field with that ID already exists`);
155
+ return;
156
+ }
157
+ }
158
+ const newFields = fields.map((f) => {
159
+ if (f.id !== id) return f;
160
+ const updated = {
161
+ ...f,
162
+ id: newId || f.id,
163
+ props: { ...f.props, ...props }
164
+ };
165
+ if (stepGroup !== void 0) {
166
+ updated.stepGroup = stepGroup;
167
+ }
168
+ return updated;
169
+ });
170
+ setFields(newFields);
171
+ notifyChange(newFields);
172
+ },
173
+ [fields, notifyChange]
174
+ );
175
+ const handleEditField = React.useCallback((id) => {
176
+ setEditDialogFieldId(id);
177
+ }, []);
178
+ const handleDeleteField = React.useCallback(
179
+ (id) => {
180
+ const newFields = fields.filter((f) => f.id !== id);
181
+ setFields(newFields);
182
+ notifyChange(newFields);
183
+ },
184
+ [fields, notifyChange]
185
+ );
186
+ const handleConfigureNested = React.useCallback((id) => {
187
+ setNestedEditorFieldId(id);
188
+ }, []);
189
+ const handleSaveNestedFields = React.useCallback(
190
+ (fieldId, nestedFields) => {
191
+ const newFields = fields.map((f) => {
192
+ if (f.id !== fieldId) return f;
193
+ if (f.type === "object") {
194
+ return { ...f, children: nestedFields };
195
+ } else if (f.type === "array") {
196
+ return { ...f, itemTemplate: nestedFields };
197
+ }
198
+ return f;
199
+ });
200
+ setFields(newFields);
201
+ notifyChange(newFields);
202
+ },
203
+ [fields, notifyChange]
204
+ );
205
+ const handleAddStep = React.useCallback(() => {
206
+ const newStep = schemaUtils.createStep(steps.length);
207
+ const newSteps = [...steps, newStep];
208
+ if (steps.length === 1) {
209
+ const updatedFields = fields.map((f) => ({ ...f, stepGroup: 0 }));
210
+ setFields(updatedFields);
211
+ setSteps(newSteps);
212
+ notifyChange(updatedFields, newSteps);
213
+ } else if (steps.length === 0) {
214
+ const firstStep = schemaUtils.createStep(0);
215
+ const secondStep = schemaUtils.createStep(1);
216
+ const bothSteps = [firstStep, secondStep];
217
+ const updatedFields = fields.map((f) => ({ ...f, stepGroup: 0 }));
218
+ setFields(updatedFields);
219
+ setSteps(bothSteps);
220
+ notifyChange(updatedFields, bothSteps);
221
+ } else {
222
+ setSteps(newSteps);
223
+ notifyChange(fields, newSteps);
224
+ }
225
+ }, [steps, fields, notifyChange]);
226
+ const handleDeleteStep = React.useCallback(
227
+ (index) => {
228
+ const fieldsWithoutDeleted = fields.filter((f) => f.stepGroup !== index);
229
+ if (steps.length <= 2) {
230
+ const updatedFields = fieldsWithoutDeleted.map((f) => {
231
+ const { stepGroup: _, ...rest } = f;
232
+ return rest;
233
+ });
234
+ setFields(updatedFields);
235
+ setSteps([]);
236
+ setActiveStepIndex(0);
237
+ notifyChange(updatedFields, []);
238
+ } else {
239
+ const newSteps = steps.filter((_, i) => i !== index);
240
+ const updatedFields = fieldsWithoutDeleted.map((f) => {
241
+ if (f.stepGroup !== void 0 && f.stepGroup > index) {
242
+ return { ...f, stepGroup: f.stepGroup - 1 };
243
+ }
244
+ return f;
245
+ });
246
+ setFields(updatedFields);
247
+ setSteps(newSteps);
248
+ if (activeStepIndex >= newSteps.length) {
249
+ setActiveStepIndex(newSteps.length - 1);
250
+ }
251
+ notifyChange(updatedFields, newSteps);
252
+ }
253
+ },
254
+ [steps, fields, activeStepIndex, notifyChange]
255
+ );
256
+ const handleRenameStep = React.useCallback(
257
+ (index, newTitle) => {
258
+ const newSteps = steps.map(
259
+ (step, i) => i === index ? { ...step, title: newTitle } : step
260
+ );
261
+ setSteps(newSteps);
262
+ notifyChange(fields, newSteps);
263
+ },
264
+ [steps, fields, notifyChange]
265
+ );
266
+ const editDialogField = fields.find((f) => f.id === editDialogFieldId) || null;
267
+ const editDialogComponent = editDialogField ? index.getComponentByType(editDialogField.type, components) || null : null;
268
+ const nestedEditorField = fields.find((f) => f.id === nestedEditorFieldId) || null;
269
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("flex flex-col lg:h-full", className), children: [
270
+ /* @__PURE__ */ jsxRuntime.jsxs(
271
+ core.DndContext,
272
+ {
273
+ id: dndContextId,
274
+ sensors,
275
+ collisionDetection: core.closestCenter,
276
+ onDragStart: handleDragStart,
277
+ onDragEnd: handleDragEnd,
278
+ children: [
279
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col lg:flex-row lg:overflow-hidden", children: [
280
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full lg:w-64 p-4 border-b lg:border-b-0 lg:border-r lg:overflow-auto shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(palette.Palette, { components }) }),
281
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 p-4 lg:overflow-auto min-h-[300px]", children: /* @__PURE__ */ jsxRuntime.jsx(
282
+ canvas.Canvas,
283
+ {
284
+ fields,
285
+ components,
286
+ onEditField: handleEditField,
287
+ onDeleteField: handleDeleteField,
288
+ onConfigureNested: handleConfigureNested,
289
+ isDraggingFromPalette: activeDragData?.type === "palette",
290
+ steps,
291
+ activeStepIndex,
292
+ onActiveStepChange: setActiveStepIndex,
293
+ onAddStep: handleAddStep,
294
+ onDeleteStep: handleDeleteStep,
295
+ onRenameStep: handleRenameStep
296
+ }
297
+ ) }),
298
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full flex-1 lg:w-96 border-t lg:border-t-0 lg:border-l lg:overflow-auto min-h-[300px]", children: /* @__PURE__ */ jsxRuntime.jsxs(tabs.Tabs, { defaultValue: "preview", className: "h-full flex flex-col", children: [
299
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 border-b", children: /* @__PURE__ */ jsxRuntime.jsxs(tabs.TabsList, { className: "w-full", children: [
300
+ /* @__PURE__ */ jsxRuntime.jsx(tabs.TabsTrigger, { value: "preview", className: "flex-1", children: "Preview" }),
301
+ /* @__PURE__ */ jsxRuntime.jsx(tabs.TabsTrigger, { value: "schema", className: "flex-1", children: "JSON Schema" })
302
+ ] }) }),
303
+ /* @__PURE__ */ jsxRuntime.jsx(tabs.TabsContent, { value: "preview", className: "flex-1 m-0 lg:overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx(formPreview.FormPreview, { schema: currentSchema, fieldComponents, defaultValues }) }),
304
+ /* @__PURE__ */ jsxRuntime.jsx(tabs.TabsContent, { value: "schema", className: "flex-1 m-0 p-4 lg:overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border bg-muted/50 p-4", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-sm overflow-auto whitespace-pre-wrap", children: JSON.stringify(currentSchema, null, 2) }) }) })
305
+ ] }) })
306
+ ] }),
307
+ /* @__PURE__ */ jsxRuntime.jsxs(core.DragOverlay, { dropAnimation: null, children: [
308
+ activeDragData?.type === "palette" && activeDragData.component && /* @__PURE__ */ jsxRuntime.jsx(palette.PaletteDragOverlay, { component: activeDragData.component }),
309
+ activeDragData?.type === "field" && activeDragData.field && /* @__PURE__ */ jsxRuntime.jsx(
310
+ sortableField.FieldDragOverlay,
311
+ {
312
+ field: activeDragData.field,
313
+ component: activeDragData.component
314
+ }
315
+ )
316
+ ] })
317
+ ]
318
+ }
319
+ ),
320
+ /* @__PURE__ */ jsxRuntime.jsx(
321
+ editFieldDialog.EditFieldDialog,
322
+ {
323
+ open: editDialogFieldId !== null,
324
+ onOpenChange: (open) => !open && setEditDialogFieldId(null),
325
+ field: editDialogField,
326
+ component: editDialogComponent,
327
+ onUpdate: handleUpdateField,
328
+ steps,
329
+ allFieldIds: fields.map((f) => f.id)
330
+ }
331
+ ),
332
+ /* @__PURE__ */ jsxRuntime.jsx(
333
+ nestedFieldEditorDialog.NestedFieldEditorDialog,
334
+ {
335
+ open: nestedEditorFieldId !== null,
336
+ onOpenChange: (open) => !open && setNestedEditorFieldId(null),
337
+ field: nestedEditorField,
338
+ components,
339
+ onSave: handleSaveNestedFields
340
+ }
341
+ )
342
+ ] });
343
+ }
344
+
345
+ exports.arrayFieldDefinition = index.arrayFieldDefinition;
346
+ exports.defaultComponents = index.defaultComponents;
347
+ exports.objectFieldDefinition = index.objectFieldDefinition;
348
+ exports.baseMetaSchema = validationSchemas.baseMetaSchema;
349
+ exports.baseMetaSchemaWithPlaceholder = validationSchemas.baseMetaSchemaWithPlaceholder;
350
+ exports.FormBuilder = FormBuilder;