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