performa 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,1623 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var lucideReact = require('lucide-react');
6
+
7
+ // src/core/types.ts
8
+ var mimeTypes = {
9
+ JPG: "image/jpeg",
10
+ JPEG: "image/jpeg",
11
+ PNG: "image/png",
12
+ GIF: "image/gif",
13
+ WEBP: "image/webp",
14
+ SVG: "image/svg+xml",
15
+ BMP: "image/bmp",
16
+ TIFF: "image/tiff",
17
+ ICO: "image/x-icon",
18
+ PDF: "application/pdf",
19
+ DOC: "application/msword",
20
+ DOCX: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
21
+ XLS: "application/vnd.ms-excel",
22
+ XLSX: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
23
+ PPT: "application/vnd.ms-powerpoint",
24
+ PPTX: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
25
+ ZIP: "application/zip",
26
+ RAR: "application/x-rar-compressed",
27
+ "7Z": "application/x-7z-compressed",
28
+ TAR: "application/x-tar",
29
+ GZ: "application/x-gzip",
30
+ BZ2: "application/x-bzip2",
31
+ ISO: "application/x-iso9660-image",
32
+ SWF: "application/x-shockwave-flash",
33
+ TTF: "application/x-font-ttf",
34
+ MP4: "video/mp4",
35
+ MP3: "audio/mpeg",
36
+ MOV: "video/quicktime",
37
+ AVI: "video/x-msvideo",
38
+ WMV: "video/x-ms-wmv",
39
+ MPEG: "video/mpeg",
40
+ TXT: "text/plain",
41
+ CSV: "text/csv"
42
+ };
43
+ var FormContext = react.createContext(null);
44
+ function useFormContext() {
45
+ const context = react.useContext(FormContext);
46
+ if (!context) {
47
+ throw new Error("useFormContext must be used within a Form component");
48
+ }
49
+ return context;
50
+ }
51
+ function useFormState() {
52
+ const { state } = useFormContext();
53
+ return state;
54
+ }
55
+ function useFormConfig() {
56
+ const { config } = useFormContext();
57
+ return config;
58
+ }
59
+ function useFieldError(fieldName) {
60
+ const { state } = useFormContext();
61
+ return state.errors?.[fieldName];
62
+ }
63
+
64
+ // src/core/utils.ts
65
+ function bytesToHumanReadable(bytes) {
66
+ const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
67
+ if (bytes === 0) return "0 Bytes";
68
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
69
+ return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + " " + sizes[i];
70
+ }
71
+ function isImage(filename) {
72
+ const imageExtensions = [
73
+ ".jpg",
74
+ ".jpeg",
75
+ ".png",
76
+ ".gif",
77
+ ".webp",
78
+ ".svg",
79
+ ".bmp",
80
+ ".tiff",
81
+ ".ico"
82
+ ];
83
+ const ext = filename.toLowerCase().slice(filename.lastIndexOf("."));
84
+ return imageExtensions.includes(ext);
85
+ }
86
+ var widthClasses = {
87
+ 1: "col-span-12 @lg:col-span-1",
88
+ 2: "col-span-4 @lg:col-span-2",
89
+ 3: "col-span-6 @lg:col-span-3",
90
+ 4: "col-span-8 @lg:col-span-4",
91
+ 5: "col-span-12 @lg:col-span-5",
92
+ 6: "col-span-12 @lg:col-span-6",
93
+ 7: "col-span-12 @lg:col-span-7",
94
+ 8: "col-span-12 @lg:col-span-8",
95
+ 9: "col-span-12 @lg:col-span-9",
96
+ 10: "col-span-12 @lg:col-span-10",
97
+ 11: "col-span-12 @lg:col-span-11",
98
+ 12: "col-span-12"
99
+ };
100
+ var defaultTheme = {
101
+ darkMode: true,
102
+ formGroup: "form-group",
103
+ form: "w-full",
104
+ fieldset: "@container grid grid-cols-12 gap-4",
105
+ label: {
106
+ base: "block text-sm font-medium text-gray-700 dark:text-gray-300",
107
+ required: "text-red-500 ml-1"
108
+ },
109
+ input: {
110
+ base: "block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring focus:ring-primary focus:border-primary",
111
+ error: "border-red-500 dark:border-red-400",
112
+ disabled: "disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed",
113
+ focus: "focus:outline-none focus:ring focus:ring-primary focus:border-primary"
114
+ },
115
+ select: {
116
+ base: "mt-1 block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring focus:ring-primary focus:border-primary disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed",
117
+ error: "border-red-500 dark:border-red-400",
118
+ disabled: "disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed",
119
+ option: "bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100"
120
+ },
121
+ textarea: {
122
+ base: "mt-1 block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring focus:ring-primary focus:border-primary disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed",
123
+ error: "border-red-500 dark:border-red-400",
124
+ disabled: "disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed"
125
+ },
126
+ checkbox: {
127
+ base: "h-4 w-4 text-primary focus:ring-primary border-gray-300 dark:border-gray-600 dark:bg-gray-800 rounded disabled:cursor-not-allowed",
128
+ error: "border-red-500 dark:border-red-400",
129
+ label: "ml-2 block text-sm font-medium text-gray-700 dark:text-gray-300"
130
+ },
131
+ toggle: {
132
+ track: "absolute inset-0 rounded-full transition-colors duration-200 bg-gray-300 dark:bg-gray-600 peer-focus:ring-2 peer-focus:ring-primary peer-focus:ring-offset-2 dark:peer-focus:ring-offset-gray-800",
133
+ trackActive: "peer-checked:bg-primary peer-checked:dark:bg-primary-light",
134
+ thumb: "absolute left-1 top-1 w-4 h-4 bg-white dark:bg-gray-200 rounded-full transition-transform duration-200 peer-checked:translate-x-5",
135
+ label: "block text-sm font-medium text-gray-700 dark:text-gray-300"
136
+ },
137
+ radio: {
138
+ base: "h-4 w-4 text-primary focus:ring-primary border-gray-300 dark:border-gray-600 dark:bg-gray-800 disabled:cursor-not-allowed",
139
+ label: "ml-2 text-sm text-gray-700 dark:text-gray-300",
140
+ group: "mt-1"
141
+ },
142
+ file: {
143
+ dropzone: "flex flex-col items-center justify-center w-full p-6 border-2 border-dashed rounded-md cursor-pointer border-gray-300 dark:border-gray-600 hover:border-primary dark:hover:border-primary transition-colors duration-200",
144
+ dropzoneActive: "border-primary bg-primary-50 dark:bg-primary-900/20",
145
+ dropzoneError: "border-red-500 dark:border-red-400 hover:border-red-500 dark:hover:border-red-400",
146
+ icon: "w-8 h-8 text-gray-400 dark:text-gray-500",
147
+ text: "mt-2 text-sm text-gray-500 dark:text-gray-400",
148
+ hint: "mt-1 text-xs text-gray-500 dark:text-gray-400"
149
+ },
150
+ submit: {
151
+ base: "mt-1 flex items-center justify-center w-full px-4 py-2 border border-transparent rounded-md shadow-sm text-white bg-primary hover:bg-primary-dark dark:bg-primary-light dark:hover:bg-primary focus:outline-none focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-gray-800 focus:ring-primary transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed",
152
+ loading: "opacity-75",
153
+ spinner: "mr-3 -ml-1 size-5 animate-spin text-white"
154
+ },
155
+ error: "mt-1 text-sm text-red-600 dark:text-red-400",
156
+ alert: {
157
+ base: "p-4 mb-4 border rounded-md",
158
+ error: "bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200 border-red-200 dark:border-red-800",
159
+ success: "bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200 border-green-200 dark:border-green-800",
160
+ warning: "bg-yellow-50 dark:bg-yellow-900/20 text-yellow-800 dark:text-yellow-200 border-yellow-200 dark:border-yellow-800",
161
+ info: "bg-blue-50 dark:bg-blue-900/20 text-blue-800 dark:text-blue-200 border-blue-200 dark:border-blue-800"
162
+ },
163
+ datetime: {
164
+ input: "block w-full px-3 py-2 pr-10 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring focus:ring-primary focus:border-primary disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed cursor-pointer",
165
+ dropdown: "absolute z-50 mt-2 p-4 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg shadow-lg w-80",
166
+ picker: "absolute z-50 mt-2 p-4 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg shadow-lg w-80",
167
+ calendar: "grid grid-cols-7 gap-1 mb-4",
168
+ day: "p-2 text-sm rounded hover:bg-primary hover:text-white transition-colors text-gray-700 dark:text-gray-300",
169
+ daySelected: "bg-primary text-white",
170
+ dayButton: "p-2 text-sm rounded hover:bg-primary hover:text-white transition-colors text-gray-700 dark:text-gray-300",
171
+ dayButtonSelected: "bg-primary text-white",
172
+ timeInput: "w-14 px-2 py-1 text-center border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100",
173
+ timeLabel: "text-xs font-medium text-gray-700 dark:text-gray-300",
174
+ periodButton: "px-3 py-1 text-xs rounded bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300",
175
+ periodButtonActive: "bg-primary text-white",
176
+ iconButton: "absolute right-2 top-1/2 -translate-y-1/2 text-gray-500 dark:text-gray-400",
177
+ navButton: "p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded text-gray-700 dark:text-white",
178
+ monthYear: "text-sm font-medium text-gray-900 dark:text-gray-100",
179
+ weekday: "text-center text-xs font-medium text-gray-500 dark:text-gray-400 p-2",
180
+ formatButton: "px-2 py-1 text-xs bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-200 dark:hover:bg-gray-600"
181
+ },
182
+ button: {
183
+ primary: "flex-1 px-3 py-2 text-sm bg-primary text-white rounded hover:bg-primary-dark focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2",
184
+ secondary: "flex-1 px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300"
185
+ },
186
+ readonly: "mt-1 block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-gray-100",
187
+ none: {
188
+ container: "form-group",
189
+ label: "block text-sm font-medium text-gray-700 dark:text-gray-300",
190
+ value: "mt-1 block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-gray-100"
191
+ }
192
+ };
193
+ var lightOnlyTheme = {
194
+ darkMode: false,
195
+ formGroup: "form-group",
196
+ form: "w-full",
197
+ fieldset: "@container grid grid-cols-12 gap-4",
198
+ label: {
199
+ base: "block text-sm font-medium text-gray-700",
200
+ required: "text-red-500 ml-1"
201
+ },
202
+ input: {
203
+ base: "block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-white text-gray-900 placeholder-gray-400 focus:outline-none focus:ring focus:ring-primary focus:border-primary",
204
+ error: "border-red-500",
205
+ disabled: "disabled:bg-gray-100 disabled:cursor-not-allowed",
206
+ focus: "focus:outline-none focus:ring focus:ring-primary focus:border-primary"
207
+ },
208
+ select: {
209
+ base: "mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-white text-gray-900 focus:outline-none focus:ring focus:ring-primary focus:border-primary disabled:bg-gray-100 disabled:cursor-not-allowed",
210
+ error: "border-red-500",
211
+ disabled: "disabled:bg-gray-100 disabled:cursor-not-allowed",
212
+ option: "bg-white text-gray-900"
213
+ },
214
+ textarea: {
215
+ base: "mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-white text-gray-900 placeholder-gray-400 focus:outline-none focus:ring focus:ring-primary focus:border-primary disabled:bg-gray-100 disabled:cursor-not-allowed",
216
+ error: "border-red-500",
217
+ disabled: "disabled:bg-gray-100 disabled:cursor-not-allowed"
218
+ },
219
+ checkbox: {
220
+ base: "h-4 w-4 text-primary focus:ring-primary border-gray-300 rounded disabled:cursor-not-allowed",
221
+ error: "border-red-500",
222
+ label: "ml-2 block text-sm font-medium text-gray-700"
223
+ },
224
+ toggle: {
225
+ track: "absolute inset-0 rounded-full transition-colors duration-200 bg-gray-300 peer-focus:ring-2 peer-focus:ring-primary peer-focus:ring-offset-2",
226
+ trackActive: "peer-checked:bg-primary",
227
+ thumb: "absolute left-1 top-1 w-4 h-4 bg-white rounded-full transition-transform duration-200 peer-checked:translate-x-5",
228
+ label: "block text-sm font-medium text-gray-700"
229
+ },
230
+ radio: {
231
+ base: "h-4 w-4 text-primary focus:ring-primary border-gray-300 disabled:cursor-not-allowed",
232
+ label: "ml-2 text-sm text-gray-700",
233
+ group: "mt-1"
234
+ },
235
+ file: {
236
+ dropzone: "flex flex-col items-center justify-center w-full p-6 border-2 border-dashed rounded-md cursor-pointer border-gray-300 hover:border-primary transition-colors duration-200",
237
+ dropzoneActive: "border-primary bg-primary-50",
238
+ dropzoneError: "border-red-500 hover:border-red-500",
239
+ icon: "w-8 h-8 text-gray-400",
240
+ text: "mt-2 text-sm text-gray-500",
241
+ hint: "mt-1 text-xs text-gray-500"
242
+ },
243
+ submit: {
244
+ base: "mt-1 flex items-center justify-center w-full px-4 py-2 border border-transparent rounded-md shadow-sm text-white bg-primary hover:bg-primary-dark focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed",
245
+ loading: "opacity-75",
246
+ spinner: "mr-3 -ml-1 size-5 animate-spin text-white"
247
+ },
248
+ error: "mt-1 text-sm text-red-600",
249
+ alert: {
250
+ base: "p-4 mb-4 border rounded-md",
251
+ error: "bg-red-50 text-red-800 border-red-200",
252
+ success: "bg-green-50 text-green-800 border-green-200",
253
+ warning: "bg-yellow-50 text-yellow-800 border-yellow-200",
254
+ info: "bg-blue-50 text-blue-800 border-blue-200"
255
+ },
256
+ datetime: {
257
+ input: "block w-full px-3 py-2 pr-10 border border-gray-300 rounded-md shadow-sm bg-white text-gray-900 placeholder-gray-400 focus:outline-none focus:ring focus:ring-primary focus:border-primary disabled:bg-gray-100 disabled:cursor-not-allowed cursor-pointer",
258
+ dropdown: "absolute z-50 mt-2 p-4 bg-white border border-gray-300 rounded-lg shadow-lg w-80",
259
+ picker: "absolute z-50 mt-2 p-4 bg-white border border-gray-300 rounded-lg shadow-lg w-80",
260
+ calendar: "grid grid-cols-7 gap-1 mb-4",
261
+ day: "p-2 text-sm rounded hover:bg-primary hover:text-white transition-colors text-gray-700",
262
+ daySelected: "bg-primary text-white",
263
+ dayButton: "p-2 text-sm rounded hover:bg-primary hover:text-white transition-colors text-gray-700",
264
+ dayButtonSelected: "bg-primary text-white",
265
+ timeInput: "w-14 px-2 py-1 text-center border border-gray-300 rounded bg-white text-gray-900",
266
+ timeLabel: "text-xs font-medium text-gray-700",
267
+ periodButton: "px-3 py-1 text-xs rounded bg-gray-100 text-gray-700",
268
+ periodButtonActive: "bg-primary text-white",
269
+ iconButton: "absolute right-2 top-1/2 -translate-y-1/2 text-gray-500",
270
+ navButton: "p-1 hover:bg-gray-100 rounded text-gray-700",
271
+ monthYear: "text-sm font-medium text-gray-900",
272
+ weekday: "text-center text-xs font-medium text-gray-500 p-2",
273
+ formatButton: "px-2 py-1 text-xs bg-gray-100 text-gray-700 rounded hover:bg-gray-200"
274
+ },
275
+ button: {
276
+ primary: "flex-1 px-3 py-2 text-sm bg-primary text-white rounded hover:bg-primary-dark focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2",
277
+ secondary: "flex-1 px-3 py-2 text-sm border border-gray-300 rounded hover:bg-gray-50 text-gray-700"
278
+ },
279
+ readonly: "mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-gray-100 text-gray-900",
280
+ none: {
281
+ container: "form-group",
282
+ label: "block text-sm font-medium text-gray-700",
283
+ value: "mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-gray-100 text-gray-900"
284
+ }
285
+ };
286
+ var defaultLabels = {
287
+ required: "*",
288
+ loading: "Loading...",
289
+ fileUpload: {
290
+ clickToUpload: "Click to upload",
291
+ dragAndDrop: "or drag and drop",
292
+ allowedTypes: "Allowed types:",
293
+ maxSize: "Max size:"
294
+ },
295
+ datetime: {
296
+ clear: "Clear",
297
+ done: "Done",
298
+ timeFormat: "Time Format"
299
+ },
300
+ select: {
301
+ loading: "Loading options...",
302
+ noOptions: "No options available"
303
+ }
304
+ };
305
+ var ThemeContext = react.createContext({
306
+ theme: defaultTheme,
307
+ labels: defaultLabels
308
+ });
309
+ function useFormTheme() {
310
+ const { theme } = react.useContext(ThemeContext);
311
+ return theme;
312
+ }
313
+ function useFormLabels() {
314
+ const { labels } = react.useContext(ThemeContext);
315
+ return labels;
316
+ }
317
+ function useFormThemeConfig() {
318
+ return react.useContext(ThemeContext);
319
+ }
320
+ function deepMerge(target, source) {
321
+ const result = { ...target };
322
+ for (const key in source) {
323
+ if (source[key] !== void 0) {
324
+ if (typeof source[key] === "object" && source[key] !== null && !Array.isArray(source[key]) && typeof target[key] === "object" && target[key] !== null) {
325
+ result[key] = deepMerge(
326
+ target[key],
327
+ source[key]
328
+ );
329
+ } else {
330
+ result[key] = source[key];
331
+ }
332
+ }
333
+ }
334
+ return result;
335
+ }
336
+ function FormThemeProvider({
337
+ children,
338
+ theme,
339
+ labels,
340
+ lightOnly = false
341
+ }) {
342
+ const baseTheme = lightOnly ? lightOnlyTheme : defaultTheme;
343
+ const mergedTheme = react.useMemo(
344
+ () => theme ? deepMerge(baseTheme, theme) : baseTheme,
345
+ [theme, baseTheme]
346
+ );
347
+ const mergedLabels = react.useMemo(
348
+ () => labels ? deepMerge(defaultLabels, labels) : defaultLabels,
349
+ [labels]
350
+ );
351
+ const contextValue = react.useMemo(
352
+ () => ({ theme: mergedTheme, labels: mergedLabels }),
353
+ [mergedTheme, mergedLabels]
354
+ );
355
+ return /* @__PURE__ */ jsxRuntime.jsx(ThemeContext.Provider, { value: contextValue, children });
356
+ }
357
+ function createTheme(customTheme, basedOn = "default") {
358
+ const baseTheme = basedOn === "lightOnly" ? lightOnlyTheme : defaultTheme;
359
+ return deepMerge(baseTheme, customTheme);
360
+ }
361
+ function cx(...classes) {
362
+ return classes.filter(Boolean).join(" ");
363
+ }
364
+ function Alert({ type, message, className = "" }) {
365
+ const theme = useFormTheme();
366
+ const alertClass = theme.alert?.[type] ?? "";
367
+ return /* @__PURE__ */ jsxRuntime.jsx(
368
+ "div",
369
+ {
370
+ className: cx(theme.alert?.base, alertClass, className),
371
+ role: "alert",
372
+ children: message
373
+ }
374
+ );
375
+ }
376
+ var Alert_default = react.memo(Alert);
377
+ function DateTimeInput({
378
+ label,
379
+ name,
380
+ placeholder,
381
+ defaultValue,
382
+ className,
383
+ disabled,
384
+ error,
385
+ rules,
386
+ before,
387
+ beforeClassName,
388
+ after,
389
+ afterClassName
390
+ }) {
391
+ const [selectedDate, setSelectedDate] = react.useState(null);
392
+ const [displayValue, setDisplayValue] = react.useState("");
393
+ const [showPicker, setShowPicker] = react.useState(false);
394
+ const [currentMonth, setCurrentMonth] = react.useState(/* @__PURE__ */ new Date());
395
+ const [hours, setHours] = react.useState("12");
396
+ const [minutes, setMinutes] = react.useState("00");
397
+ const [period, setPeriod] = react.useState("PM");
398
+ const [use24Hour, setUse24Hour] = react.useState(true);
399
+ const pickerRef = react.useRef(null);
400
+ const theme = useFormTheme();
401
+ const labels = useFormLabels();
402
+ react.useEffect(() => {
403
+ if (defaultValue) {
404
+ const date = new Date(defaultValue.toString());
405
+ if (!isNaN(date.getTime())) {
406
+ setSelectedDate(date);
407
+ setCurrentMonth(date);
408
+ updateDisplayValue(date);
409
+ const h24 = date.getHours();
410
+ const m = date.getMinutes();
411
+ const p = h24 >= 12 ? "PM" : "AM";
412
+ const h12 = h24 % 12 || 12;
413
+ if (use24Hour) {
414
+ setHours(String(h24).padStart(2, "0"));
415
+ } else {
416
+ setHours(String(h12).padStart(2, "0"));
417
+ }
418
+ setMinutes(String(m).padStart(2, "0"));
419
+ setPeriod(p);
420
+ }
421
+ }
422
+ }, [defaultValue, use24Hour]);
423
+ react.useEffect(() => {
424
+ const handleClickOutside = (event) => {
425
+ if (pickerRef.current && !pickerRef.current.contains(event.target)) {
426
+ setShowPicker(false);
427
+ }
428
+ };
429
+ if (showPicker) {
430
+ document.addEventListener("mousedown", handleClickOutside);
431
+ }
432
+ return () => {
433
+ document.removeEventListener("mousedown", handleClickOutside);
434
+ };
435
+ }, [showPicker]);
436
+ const updateDisplayValue = (date) => {
437
+ setDisplayValue(date.toLocaleString());
438
+ };
439
+ const getDaysInMonth = (date) => {
440
+ const year = date.getFullYear();
441
+ const month = date.getMonth();
442
+ const firstDay = new Date(year, month, 1);
443
+ const lastDay = new Date(year, month + 1, 0);
444
+ const daysInMonth = lastDay.getDate();
445
+ const startingDayOfWeek = firstDay.getDay();
446
+ return { daysInMonth, startingDayOfWeek };
447
+ };
448
+ const handleDateSelect = (day) => {
449
+ let hour24 = parseInt(hours, 10);
450
+ if (!use24Hour) {
451
+ if (period === "PM" && hour24 !== 12) hour24 += 12;
452
+ if (period === "AM" && hour24 === 12) hour24 = 0;
453
+ }
454
+ const newDate = new Date(
455
+ currentMonth.getFullYear(),
456
+ currentMonth.getMonth(),
457
+ day,
458
+ hour24,
459
+ parseInt(minutes, 10)
460
+ );
461
+ setSelectedDate(newDate);
462
+ updateDisplayValue(newDate);
463
+ };
464
+ const handleTimeChange = () => {
465
+ if (selectedDate) {
466
+ const newDate = new Date(selectedDate);
467
+ let h = parseInt(hours, 10);
468
+ if (!use24Hour) {
469
+ if (period === "PM" && h !== 12) h += 12;
470
+ if (period === "AM" && h === 12) h = 0;
471
+ }
472
+ newDate.setHours(h, parseInt(minutes, 10));
473
+ setSelectedDate(newDate);
474
+ updateDisplayValue(newDate);
475
+ }
476
+ };
477
+ const changeMonth = (offset) => {
478
+ setCurrentMonth(
479
+ (prev) => new Date(prev.getFullYear(), prev.getMonth() + offset, 1)
480
+ );
481
+ };
482
+ const renderCalendar = () => {
483
+ const { daysInMonth, startingDayOfWeek } = getDaysInMonth(currentMonth);
484
+ const days = [];
485
+ for (let i = 0; i < startingDayOfWeek; i++) {
486
+ days.push(/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2" }, `empty-${i}`));
487
+ }
488
+ for (let day = 1; day <= daysInMonth; day++) {
489
+ const isSelected = selectedDate && selectedDate.getDate() === day && selectedDate.getMonth() === currentMonth.getMonth() && selectedDate.getFullYear() === currentMonth.getFullYear();
490
+ days.push(
491
+ /* @__PURE__ */ jsxRuntime.jsx(
492
+ "button",
493
+ {
494
+ type: "button",
495
+ onClick: () => handleDateSelect(day),
496
+ className: cx(
497
+ theme.datetime?.day,
498
+ isSelected && theme.datetime?.daySelected
499
+ ),
500
+ children: day
501
+ },
502
+ day
503
+ )
504
+ );
505
+ }
506
+ return days;
507
+ };
508
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx(theme.formGroup, className), ref: pickerRef, children: [
509
+ before && /* @__PURE__ */ jsxRuntime.jsx("p", { className: beforeClassName ?? "", children: before }),
510
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: name, className: theme.label?.base, children: [
511
+ label,
512
+ " ",
513
+ rules?.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: theme.label?.required, children: "*" })
514
+ ] }),
515
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative mt-1", children: [
516
+ /* @__PURE__ */ jsxRuntime.jsx(
517
+ "input",
518
+ {
519
+ type: "text",
520
+ value: displayValue,
521
+ placeholder,
522
+ readOnly: true,
523
+ onFocus: () => !disabled && setShowPicker(true),
524
+ onClick: () => !disabled && setShowPicker(true),
525
+ className: cx(
526
+ theme.datetime?.input,
527
+ error && theme.input?.error
528
+ )
529
+ }
530
+ ),
531
+ /* @__PURE__ */ jsxRuntime.jsx(
532
+ "button",
533
+ {
534
+ type: "button",
535
+ onClick: () => !disabled && setShowPicker(true),
536
+ disabled,
537
+ className: theme.datetime?.iconButton,
538
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "h-5 w-5" })
539
+ }
540
+ ),
541
+ /* @__PURE__ */ jsxRuntime.jsx(
542
+ "input",
543
+ {
544
+ type: "hidden",
545
+ name,
546
+ id: name,
547
+ value: selectedDate ? selectedDate.toISOString() : "",
548
+ "aria-invalid": !!error,
549
+ "aria-describedby": error ? `${name}-error` : void 0
550
+ }
551
+ ),
552
+ showPicker && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: theme.datetime?.dropdown, children: [
553
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-4", children: [
554
+ /* @__PURE__ */ jsxRuntime.jsx(
555
+ "button",
556
+ {
557
+ type: "button",
558
+ onClick: () => changeMonth(-1),
559
+ className: theme.datetime?.navButton,
560
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "w-5 h-5" })
561
+ }
562
+ ),
563
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: theme.datetime?.monthYear, children: currentMonth.toLocaleDateString("en-GB", {
564
+ month: "long",
565
+ year: "numeric"
566
+ }) }),
567
+ /* @__PURE__ */ jsxRuntime.jsx(
568
+ "button",
569
+ {
570
+ type: "button",
571
+ onClick: () => changeMonth(1),
572
+ className: theme.datetime?.navButton,
573
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "w-5 h-5" })
574
+ }
575
+ )
576
+ ] }),
577
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 gap-1 mb-2", children: (labels.datetime?.weekdays ?? [
578
+ "Su",
579
+ "Mo",
580
+ "Tu",
581
+ "We",
582
+ "Th",
583
+ "Fr",
584
+ "Sa"
585
+ ]).map((day) => /* @__PURE__ */ jsxRuntime.jsx(
586
+ "div",
587
+ {
588
+ className: theme.datetime?.weekday,
589
+ children: day
590
+ },
591
+ day
592
+ )) }),
593
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 gap-1 mb-4", children: renderCalendar() }),
594
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-gray-200 dark:border-gray-700 pt-4", children: [
595
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
596
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: theme.datetime?.timeLabel, children: labels.datetime?.timeFormat }),
597
+ /* @__PURE__ */ jsxRuntime.jsx(
598
+ "button",
599
+ {
600
+ type: "button",
601
+ onClick: () => {
602
+ const newFormat = !use24Hour;
603
+ setUse24Hour(newFormat);
604
+ if (selectedDate) {
605
+ const h24 = selectedDate.getHours();
606
+ if (newFormat) {
607
+ setHours(
608
+ String(h24).padStart(2, "0")
609
+ );
610
+ } else {
611
+ const h12 = h24 % 12 || 12;
612
+ setHours(
613
+ String(h12).padStart(2, "0")
614
+ );
615
+ setPeriod(
616
+ h24 >= 12 ? "PM" : "AM"
617
+ );
618
+ }
619
+ }
620
+ },
621
+ className: theme.datetime?.formatButton,
622
+ children: use24Hour ? "24hr" : "12hr"
623
+ }
624
+ )
625
+ ] }),
626
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-2", children: [
627
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "h-4 w-4 text-gray-500 dark:text-gray-400" }),
628
+ /* @__PURE__ */ jsxRuntime.jsx(
629
+ "input",
630
+ {
631
+ type: "number",
632
+ min: use24Hour ? "0" : "1",
633
+ max: use24Hour ? "23" : "12",
634
+ value: hours,
635
+ onChange: (e) => {
636
+ const val = parseInt(e.target.value, 10);
637
+ const max = use24Hour ? 23 : 12;
638
+ const min = use24Hour ? 0 : 1;
639
+ if (val >= min && val <= max) {
640
+ setHours(
641
+ e.target.value.padStart(2, "0")
642
+ );
643
+ handleTimeChange();
644
+ }
645
+ },
646
+ className: theme.datetime?.timeInput
647
+ }
648
+ ),
649
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-900 dark:text-gray-100", children: ":" }),
650
+ /* @__PURE__ */ jsxRuntime.jsx(
651
+ "input",
652
+ {
653
+ type: "number",
654
+ min: "0",
655
+ max: "59",
656
+ value: minutes,
657
+ onChange: (e) => {
658
+ const val = parseInt(e.target.value, 10);
659
+ if (val >= 0 && val <= 59) {
660
+ setMinutes(
661
+ e.target.value.padStart(2, "0")
662
+ );
663
+ handleTimeChange();
664
+ }
665
+ },
666
+ className: theme.datetime?.timeInput
667
+ }
668
+ ),
669
+ !use24Hour && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1", children: [
670
+ /* @__PURE__ */ jsxRuntime.jsx(
671
+ "button",
672
+ {
673
+ type: "button",
674
+ onClick: () => {
675
+ setPeriod("AM");
676
+ handleTimeChange();
677
+ },
678
+ className: cx(
679
+ theme.datetime?.periodButton,
680
+ period === "AM" && theme.datetime?.periodButtonActive
681
+ ),
682
+ children: "AM"
683
+ }
684
+ ),
685
+ /* @__PURE__ */ jsxRuntime.jsx(
686
+ "button",
687
+ {
688
+ type: "button",
689
+ onClick: () => {
690
+ setPeriod("PM");
691
+ handleTimeChange();
692
+ },
693
+ className: cx(
694
+ theme.datetime?.periodButton,
695
+ period === "PM" && theme.datetime?.periodButtonActive
696
+ ),
697
+ children: "PM"
698
+ }
699
+ )
700
+ ] })
701
+ ] })
702
+ ] }),
703
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 mt-4", children: [
704
+ /* @__PURE__ */ jsxRuntime.jsx(
705
+ "button",
706
+ {
707
+ type: "button",
708
+ onClick: () => {
709
+ setSelectedDate(null);
710
+ setDisplayValue("");
711
+ setShowPicker(false);
712
+ },
713
+ className: theme.button?.secondary,
714
+ children: labels.datetime?.clear
715
+ }
716
+ ),
717
+ /* @__PURE__ */ jsxRuntime.jsx(
718
+ "button",
719
+ {
720
+ type: "button",
721
+ onClick: () => setShowPicker(false),
722
+ className: theme.button?.primary,
723
+ children: labels.datetime?.done
724
+ }
725
+ )
726
+ ] })
727
+ ] })
728
+ ] }),
729
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { id: `${name}-error`, className: theme.error, children: error }),
730
+ after && /* @__PURE__ */ jsxRuntime.jsx("p", { className: afterClassName ?? "", children: after })
731
+ ] });
732
+ }
733
+ var DateTimeInput_default = react.memo(DateTimeInput);
734
+ function TextInput({
735
+ label,
736
+ placeholder,
737
+ name,
738
+ defaultValue,
739
+ className,
740
+ disabled,
741
+ error,
742
+ rules,
743
+ type = "text",
744
+ before,
745
+ beforeClassName,
746
+ after,
747
+ afterClassName
748
+ }) {
749
+ const [passwordVisible, setPasswordVisible] = react.useState(false);
750
+ const theme = useFormTheme();
751
+ const onTogglePassword = () => {
752
+ setPasswordVisible((prev) => !prev);
753
+ };
754
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx(theme.formGroup, className), children: [
755
+ before && /* @__PURE__ */ jsxRuntime.jsx("p", { className: beforeClassName ?? "", children: before }),
756
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: name, className: theme.label?.base, children: [
757
+ label,
758
+ rules?.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: theme.label?.required, children: "*" })
759
+ ] }),
760
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative mt-1", children: [
761
+ /* @__PURE__ */ jsxRuntime.jsx(
762
+ "input",
763
+ {
764
+ type: type === "password" ? passwordVisible ? "text" : "password" : type,
765
+ name,
766
+ id: name,
767
+ placeholder,
768
+ defaultValue: defaultValue?.toString(),
769
+ disabled,
770
+ "aria-invalid": !!error,
771
+ "aria-describedby": error ? `${name}-error` : void 0,
772
+ className: cx(
773
+ theme.input?.base,
774
+ error && theme.input?.error,
775
+ theme.input?.disabled
776
+ )
777
+ }
778
+ ),
779
+ type === "password" && /* @__PURE__ */ jsxRuntime.jsxs(
780
+ "button",
781
+ {
782
+ type: "button",
783
+ onClick: onTogglePassword,
784
+ className: "absolute right-2 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 z-10",
785
+ "aria-label": passwordVisible ? "Hide password" : "Show password",
786
+ children: [
787
+ passwordVisible ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { className: "h-5 w-5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, { className: "h-5 w-5 opacity-50" }),
788
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: passwordVisible ? "Hide password" : "Show password" })
789
+ ]
790
+ }
791
+ )
792
+ ] }),
793
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { id: `${name}-error`, className: theme.error, children: error }),
794
+ after && /* @__PURE__ */ jsxRuntime.jsx("p", { className: afterClassName ?? "", children: after })
795
+ ] });
796
+ }
797
+ var TextInput_default = react.memo(TextInput);
798
+ function SelectInput({
799
+ label,
800
+ name,
801
+ options,
802
+ defaultValue,
803
+ className,
804
+ disabled,
805
+ error,
806
+ rules,
807
+ before,
808
+ beforeClassName,
809
+ after,
810
+ afterClassName
811
+ }) {
812
+ const theme = useFormTheme();
813
+ const labels = useFormLabels();
814
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx(theme.formGroup, className), children: [
815
+ before && /* @__PURE__ */ jsxRuntime.jsx("p", { className: beforeClassName ?? "", children: before }),
816
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: name, className: theme.label?.base, children: [
817
+ label,
818
+ rules?.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: theme.label?.required, children: "*" })
819
+ ] }),
820
+ /* @__PURE__ */ jsxRuntime.jsx(
821
+ "select",
822
+ {
823
+ name,
824
+ id: name,
825
+ defaultValue: defaultValue?.toString(),
826
+ disabled,
827
+ "aria-invalid": !!error,
828
+ "aria-describedby": error ? `${name}-error` : void 0,
829
+ className: cx(
830
+ theme.select?.base,
831
+ error && theme.select?.error
832
+ ),
833
+ children: !options || options.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, className: theme.select?.option, children: !options ? labels.select?.loading : labels.select?.noOptions }) : options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
834
+ "option",
835
+ {
836
+ value: option.value,
837
+ className: theme.select?.option,
838
+ children: option.label
839
+ },
840
+ option.value
841
+ ))
842
+ }
843
+ ),
844
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { id: `${name}-error`, className: theme.error, children: error }),
845
+ after && /* @__PURE__ */ jsxRuntime.jsx("p", { className: afterClassName ?? "", children: after })
846
+ ] });
847
+ }
848
+ var SelectInput_default = react.memo(SelectInput);
849
+ function TextAreaInput({
850
+ label,
851
+ name,
852
+ placeholder,
853
+ defaultValue,
854
+ className,
855
+ disabled,
856
+ error,
857
+ rules,
858
+ before,
859
+ beforeClassName,
860
+ after,
861
+ afterClassName
862
+ }) {
863
+ const theme = useFormTheme();
864
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx(theme.formGroup, className), children: [
865
+ before && /* @__PURE__ */ jsxRuntime.jsx("p", { className: beforeClassName ?? "", children: before }),
866
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: name, className: theme.label?.base, children: [
867
+ label,
868
+ rules?.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: theme.label?.required, children: "*" })
869
+ ] }),
870
+ /* @__PURE__ */ jsxRuntime.jsx(
871
+ "textarea",
872
+ {
873
+ name,
874
+ id: name,
875
+ placeholder,
876
+ defaultValue: defaultValue?.toString(),
877
+ disabled,
878
+ "aria-invalid": !!error,
879
+ "aria-describedby": error ? `${name}-error` : void 0,
880
+ className: cx(
881
+ theme.textarea?.base,
882
+ error && theme.textarea?.error
883
+ ),
884
+ rows: 4
885
+ }
886
+ ),
887
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { id: `${name}-error`, className: theme.error, children: error }),
888
+ after && /* @__PURE__ */ jsxRuntime.jsx("p", { className: afterClassName ?? "", children: after })
889
+ ] });
890
+ }
891
+ var TextAreaInput_default = react.memo(TextAreaInput);
892
+ function CheckboxInput({
893
+ label,
894
+ name,
895
+ defaultChecked,
896
+ className,
897
+ disabled,
898
+ error,
899
+ rules,
900
+ before,
901
+ beforeClassName,
902
+ after,
903
+ afterClassName
904
+ }) {
905
+ const theme = useFormTheme();
906
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx(theme.formGroup, className), children: [
907
+ before && /* @__PURE__ */ jsxRuntime.jsx("p", { className: beforeClassName ?? "", children: before }),
908
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
909
+ /* @__PURE__ */ jsxRuntime.jsx(
910
+ "input",
911
+ {
912
+ type: "checkbox",
913
+ name,
914
+ id: name,
915
+ defaultChecked,
916
+ disabled,
917
+ "aria-invalid": !!error,
918
+ "aria-describedby": error ? `${name}-error` : void 0,
919
+ className: cx(
920
+ theme.checkbox?.base,
921
+ error && theme.checkbox?.error
922
+ )
923
+ }
924
+ ),
925
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: name, className: theme.checkbox?.label, children: [
926
+ label,
927
+ rules?.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: theme.label?.required, children: "*" })
928
+ ] })
929
+ ] }),
930
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { id: `${name}-error`, className: theme.error, children: error }),
931
+ after && /* @__PURE__ */ jsxRuntime.jsx("p", { className: afterClassName ?? "", children: after })
932
+ ] });
933
+ }
934
+ var CheckboxInput_default = react.memo(CheckboxInput);
935
+ function ToggleInput({
936
+ label,
937
+ name,
938
+ defaultChecked,
939
+ className,
940
+ disabled,
941
+ error,
942
+ rules,
943
+ before,
944
+ beforeClassName,
945
+ after,
946
+ afterClassName
947
+ }) {
948
+ const theme = useFormTheme();
949
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx(theme.formGroup, className), children: [
950
+ before && /* @__PURE__ */ jsxRuntime.jsx("p", { className: beforeClassName ?? "", children: before }),
951
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
952
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: name, className: theme.toggle?.label, children: [
953
+ label,
954
+ rules?.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: theme.label?.required, children: "*" })
955
+ ] }),
956
+ /* @__PURE__ */ jsxRuntime.jsxs(
957
+ "label",
958
+ {
959
+ htmlFor: name,
960
+ className: "relative inline-block w-11 h-6 cursor-pointer",
961
+ children: [
962
+ /* @__PURE__ */ jsxRuntime.jsx(
963
+ "input",
964
+ {
965
+ type: "checkbox",
966
+ name,
967
+ id: name,
968
+ defaultChecked,
969
+ disabled,
970
+ "aria-invalid": !!error,
971
+ "aria-describedby": error ? `${name}-error` : void 0,
972
+ className: "sr-only peer"
973
+ }
974
+ ),
975
+ /* @__PURE__ */ jsxRuntime.jsx(
976
+ "span",
977
+ {
978
+ className: cx(
979
+ theme.toggle?.track,
980
+ !disabled && theme.toggle?.trackActive,
981
+ disabled && "cursor-not-allowed"
982
+ )
983
+ }
984
+ ),
985
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: theme.toggle?.thumb })
986
+ ]
987
+ }
988
+ )
989
+ ] }),
990
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { id: `${name}-error`, className: theme.error, children: error }),
991
+ after && /* @__PURE__ */ jsxRuntime.jsx("p", { className: afterClassName ?? "", children: after })
992
+ ] });
993
+ }
994
+ var ToggleInput_default = react.memo(ToggleInput);
995
+ function RadioInput({
996
+ label,
997
+ name,
998
+ options,
999
+ defaultValue,
1000
+ className,
1001
+ disabled,
1002
+ error,
1003
+ rules,
1004
+ before,
1005
+ beforeClassName,
1006
+ after,
1007
+ afterClassName
1008
+ }) {
1009
+ const theme = useFormTheme();
1010
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx(theme.formGroup, className), children: [
1011
+ before && /* @__PURE__ */ jsxRuntime.jsx("p", { className: beforeClassName ?? "", children: before }),
1012
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { id: `${name}-group`, className: theme.label?.base, children: [
1013
+ label,
1014
+ rules?.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: theme.label?.required, children: "*" })
1015
+ ] }),
1016
+ /* @__PURE__ */ jsxRuntime.jsx(
1017
+ "div",
1018
+ {
1019
+ className: theme.radio?.group,
1020
+ role: "radiogroup",
1021
+ "aria-labelledby": `${name}-group`,
1022
+ children: options?.map((option) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center mb-2", children: [
1023
+ /* @__PURE__ */ jsxRuntime.jsx(
1024
+ "input",
1025
+ {
1026
+ type: "radio",
1027
+ name,
1028
+ id: `${name}-${option.value}`,
1029
+ value: option.value,
1030
+ defaultChecked: defaultValue === option.value,
1031
+ disabled,
1032
+ "aria-invalid": !!error,
1033
+ className: theme.radio?.base
1034
+ }
1035
+ ),
1036
+ /* @__PURE__ */ jsxRuntime.jsx(
1037
+ "label",
1038
+ {
1039
+ htmlFor: `${name}-${option.value}`,
1040
+ className: theme.radio?.label,
1041
+ children: option.label
1042
+ }
1043
+ )
1044
+ ] }, option.value))
1045
+ }
1046
+ ),
1047
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { id: `${name}-error`, className: theme.error, children: error }),
1048
+ after && /* @__PURE__ */ jsxRuntime.jsx("p", { className: afterClassName ?? "", children: after })
1049
+ ] });
1050
+ }
1051
+ var RadioInput_default = react.memo(RadioInput);
1052
+ function FileInput({
1053
+ label,
1054
+ name,
1055
+ className,
1056
+ disabled,
1057
+ error,
1058
+ rules,
1059
+ before,
1060
+ beforeClassName,
1061
+ after,
1062
+ afterClassName,
1063
+ defaultValue,
1064
+ metaData,
1065
+ uploadDir,
1066
+ baseUrl
1067
+ }) {
1068
+ const [fileName, setFileName] = react.useState(null);
1069
+ const [isDragging, setIsDragging] = react.useState(false);
1070
+ const inputRef = react.useRef(null);
1071
+ const theme = useFormTheme();
1072
+ const labels = useFormLabels();
1073
+ const handleChange = (e) => {
1074
+ if (e.target.files && e.target.files.length > 0) {
1075
+ setFileName(e.target.files[0].name);
1076
+ } else {
1077
+ setFileName(null);
1078
+ }
1079
+ };
1080
+ const handleDragEnter = (e) => {
1081
+ e.preventDefault();
1082
+ e.stopPropagation();
1083
+ if (!disabled) setIsDragging(true);
1084
+ };
1085
+ const handleDragLeave = (e) => {
1086
+ e.preventDefault();
1087
+ e.stopPropagation();
1088
+ setIsDragging(false);
1089
+ };
1090
+ const handleDragOver = (e) => {
1091
+ e.preventDefault();
1092
+ e.stopPropagation();
1093
+ if (!disabled) setIsDragging(true);
1094
+ };
1095
+ const handleDrop = (e) => {
1096
+ e.preventDefault();
1097
+ e.stopPropagation();
1098
+ setIsDragging(false);
1099
+ if (disabled) return;
1100
+ if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
1101
+ if (inputRef.current) {
1102
+ inputRef.current.files = e.dataTransfer.files;
1103
+ setFileName(e.dataTransfer.files[0].name);
1104
+ const event = new Event("change", { bubbles: true });
1105
+ inputRef.current.dispatchEvent(event);
1106
+ }
1107
+ }
1108
+ };
1109
+ const getFileUrl = () => {
1110
+ if (!defaultValue) return null;
1111
+ if (baseUrl && uploadDir) {
1112
+ return `${baseUrl}/${uploadDir}/${defaultValue}`;
1113
+ }
1114
+ if (baseUrl) {
1115
+ return `${baseUrl}/${defaultValue}`;
1116
+ }
1117
+ return null;
1118
+ };
1119
+ const fileUrl = getFileUrl();
1120
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx(theme.formGroup, className), children: [
1121
+ before && /* @__PURE__ */ jsxRuntime.jsx("p", { className: beforeClassName ?? "", children: before }),
1122
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx(theme.label?.base, "mb-1"), children: [
1123
+ label,
1124
+ rules?.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: theme.label?.required, children: "*" })
1125
+ ] }),
1126
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1127
+ /* @__PURE__ */ jsxRuntime.jsx(
1128
+ "input",
1129
+ {
1130
+ ref: inputRef,
1131
+ type: "file",
1132
+ name,
1133
+ id: name,
1134
+ disabled,
1135
+ onChange: handleChange,
1136
+ "aria-invalid": !!error,
1137
+ "aria-describedby": error ? `${name}-error` : void 0,
1138
+ className: "sr-only",
1139
+ accept: rules?.mimeTypes ? rules.mimeTypes.map((type) => mimeTypes[type]).join(",") : "*"
1140
+ }
1141
+ ),
1142
+ /* @__PURE__ */ jsxRuntime.jsx(
1143
+ "label",
1144
+ {
1145
+ htmlFor: name,
1146
+ onDragEnter: handleDragEnter,
1147
+ onDragLeave: handleDragLeave,
1148
+ onDragOver: handleDragOver,
1149
+ onDrop: handleDrop,
1150
+ className: cx(
1151
+ theme.file?.dropzone,
1152
+ disabled && "cursor-not-allowed",
1153
+ isDragging && theme.file?.dropzoneActive,
1154
+ error && theme.file?.dropzoneError
1155
+ ),
1156
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center", children: [
1157
+ /* @__PURE__ */ jsxRuntime.jsx(
1158
+ "svg",
1159
+ {
1160
+ xmlns: "http://www.w3.org/2000/svg",
1161
+ className: theme.file?.icon,
1162
+ fill: "none",
1163
+ viewBox: "0 0 24 24",
1164
+ stroke: "currentColor",
1165
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1166
+ "path",
1167
+ {
1168
+ strokeLinecap: "round",
1169
+ strokeLinejoin: "round",
1170
+ strokeWidth: 2,
1171
+ d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
1172
+ }
1173
+ )
1174
+ }
1175
+ ),
1176
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: theme.file?.text, children: fileName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-primary", children: fileName }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1177
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: labels.fileUpload?.clickToUpload }),
1178
+ " ",
1179
+ labels.fileUpload?.dragAndDrop
1180
+ ] }) }),
1181
+ rules?.mimeTypes && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: theme.file?.hint, children: [
1182
+ labels.fileUpload?.allowedTypes,
1183
+ " ",
1184
+ Object.values(rules.mimeTypes).join(", ")
1185
+ ] }),
1186
+ rules?.maxFileSize && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: theme.file?.hint, children: [
1187
+ labels.fileUpload?.maxSize,
1188
+ " ",
1189
+ Math.round(
1190
+ rules.maxFileSize / 1024 / 1024 * 10
1191
+ ) / 10,
1192
+ " ",
1193
+ "MB"
1194
+ ] })
1195
+ ] })
1196
+ }
1197
+ ),
1198
+ fileUrl && defaultValue && isImage(defaultValue.toString()) && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1199
+ /* @__PURE__ */ jsxRuntime.jsx(
1200
+ "img",
1201
+ {
1202
+ src: fileUrl,
1203
+ alt: "",
1204
+ className: "mt-2 max-h-40 object-contain rounded-md border border-gray-300 dark:border-gray-600"
1205
+ }
1206
+ ),
1207
+ /* @__PURE__ */ jsxRuntime.jsxs(
1208
+ "a",
1209
+ {
1210
+ href: fileUrl,
1211
+ target: "_blank",
1212
+ rel: "noopener noreferrer",
1213
+ className: "mt-2 inline-flex items-center text-xs text-primary hover:underline dark:text-gray-50",
1214
+ children: [
1215
+ "View Current ",
1216
+ label,
1217
+ /* @__PURE__ */ jsxRuntime.jsx(
1218
+ "svg",
1219
+ {
1220
+ xmlns: "http://www.w3.org/2000/svg",
1221
+ className: "ml-1 h-4 w-4",
1222
+ fill: "none",
1223
+ viewBox: "0 0 24 24",
1224
+ stroke: "currentColor",
1225
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1226
+ "path",
1227
+ {
1228
+ strokeLinecap: "round",
1229
+ strokeLinejoin: "round",
1230
+ strokeWidth: 2,
1231
+ d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
1232
+ }
1233
+ )
1234
+ }
1235
+ )
1236
+ ]
1237
+ }
1238
+ )
1239
+ ] })
1240
+ ] }),
1241
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { id: `${name}-error`, className: theme.error, children: error }),
1242
+ after && /* @__PURE__ */ jsxRuntime.jsx("p", { className: afterClassName ?? "", children: after })
1243
+ ] });
1244
+ }
1245
+ var FileInput_default = react.memo(FileInput);
1246
+ function HiddenInput({
1247
+ name,
1248
+ defaultValue,
1249
+ className,
1250
+ disabled
1251
+ }) {
1252
+ return /* @__PURE__ */ jsxRuntime.jsx(
1253
+ "input",
1254
+ {
1255
+ type: "hidden",
1256
+ name,
1257
+ defaultValue: defaultValue?.toString(),
1258
+ disabled,
1259
+ className
1260
+ }
1261
+ );
1262
+ }
1263
+ function SubmitInput({
1264
+ label,
1265
+ name,
1266
+ className,
1267
+ disabled,
1268
+ loading,
1269
+ defaultValue,
1270
+ hideSpinner
1271
+ }) {
1272
+ const theme = useFormTheme();
1273
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1274
+ "button",
1275
+ {
1276
+ type: "submit",
1277
+ name,
1278
+ disabled: disabled || loading,
1279
+ value: defaultValue?.toString() ?? "",
1280
+ className: cx(
1281
+ theme.submit?.base,
1282
+ loading && theme.submit?.loading,
1283
+ className
1284
+ ),
1285
+ children: [
1286
+ loading && hideSpinner !== true && /* @__PURE__ */ jsxRuntime.jsxs(
1287
+ "svg",
1288
+ {
1289
+ className: theme.submit?.spinner,
1290
+ xmlns: "http://www.w3.org/2000/svg",
1291
+ fill: "none",
1292
+ viewBox: "0 0 24 24",
1293
+ children: [
1294
+ /* @__PURE__ */ jsxRuntime.jsx(
1295
+ "circle",
1296
+ {
1297
+ className: "opacity-25",
1298
+ cx: "12",
1299
+ cy: "12",
1300
+ r: "10",
1301
+ stroke: "currentColor",
1302
+ strokeWidth: "4"
1303
+ }
1304
+ ),
1305
+ /* @__PURE__ */ jsxRuntime.jsx(
1306
+ "path",
1307
+ {
1308
+ className: "opacity-75",
1309
+ fill: "currentColor",
1310
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
1311
+ }
1312
+ )
1313
+ ]
1314
+ }
1315
+ ),
1316
+ label
1317
+ ]
1318
+ }
1319
+ );
1320
+ }
1321
+ function NoneInput({ label, value, className }) {
1322
+ const theme = useFormTheme();
1323
+ const isJsonString = (str) => {
1324
+ try {
1325
+ JSON.parse(str);
1326
+ return true;
1327
+ } catch {
1328
+ return false;
1329
+ }
1330
+ };
1331
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx(theme.formGroup, className), children: [
1332
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: theme.label?.base, children: label }),
1333
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: theme.readonly, children: isJsonString(value) ? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "list-disc list-inside space-y-1", children: Object.entries(JSON.parse(value)).map(([key, val]) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "text-sm", children: [
1334
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
1335
+ key,
1336
+ ":"
1337
+ ] }),
1338
+ " ",
1339
+ String(val)
1340
+ ] }, key)) }) : value })
1341
+ ] });
1342
+ }
1343
+ var NoneInput_default = react.memo(NoneInput);
1344
+ function Form({
1345
+ config,
1346
+ className,
1347
+ errors,
1348
+ isSubmitting = false,
1349
+ formElement: FormElement,
1350
+ formProps = {},
1351
+ fileBaseUrl
1352
+ }) {
1353
+ const theme = useFormTheme();
1354
+ const {
1355
+ method = "post",
1356
+ encType = config.encType || "application/x-www-form-urlencoded",
1357
+ action = "",
1358
+ fields
1359
+ } = config;
1360
+ const state = {
1361
+ errors,
1362
+ isSubmitting
1363
+ };
1364
+ const contextValue = {
1365
+ state,
1366
+ config
1367
+ };
1368
+ const FormTag = FormElement || "form";
1369
+ const formContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1370
+ errors && "__server" in errors && errors.__server ? /* @__PURE__ */ jsxRuntime.jsx(Alert_default, { type: "error", message: errors.__server }) : null,
1371
+ /* @__PURE__ */ jsxRuntime.jsx(
1372
+ "fieldset",
1373
+ {
1374
+ className: theme.fieldset,
1375
+ disabled: isSubmitting,
1376
+ children: Object.entries(fields).map(([key, field]) => {
1377
+ const fieldError = errors?.[key];
1378
+ switch (field.type) {
1379
+ case "text":
1380
+ case "email":
1381
+ case "password":
1382
+ case "number":
1383
+ return /* @__PURE__ */ jsxRuntime.jsx(
1384
+ TextInput_default,
1385
+ {
1386
+ label: field.label,
1387
+ placeholder: field.placeholder,
1388
+ name: key,
1389
+ defaultValue: field.defaultValue,
1390
+ className: `${widthClasses[field.width || 12]} ${field.className || ""}`,
1391
+ disabled: field.disabled,
1392
+ error: fieldError,
1393
+ rules: field.rules,
1394
+ type: field.type,
1395
+ before: field.before,
1396
+ beforeClassName: field.beforeClassName,
1397
+ after: field.after,
1398
+ afterClassName: field.afterClassName
1399
+ },
1400
+ key
1401
+ );
1402
+ case "datetime":
1403
+ return /* @__PURE__ */ jsxRuntime.jsx(
1404
+ DateTimeInput_default,
1405
+ {
1406
+ label: field.label,
1407
+ placeholder: field.placeholder,
1408
+ name: key,
1409
+ defaultValue: field.defaultValue,
1410
+ className: `${widthClasses[field.width || 12]} ${field.className || ""}`,
1411
+ disabled: field.disabled,
1412
+ error: fieldError,
1413
+ rules: field.rules,
1414
+ before: field.before,
1415
+ beforeClassName: field.beforeClassName,
1416
+ after: field.after,
1417
+ afterClassName: field.afterClassName
1418
+ },
1419
+ key
1420
+ );
1421
+ case "select":
1422
+ return /* @__PURE__ */ jsxRuntime.jsx(
1423
+ SelectInput_default,
1424
+ {
1425
+ label: field.label,
1426
+ name: key,
1427
+ options: field.options,
1428
+ defaultValue: field.defaultValue,
1429
+ className: `${widthClasses[field.width || 12]} ${field.className || ""}`,
1430
+ disabled: field.disabled,
1431
+ error: fieldError,
1432
+ rules: field.rules,
1433
+ before: field.before,
1434
+ beforeClassName: field.beforeClassName,
1435
+ after: field.after,
1436
+ afterClassName: field.afterClassName
1437
+ },
1438
+ key
1439
+ );
1440
+ case "textarea":
1441
+ return /* @__PURE__ */ jsxRuntime.jsx(
1442
+ TextAreaInput_default,
1443
+ {
1444
+ label: field.label,
1445
+ placeholder: field.placeholder,
1446
+ name: key,
1447
+ defaultValue: field.defaultValue,
1448
+ className: `${widthClasses[field.width || 12]} ${field.className || ""}`,
1449
+ disabled: field.disabled,
1450
+ error: fieldError,
1451
+ rules: field.rules,
1452
+ before: field.before,
1453
+ beforeClassName: field.beforeClassName,
1454
+ after: field.after,
1455
+ afterClassName: field.afterClassName
1456
+ },
1457
+ key
1458
+ );
1459
+ case "checkbox":
1460
+ return /* @__PURE__ */ jsxRuntime.jsx(
1461
+ CheckboxInput_default,
1462
+ {
1463
+ label: field.label,
1464
+ name: key,
1465
+ defaultChecked: field.defaultChecked,
1466
+ className: `${widthClasses[field.width || 12]} ${field.className || ""}`,
1467
+ disabled: field.disabled,
1468
+ error: fieldError,
1469
+ rules: field.rules,
1470
+ before: field.before,
1471
+ beforeClassName: field.beforeClassName,
1472
+ after: field.after,
1473
+ afterClassName: field.afterClassName
1474
+ },
1475
+ key
1476
+ );
1477
+ case "toggle":
1478
+ return /* @__PURE__ */ jsxRuntime.jsx(
1479
+ ToggleInput_default,
1480
+ {
1481
+ label: field.label,
1482
+ name: key,
1483
+ defaultChecked: field.defaultChecked,
1484
+ className: `${widthClasses[field.width || 12]} ${field.className || ""}`,
1485
+ disabled: field.disabled,
1486
+ error: fieldError,
1487
+ rules: field.rules,
1488
+ before: field.before,
1489
+ beforeClassName: field.beforeClassName,
1490
+ after: field.after,
1491
+ afterClassName: field.afterClassName
1492
+ },
1493
+ key
1494
+ );
1495
+ case "radio":
1496
+ return /* @__PURE__ */ jsxRuntime.jsx(
1497
+ RadioInput_default,
1498
+ {
1499
+ label: field.label,
1500
+ name: key,
1501
+ options: field.options,
1502
+ defaultValue: field.defaultValue,
1503
+ className: `${widthClasses[field.width || 12]} ${field.className || ""}`,
1504
+ disabled: field.disabled,
1505
+ error: fieldError,
1506
+ rules: field.rules,
1507
+ before: field.before,
1508
+ beforeClassName: field.beforeClassName,
1509
+ after: field.after,
1510
+ afterClassName: field.afterClassName
1511
+ },
1512
+ key
1513
+ );
1514
+ case "file":
1515
+ return /* @__PURE__ */ jsxRuntime.jsx(
1516
+ FileInput_default,
1517
+ {
1518
+ label: field.label,
1519
+ name: key,
1520
+ className: `${widthClasses[field.width || 12]} ${field.className || ""}`,
1521
+ disabled: field.disabled,
1522
+ defaultValue: field.defaultValue,
1523
+ error: fieldError,
1524
+ rules: field.rules,
1525
+ before: field.before,
1526
+ beforeClassName: field.beforeClassName,
1527
+ after: field.after,
1528
+ afterClassName: field.afterClassName,
1529
+ metaData: field.metaData,
1530
+ uploadDir: field.uploadDir,
1531
+ baseUrl: fileBaseUrl
1532
+ },
1533
+ key
1534
+ );
1535
+ case "hidden":
1536
+ return /* @__PURE__ */ jsxRuntime.jsx(
1537
+ HiddenInput,
1538
+ {
1539
+ name: key,
1540
+ defaultValue: field.defaultValue,
1541
+ disabled: field.disabled
1542
+ },
1543
+ key
1544
+ );
1545
+ case "submit":
1546
+ return /* @__PURE__ */ jsxRuntime.jsx(
1547
+ SubmitInput,
1548
+ {
1549
+ label: field.label,
1550
+ name: key,
1551
+ className: `${widthClasses[field.width || 12]} ${field.className || ""}`,
1552
+ disabled: field.disabled,
1553
+ rules: field.rules,
1554
+ loading: isSubmitting,
1555
+ defaultValue: field.defaultValue,
1556
+ hideSpinner: field.hideSpinner
1557
+ },
1558
+ key
1559
+ );
1560
+ case "none":
1561
+ return /* @__PURE__ */ jsxRuntime.jsx(
1562
+ NoneInput_default,
1563
+ {
1564
+ className: `${widthClasses[field.width || 12]} ${field.className || ""}`,
1565
+ value: field.defaultValue?.toString() ?? "",
1566
+ label: field.label
1567
+ },
1568
+ key
1569
+ );
1570
+ default:
1571
+ return null;
1572
+ }
1573
+ })
1574
+ }
1575
+ )
1576
+ ] });
1577
+ return /* @__PURE__ */ jsxRuntime.jsx(FormContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
1578
+ FormTag,
1579
+ {
1580
+ method,
1581
+ encType,
1582
+ action,
1583
+ className: cx(theme.form, className),
1584
+ noValidate: true,
1585
+ ...formProps,
1586
+ children: formContent
1587
+ }
1588
+ ) });
1589
+ }
1590
+
1591
+ exports.Alert = Alert_default;
1592
+ exports.CheckboxInput = CheckboxInput_default;
1593
+ exports.DateTimeInput = DateTimeInput_default;
1594
+ exports.FileInput = FileInput_default;
1595
+ exports.Form = Form;
1596
+ exports.FormContext = FormContext;
1597
+ exports.FormThemeProvider = FormThemeProvider;
1598
+ exports.HiddenInput = HiddenInput;
1599
+ exports.NoneInput = NoneInput_default;
1600
+ exports.RadioInput = RadioInput_default;
1601
+ exports.SelectInput = SelectInput_default;
1602
+ exports.SubmitInput = SubmitInput;
1603
+ exports.TextAreaInput = TextAreaInput_default;
1604
+ exports.TextInput = TextInput_default;
1605
+ exports.ToggleInput = ToggleInput_default;
1606
+ exports.bytesToHumanReadable = bytesToHumanReadable;
1607
+ exports.createTheme = createTheme;
1608
+ exports.cx = cx;
1609
+ exports.defaultLabels = defaultLabels;
1610
+ exports.defaultTheme = defaultTheme;
1611
+ exports.isImage = isImage;
1612
+ exports.lightOnlyTheme = lightOnlyTheme;
1613
+ exports.mimeTypes = mimeTypes;
1614
+ exports.useFieldError = useFieldError;
1615
+ exports.useFormConfig = useFormConfig;
1616
+ exports.useFormContext = useFormContext;
1617
+ exports.useFormLabels = useFormLabels;
1618
+ exports.useFormState = useFormState;
1619
+ exports.useFormTheme = useFormTheme;
1620
+ exports.useFormThemeConfig = useFormThemeConfig;
1621
+ exports.widthClasses = widthClasses;
1622
+ //# sourceMappingURL=index.cjs.map
1623
+ //# sourceMappingURL=index.cjs.map