config-driven-form 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7,6 +7,10 @@ var jsxRuntime = require('react/jsx-runtime');
7
7
  var lucideReact = require('lucide-react');
8
8
  var react$1 = require('@tiptap/react');
9
9
  var StarterKit = require('@tiptap/starter-kit');
10
+ var core = require('@dnd-kit/core');
11
+ var sortable = require('@dnd-kit/sortable');
12
+ var uuid = require('uuid');
13
+ var utilities = require('@dnd-kit/utilities');
10
14
 
11
15
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
16
 
@@ -34,6 +38,14 @@ var TextField = ({ name, schema, uiSchema, isRequired }) => {
34
38
  schema.title || name,
35
39
  isRequired && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cdf-required-mark", children: "*" })
36
40
  ] }),
41
+ schema.description && /* @__PURE__ */ jsxRuntime.jsx(
42
+ "p",
43
+ {
44
+ className: cx("cdf-description", globalClasses.description, localClasses.description),
45
+ style: { fontSize: "0.875rem", color: "#6b7280", margin: "-0.25rem 0 0.5rem 0" },
46
+ children: schema.description
47
+ }
48
+ ),
37
49
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cdf-input-wrapper", children: /* @__PURE__ */ jsxRuntime.jsx(
38
50
  "input",
39
51
  {
@@ -76,6 +88,14 @@ var PasswordField = ({
76
88
  schema.title || name,
77
89
  isRequired && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cdf-required-mark", children: "*" })
78
90
  ] }),
91
+ schema.description && /* @__PURE__ */ jsxRuntime.jsx(
92
+ "p",
93
+ {
94
+ className: cx("cdf-description", globalClasses.description, localClasses.description),
95
+ style: { fontSize: "0.875rem", color: "#6b7280", margin: "-0.25rem 0 0.5rem 0" },
96
+ children: schema.description
97
+ }
98
+ ),
79
99
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cdf-input-wrapper", children: [
80
100
  /* @__PURE__ */ jsxRuntime.jsx(
81
101
  "input",
@@ -125,6 +145,14 @@ var NumberField = ({ name, schema, uiSchema, isRequired }) => {
125
145
  schema.title || name,
126
146
  isRequired && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cdf-required-mark", children: "*" })
127
147
  ] }),
148
+ schema.description && /* @__PURE__ */ jsxRuntime.jsx(
149
+ "p",
150
+ {
151
+ className: cx("cdf-description", globalClasses.description, localClasses.description),
152
+ style: { fontSize: "0.875rem", color: "#6b7280", margin: "-0.25rem 0 0.5rem 0" },
153
+ children: schema.description
154
+ }
155
+ ),
128
156
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cdf-input-wrapper", children: /* @__PURE__ */ jsxRuntime.jsx(
129
157
  "input",
130
158
  {
@@ -182,6 +210,14 @@ var RichTextField = ({
182
210
  schema.title || name,
183
211
  isRequired && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cdf-required-mark", children: "*" })
184
212
  ] }),
213
+ schema.description && /* @__PURE__ */ jsxRuntime.jsx(
214
+ "p",
215
+ {
216
+ className: cx("cdf-description", globalClasses.description, localClasses.description),
217
+ style: { fontSize: "0.875rem", color: "#6b7280", margin: "-0.25rem 0 0.5rem 0" },
218
+ children: schema.description
219
+ }
220
+ ),
185
221
  /* @__PURE__ */ jsxRuntime.jsxs(
186
222
  "div",
187
223
  {
@@ -263,6 +299,14 @@ var SelectField = ({ name, schema, uiSchema, isRequired }) => {
263
299
  schema.title || name,
264
300
  isRequired && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cdf-required-mark", children: "*" })
265
301
  ] }),
302
+ schema.description && /* @__PURE__ */ jsxRuntime.jsx(
303
+ "p",
304
+ {
305
+ className: cx("cdf-description", globalClasses.description, localClasses.description),
306
+ style: { fontSize: "0.875rem", color: "#6b7280", margin: "-0.25rem 0 0.5rem 0" },
307
+ children: schema.description
308
+ }
309
+ ),
266
310
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cdf-input-wrapper", children: /* @__PURE__ */ jsxRuntime.jsxs(
267
311
  "select",
268
312
  {
@@ -318,6 +362,14 @@ var RadioField = ({ name, schema, uiSchema, isRequired }) => {
318
362
  schema.title || name,
319
363
  isRequired && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cdf-required-mark", children: "*" })
320
364
  ] }),
365
+ schema.description && /* @__PURE__ */ jsxRuntime.jsx(
366
+ "p",
367
+ {
368
+ className: cx("cdf-description", globalClasses.description, localClasses.description),
369
+ style: { fontSize: "0.875rem", color: "#6b7280", margin: "-0.25rem 0 0.5rem 0" },
370
+ children: schema.description
371
+ }
372
+ ),
321
373
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: cx("cdf-radio-group", globalClasses.radioGroup, localClasses.radioGroup), children: (_a = schema.enum) == null ? void 0 : _a.map((option) => /* @__PURE__ */ jsxRuntime.jsxs(
322
374
  "label",
323
375
  {
@@ -452,6 +504,14 @@ var CheckboxGroupField = ({
452
504
  schema.title || name,
453
505
  isRequired && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cdf-required-mark", children: "*" })
454
506
  ] }),
507
+ schema.description && /* @__PURE__ */ jsxRuntime.jsx(
508
+ "p",
509
+ {
510
+ className: cx("cdf-description", globalClasses.description, localClasses.description),
511
+ style: { fontSize: "0.875rem", color: "#6b7280", margin: "-0.25rem 0 0.5rem 0" },
512
+ children: schema.description
513
+ }
514
+ ),
455
515
  /* @__PURE__ */ jsxRuntime.jsx(
456
516
  "div",
457
517
  {
@@ -540,6 +600,14 @@ var FileField = ({ name, schema, uiSchema, isRequired }) => {
540
600
  schema.title || name,
541
601
  isRequired && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cdf-required-mark", children: "*" })
542
602
  ] }),
603
+ schema.description && /* @__PURE__ */ jsxRuntime.jsx(
604
+ "p",
605
+ {
606
+ className: cx("cdf-description", globalClasses.description, localClasses.description),
607
+ style: { fontSize: "0.875rem", color: "#6b7280", margin: "-0.25rem 0 0.5rem 0" },
608
+ children: schema.description
609
+ }
610
+ ),
543
611
  /* @__PURE__ */ jsxRuntime.jsxs(
544
612
  "div",
545
613
  {
@@ -696,7 +764,1435 @@ var SchemaForm = ({
696
764
  ] }) });
697
765
  };
698
766
 
767
+ // src/builder/types.ts
768
+ var FIELD_TEMPLATES = {
769
+ text: {
770
+ type: "text",
771
+ schema: { type: "string", title: "New Text Field" }
772
+ },
773
+ number: {
774
+ type: "number",
775
+ schema: { type: "number", title: "New Number Field" }
776
+ },
777
+ email: {
778
+ type: "email",
779
+ schema: { type: "string", format: "email", title: "Email Address" }
780
+ },
781
+ password: {
782
+ type: "password",
783
+ schema: { type: "string", format: "password", title: "Password" }
784
+ },
785
+ "rich-text": {
786
+ type: "rich-text",
787
+ schema: { type: "string", format: "rich-text", title: "Rich Text" }
788
+ },
789
+ file: {
790
+ type: "file",
791
+ schema: { type: "string", format: "data-url", title: "File Upload" }
792
+ },
793
+ checkbox: {
794
+ type: "checkbox",
795
+ schema: { type: "boolean", title: "Checkbox" }
796
+ },
797
+ checkboxes: {
798
+ type: "checkboxes",
799
+ schema: {
800
+ type: "array",
801
+ title: "Multiple Checkboxes",
802
+ items: { type: "string", enum: ["Option 1", "Option 2"] }
803
+ }
804
+ },
805
+ select: {
806
+ type: "select",
807
+ schema: { type: "string", title: "Dropdown", enum: ["Option 1", "Option 2"] }
808
+ },
809
+ radio: {
810
+ type: "radio",
811
+ schema: { type: "string", title: "Radio Buttons", enum: ["Option 1", "Option 2"] },
812
+ uiSchema: { "ui:widget": "radio" }
813
+ }
814
+ };
815
+
816
+ // src/builder/useFormBuilder.ts
817
+ var useFormBuilder = (initialSchema, initialUiSchema, initialColumns, initialTheme) => {
818
+ const [fields, setFields] = react.useState(() => {
819
+ if (!initialSchema || !initialSchema.properties) return [];
820
+ return Object.entries(initialSchema.properties).map(([key, propSchema]) => {
821
+ var _a;
822
+ let type = "text";
823
+ if (propSchema.type === "string") {
824
+ if (propSchema.format === "email") type = "email";
825
+ else if (propSchema.format === "password") type = "password";
826
+ else if (propSchema.format === "data-url") type = "file";
827
+ else if (propSchema.format === "rich-text") type = "rich-text";
828
+ else if (propSchema.enum) type = "select";
829
+ } else if (propSchema.type === "number" || propSchema.type === "integer") {
830
+ type = "number";
831
+ } else if (propSchema.type === "boolean") {
832
+ type = "checkbox";
833
+ } else if (propSchema.type === "array") {
834
+ type = "checkboxes";
835
+ }
836
+ const uiSchema = initialUiSchema == null ? void 0 : initialUiSchema[key];
837
+ if (propSchema.enum && (uiSchema == null ? void 0 : uiSchema["ui:widget"]) === "radio") {
838
+ type = "radio";
839
+ }
840
+ return {
841
+ id: uuid.v4(),
842
+ key,
843
+ type,
844
+ schema: propSchema,
845
+ uiSchema,
846
+ isRequired: (_a = initialSchema.required) == null ? void 0 : _a.includes(key)
847
+ };
848
+ });
849
+ });
850
+ const [selectedFieldId, setSelectedFieldId] = react.useState(null);
851
+ const addField = react.useCallback((type, index) => {
852
+ const template = FIELD_TEMPLATES[type];
853
+ const newField = {
854
+ id: uuid.v4(),
855
+ key: `field_${Date.now()}`,
856
+ type,
857
+ // Deep clone template schemas
858
+ schema: JSON.parse(JSON.stringify(template.schema)),
859
+ uiSchema: template.uiSchema ? JSON.parse(JSON.stringify(template.uiSchema)) : void 0
860
+ };
861
+ setFields((prev) => {
862
+ if (typeof index === "number") {
863
+ const newFields = [...prev];
864
+ newFields.splice(index, 0, newField);
865
+ return newFields;
866
+ }
867
+ return [...prev, newField];
868
+ });
869
+ setSelectedFieldId(newField.id);
870
+ }, []);
871
+ const removeField = react.useCallback(
872
+ (id) => {
873
+ setFields((prev) => prev.filter((f) => f.id !== id));
874
+ if (selectedFieldId === id) setSelectedFieldId(null);
875
+ },
876
+ [selectedFieldId]
877
+ );
878
+ const updateField = react.useCallback((id, updates) => {
879
+ setFields((prev) => prev.map((f) => f.id === id ? { ...f, ...updates } : f));
880
+ }, []);
881
+ const reorderFields = react.useCallback((activeId, overId) => {
882
+ setFields((prev) => {
883
+ const oldIndex = prev.findIndex((f) => f.id === activeId);
884
+ const newIndex = prev.findIndex((f) => f.id === overId);
885
+ return sortable.arrayMove(prev, oldIndex, newIndex);
886
+ });
887
+ }, []);
888
+ const selectedField = react.useMemo(
889
+ () => fields.find((f) => f.id === selectedFieldId),
890
+ [fields, selectedFieldId]
891
+ );
892
+ const compileSchemas = react.useCallback(() => {
893
+ var _a;
894
+ const finalSchema = {
895
+ type: "object",
896
+ title: (initialSchema == null ? void 0 : initialSchema.title) || "Generated Form",
897
+ description: (initialSchema == null ? void 0 : initialSchema.description) || "",
898
+ properties: {},
899
+ required: []
900
+ };
901
+ const finalUiSchema = {};
902
+ fields.forEach((field) => {
903
+ if (finalSchema.properties) {
904
+ finalSchema.properties[field.key] = field.schema;
905
+ }
906
+ if (field.isRequired && finalSchema.required) {
907
+ finalSchema.required.push(field.key);
908
+ }
909
+ if (field.uiSchema) {
910
+ finalUiSchema[field.key] = field.uiSchema;
911
+ }
912
+ });
913
+ if (((_a = finalSchema.required) == null ? void 0 : _a.length) === 0) {
914
+ delete finalSchema.required;
915
+ }
916
+ return { schema: finalSchema, uiSchema: finalUiSchema };
917
+ }, [fields, initialSchema]);
918
+ const [formSettings, setFormSettings] = react.useState({
919
+ columns: initialColumns || 1,
920
+ theme: initialTheme || {}
921
+ });
922
+ const updateFormSettings = react.useCallback((updates) => {
923
+ setFormSettings((prev) => ({
924
+ ...prev,
925
+ ...updates,
926
+ theme: { ...prev.theme, ...updates.theme || {} }
927
+ }));
928
+ }, []);
929
+ return {
930
+ fields,
931
+ selectedFieldId,
932
+ setSelectedFieldId,
933
+ selectedField,
934
+ addField,
935
+ removeField,
936
+ updateField,
937
+ reorderFields,
938
+ compileSchemas,
939
+ formSettings,
940
+ updateFormSettings
941
+ };
942
+ };
943
+ var TOOLS = [
944
+ { type: "text", label: "Text Field", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Type, { size: 18 }) },
945
+ { type: "number", label: "Number", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Hash, { size: 18 }) },
946
+ { type: "email", label: "Email", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Mail, { size: 18 }) },
947
+ { type: "password", label: "Password", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Key, { size: 18 }) },
948
+ { type: "rich-text", label: "Rich Text", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignLeft, { size: 18 }) },
949
+ { type: "select", label: "Dropdown", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 18 }) },
950
+ { type: "radio", label: "Radio Group", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { size: 18 }) },
951
+ { type: "checkbox", label: "Checkbox", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckSquare, { size: 18 }) },
952
+ { type: "checkboxes", label: "Checkbox Group", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.List, { size: 18 }) },
953
+ { type: "file", label: "File Upload", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileUp, { size: 18 }) }
954
+ ];
955
+ var DraggableTool = ({
956
+ type,
957
+ label,
958
+ icon
959
+ }) => {
960
+ const { attributes, listeners, setNodeRef, isDragging } = core.useDraggable({
961
+ id: `toolbox-${type}`,
962
+ data: {
963
+ type: "ToolboxItem",
964
+ fieldType: type
965
+ }
966
+ });
967
+ return /* @__PURE__ */ jsxRuntime.jsxs(
968
+ "div",
969
+ {
970
+ ref: setNodeRef,
971
+ ...listeners,
972
+ ...attributes,
973
+ style: {
974
+ display: "flex",
975
+ alignItems: "center",
976
+ gap: "0.75rem",
977
+ padding: "0.75rem",
978
+ backgroundColor: "white",
979
+ border: "1px solid #e5e7eb",
980
+ borderRadius: "0.5rem",
981
+ cursor: isDragging ? "grabbing" : "grab",
982
+ opacity: isDragging ? 0.5 : 1,
983
+ marginBottom: "0.5rem",
984
+ boxShadow: "0 1px 2px rgba(0,0,0,0.05)",
985
+ transition: "all 0.2s"
986
+ },
987
+ onMouseEnter: (e) => {
988
+ e.currentTarget.style.borderColor = "#6366f1";
989
+ e.currentTarget.style.boxShadow = "0 4px 6px rgba(99, 102, 241, 0.1)";
990
+ },
991
+ onMouseLeave: (e) => {
992
+ e.currentTarget.style.borderColor = "#e5e7eb";
993
+ e.currentTarget.style.boxShadow = "0 1px 2px rgba(0,0,0,0.05)";
994
+ },
995
+ children: [
996
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#6b7280" }, children: icon }),
997
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.875rem", fontWeight: 500, color: "#374151" }, children: label })
998
+ ]
999
+ }
1000
+ );
1001
+ };
1002
+ var Toolbox = () => {
1003
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1004
+ "div",
1005
+ {
1006
+ style: {
1007
+ padding: "1.5rem",
1008
+ width: "280px",
1009
+ borderRight: "1px solid #e5e7eb",
1010
+ backgroundColor: "#f9fafb",
1011
+ height: "100%",
1012
+ overflowY: "auto"
1013
+ },
1014
+ children: [
1015
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { fontSize: "1rem", fontWeight: 600, color: "#111827", marginBottom: "1rem" }, children: "Form Elements" }),
1016
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.875rem", color: "#6b7280", marginBottom: "1.5rem" }, children: "Drag and drop fields onto the canvas to build your form." }),
1017
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, children: TOOLS.map((tool) => /* @__PURE__ */ jsxRuntime.jsx(DraggableTool, { ...tool }, tool.type)) })
1018
+ ]
1019
+ }
1020
+ );
1021
+ };
1022
+ var SortableField = ({
1023
+ field,
1024
+ isSelected,
1025
+ onClick,
1026
+ onRemove,
1027
+ onDuplicate
1028
+ }) => {
1029
+ var _a, _b;
1030
+ const { attributes, listeners, setNodeRef, transform, transition, isDragging } = sortable.useSortable({
1031
+ id: field.id,
1032
+ data: {
1033
+ type: "SortableField",
1034
+ field
1035
+ }
1036
+ });
1037
+ const style = {
1038
+ transform: utilities.CSS.Transform.toString(transform),
1039
+ transition,
1040
+ opacity: isDragging ? 0.6 : 1,
1041
+ position: "relative",
1042
+ zIndex: isDragging ? 10 : 1,
1043
+ padding: "2rem 1.5rem 1.5rem",
1044
+ // Extra top padding for drag handle
1045
+ backgroundColor: "white",
1046
+ borderRadius: "0.75rem",
1047
+ border: `2px solid ${isSelected ? "#6366f1" : "#e5e7eb"}`,
1048
+ boxShadow: isSelected ? "0 4px 12px rgba(99, 102, 241, 0.15)" : "0 1px 3px rgba(0,0,0,0.05)",
1049
+ marginBottom: "1rem",
1050
+ cursor: "pointer",
1051
+ gridColumn: `span ${((_a = field.uiSchema) == null ? void 0 : _a["ui:columnSpan"]) || 1} / span ${((_b = field.uiSchema) == null ? void 0 : _b["ui:columnSpan"]) || 1}`
1052
+ };
1053
+ const methods = reactHookForm.useForm();
1054
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1055
+ "div",
1056
+ {
1057
+ ref: setNodeRef,
1058
+ style,
1059
+ onClick: (e) => {
1060
+ e.stopPropagation();
1061
+ onClick();
1062
+ },
1063
+ children: [
1064
+ /* @__PURE__ */ jsxRuntime.jsx(
1065
+ "div",
1066
+ {
1067
+ ...attributes,
1068
+ ...listeners,
1069
+ style: {
1070
+ position: "absolute",
1071
+ top: "0",
1072
+ left: "50%",
1073
+ transform: "translateX(-50%)",
1074
+ width: "40px",
1075
+ height: "24px",
1076
+ backgroundColor: isSelected ? "#eef2ff" : "#f3f4f6",
1077
+ borderBottomLeftRadius: "8px",
1078
+ borderBottomRightRadius: "8px",
1079
+ display: "flex",
1080
+ alignItems: "center",
1081
+ justifyContent: "center",
1082
+ cursor: isDragging ? "grabbing" : "grab",
1083
+ color: isSelected ? "#6366f1" : "#9ca3af",
1084
+ zIndex: 2
1085
+ },
1086
+ onClick: (e) => e.stopPropagation(),
1087
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GripVertical, { size: 16 })
1088
+ }
1089
+ ),
1090
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative" }, children: [
1091
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", inset: 0, zIndex: 1, cursor: "pointer" } }),
1092
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { pointerEvents: "none" }, children: /* @__PURE__ */ jsxRuntime.jsx(reactHookForm.FormProvider, { ...methods, children: /* @__PURE__ */ jsxRuntime.jsx("form", { children: /* @__PURE__ */ jsxRuntime.jsx(
1093
+ FieldRenderer,
1094
+ {
1095
+ name: field.key,
1096
+ schema: field.schema,
1097
+ uiSchema: field.uiSchema,
1098
+ isRequired: field.isRequired
1099
+ }
1100
+ ) }) }) })
1101
+ ] }),
1102
+ isSelected && /* @__PURE__ */ jsxRuntime.jsxs(
1103
+ "div",
1104
+ {
1105
+ style: {
1106
+ position: "absolute",
1107
+ top: "-12px",
1108
+ right: "1rem",
1109
+ display: "flex",
1110
+ gap: "0.25rem",
1111
+ backgroundColor: "#ffffff",
1112
+ border: "1px solid #e5e7eb",
1113
+ padding: "0.25rem",
1114
+ borderRadius: "0.5rem",
1115
+ boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1)",
1116
+ zIndex: 10
1117
+ },
1118
+ children: [
1119
+ /* @__PURE__ */ jsxRuntime.jsx(
1120
+ "button",
1121
+ {
1122
+ onClick: (e) => {
1123
+ e.stopPropagation();
1124
+ onDuplicate();
1125
+ },
1126
+ style: {
1127
+ color: "#4f46e5",
1128
+ backgroundColor: "#eef2ff",
1129
+ border: "none",
1130
+ cursor: "pointer",
1131
+ padding: "0.375rem",
1132
+ borderRadius: "0.375rem",
1133
+ display: "flex",
1134
+ alignItems: "center",
1135
+ justifyContent: "center"
1136
+ },
1137
+ title: "Duplicate Field",
1138
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { size: 14 })
1139
+ }
1140
+ ),
1141
+ /* @__PURE__ */ jsxRuntime.jsx(
1142
+ "button",
1143
+ {
1144
+ onClick: (e) => {
1145
+ e.stopPropagation();
1146
+ onRemove();
1147
+ },
1148
+ style: {
1149
+ color: "#ef4444",
1150
+ backgroundColor: "#fef2f2",
1151
+ border: "none",
1152
+ cursor: "pointer",
1153
+ padding: "0.375rem",
1154
+ borderRadius: "0.375rem",
1155
+ display: "flex",
1156
+ alignItems: "center",
1157
+ justifyContent: "center"
1158
+ },
1159
+ title: "Remove Field",
1160
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { size: 14 })
1161
+ }
1162
+ )
1163
+ ]
1164
+ }
1165
+ )
1166
+ ]
1167
+ }
1168
+ );
1169
+ };
1170
+ var Canvas = ({
1171
+ fields,
1172
+ selectedFieldId,
1173
+ onSelectField,
1174
+ onRemoveField,
1175
+ onDuplicateField
1176
+ }) => {
1177
+ const { setNodeRef, isOver } = core.useDroppable({
1178
+ id: "canvas-droppable",
1179
+ data: {
1180
+ type: "Canvas"
1181
+ }
1182
+ });
1183
+ return /* @__PURE__ */ jsxRuntime.jsx(
1184
+ "div",
1185
+ {
1186
+ style: {
1187
+ flex: 1,
1188
+ padding: "2rem",
1189
+ backgroundColor: "#f3f4f6",
1190
+ overflowY: "auto"
1191
+ },
1192
+ onClick: () => onSelectField(""),
1193
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1194
+ "div",
1195
+ {
1196
+ ref: setNodeRef,
1197
+ style: {
1198
+ margin: "0 auto",
1199
+ height: "fit-content",
1200
+ width: "100%",
1201
+ maxWidth: "800px",
1202
+ minHeight: "400px",
1203
+ backgroundColor: fields.length === 0 ? "transparent" : "white",
1204
+ border: fields.length === 0 ? "2px dashed #d1d5db" : "1px solid #e5e7eb",
1205
+ borderRadius: "0.75rem",
1206
+ padding: fields.length === 0 ? "0" : "2rem",
1207
+ display: "flex",
1208
+ flexDirection: "column",
1209
+ boxShadow: fields.length === 0 ? "none" : "0 10px 15px -3px rgba(0, 0, 0, 0.1)",
1210
+ transition: "all 0.2s ease",
1211
+ ...isOver && fields.length === 0 ? { backgroundColor: "#eef2ff", borderColor: "#6366f1" } : {}
1212
+ },
1213
+ children: fields.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { margin: "auto", textAlign: "center", color: "#6b7280" }, children: [
1214
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "1.125rem", fontWeight: 500, marginBottom: "0.5rem" }, children: "Your form is empty" }),
1215
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.875rem" }, children: "Drag and drop a field from the left panel to get started." })
1216
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: "1rem" }, children: /* @__PURE__ */ jsxRuntime.jsx(sortable.SortableContext, { items: fields.map((f) => f.id), strategy: sortable.verticalListSortingStrategy, children: fields.map((field) => /* @__PURE__ */ jsxRuntime.jsx(
1217
+ SortableField,
1218
+ {
1219
+ field,
1220
+ isSelected: selectedFieldId === field.id,
1221
+ onClick: () => onSelectField(field.id),
1222
+ onRemove: () => onRemoveField(field.id),
1223
+ onDuplicate: () => onDuplicateField(field)
1224
+ },
1225
+ field.id
1226
+ )) }) })
1227
+ }
1228
+ )
1229
+ }
1230
+ );
1231
+ };
1232
+ var PropertiesPanel = ({
1233
+ field,
1234
+ formSettings,
1235
+ onUpdate,
1236
+ onUpdateSettings
1237
+ }) => {
1238
+ var _a, _b, _c, _d, _e, _f, _g;
1239
+ const [activeTab, setActiveTab] = react.useState("general");
1240
+ if (!field) {
1241
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1242
+ "div",
1243
+ {
1244
+ style: {
1245
+ width: "320px",
1246
+ borderLeft: "1px solid #e5e7eb",
1247
+ backgroundColor: "white",
1248
+ display: "flex",
1249
+ flexDirection: "column",
1250
+ height: "100%",
1251
+ overflowY: "auto"
1252
+ },
1253
+ children: [
1254
+ /* @__PURE__ */ jsxRuntime.jsxs(
1255
+ "div",
1256
+ {
1257
+ style: {
1258
+ padding: "1.5rem",
1259
+ borderBottom: "1px solid #e5e7eb",
1260
+ backgroundColor: "#f9fafb"
1261
+ },
1262
+ children: [
1263
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { fontSize: "1.125rem", fontWeight: 600, color: "#111827", margin: 0 }, children: "Global Form Settings" }),
1264
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.875rem", color: "#6b7280", margin: "0.25rem 0 0" }, children: "Click a field to edit its properties, or configure global form settings here." })
1265
+ ]
1266
+ }
1267
+ ),
1268
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "1.5rem", display: "flex", flexDirection: "column", gap: "1.5rem" }, children: [
1269
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1270
+ /* @__PURE__ */ jsxRuntime.jsxs(
1271
+ "h4",
1272
+ {
1273
+ style: {
1274
+ fontSize: "0.875rem",
1275
+ fontWeight: 600,
1276
+ color: "#374151",
1277
+ marginBottom: "0.75rem",
1278
+ display: "flex",
1279
+ alignItems: "center",
1280
+ gap: "0.375rem"
1281
+ },
1282
+ children: [
1283
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LayoutTemplate, { size: 16 }),
1284
+ " Layout Options"
1285
+ ]
1286
+ }
1287
+ ),
1288
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: [
1289
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.75rem", fontWeight: 500, color: "#6b7280" }, children: "Global Columns" }),
1290
+ /* @__PURE__ */ jsxRuntime.jsxs(
1291
+ "select",
1292
+ {
1293
+ value: formSettings.columns,
1294
+ onChange: (e) => onUpdateSettings({ columns: Number(e.target.value) }),
1295
+ style: {
1296
+ width: "100%",
1297
+ padding: "0.5rem",
1298
+ border: "1px solid #d1d5db",
1299
+ borderRadius: "0.375rem",
1300
+ fontSize: "0.875rem"
1301
+ },
1302
+ children: [
1303
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: 1, children: "1 Column" }),
1304
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: 2, children: "2 Columns" }),
1305
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: 3, children: "3 Columns" }),
1306
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: 4, children: "4 Columns" })
1307
+ ]
1308
+ }
1309
+ )
1310
+ ] })
1311
+ ] }),
1312
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1313
+ /* @__PURE__ */ jsxRuntime.jsxs(
1314
+ "h4",
1315
+ {
1316
+ style: {
1317
+ fontSize: "0.875rem",
1318
+ fontWeight: 600,
1319
+ color: "#374151",
1320
+ marginBottom: "0.75rem",
1321
+ display: "flex",
1322
+ alignItems: "center",
1323
+ gap: "0.375rem"
1324
+ },
1325
+ children: [
1326
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Palette, { size: 16 }),
1327
+ " Theme Colors"
1328
+ ]
1329
+ }
1330
+ ),
1331
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
1332
+ /* @__PURE__ */ jsxRuntime.jsxs(
1333
+ "div",
1334
+ {
1335
+ style: {
1336
+ display: "flex",
1337
+ alignItems: "center",
1338
+ justifyContent: "space-between",
1339
+ gap: "0.5rem"
1340
+ },
1341
+ children: [
1342
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.875rem", fontWeight: 500, color: "#4b5563" }, children: "Primary Color" }),
1343
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
1344
+ /* @__PURE__ */ jsxRuntime.jsx(
1345
+ "input",
1346
+ {
1347
+ type: "color",
1348
+ value: formSettings.theme.primary || "#6366f1",
1349
+ onChange: (e) => onUpdateSettings({
1350
+ theme: { ...formSettings.theme, primary: e.target.value }
1351
+ }),
1352
+ style: {
1353
+ width: "28px",
1354
+ height: "28px",
1355
+ padding: "0",
1356
+ border: "none",
1357
+ borderRadius: "4px",
1358
+ cursor: "pointer"
1359
+ }
1360
+ }
1361
+ ),
1362
+ /* @__PURE__ */ jsxRuntime.jsx(
1363
+ "input",
1364
+ {
1365
+ type: "text",
1366
+ value: formSettings.theme.primary || "",
1367
+ placeholder: "#6366f1",
1368
+ onChange: (e) => onUpdateSettings({
1369
+ theme: { ...formSettings.theme, primary: e.target.value }
1370
+ }),
1371
+ style: {
1372
+ width: "80px",
1373
+ padding: "0.25rem 0.5rem",
1374
+ border: "1px solid #d1d5db",
1375
+ borderRadius: "0.25rem",
1376
+ fontSize: "0.75rem",
1377
+ fontFamily: "monospace"
1378
+ }
1379
+ }
1380
+ )
1381
+ ] })
1382
+ ]
1383
+ }
1384
+ ),
1385
+ /* @__PURE__ */ jsxRuntime.jsxs(
1386
+ "div",
1387
+ {
1388
+ style: {
1389
+ display: "flex",
1390
+ alignItems: "center",
1391
+ justifyContent: "space-between",
1392
+ gap: "0.5rem"
1393
+ },
1394
+ children: [
1395
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.875rem", fontWeight: 500, color: "#4b5563" }, children: "Background Color" }),
1396
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
1397
+ /* @__PURE__ */ jsxRuntime.jsx(
1398
+ "input",
1399
+ {
1400
+ type: "color",
1401
+ value: formSettings.theme.background || "#ffffff",
1402
+ onChange: (e) => onUpdateSettings({
1403
+ theme: { ...formSettings.theme, background: e.target.value }
1404
+ }),
1405
+ style: {
1406
+ width: "28px",
1407
+ height: "28px",
1408
+ padding: "0",
1409
+ border: "none",
1410
+ borderRadius: "4px",
1411
+ cursor: "pointer"
1412
+ }
1413
+ }
1414
+ ),
1415
+ /* @__PURE__ */ jsxRuntime.jsx(
1416
+ "input",
1417
+ {
1418
+ type: "text",
1419
+ value: formSettings.theme.background || "",
1420
+ placeholder: "#ffffff",
1421
+ onChange: (e) => onUpdateSettings({
1422
+ theme: { ...formSettings.theme, background: e.target.value }
1423
+ }),
1424
+ style: {
1425
+ width: "80px",
1426
+ padding: "0.25rem 0.5rem",
1427
+ border: "1px solid #d1d5db",
1428
+ borderRadius: "0.25rem",
1429
+ fontSize: "0.75rem",
1430
+ fontFamily: "monospace"
1431
+ }
1432
+ }
1433
+ )
1434
+ ] })
1435
+ ]
1436
+ }
1437
+ )
1438
+ ] })
1439
+ ] })
1440
+ ] })
1441
+ ]
1442
+ }
1443
+ );
1444
+ }
1445
+ const handleSchemaChange = (key, value) => {
1446
+ onUpdate(field.id, {
1447
+ schema: { ...field.schema, [key]: value }
1448
+ });
1449
+ };
1450
+ const handleUiSchemaChange = (key, value) => {
1451
+ onUpdate(field.id, {
1452
+ uiSchema: { ...field.uiSchema || {}, [key]: value }
1453
+ });
1454
+ };
1455
+ const handleClassNamesChange = (element, value) => {
1456
+ var _a2;
1457
+ const existingUiClassNames = ((_a2 = field.uiSchema) == null ? void 0 : _a2["ui:classNames"]) || {};
1458
+ handleUiSchemaChange("ui:classNames", {
1459
+ ...existingUiClassNames,
1460
+ [element]: value
1461
+ });
1462
+ };
1463
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1464
+ "div",
1465
+ {
1466
+ style: {
1467
+ width: "320px",
1468
+ borderLeft: "1px solid #e5e7eb",
1469
+ backgroundColor: "white",
1470
+ display: "flex",
1471
+ flexDirection: "column",
1472
+ height: "100%",
1473
+ overflowY: "auto"
1474
+ },
1475
+ children: [
1476
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "1.5rem 1.5rem 0", borderBottom: "1px solid #e5e7eb" }, children: [
1477
+ /* @__PURE__ */ jsxRuntime.jsx(
1478
+ "h3",
1479
+ {
1480
+ style: { fontSize: "1.125rem", fontWeight: 600, color: "#111827", marginBottom: "1rem" },
1481
+ children: "Field Settings"
1482
+ }
1483
+ ),
1484
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", borderBottom: "1px solid #e5e7eb" }, children: [
1485
+ /* @__PURE__ */ jsxRuntime.jsxs(
1486
+ "button",
1487
+ {
1488
+ onClick: () => setActiveTab("general"),
1489
+ style: {
1490
+ flex: 1,
1491
+ padding: "0.75rem 0",
1492
+ fontSize: "0.875rem",
1493
+ fontWeight: 500,
1494
+ backgroundColor: "transparent",
1495
+ border: "none",
1496
+ borderBottom: `2px solid ${activeTab === "general" ? "#6366f1" : "transparent"}`,
1497
+ color: activeTab === "general" ? "#6366f1" : "#6b7280",
1498
+ cursor: "pointer",
1499
+ display: "flex",
1500
+ alignItems: "center",
1501
+ justifyContent: "center",
1502
+ gap: "0.25rem"
1503
+ },
1504
+ children: [
1505
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { size: 14 }),
1506
+ " General"
1507
+ ]
1508
+ }
1509
+ ),
1510
+ /* @__PURE__ */ jsxRuntime.jsxs(
1511
+ "button",
1512
+ {
1513
+ onClick: () => setActiveTab("validation"),
1514
+ style: {
1515
+ flex: 1,
1516
+ padding: "0.75rem 0",
1517
+ fontSize: "0.875rem",
1518
+ fontWeight: 500,
1519
+ backgroundColor: "transparent",
1520
+ border: "none",
1521
+ borderBottom: `2px solid ${activeTab === "validation" ? "#6366f1" : "transparent"}`,
1522
+ color: activeTab === "validation" ? "#6366f1" : "#6b7280",
1523
+ cursor: "pointer",
1524
+ display: "flex",
1525
+ alignItems: "center",
1526
+ justifyContent: "center",
1527
+ gap: "0.25rem"
1528
+ },
1529
+ children: [
1530
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { size: 14 }),
1531
+ " Validation"
1532
+ ]
1533
+ }
1534
+ ),
1535
+ /* @__PURE__ */ jsxRuntime.jsxs(
1536
+ "button",
1537
+ {
1538
+ onClick: () => setActiveTab("design"),
1539
+ style: {
1540
+ flex: 1,
1541
+ padding: "0.75rem 0",
1542
+ fontSize: "0.875rem",
1543
+ fontWeight: 500,
1544
+ backgroundColor: "transparent",
1545
+ border: "none",
1546
+ borderBottom: `2px solid ${activeTab === "design" ? "#6366f1" : "transparent"}`,
1547
+ color: activeTab === "design" ? "#6366f1" : "#6b7280",
1548
+ cursor: "pointer",
1549
+ display: "flex",
1550
+ alignItems: "center",
1551
+ justifyContent: "center",
1552
+ gap: "0.25rem"
1553
+ },
1554
+ children: [
1555
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Paintbrush, { size: 14 }),
1556
+ " Design"
1557
+ ]
1558
+ }
1559
+ )
1560
+ ] })
1561
+ ] }),
1562
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "1.5rem", display: "flex", flexDirection: "column", gap: "1.25rem" }, children: [
1563
+ activeTab === "general" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1564
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: [
1565
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.875rem", fontWeight: 500, color: "#374151" }, children: "Property Key" }),
1566
+ /* @__PURE__ */ jsxRuntime.jsx(
1567
+ "input",
1568
+ {
1569
+ type: "text",
1570
+ value: field.key,
1571
+ onChange: (e) => onUpdate(field.id, { key: e.target.value.replace(/[^a-zA-Z0-9_]/g, "") }),
1572
+ style: {
1573
+ width: "100%",
1574
+ padding: "0.5rem",
1575
+ border: "1px solid #d1d5db",
1576
+ borderRadius: "0.375rem",
1577
+ fontSize: "0.875rem"
1578
+ },
1579
+ placeholder: "e.g. firstName"
1580
+ }
1581
+ ),
1582
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.75rem", color: "#9ca3af" }, children: "The key used in the final JSON output." })
1583
+ ] }),
1584
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: [
1585
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.875rem", fontWeight: 500, color: "#374151" }, children: "Label / Title" }),
1586
+ /* @__PURE__ */ jsxRuntime.jsx(
1587
+ "input",
1588
+ {
1589
+ type: "text",
1590
+ value: field.schema.title || "",
1591
+ onChange: (e) => handleSchemaChange("title", e.target.value),
1592
+ style: {
1593
+ width: "100%",
1594
+ padding: "0.5rem",
1595
+ border: "1px solid #d1d5db",
1596
+ borderRadius: "0.375rem",
1597
+ fontSize: "0.875rem"
1598
+ }
1599
+ }
1600
+ )
1601
+ ] }),
1602
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: [
1603
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.875rem", fontWeight: 500, color: "#374151" }, children: "Description" }),
1604
+ /* @__PURE__ */ jsxRuntime.jsx(
1605
+ "textarea",
1606
+ {
1607
+ value: field.schema.description || "",
1608
+ onChange: (e) => handleSchemaChange("description", e.target.value),
1609
+ style: {
1610
+ width: "100%",
1611
+ padding: "0.5rem",
1612
+ border: "1px solid #d1d5db",
1613
+ borderRadius: "0.375rem",
1614
+ fontSize: "0.875rem",
1615
+ minHeight: "80px"
1616
+ }
1617
+ }
1618
+ )
1619
+ ] }),
1620
+ (field.type === "select" || field.type === "radio" || field.type === "checkboxes") && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: [
1621
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.875rem", fontWeight: 500, color: "#374151" }, children: "Options (Comma separated)" }),
1622
+ /* @__PURE__ */ jsxRuntime.jsx(
1623
+ "input",
1624
+ {
1625
+ type: "text",
1626
+ value: field.type === "checkboxes" ? field.schema.items && !Array.isArray(field.schema.items) ? (_a = field.schema.items.enum) == null ? void 0 : _a.join(", ") : "" : ((_b = field.schema.enum) == null ? void 0 : _b.join(", ")) || "",
1627
+ onChange: (e) => {
1628
+ const valArray = e.target.value.split(",").map((s) => s.trim()).filter(Boolean);
1629
+ if (field.type === "checkboxes") {
1630
+ handleSchemaChange("items", {
1631
+ ...field.schema.items || {},
1632
+ enum: valArray
1633
+ });
1634
+ } else {
1635
+ handleSchemaChange("enum", valArray);
1636
+ }
1637
+ },
1638
+ style: {
1639
+ width: "100%",
1640
+ padding: "0.5rem",
1641
+ border: "1px solid #d1d5db",
1642
+ borderRadius: "0.375rem",
1643
+ fontSize: "0.875rem"
1644
+ }
1645
+ }
1646
+ )
1647
+ ] })
1648
+ ] }),
1649
+ activeTab === "validation" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1650
+ /* @__PURE__ */ jsxRuntime.jsxs(
1651
+ "label",
1652
+ {
1653
+ style: {
1654
+ display: "flex",
1655
+ alignItems: "center",
1656
+ gap: "0.5rem",
1657
+ fontSize: "0.875rem",
1658
+ fontWeight: 500,
1659
+ color: "#374151",
1660
+ cursor: "pointer"
1661
+ },
1662
+ children: [
1663
+ /* @__PURE__ */ jsxRuntime.jsx(
1664
+ "input",
1665
+ {
1666
+ type: "checkbox",
1667
+ checked: field.isRequired || false,
1668
+ onChange: (e) => onUpdate(field.id, { isRequired: e.target.checked })
1669
+ }
1670
+ ),
1671
+ "Required Field"
1672
+ ]
1673
+ }
1674
+ ),
1675
+ (field.type === "text" || field.type === "email" || field.type === "password") && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1676
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: [
1677
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.875rem", fontWeight: 500, color: "#374151" }, children: "Min Length" }),
1678
+ /* @__PURE__ */ jsxRuntime.jsx(
1679
+ "input",
1680
+ {
1681
+ type: "number",
1682
+ value: field.schema.minLength || "",
1683
+ onChange: (e) => handleSchemaChange(
1684
+ "minLength",
1685
+ e.target.value ? Number(e.target.value) : void 0
1686
+ ),
1687
+ style: {
1688
+ width: "100%",
1689
+ padding: "0.5rem",
1690
+ border: "1px solid #d1d5db",
1691
+ borderRadius: "0.375rem",
1692
+ fontSize: "0.875rem"
1693
+ }
1694
+ }
1695
+ )
1696
+ ] }),
1697
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: [
1698
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.875rem", fontWeight: 500, color: "#374151" }, children: "Max Length" }),
1699
+ /* @__PURE__ */ jsxRuntime.jsx(
1700
+ "input",
1701
+ {
1702
+ type: "number",
1703
+ value: field.schema.maxLength || "",
1704
+ onChange: (e) => handleSchemaChange(
1705
+ "maxLength",
1706
+ e.target.value ? Number(e.target.value) : void 0
1707
+ ),
1708
+ style: {
1709
+ width: "100%",
1710
+ padding: "0.5rem",
1711
+ border: "1px solid #d1d5db",
1712
+ borderRadius: "0.375rem",
1713
+ fontSize: "0.875rem"
1714
+ }
1715
+ }
1716
+ )
1717
+ ] }),
1718
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: [
1719
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.875rem", fontWeight: 500, color: "#374151" }, children: "Regex Pattern" }),
1720
+ /* @__PURE__ */ jsxRuntime.jsx(
1721
+ "input",
1722
+ {
1723
+ type: "text",
1724
+ value: field.schema.pattern || "",
1725
+ onChange: (e) => handleSchemaChange("pattern", e.target.value || void 0),
1726
+ style: {
1727
+ width: "100%",
1728
+ padding: "0.5rem",
1729
+ border: "1px solid #d1d5db",
1730
+ borderRadius: "0.375rem",
1731
+ fontSize: "0.875rem"
1732
+ }
1733
+ }
1734
+ )
1735
+ ] })
1736
+ ] }),
1737
+ field.type === "number" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1738
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: [
1739
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.875rem", fontWeight: 500, color: "#374151" }, children: "Minimum Value" }),
1740
+ /* @__PURE__ */ jsxRuntime.jsx(
1741
+ "input",
1742
+ {
1743
+ type: "number",
1744
+ value: field.schema.minimum || "",
1745
+ onChange: (e) => handleSchemaChange(
1746
+ "minimum",
1747
+ e.target.value ? Number(e.target.value) : void 0
1748
+ ),
1749
+ style: {
1750
+ width: "100%",
1751
+ padding: "0.5rem",
1752
+ border: "1px solid #d1d5db",
1753
+ borderRadius: "0.375rem",
1754
+ fontSize: "0.875rem"
1755
+ }
1756
+ }
1757
+ )
1758
+ ] }),
1759
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: [
1760
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.875rem", fontWeight: 500, color: "#374151" }, children: "Maximum Value" }),
1761
+ /* @__PURE__ */ jsxRuntime.jsx(
1762
+ "input",
1763
+ {
1764
+ type: "number",
1765
+ value: field.schema.maximum || "",
1766
+ onChange: (e) => handleSchemaChange(
1767
+ "maximum",
1768
+ e.target.value ? Number(e.target.value) : void 0
1769
+ ),
1770
+ style: {
1771
+ width: "100%",
1772
+ padding: "0.5rem",
1773
+ border: "1px solid #d1d5db",
1774
+ borderRadius: "0.375rem",
1775
+ fontSize: "0.875rem"
1776
+ }
1777
+ }
1778
+ )
1779
+ ] })
1780
+ ] })
1781
+ ] }),
1782
+ activeTab === "design" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1783
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: [
1784
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.875rem", fontWeight: 500, color: "#374151" }, children: "Column Span" }),
1785
+ /* @__PURE__ */ jsxRuntime.jsxs(
1786
+ "select",
1787
+ {
1788
+ value: ((_c = field.uiSchema) == null ? void 0 : _c["ui:columnSpan"]) || 1,
1789
+ onChange: (e) => handleUiSchemaChange("ui:columnSpan", Number(e.target.value)),
1790
+ style: {
1791
+ width: "100%",
1792
+ padding: "0.5rem",
1793
+ border: "1px solid #d1d5db",
1794
+ borderRadius: "0.375rem",
1795
+ fontSize: "0.875rem"
1796
+ },
1797
+ children: [
1798
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: 1, children: "1 Column" }),
1799
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: 2, children: "2 Columns" }),
1800
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: 3, children: "3 Columns" }),
1801
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: 4, children: "4 Columns" })
1802
+ ]
1803
+ }
1804
+ )
1805
+ ] }),
1806
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1rem", borderTop: "1px solid #e5e7eb", paddingTop: "1rem" }, children: [
1807
+ /* @__PURE__ */ jsxRuntime.jsx(
1808
+ "h4",
1809
+ {
1810
+ style: {
1811
+ fontSize: "0.875rem",
1812
+ fontWeight: 600,
1813
+ color: "#111827",
1814
+ marginBottom: "0.5rem"
1815
+ },
1816
+ children: "Tailwind Classes (ui:classNames)"
1817
+ }
1818
+ ),
1819
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
1820
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, children: [
1821
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.75rem", color: "#6b7280" }, children: "Input" }),
1822
+ /* @__PURE__ */ jsxRuntime.jsx(
1823
+ "input",
1824
+ {
1825
+ type: "text",
1826
+ value: ((_e = (_d = field.uiSchema) == null ? void 0 : _d["ui:classNames"]) == null ? void 0 : _e.input) || "",
1827
+ onChange: (e) => handleClassNamesChange("input", e.target.value),
1828
+ style: {
1829
+ width: "100%",
1830
+ padding: "0.4rem",
1831
+ border: "1px solid #d1d5db",
1832
+ borderRadius: "0.25rem",
1833
+ fontSize: "0.75rem",
1834
+ fontFamily: "monospace"
1835
+ },
1836
+ placeholder: "e.g. bg-gray-50 border-blue-500"
1837
+ }
1838
+ )
1839
+ ] }),
1840
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, children: [
1841
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.75rem", color: "#6b7280" }, children: "Label" }),
1842
+ /* @__PURE__ */ jsxRuntime.jsx(
1843
+ "input",
1844
+ {
1845
+ type: "text",
1846
+ value: ((_g = (_f = field.uiSchema) == null ? void 0 : _f["ui:classNames"]) == null ? void 0 : _g.label) || "",
1847
+ onChange: (e) => handleClassNamesChange("label", e.target.value),
1848
+ style: {
1849
+ width: "100%",
1850
+ padding: "0.4rem",
1851
+ border: "1px solid #d1d5db",
1852
+ borderRadius: "0.25rem",
1853
+ fontSize: "0.75rem",
1854
+ fontFamily: "monospace"
1855
+ },
1856
+ placeholder: "e.g. text-blue-600 font-bold"
1857
+ }
1858
+ )
1859
+ ] })
1860
+ ] })
1861
+ ] })
1862
+ ] })
1863
+ ] })
1864
+ ]
1865
+ }
1866
+ );
1867
+ };
1868
+ var FormBuilder = ({
1869
+ initialSchema,
1870
+ initialUiSchema,
1871
+ initialColumns,
1872
+ initialTheme,
1873
+ onSave
1874
+ }) => {
1875
+ const {
1876
+ fields,
1877
+ selectedFieldId,
1878
+ setSelectedFieldId,
1879
+ selectedField,
1880
+ addField,
1881
+ removeField,
1882
+ updateField,
1883
+ reorderFields,
1884
+ compileSchemas,
1885
+ formSettings,
1886
+ updateFormSettings
1887
+ } = useFormBuilder(initialSchema, initialUiSchema, initialColumns, initialTheme);
1888
+ const [activeDragType, setActiveDragType] = react.useState(null);
1889
+ const [isPreviewMode, setIsPreviewMode] = react.useState(false);
1890
+ const sensors = core.useSensors(
1891
+ core.useSensor(core.PointerSensor),
1892
+ core.useSensor(core.KeyboardSensor, {
1893
+ coordinateGetter: sortable.sortableKeyboardCoordinates
1894
+ })
1895
+ );
1896
+ const handleDragStart = (event) => {
1897
+ var _a;
1898
+ const { active } = event;
1899
+ if (((_a = active.data.current) == null ? void 0 : _a.type) === "ToolboxItem") {
1900
+ setActiveDragType(active.data.current.fieldType);
1901
+ }
1902
+ };
1903
+ const handleDragEnd = (event) => {
1904
+ var _a, _b;
1905
+ const { active, over } = event;
1906
+ setActiveDragType(null);
1907
+ if (!over) return;
1908
+ if (((_a = active.data.current) == null ? void 0 : _a.type) === "ToolboxItem") {
1909
+ if (over.id === "canvas-droppable" || fields.find((f) => f.id === over.id)) {
1910
+ const overIndex = fields.findIndex((f) => f.id === over.id);
1911
+ addField(
1912
+ active.data.current.fieldType,
1913
+ overIndex >= 0 ? overIndex : void 0
1914
+ );
1915
+ }
1916
+ return;
1917
+ }
1918
+ if (((_b = active.data.current) == null ? void 0 : _b.type) === "SortableField" && active.id !== over.id) {
1919
+ reorderFields(active.id, over.id);
1920
+ }
1921
+ };
1922
+ const handleSave = () => {
1923
+ if (onSave) {
1924
+ const { schema, uiSchema } = compileSchemas();
1925
+ onSave(schema, uiSchema, formSettings);
1926
+ }
1927
+ };
1928
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1929
+ "div",
1930
+ {
1931
+ style: {
1932
+ display: "flex",
1933
+ flexDirection: "column",
1934
+ height: "100vh",
1935
+ width: "100vw",
1936
+ fontFamily: "system-ui, sans-serif"
1937
+ },
1938
+ children: [
1939
+ /* @__PURE__ */ jsxRuntime.jsxs(
1940
+ "div",
1941
+ {
1942
+ style: {
1943
+ height: "60px",
1944
+ borderBottom: "1px solid #e5e7eb",
1945
+ backgroundColor: "white",
1946
+ display: "flex",
1947
+ alignItems: "center",
1948
+ justifyContent: "space-between",
1949
+ padding: "0 1.5rem",
1950
+ zIndex: 20
1951
+ },
1952
+ children: [
1953
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
1954
+ /* @__PURE__ */ jsxRuntime.jsx(
1955
+ "div",
1956
+ {
1957
+ style: {
1958
+ width: "32px",
1959
+ height: "32px",
1960
+ backgroundColor: "#6366f1",
1961
+ borderRadius: "0.5rem",
1962
+ display: "flex",
1963
+ alignItems: "center",
1964
+ justifyContent: "center",
1965
+ color: "white"
1966
+ },
1967
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code2, { size: 20 })
1968
+ }
1969
+ ),
1970
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { style: { fontSize: "1.25rem", fontWeight: 700, color: "#111827", margin: 0 }, children: "Visual Form Builder" })
1971
+ ] }),
1972
+ /* @__PURE__ */ jsxRuntime.jsxs(
1973
+ "div",
1974
+ {
1975
+ style: {
1976
+ display: "flex",
1977
+ backgroundColor: "#f3f4f6",
1978
+ padding: "0.25rem",
1979
+ borderRadius: "0.5rem"
1980
+ },
1981
+ children: [
1982
+ /* @__PURE__ */ jsxRuntime.jsxs(
1983
+ "button",
1984
+ {
1985
+ onClick: () => setIsPreviewMode(false),
1986
+ style: {
1987
+ display: "flex",
1988
+ alignItems: "center",
1989
+ gap: "0.375rem",
1990
+ padding: "0.375rem 0.75rem",
1991
+ fontSize: "0.875rem",
1992
+ fontWeight: 500,
1993
+ border: "none",
1994
+ borderRadius: "0.375rem",
1995
+ cursor: "pointer",
1996
+ transition: "all 0.2s",
1997
+ backgroundColor: !isPreviewMode ? "white" : "transparent",
1998
+ color: !isPreviewMode ? "#111827" : "#6b7280",
1999
+ boxShadow: !isPreviewMode ? "0 1px 3px rgba(0,0,0,0.1)" : "none"
2000
+ },
2001
+ children: [
2002
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LayoutTemplate, { size: 16 }),
2003
+ " Builder"
2004
+ ]
2005
+ }
2006
+ ),
2007
+ /* @__PURE__ */ jsxRuntime.jsxs(
2008
+ "button",
2009
+ {
2010
+ onClick: () => setIsPreviewMode(true),
2011
+ style: {
2012
+ display: "flex",
2013
+ alignItems: "center",
2014
+ gap: "0.375rem",
2015
+ padding: "0.375rem 0.75rem",
2016
+ fontSize: "0.875rem",
2017
+ fontWeight: 500,
2018
+ border: "none",
2019
+ borderRadius: "0.375rem",
2020
+ cursor: "pointer",
2021
+ transition: "all 0.2s",
2022
+ backgroundColor: isPreviewMode ? "white" : "transparent",
2023
+ color: isPreviewMode ? "#111827" : "#6b7280",
2024
+ boxShadow: isPreviewMode ? "0 1px 3px rgba(0,0,0,0.1)" : "none"
2025
+ },
2026
+ children: [
2027
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: 16 }),
2028
+ " Preview"
2029
+ ]
2030
+ }
2031
+ )
2032
+ ]
2033
+ }
2034
+ ),
2035
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(
2036
+ "button",
2037
+ {
2038
+ onClick: handleSave,
2039
+ style: {
2040
+ display: "flex",
2041
+ alignItems: "center",
2042
+ gap: "0.5rem",
2043
+ backgroundColor: "#6366f1",
2044
+ color: "white",
2045
+ border: "none",
2046
+ padding: "0.5rem 1rem",
2047
+ borderRadius: "0.375rem",
2048
+ fontWeight: 600,
2049
+ cursor: "pointer",
2050
+ transition: "background-color 0.2s"
2051
+ },
2052
+ onMouseEnter: (e) => e.currentTarget.style.backgroundColor = "#4f46e5",
2053
+ onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "#6366f1",
2054
+ children: [
2055
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Save, { size: 16 }),
2056
+ " Save Form"
2057
+ ]
2058
+ }
2059
+ ) })
2060
+ ]
2061
+ }
2062
+ ),
2063
+ /* @__PURE__ */ jsxRuntime.jsx(
2064
+ "div",
2065
+ {
2066
+ style: {
2067
+ display: "flex",
2068
+ flex: 1,
2069
+ overflow: "hidden",
2070
+ backgroundColor: "#f3f4f6",
2071
+ minHeight: 0
2072
+ },
2073
+ children: isPreviewMode ? /* @__PURE__ */ jsxRuntime.jsx(
2074
+ "div",
2075
+ {
2076
+ style: {
2077
+ flex: 1,
2078
+ padding: "3rem",
2079
+ overflowY: "auto"
2080
+ },
2081
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
2082
+ "div",
2083
+ {
2084
+ style: {
2085
+ margin: "0 auto",
2086
+ height: "fit-content",
2087
+ width: "100%",
2088
+ maxWidth: "800px",
2089
+ backgroundColor: "white",
2090
+ padding: "2rem",
2091
+ borderRadius: "1rem",
2092
+ boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)"
2093
+ },
2094
+ children: [
2095
+ /* @__PURE__ */ jsxRuntime.jsx(
2096
+ "div",
2097
+ {
2098
+ style: {
2099
+ marginBottom: "2rem",
2100
+ paddingBottom: "1rem",
2101
+ borderBottom: "1px solid #e5e7eb",
2102
+ display: "flex",
2103
+ justifyContent: "space-between",
2104
+ alignItems: "center"
2105
+ },
2106
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2107
+ "span",
2108
+ {
2109
+ style: {
2110
+ fontSize: "0.875rem",
2111
+ fontWeight: 600,
2112
+ color: "#6366f1",
2113
+ textTransform: "uppercase",
2114
+ letterSpacing: "0.05em"
2115
+ },
2116
+ children: "Live Preview"
2117
+ }
2118
+ )
2119
+ }
2120
+ ),
2121
+ /* @__PURE__ */ jsxRuntime.jsx(
2122
+ SchemaForm,
2123
+ {
2124
+ schema: compileSchemas().schema,
2125
+ uiSchema: compileSchemas().uiSchema,
2126
+ columns: formSettings.columns,
2127
+ theme: formSettings.theme,
2128
+ onSubmit: (data) => alert("Preview Form Submitted!\n\n" + JSON.stringify(data, null, 2))
2129
+ }
2130
+ )
2131
+ ]
2132
+ }
2133
+ )
2134
+ }
2135
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
2136
+ core.DndContext,
2137
+ {
2138
+ sensors,
2139
+ collisionDetection: core.closestCenter,
2140
+ onDragStart: handleDragStart,
2141
+ onDragEnd: handleDragEnd,
2142
+ children: [
2143
+ /* @__PURE__ */ jsxRuntime.jsx(Toolbox, {}),
2144
+ /* @__PURE__ */ jsxRuntime.jsx(
2145
+ Canvas,
2146
+ {
2147
+ fields,
2148
+ selectedFieldId,
2149
+ onSelectField: setSelectedFieldId,
2150
+ onRemoveField: removeField,
2151
+ onDuplicateField: (f) => {
2152
+ const idx = fields.findIndex((field) => field.id === f.id);
2153
+ addField(f.type, idx + 1);
2154
+ }
2155
+ }
2156
+ ),
2157
+ /* @__PURE__ */ jsxRuntime.jsx(
2158
+ PropertiesPanel,
2159
+ {
2160
+ field: selectedField || null,
2161
+ formSettings,
2162
+ onUpdate: updateField,
2163
+ onUpdateSettings: updateFormSettings
2164
+ }
2165
+ ),
2166
+ /* @__PURE__ */ jsxRuntime.jsx(core.DragOverlay, { children: activeDragType ? /* @__PURE__ */ jsxRuntime.jsxs(
2167
+ "div",
2168
+ {
2169
+ style: {
2170
+ padding: "0.75rem",
2171
+ backgroundColor: "#6366f1",
2172
+ color: "white",
2173
+ borderRadius: "0.5rem",
2174
+ opacity: 0.8,
2175
+ fontWeight: 500
2176
+ },
2177
+ children: [
2178
+ "Dropping ",
2179
+ activeDragType,
2180
+ "..."
2181
+ ]
2182
+ }
2183
+ ) : null })
2184
+ ]
2185
+ }
2186
+ )
2187
+ }
2188
+ )
2189
+ ]
2190
+ }
2191
+ );
2192
+ };
2193
+
699
2194
  exports.FieldRenderer = FieldRenderer;
2195
+ exports.FormBuilder = FormBuilder;
700
2196
  exports.SchemaForm = SchemaForm;
701
2197
  //# sourceMappingURL=index.js.map
702
2198
  //# sourceMappingURL=index.js.map