@jameskabz/nextcraft-ui 0.6.2 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/craft/components.cjs +64 -1779
  2. package/dist/craft/components.cjs.map +1 -1
  3. package/dist/craft/components.js +31 -42
  4. package/dist/craft/components.js.map +1 -1
  5. package/dist/craft/forms.cjs +6 -1347
  6. package/dist/craft/forms.cjs.map +1 -1
  7. package/dist/craft/forms.js +3 -8
  8. package/dist/craft/forms.js.map +1 -1
  9. package/dist/craft/layout.cjs +20 -374
  10. package/dist/craft/layout.cjs.map +1 -1
  11. package/dist/craft/layout.js +10 -14
  12. package/dist/craft/layout.js.map +1 -1
  13. package/dist/craft/table.cjs +8 -632
  14. package/dist/craft/table.cjs.map +1 -1
  15. package/dist/craft/table.js +4 -8
  16. package/dist/craft/table.js.map +1 -1
  17. package/dist/craft/theme.cjs +5 -137
  18. package/dist/craft/theme.cjs.map +1 -1
  19. package/dist/craft/theme.js +2 -6
  20. package/dist/craft/theme.js.map +1 -1
  21. package/dist/index.cjs +103 -3426
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.js +50 -70
  24. package/dist/index.js.map +1 -1
  25. package/dist/styles.css +0 -31
  26. package/package.json +8 -4
  27. package/dist/chunk-6F7FN2ZF.js +0 -671
  28. package/dist/chunk-6F7FN2ZF.js.map +0 -1
  29. package/dist/chunk-7Q4Z47HT.js +0 -657
  30. package/dist/chunk-7Q4Z47HT.js.map +0 -1
  31. package/dist/chunk-7SKDTIEK.js +0 -49
  32. package/dist/chunk-7SKDTIEK.js.map +0 -1
  33. package/dist/chunk-FEFH5O5K.js +0 -49
  34. package/dist/chunk-FEFH5O5K.js.map +0 -1
  35. package/dist/chunk-M2EKVXB6.js +0 -127
  36. package/dist/chunk-M2EKVXB6.js.map +0 -1
  37. package/dist/chunk-SBLIF6UU.js +0 -1029
  38. package/dist/chunk-SBLIF6UU.js.map +0 -1
  39. package/dist/chunk-VQ6T3HIX.js +0 -9
  40. package/dist/chunk-VQ6T3HIX.js.map +0 -1
  41. package/dist/chunk-YVZL4GET.js +0 -328
  42. package/dist/chunk-YVZL4GET.js.map +0 -1
  43. package/dist/chunk-ZRV4Y374.js +0 -582
  44. package/dist/chunk-ZRV4Y374.js.map +0 -1
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,1356 +15,17 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/craft/forms.ts
31
19
  var forms_exports = {};
32
20
  __export(forms_exports, {
33
- CraftForm: () => CraftForm,
34
- CraftFormBuilder: () => CraftFormBuilder,
35
- CraftFormField: () => CraftFormField
21
+ CraftForm: () => import_craft_form.CraftForm,
22
+ CraftFormBuilder: () => import_craft_form_builder.CraftFormBuilder,
23
+ CraftFormField: () => import_craft_form_field.CraftFormField
36
24
  });
37
25
  module.exports = __toCommonJS(forms_exports);
38
-
39
- // src/components/craft-form.tsx
40
- var React2 = __toESM(require("react"), 1);
41
- var import_react_hook_form2 = require("react-hook-form");
42
-
43
- // src/utils/cn.ts
44
- function cn(...values) {
45
- return values.filter(Boolean).join(" ");
46
- }
47
-
48
- // src/components/craft-modal.tsx
49
- var React = __toESM(require("react"), 1);
50
- var import_react_dom = require("react-dom");
51
- var import_jsx_runtime = require("react/jsx-runtime");
52
- var FOCUSABLE_SELECTORS = [
53
- "a[href]",
54
- "button:not([disabled])",
55
- "textarea:not([disabled])",
56
- "input:not([disabled])",
57
- "select:not([disabled])",
58
- "[tabindex]:not([tabindex='-1'])"
59
- ].join(",");
60
- function useFocusTrap(active) {
61
- const ref = React.useRef(null);
62
- React.useEffect(() => {
63
- if (!active || !ref.current) return;
64
- const root = ref.current;
65
- const getFocusable = () => Array.from(root.querySelectorAll(FOCUSABLE_SELECTORS));
66
- const focusables = getFocusable();
67
- if (focusables.length) {
68
- focusables[0].focus();
69
- } else {
70
- root.focus();
71
- }
72
- const handleKeyDown = (event) => {
73
- if (event.key !== "Tab") return;
74
- const items = getFocusable();
75
- if (!items.length) return;
76
- const first = items[0];
77
- const last = items[items.length - 1];
78
- const activeEl = document.activeElement;
79
- if (event.shiftKey && activeEl === first) {
80
- event.preventDefault();
81
- last.focus();
82
- } else if (!event.shiftKey && activeEl === last) {
83
- event.preventDefault();
84
- first.focus();
85
- }
86
- };
87
- root.addEventListener("keydown", handleKeyDown);
88
- return () => root.removeEventListener("keydown", handleKeyDown);
89
- }, [active]);
90
- return ref;
91
- }
92
- function CraftModal({
93
- open,
94
- defaultOpen = false,
95
- onOpenChange,
96
- tone,
97
- title,
98
- description,
99
- children,
100
- trigger,
101
- footer,
102
- className
103
- }) {
104
- const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);
105
- const isControlled = typeof open === "boolean";
106
- const isOpen = isControlled ? open : uncontrolledOpen;
107
- const setOpen = React.useCallback(
108
- (next) => {
109
- if (!isControlled) {
110
- setUncontrolledOpen(next);
111
- }
112
- onOpenChange == null ? void 0 : onOpenChange(next);
113
- },
114
- [isControlled, onOpenChange]
115
- );
116
- React.useEffect(() => {
117
- if (!isOpen) return;
118
- const handleKey = (event) => {
119
- if (event.key === "Escape") setOpen(false);
120
- };
121
- document.addEventListener("keydown", handleKey);
122
- return () => document.removeEventListener("keydown", handleKey);
123
- }, [isOpen, setOpen]);
124
- const ref = useFocusTrap(isOpen);
125
- const content = isOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "fixed inset-0 z-50 flex items-center justify-center px-4 py-8", children: [
126
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
127
- "div",
128
- {
129
- className: "absolute inset-0 backdrop-blur-sm",
130
- onClick: () => setOpen(false)
131
- }
132
- ),
133
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
134
- "div",
135
- {
136
- ref,
137
- tabIndex: -1,
138
- className: cn(
139
- "relative z-10 w-full max-w-7xl rounded-3xl border border-[rgb(var(--nc-border)/0.45)] p-6 text-[rgb(var(--nc-fg))] shadow-[0_20px_60px_rgba(0,0,0,0.45)] backdrop-blur-2xl",
140
- "max-h-[calc(100vh-1rem)] overflow-y-auto",
141
- className
142
- ),
143
- "data-nc-theme": tone,
144
- children: [
145
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-start justify-between gap-4", children: [
146
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1", children: [
147
- title && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "text-2xl font-semibold", children: title }),
148
- description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-[rgb(var(--nc-fg-muted))]", children: description })
149
- ] }),
150
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
151
- "button",
152
- {
153
- className: "rounded-full border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] p-2 text-[rgb(var(--nc-fg-soft))] transition hover:text-[rgb(var(--nc-fg))]",
154
- onClick: () => setOpen(false),
155
- "aria-label": "Close",
156
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 20 20", className: "h-4 w-4", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" }) })
157
- }
158
- )
159
- ] }),
160
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mt-5 space-y-4", children }),
161
- footer && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mt-6", children: footer })
162
- ]
163
- }
164
- )
165
- ] }) : null;
166
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
167
- trigger && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
168
- "span",
169
- {
170
- onClick: () => setOpen(true),
171
- onKeyDown: (event) => {
172
- if (event.key === "Enter" || event.key === " ") setOpen(true);
173
- },
174
- role: "button",
175
- tabIndex: 0,
176
- className: "inline-flex",
177
- children: trigger
178
- }
179
- ),
180
- typeof document !== "undefined" && content ? (0, import_react_dom.createPortal)(content, document.body) : content
181
- ] });
182
- }
183
-
184
- // src/components/craft-button.tsx
185
- var import_jsx_runtime2 = require("react/jsx-runtime");
186
- var sizeClasses = {
187
- sm: "h-9 px-4 text-xs",
188
- md: "h-11 px-6 text-sm",
189
- lg: "h-13 px-8 text-base"
190
- };
191
- var variantClasses = {
192
- solid: "bg-gradient-to-br from-[rgb(var(--nc-accent-1))] via-[rgb(var(--nc-accent-2))] to-[rgb(var(--nc-accent-3))] text-white shadow-[0_12px_30px_rgb(var(--nc-accent-1)/0.45)] hover:shadow-[0_16px_36px_rgb(var(--nc-accent-1)/0.6)] hover:scale-[1.02] active:scale-[0.98]",
193
- ghost: "bg-[color:rgb(var(--nc-surface)/0.12)] text-[rgb(var(--nc-fg))] hover:bg-[color:rgb(var(--nc-surface)/0.18)] backdrop-blur-sm border border-[rgb(var(--nc-border)/0.35)] hover:border-[color:rgb(var(--nc-border)/0.5)]",
194
- outline: "bg-transparent text-[color:rgb(var(--nc-accent-1))] border-2 border-[color:rgb(var(--nc-accent-1)/0.5)] hover:border-[color:rgb(var(--nc-accent-1))] hover:bg-[color:rgb(var(--nc-accent-1)/0.1)]",
195
- gradient: "bg-gradient-to-r from-[rgb(var(--nc-accent-1))] via-[rgb(var(--nc-accent-2))] to-[rgb(var(--nc-accent-3))] text-white shadow-[0_12px_30px_rgb(var(--nc-accent-2)/0.45)] hover:shadow-[0_16px_36px_rgb(var(--nc-accent-2)/0.6)] hover:scale-[1.02] active:scale-[0.98]"
196
- };
197
- function CraftButton({
198
- className,
199
- variant = "solid",
200
- size = "md",
201
- glow = true,
202
- tone,
203
- disabled,
204
- ...props
205
- }) {
206
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
207
- "button",
208
- {
209
- className: cn(
210
- "relative inline-flex items-center justify-center gap-2 rounded-xl font-semibold tracking-wide transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[rgb(var(--nc-accent-1)/0.6)] focus-visible:ring-offset-2 focus-visible:ring-offset-slate-900 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100",
211
- sizeClasses[size],
212
- variantClasses[variant],
213
- glow && (variant === "solid" || variant === "gradient") ? "before:absolute before:-inset-1 before:rounded-xl before:bg-linear-to-r before:from-[rgb(var(--nc-accent-1)/0.2)] before:via-[rgb(var(--nc-accent-2)/0.2)] before:to-[rgb(var(--nc-accent-3)/0.2)] before:blur-xl before:-z-10 before:opacity-0 hover:before:opacity-100 before:transition-opacity" : "",
214
- className
215
- ),
216
- "data-nc-theme": tone,
217
- disabled,
218
- ...props
219
- }
220
- );
221
- }
222
-
223
- // src/components/craft-submit-button.tsx
224
- var import_react_hook_form = require("react-hook-form");
225
- var import_jsx_runtime3 = require("react/jsx-runtime");
226
- function CraftSubmitButton({
227
- className,
228
- tone,
229
- loading,
230
- loadingLabel = "Submitting...",
231
- disableWhenInvalid = true,
232
- disabled,
233
- children,
234
- ...props
235
- }) {
236
- var _a, _b, _c, _d;
237
- const form = (0, import_react_hook_form.useFormContext)();
238
- const isSubmitting = (_b = loading != null ? loading : (_a = form == null ? void 0 : form.formState) == null ? void 0 : _a.isSubmitting) != null ? _b : false;
239
- const isValid = (_d = (_c = form == null ? void 0 : form.formState) == null ? void 0 : _c.isValid) != null ? _d : true;
240
- const isDisabled = disabled || isSubmitting || disableWhenInvalid && !isValid;
241
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
242
- "button",
243
- {
244
- type: "submit",
245
- className: cn(
246
- "relative inline-flex items-center justify-center gap-2 rounded-xl px-6 py-2 text-sm font-semibold",
247
- "bg-linear-to-br from-[rgb(var(--nc-accent-1))] via-[rgb(var(--nc-accent-2))] to-[rgb(var(--nc-accent-3))]",
248
- "text-white shadow-[0_12px_30px_rgb(var(--nc-accent-1)/0.35)]",
249
- "transition-all duration-200",
250
- "hover:shadow-[0_16px_36px_rgb(var(--nc-accent-1)/0.5)] hover:scale-[1.02] active:scale-[0.98]",
251
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[rgb(var(--nc-accent-1)/0.6)]",
252
- "disabled:opacity-60 disabled:cursor-not-allowed disabled:hover:scale-100",
253
- className
254
- ),
255
- "data-nc-theme": tone,
256
- disabled: isDisabled,
257
- ...props,
258
- children: [
259
- isSubmitting && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "inline-flex h-4 w-4 animate-spin rounded-full border-2 border-white/60 border-t-white" }),
260
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: isSubmitting ? loadingLabel : children })
261
- ]
262
- }
263
- );
264
- }
265
-
266
- // src/components/craft-form.tsx
267
- var import_jsx_runtime4 = require("react/jsx-runtime");
268
- function CraftForm({
269
- form,
270
- onSubmit,
271
- open,
272
- defaultOpen = false,
273
- onOpenChange,
274
- trigger,
275
- title,
276
- description,
277
- submitLabel = "Save",
278
- cancelLabel = "Cancel",
279
- tone,
280
- className,
281
- children,
282
- footer,
283
- disableSubmitWhenInvalid = true,
284
- closeOnSubmit = true,
285
- formClassName
286
- }) {
287
- const [uncontrolledOpen, setUncontrolledOpen] = React2.useState(defaultOpen);
288
- const isControlled = typeof open === "boolean";
289
- const isOpen = isControlled ? open : uncontrolledOpen;
290
- const setOpen = React2.useCallback(
291
- (next) => {
292
- if (!isControlled) setUncontrolledOpen(next);
293
- onOpenChange == null ? void 0 : onOpenChange(next);
294
- },
295
- [isControlled, onOpenChange]
296
- );
297
- const formId = React2.useId();
298
- const handleSubmit = form.handleSubmit(async (values) => {
299
- await onSubmit(values);
300
- if (closeOnSubmit) setOpen(false);
301
- });
302
- const footerContent = footer != null ? footer : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-wrap items-center justify-end gap-3", children: [
303
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CraftButton, { type: "button", variant: "ghost", onClick: () => setOpen(false), children: cancelLabel }),
304
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
305
- CraftSubmitButton,
306
- {
307
- form: formId,
308
- disableWhenInvalid: disableSubmitWhenInvalid,
309
- children: submitLabel
310
- }
311
- )
312
- ] });
313
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_hook_form2.FormProvider, { ...form, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
314
- CraftModal,
315
- {
316
- open: isOpen,
317
- onOpenChange: setOpen,
318
- trigger,
319
- title,
320
- description,
321
- tone,
322
- className,
323
- footer: footerContent,
324
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
325
- "form",
326
- {
327
- id: formId,
328
- onSubmit: handleSubmit,
329
- className: cn("space-y-5", formClassName),
330
- children
331
- }
332
- )
333
- }
334
- ) });
335
- }
336
-
337
- // src/components/craft-form-builder.tsx
338
- var React11 = __toESM(require("react"), 1);
339
- var import_react_hook_form4 = require("react-hook-form");
340
-
341
- // src/components/craft-form-field.tsx
342
- var import_react_hook_form3 = require("react-hook-form");
343
-
344
- // src/components/craft-input.tsx
345
- var React3 = __toESM(require("react"), 1);
346
- var import_jsx_runtime5 = require("react/jsx-runtime");
347
- var inputSizeClasses = {
348
- sm: "h-10 px-4 text-sm",
349
- md: "h-12 px-5 text-base",
350
- lg: "h-14 px-6 text-lg"
351
- };
352
- var CraftInput = React3.forwardRef(
353
- ({ className, tone, inputSize = "md", glow = true, icon, ...props }, ref) => {
354
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative w-full", "data-nc-theme": tone, children: [
355
- icon && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "absolute left-4 top-1/2 -translate-y-1/2 text-[rgb(var(--nc-fg-soft))]", children: icon }),
356
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
357
- "input",
358
- {
359
- ref,
360
- className: cn(
361
- "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
362
- "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
363
- "focus:outline-none focus:ring-4",
364
- "transition-all duration-300",
365
- "disabled:opacity-50 disabled:cursor-not-allowed",
366
- inputSizeClasses[inputSize],
367
- "border-[rgb(var(--nc-border)/0.35)]",
368
- "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
369
- "placeholder:text-[rgb(var(--nc-fg-soft))]",
370
- glow ? "focus:shadow-[0_0_30px_-5px_var(--glow-color)]" : "",
371
- icon ? "pl-12" : "",
372
- className
373
- ),
374
- style: {
375
- "--glow-color": "rgb(var(--nc-accent-1) / 0.5)"
376
- },
377
- ...props
378
- }
379
- )
380
- ] });
381
- }
382
- );
383
- CraftInput.displayName = "CraftInput";
384
-
385
- // src/components/craft-textarea.tsx
386
- var React4 = __toESM(require("react"), 1);
387
- var import_jsx_runtime6 = require("react/jsx-runtime");
388
- var CraftTextarea = React4.forwardRef(
389
- ({ className, tone, rows = 4, ...props }, ref) => {
390
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "relative w-full", "data-nc-theme": tone, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
391
- "textarea",
392
- {
393
- ref,
394
- rows,
395
- className: cn(
396
- "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
397
- "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
398
- "focus:outline-none focus:ring-4",
399
- "transition-all duration-300",
400
- "disabled:opacity-50 disabled:cursor-not-allowed",
401
- "border-[rgb(var(--nc-border)/0.35)]",
402
- "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
403
- "placeholder:text-[rgb(var(--nc-fg-soft))]",
404
- "px-5 py-3 text-base",
405
- className
406
- ),
407
- style: {
408
- "--glow-color": "rgb(var(--nc-accent-1) / 0.5)"
409
- },
410
- ...props
411
- }
412
- ) });
413
- }
414
- );
415
- CraftTextarea.displayName = "CraftTextarea";
416
-
417
- // src/components/craft-select.tsx
418
- var React5 = __toESM(require("react"), 1);
419
- var import_jsx_runtime7 = require("react/jsx-runtime");
420
- var CraftSelect = React5.forwardRef(
421
- ({ className, tone, children, ...props }, ref) => {
422
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "relative w-full", "data-nc-theme": tone, children: [
423
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
424
- "select",
425
- {
426
- ref,
427
- className: cn(
428
- "w-full appearance-none rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
429
- "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
430
- "focus:outline-none focus:ring-4",
431
- "transition-all duration-300",
432
- "disabled:opacity-50 disabled:cursor-not-allowed",
433
- "border-[rgb(var(--nc-border)/0.35)]",
434
- "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
435
- "px-5 py-3 pr-10 text-base",
436
- className
437
- ),
438
- ...props,
439
- children
440
- }
441
- ),
442
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
443
- "svg",
444
- {
445
- className: "pointer-events-none absolute right-4 top-1/2 h-4 w-4 -translate-y-1/2 text-[rgb(var(--nc-fg-soft))]",
446
- viewBox: "0 0 20 20",
447
- fill: "currentColor",
448
- "aria-hidden": "true",
449
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
450
- "path",
451
- {
452
- fillRule: "evenodd",
453
- d: "M5.23 7.21a.75.75 0 011.06.02L10 10.94l3.71-3.7a.75.75 0 111.06 1.06l-4.24 4.24a.75.75 0 01-1.06 0L5.21 8.29a.75.75 0 01.02-1.08z",
454
- clipRule: "evenodd"
455
- }
456
- )
457
- }
458
- )
459
- ] });
460
- }
461
- );
462
- CraftSelect.displayName = "CraftSelect";
463
-
464
- // src/components/craft-checkbox.tsx
465
- var React6 = __toESM(require("react"), 1);
466
- var import_jsx_runtime8 = require("react/jsx-runtime");
467
- var CraftCheckbox = React6.forwardRef(
468
- ({ className, tone, label, description, ...props }, ref) => {
469
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
470
- "label",
471
- {
472
- className: cn(
473
- "flex items-start gap-3 text-sm text-[rgb(var(--nc-fg))]",
474
- props.disabled ? "opacity-60" : "cursor-pointer",
475
- className
476
- ),
477
- "data-nc-theme": tone,
478
- children: [
479
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "relative mt-0.5", children: [
480
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
481
- "input",
482
- {
483
- ref,
484
- type: "checkbox",
485
- className: "peer sr-only",
486
- ...props
487
- }
488
- ),
489
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
490
- "span",
491
- {
492
- className: cn(
493
- "flex h-5 w-5 items-center justify-center rounded-md border-2",
494
- "border-[rgb(var(--nc-border)/0.45)] bg-[rgb(var(--nc-surface)/0.08)]",
495
- "transition-all duration-200",
496
- "peer-checked:border-[rgb(var(--nc-accent-1))] peer-checked:bg-[rgb(var(--nc-accent-1)/0.25)]",
497
- "peer-focus-visible:ring-2 peer-focus-visible:ring-[rgb(var(--nc-accent-1)/0.5)]"
498
- ),
499
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
500
- "svg",
501
- {
502
- className: "h-3 w-3 text-[rgb(var(--nc-fg))] opacity-0 transition-opacity peer-checked:opacity-100",
503
- viewBox: "0 0 20 20",
504
- fill: "currentColor",
505
- "aria-hidden": "true",
506
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
507
- "path",
508
- {
509
- fillRule: "evenodd",
510
- d: "M16.704 5.29a1 1 0 010 1.415l-7.2 7.2a1 1 0 01-1.415 0l-3.2-3.2a1 1 0 111.415-1.415l2.492 2.493 6.493-6.493a1 1 0 011.415 0z",
511
- clipRule: "evenodd"
512
- }
513
- )
514
- }
515
- )
516
- }
517
- )
518
- ] }),
519
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "space-y-1", children: [
520
- label && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "block font-medium text-[rgb(var(--nc-fg))]", children: label }),
521
- description && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "block text-xs text-[rgb(var(--nc-fg-muted))]", children: description })
522
- ] })
523
- ]
524
- }
525
- );
526
- }
527
- );
528
- CraftCheckbox.displayName = "CraftCheckbox";
529
-
530
- // src/components/craft-switch.tsx
531
- var React7 = __toESM(require("react"), 1);
532
- var import_jsx_runtime9 = require("react/jsx-runtime");
533
- var CraftSwitch = React7.forwardRef(
534
- ({ className, tone, label, ...props }, ref) => {
535
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
536
- "label",
537
- {
538
- className: cn(
539
- "inline-flex items-center gap-3 text-sm text-[rgb(var(--nc-fg))]",
540
- props.disabled ? "opacity-60" : "cursor-pointer",
541
- className
542
- ),
543
- "data-nc-theme": tone,
544
- children: [
545
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("input", { ref, type: "checkbox", className: "peer sr-only", ...props }),
546
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
547
- "span",
548
- {
549
- className: cn(
550
- "relative h-6 w-11 rounded-full border-2 border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.08)]",
551
- "transition-all duration-200",
552
- "peer-focus-visible:ring-2 peer-focus-visible:ring-[rgb(var(--nc-accent-1)/0.5)]",
553
- "peer-checked:border-[rgb(var(--nc-accent-1)/0.6)] peer-checked:bg-[rgb(var(--nc-accent-1)/0.25)]"
554
- ),
555
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
556
- "span",
557
- {
558
- className: cn(
559
- "absolute left-0.5 top-0.5 h-4 w-4 rounded-full bg-[rgb(var(--nc-surface-muted)/0.9)]",
560
- "transition-all duration-200",
561
- "peer-checked:translate-x-5 peer-checked:bg-[rgb(var(--nc-surface-muted))]"
562
- )
563
- }
564
- )
565
- }
566
- ),
567
- label && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: label })
568
- ]
569
- }
570
- );
571
- }
572
- );
573
- CraftSwitch.displayName = "CraftSwitch";
574
-
575
- // src/components/craft-date-picker.tsx
576
- var React8 = __toESM(require("react"), 1);
577
- var import_jsx_runtime10 = require("react/jsx-runtime");
578
- var WEEK_DAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
579
- function formatDate(date) {
580
- const year = date.getFullYear();
581
- const month = `${date.getMonth() + 1}`.padStart(2, "0");
582
- const day = `${date.getDate()}`.padStart(2, "0");
583
- return `${year}-${month}-${day}`;
584
- }
585
- function parseDate(value) {
586
- if (!value) return null;
587
- const [year, month, day] = value.split("-").map(Number);
588
- if (!year || !month || !day) return null;
589
- return new Date(year, month - 1, day);
590
- }
591
- function isSameDay(a, b) {
592
- return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
593
- }
594
- function isOutsideRange(date, min, max) {
595
- const minDate = parseDate(min);
596
- const maxDate = parseDate(max);
597
- if (minDate && date < minDate) return true;
598
- if (maxDate && date > maxDate) return true;
599
- return false;
600
- }
601
- function CraftDatePicker({
602
- value,
603
- defaultValue,
604
- onChange,
605
- tone,
606
- min,
607
- max,
608
- placeholder = "Select date",
609
- className
610
- }) {
611
- const [open, setOpen] = React8.useState(false);
612
- const [uncontrolledValue, setUncontrolledValue] = React8.useState(defaultValue != null ? defaultValue : "");
613
- const isControlled = value !== void 0;
614
- const selectedValue = isControlled ? value != null ? value : "" : uncontrolledValue;
615
- const selectedDate = parseDate(selectedValue);
616
- const initialMonth = selectedDate != null ? selectedDate : /* @__PURE__ */ new Date();
617
- const [viewDate, setViewDate] = React8.useState(initialMonth);
618
- React8.useEffect(() => {
619
- if (selectedDate) setViewDate(selectedDate);
620
- }, [selectedDate]);
621
- const wrapperRef = React8.useRef(null);
622
- React8.useEffect(() => {
623
- if (!open) return;
624
- const handleClick = (event) => {
625
- var _a;
626
- if (!((_a = wrapperRef.current) == null ? void 0 : _a.contains(event.target))) {
627
- setOpen(false);
628
- }
629
- };
630
- const handleKey = (event) => {
631
- if (event.key === "Escape") setOpen(false);
632
- };
633
- document.addEventListener("mousedown", handleClick);
634
- document.addEventListener("keydown", handleKey);
635
- return () => {
636
- document.removeEventListener("mousedown", handleClick);
637
- document.removeEventListener("keydown", handleKey);
638
- };
639
- }, [open]);
640
- const setValue = React8.useCallback(
641
- (next) => {
642
- if (!isControlled) setUncontrolledValue(next);
643
- onChange == null ? void 0 : onChange(next);
644
- },
645
- [isControlled, onChange]
646
- );
647
- const monthStart = new Date(viewDate.getFullYear(), viewDate.getMonth(), 1);
648
- const monthEnd = new Date(viewDate.getFullYear(), viewDate.getMonth() + 1, 0);
649
- const startDay = monthStart.getDay();
650
- const daysInMonth = monthEnd.getDate();
651
- const cells = Array.from({ length: startDay + daysInMonth }, (_, i) => {
652
- const dayNumber = i - startDay + 1;
653
- if (dayNumber < 1) return null;
654
- return new Date(viewDate.getFullYear(), viewDate.getMonth(), dayNumber);
655
- });
656
- const handleDaySelect = (date) => {
657
- if (isOutsideRange(date, min, max)) return;
658
- const next = formatDate(date);
659
- setValue(next);
660
- setOpen(false);
661
- };
662
- const handleKeyDown = (event) => {
663
- if (!open) return;
664
- if (!selectedDate) return;
665
- const next = new Date(selectedDate);
666
- if (event.key === "ArrowRight") next.setDate(next.getDate() + 1);
667
- if (event.key === "ArrowLeft") next.setDate(next.getDate() - 1);
668
- if (event.key === "ArrowDown") next.setDate(next.getDate() + 7);
669
- if (event.key === "ArrowUp") next.setDate(next.getDate() - 7);
670
- if (event.key === "Enter") {
671
- event.preventDefault();
672
- handleDaySelect(selectedDate);
673
- return;
674
- }
675
- if (next.getTime() !== selectedDate.getTime()) {
676
- event.preventDefault();
677
- if (!isOutsideRange(next, min, max)) {
678
- setValue(formatDate(next));
679
- setViewDate(next);
680
- }
681
- }
682
- };
683
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "relative w-full", "data-nc-theme": tone, ref: wrapperRef, children: [
684
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
685
- "button",
686
- {
687
- type: "button",
688
- onClick: () => setOpen((prev) => !prev),
689
- className: cn(
690
- "flex w-full items-center justify-between rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] px-5 py-3 text-left text-base text-[rgb(var(--nc-fg))] backdrop-blur-xl",
691
- "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
692
- "transition-all duration-300",
693
- "border-[rgb(var(--nc-border)/0.35)]",
694
- "focus:outline-none focus:ring-4 focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
695
- className
696
- ),
697
- children: [
698
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: selectedValue ? "text-[rgb(var(--nc-fg))]" : "text-[rgb(var(--nc-fg-soft))]", children: selectedValue || placeholder }),
699
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "h-4 w-4 text-[rgb(var(--nc-fg-soft))]", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M6 2a1 1 0 011 1v1h6V3a1 1 0 112 0v1h1a2 2 0 012 2v10a2 2 0 01-2 2H4a2 2 0 01-2-2V6a2 2 0 012-2h1V3a1 1 0 011-1zm10 6H4v8h12V8z" }) })
700
- ]
701
- }
702
- ),
703
- open && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
704
- "div",
705
- {
706
- className: cn(
707
- "absolute left-0 top-full z-20 mt-3 w-full rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/1.52)] p-4 text-[rgb(var(--nc-fg))] shadow-[0_20px_60px_rgba(0,0,0,0.55)] backdrop-blur-10xl"
708
- ),
709
- onKeyDown: handleKeyDown,
710
- tabIndex: -1,
711
- children: [
712
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
713
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
714
- "button",
715
- {
716
- type: "button",
717
- className: "rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-1 text-sm text-[rgb(var(--nc-fg))]",
718
- onClick: () => setViewDate(
719
- new Date(viewDate.getFullYear(), viewDate.getMonth() - 1, 1)
720
- ),
721
- children: "Prev"
722
- }
723
- ),
724
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "text-sm font-semibold", children: viewDate.toLocaleString(void 0, { month: "long", year: "numeric" }) }),
725
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
726
- "button",
727
- {
728
- type: "button",
729
- className: "rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-1 text-sm text-[rgb(var(--nc-fg))]",
730
- onClick: () => setViewDate(
731
- new Date(viewDate.getFullYear(), viewDate.getMonth() + 1, 1)
732
- ),
733
- children: "Next"
734
- }
735
- )
736
- ] }),
737
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-4 grid grid-cols-7 gap-2 text-xs text-[rgb(var(--nc-fg-muted))]", children: WEEK_DAYS.map((day) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "text-center", children: day }, day)) }),
738
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-2 grid grid-cols-7 gap-2", children: cells.map((date, index) => {
739
- if (!date) return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", {}, `empty-${index}`);
740
- const disabled = isOutsideRange(date, min, max);
741
- const selected = selectedDate && isSameDay(date, selectedDate);
742
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
743
- "button",
744
- {
745
- type: "button",
746
- onClick: () => handleDaySelect(date),
747
- disabled,
748
- className: cn(
749
- "rounded-lg py-2 text-sm transition-all",
750
- selected ? "bg-[rgb(var(--nc-accent-1)/0.3)] text-[rgb(var(--nc-fg))]" : "text-[rgb(var(--nc-fg-muted))] hover:bg-[rgb(var(--nc-surface)/0.12)]",
751
- disabled && "opacity-40 hover:bg-transparent"
752
- ),
753
- children: date.getDate()
754
- },
755
- date.toISOString()
756
- );
757
- }) })
758
- ]
759
- }
760
- )
761
- ] });
762
- }
763
-
764
- // src/components/craft-number-input.tsx
765
- var React9 = __toESM(require("react"), 1);
766
- var import_jsx_runtime11 = require("react/jsx-runtime");
767
- var CraftNumberInput = React9.forwardRef(({ className, tone, ...props }, ref) => {
768
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "relative w-full", "data-nc-theme": tone, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
769
- "input",
770
- {
771
- ref,
772
- type: "number",
773
- className: cn(
774
- "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
775
- "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
776
- "focus:outline-none focus:ring-4",
777
- "transition-all duration-300",
778
- "disabled:opacity-50 disabled:cursor-not-allowed",
779
- "border-[rgb(var(--nc-border)/0.35)]",
780
- "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
781
- "px-5 py-3 text-base",
782
- className
783
- ),
784
- ...props
785
- }
786
- ) });
787
- });
788
- CraftNumberInput.displayName = "CraftNumberInput";
789
-
790
- // src/components/craft-currency-input.tsx
791
- var React10 = __toESM(require("react"), 1);
792
- var import_jsx_runtime12 = require("react/jsx-runtime");
793
- var CraftCurrencyInput = React10.forwardRef(({ className, tone, currencySymbol = "$", ...props }, ref) => {
794
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "relative w-full", "data-nc-theme": tone, children: [
795
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pointer-events-none absolute left-4 top-1/2 -translate-y-1/2 text-[rgb(var(--nc-fg-soft))]", children: currencySymbol }),
796
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
797
- "input",
798
- {
799
- ref,
800
- type: "text",
801
- inputMode: "decimal",
802
- className: cn(
803
- "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
804
- "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
805
- "focus:outline-none focus:ring-4",
806
- "transition-all duration-300",
807
- "disabled:opacity-50 disabled:cursor-not-allowed",
808
- "border-[rgb(var(--nc-border)/0.35)]",
809
- "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
810
- "placeholder:text-[rgb(var(--nc-fg-soft))]",
811
- "px-5 py-3 pl-9 text-base",
812
- className
813
- ),
814
- ...props
815
- }
816
- )
817
- ] });
818
- });
819
- CraftCurrencyInput.displayName = "CraftCurrencyInput";
820
-
821
- // src/components/craft-form-field.tsx
822
- var import_jsx_runtime13 = require("react/jsx-runtime");
823
- function getFieldError(errors, name) {
824
- if (!errors || typeof errors !== "object") return void 0;
825
- const segments = name.split(".");
826
- let current = errors;
827
- for (const segment of segments) {
828
- if (!current || typeof current !== "object") return void 0;
829
- current = current[segment];
830
- }
831
- return current;
832
- }
833
- var baseInputClass = "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)] focus:outline-none focus:ring-4 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed border-[rgb(var(--nc-border)/0.35)] focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)] px-5 py-3 text-base placeholder:text-[rgb(var(--nc-fg-soft))]";
834
- function CraftFormField({
835
- name,
836
- label,
837
- description,
838
- type = "text",
839
- options = [],
840
- placeholder,
841
- tone,
842
- className,
843
- inputClassName,
844
- labelClassName,
845
- descriptionClassName,
846
- rules,
847
- disabled,
848
- fieldProps
849
- }) {
850
- const { register, control, formState } = (0, import_react_hook_form3.useFormContext)();
851
- const error = getFieldError(formState.errors, name);
852
- const errorMessage = typeof (error == null ? void 0 : error.message) === "string" ? error.message : void 0;
853
- if (type === "hidden") {
854
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "hidden", ...register(name, rules) });
855
- }
856
- const labelNode = label ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
857
- "label",
858
- {
859
- htmlFor: name,
860
- className: cn(
861
- "text-sm font-semibold text-[rgb(var(--nc-fg))]",
862
- labelClassName
863
- ),
864
- children: label
865
- }
866
- ) : null;
867
- const descriptionNode = description ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
868
- "p",
869
- {
870
- className: cn(
871
- "text-xs text-[rgb(var(--nc-fg-muted))]",
872
- descriptionClassName
873
- ),
874
- children: description
875
- }
876
- ) : null;
877
- const errorNode = errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-xs text-[rgb(var(--nc-accent-3))]", children: errorMessage }) : null;
878
- const renderInput = () => {
879
- if (type === "textarea") {
880
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
881
- CraftTextarea,
882
- {
883
- id: name,
884
- placeholder,
885
- tone,
886
- className: inputClassName,
887
- disabled,
888
- ...fieldProps,
889
- ...register(name, rules)
890
- }
891
- );
892
- }
893
- if (type === "select" || type === "multiselect") {
894
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
895
- CraftSelect,
896
- {
897
- id: name,
898
- tone,
899
- className: inputClassName,
900
- multiple: type === "multiselect",
901
- disabled,
902
- ...fieldProps,
903
- ...register(name, rules),
904
- children: [
905
- placeholder && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "", disabled: true, children: placeholder }),
906
- options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
907
- "option",
908
- {
909
- value: option.value,
910
- disabled: option.disabled,
911
- children: option.label
912
- },
913
- option.value
914
- ))
915
- ]
916
- }
917
- );
918
- }
919
- if (type === "checkbox") {
920
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
921
- CraftCheckbox,
922
- {
923
- tone,
924
- label,
925
- description,
926
- disabled,
927
- ...fieldProps,
928
- ...register(name, rules)
929
- }
930
- );
931
- }
932
- if (type === "switch") {
933
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
934
- CraftSwitch,
935
- {
936
- tone,
937
- label,
938
- disabled,
939
- ...fieldProps,
940
- ...register(name, rules)
941
- }
942
- );
943
- }
944
- if (type === "date") {
945
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
946
- import_react_hook_form3.Controller,
947
- {
948
- control,
949
- name,
950
- rules,
951
- render: ({ field }) => {
952
- var _a;
953
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
954
- CraftDatePicker,
955
- {
956
- value: (_a = field.value) != null ? _a : "",
957
- onChange: field.onChange,
958
- tone,
959
- placeholder,
960
- ...fieldProps
961
- }
962
- );
963
- }
964
- }
965
- );
966
- }
967
- if (type === "number") {
968
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
969
- CraftNumberInput,
970
- {
971
- id: name,
972
- tone,
973
- placeholder,
974
- className: inputClassName,
975
- disabled,
976
- ...fieldProps,
977
- ...register(name, rules)
978
- }
979
- );
980
- }
981
- if (type === "currency") {
982
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
983
- CraftCurrencyInput,
984
- {
985
- id: name,
986
- tone,
987
- placeholder,
988
- className: inputClassName,
989
- disabled,
990
- ...fieldProps,
991
- ...register(name, rules)
992
- }
993
- );
994
- }
995
- if (type === "radio") {
996
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "grid gap-3", children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
997
- "label",
998
- {
999
- className: cn(
1000
- "flex items-center gap-3 rounded-2xl border border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.08)] px-4 py-3 text-sm text-[rgb(var(--nc-fg))]",
1001
- "transition-all duration-200",
1002
- "focus-within:ring-2 focus-within:ring-[rgb(var(--nc-accent-1)/0.5)]",
1003
- option.disabled ? "opacity-60" : "cursor-pointer"
1004
- ),
1005
- "data-nc-theme": tone,
1006
- children: [
1007
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1008
- "input",
1009
- {
1010
- type: "radio",
1011
- value: option.value,
1012
- disabled: option.disabled || disabled,
1013
- className: "h-4 w-4 accent-[rgb(var(--nc-accent-1))]",
1014
- ...fieldProps,
1015
- ...register(name, rules)
1016
- }
1017
- ),
1018
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: option.label })
1019
- ]
1020
- },
1021
- option.value
1022
- )) });
1023
- }
1024
- if (type === "range" || type === "slider") {
1025
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1026
- "input",
1027
- {
1028
- id: name,
1029
- type: "range",
1030
- className: cn(
1031
- "w-full accent-[rgb(var(--nc-accent-1))]",
1032
- inputClassName
1033
- ),
1034
- disabled,
1035
- ...fieldProps,
1036
- ...register(name, rules)
1037
- }
1038
- );
1039
- }
1040
- if (type === "file" || type === "multifile") {
1041
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1042
- "input",
1043
- {
1044
- id: name,
1045
- type: "file",
1046
- multiple: type === "multifile",
1047
- className: cn(
1048
- baseInputClass,
1049
- "file:mr-4 file:rounded-xl file:border-0 file:bg-[rgb(var(--nc-surface)/0.35)] file:px-4 file:py-2 file:text-sm file:font-semibold file:text-[rgb(var(--nc-fg))]",
1050
- inputClassName
1051
- ),
1052
- disabled,
1053
- ...fieldProps,
1054
- ...register(name, rules)
1055
- }
1056
- );
1057
- }
1058
- const inputType = type === "search" || type === "password" || type === "email" || type === "tel" || type === "url" || type === "time" || type === "datetime-local" || type === "month" || type === "week" || type === "color" ? type : "text";
1059
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1060
- CraftInput,
1061
- {
1062
- id: name,
1063
- type: inputType,
1064
- placeholder,
1065
- tone,
1066
- className: inputClassName,
1067
- disabled,
1068
- ...fieldProps,
1069
- ...register(name, rules)
1070
- }
1071
- );
1072
- };
1073
- const showLabel = type !== "checkbox" && type !== "switch";
1074
- const showDescriptionAbove = type !== "checkbox" && type !== "switch";
1075
- const showDescriptionBelow = type === "switch";
1076
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: cn("space-y-2", className), "data-nc-theme": tone, children: [
1077
- showLabel ? labelNode : null,
1078
- showDescriptionAbove ? descriptionNode : null,
1079
- renderInput(),
1080
- showDescriptionBelow ? descriptionNode : null,
1081
- errorNode
1082
- ] });
1083
- }
1084
-
1085
- // src/components/craft-form-builder.tsx
1086
- var import_jsx_runtime14 = require("react/jsx-runtime");
1087
- function defaultValueForField(field) {
1088
- var _a, _b, _c, _d;
1089
- if (field.defaultValue !== void 0) return field.defaultValue;
1090
- switch (field.type) {
1091
- case "checkbox":
1092
- case "switch":
1093
- return false;
1094
- case "number":
1095
- case "slider":
1096
- case "range":
1097
- return (_a = field.min) != null ? _a : 0;
1098
- case "multifile":
1099
- return [];
1100
- case "file":
1101
- return null;
1102
- case "multiselect":
1103
- return [];
1104
- case "radio":
1105
- return (_d = (_c = (_b = field.options) == null ? void 0 : _b[0]) == null ? void 0 : _c.value) != null ? _d : "";
1106
- default:
1107
- return "";
1108
- }
1109
- }
1110
- function buildDefaultValues(fields, initialData) {
1111
- const values = {};
1112
- fields.forEach((field) => {
1113
- const initialValue = initialData == null ? void 0 : initialData[field.name];
1114
- if (initialValue !== void 0 && initialValue !== null) {
1115
- values[field.name] = initialValue;
1116
- } else {
1117
- values[field.name] = defaultValueForField(field);
1118
- }
1119
- });
1120
- return values;
1121
- }
1122
- function buildRules(field, getValues) {
1123
- var _a;
1124
- const rules = { ...field.rules };
1125
- const mergeValidate = (current, next) => {
1126
- if (!current) return next;
1127
- if (typeof current === "function") {
1128
- return (value) => {
1129
- const result = current(
1130
- value,
1131
- getValues()
1132
- );
1133
- if (result !== true) return result;
1134
- return next(value);
1135
- };
1136
- }
1137
- if (typeof current === "object") {
1138
- return (value) => {
1139
- const entries = Object.entries(current);
1140
- for (const [, validator] of entries) {
1141
- const result = validator(
1142
- value,
1143
- getValues()
1144
- );
1145
- if (result !== true) return result;
1146
- }
1147
- return next(value);
1148
- };
1149
- }
1150
- return next;
1151
- };
1152
- if (field.required && field.type !== "hidden") {
1153
- if (field.type === "checkbox" || field.type === "switch") {
1154
- rules.validate = mergeValidate(
1155
- rules.validate,
1156
- (value) => {
1157
- var _a2;
1158
- return value ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
1159
- }
1160
- );
1161
- } else if (field.type === "multiselect") {
1162
- rules.validate = mergeValidate(
1163
- rules.validate,
1164
- (value) => {
1165
- var _a2;
1166
- return Array.isArray(value) && value.length > 0 ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
1167
- }
1168
- );
1169
- } else if (field.type === "file") {
1170
- rules.validate = mergeValidate(
1171
- rules.validate,
1172
- (value) => {
1173
- var _a2;
1174
- return value instanceof FileList && value.length > 0 ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
1175
- }
1176
- );
1177
- } else if (field.type === "multifile") {
1178
- rules.validate = mergeValidate(
1179
- rules.validate,
1180
- (value) => {
1181
- var _a2;
1182
- return Array.isArray(value) && value.length > 0 ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
1183
- }
1184
- );
1185
- } else {
1186
- rules.required = `${String((_a = field.label) != null ? _a : field.name)} is required`;
1187
- }
1188
- }
1189
- if (field.min !== void 0) {
1190
- rules.min = { value: field.min, message: `Min ${field.min}` };
1191
- }
1192
- if (field.max !== void 0) {
1193
- rules.max = { value: field.max, message: `Max ${field.max}` };
1194
- }
1195
- if (field.type === "email") {
1196
- rules.pattern = {
1197
- value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
1198
- message: "Please enter a valid email address"
1199
- };
1200
- }
1201
- if (field.type === "url") {
1202
- rules.pattern = {
1203
- value: /^https?:\/\/.+/,
1204
- message: "Please enter a valid URL"
1205
- };
1206
- }
1207
- if (field.validate) {
1208
- rules.validate = mergeValidate(
1209
- rules.validate,
1210
- (value) => {
1211
- var _a2;
1212
- return (_a2 = field.validate) == null ? void 0 : _a2.call(field, value, getValues());
1213
- }
1214
- );
1215
- }
1216
- return rules;
1217
- }
1218
- function CraftFormBuilder({
1219
- title = "Form",
1220
- description,
1221
- fields,
1222
- initialData = null,
1223
- open,
1224
- defaultOpen = false,
1225
- onOpenChange,
1226
- trigger,
1227
- submitLabel = "Submit",
1228
- cancelLabel = "Cancel",
1229
- resetLabel = "Reset",
1230
- showReset = true,
1231
- showCancel = true,
1232
- tone,
1233
- className,
1234
- formClassName,
1235
- loading = false,
1236
- disableSubmitWhenInvalid = true,
1237
- closeOnSubmit = true,
1238
- closeOnCancel = true,
1239
- onSubmit,
1240
- onReset,
1241
- onCancel,
1242
- customValidation
1243
- }) {
1244
- const [uncontrolledOpen, setUncontrolledOpen] = React11.useState(defaultOpen);
1245
- const isControlled = typeof open === "boolean";
1246
- const isOpen = isControlled ? open : uncontrolledOpen;
1247
- const setOpen = React11.useCallback(
1248
- (next) => {
1249
- if (!isControlled) setUncontrolledOpen(next);
1250
- onOpenChange == null ? void 0 : onOpenChange(next);
1251
- },
1252
- [isControlled, onOpenChange]
1253
- );
1254
- const defaultValues = React11.useMemo(
1255
- () => buildDefaultValues(fields, initialData),
1256
- [fields, initialData]
1257
- );
1258
- const form = (0, import_react_hook_form4.useForm)({
1259
- mode: "onChange",
1260
- defaultValues
1261
- });
1262
- const formId = React11.useId();
1263
- React11.useEffect(() => {
1264
- form.reset(defaultValues);
1265
- }, [defaultValues, form]);
1266
- const handleSubmit = form.handleSubmit(async (values) => {
1267
- if (customValidation) {
1268
- const customErrors = customValidation(values);
1269
- if (customErrors && Object.keys(customErrors).length > 0) {
1270
- Object.entries(customErrors).forEach(([key, message]) => {
1271
- if (message) {
1272
- form.setError(key, {
1273
- type: "custom",
1274
- message: String(message)
1275
- });
1276
- }
1277
- });
1278
- return;
1279
- }
1280
- }
1281
- await onSubmit(values);
1282
- if (closeOnSubmit) setOpen(false);
1283
- });
1284
- const handleReset = () => {
1285
- form.reset(defaultValues);
1286
- onReset == null ? void 0 : onReset();
1287
- };
1288
- const handleCancel = () => {
1289
- onCancel == null ? void 0 : onCancel();
1290
- if (closeOnCancel) setOpen(false);
1291
- };
1292
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_hook_form4.FormProvider, { ...form, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1293
- CraftModal,
1294
- {
1295
- open: isOpen,
1296
- onOpenChange: setOpen,
1297
- trigger,
1298
- title,
1299
- description,
1300
- tone,
1301
- className,
1302
- footer: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-wrap items-center justify-end gap-3", children: [
1303
- showReset && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1304
- CraftButton,
1305
- {
1306
- type: "button",
1307
- variant: "outline",
1308
- onClick: handleReset,
1309
- disabled: loading,
1310
- children: resetLabel
1311
- }
1312
- ),
1313
- showCancel && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1314
- CraftButton,
1315
- {
1316
- type: "button",
1317
- variant: "ghost",
1318
- onClick: handleCancel,
1319
- disabled: loading,
1320
- children: cancelLabel
1321
- }
1322
- ),
1323
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1324
- CraftSubmitButton,
1325
- {
1326
- loading,
1327
- disableWhenInvalid: disableSubmitWhenInvalid,
1328
- form: formId,
1329
- children: submitLabel
1330
- }
1331
- )
1332
- ] }),
1333
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1334
- "form",
1335
- {
1336
- id: formId,
1337
- onSubmit: handleSubmit,
1338
- className: cn("space-y-5", formClassName),
1339
- children: fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-2", children: [
1340
- field.helpText && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-xs text-[rgb(var(--nc-fg-muted))]", children: field.helpText }),
1341
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1342
- CraftFormField,
1343
- {
1344
- name: field.name,
1345
- label: field.label,
1346
- description: field.description,
1347
- type: field.type,
1348
- placeholder: field.placeholder,
1349
- options: field.options,
1350
- tone,
1351
- disabled: field.disabled || loading,
1352
- rules: buildRules(field, form.getValues),
1353
- fieldProps: {
1354
- min: field.min,
1355
- max: field.max,
1356
- step: field.step,
1357
- rows: field.rows,
1358
- accept: field.accept,
1359
- multiple: field.type === "multifile",
1360
- ...field.fieldProps
1361
- }
1362
- }
1363
- )
1364
- ] }, field.name))
1365
- }
1366
- )
1367
- }
1368
- ) });
1369
- }
26
+ var import_craft_form = require("@/components/craft-form");
27
+ var import_craft_form_builder = require("@/components/craft-form-builder");
28
+ var import_craft_form_field = require("@/components/craft-form-field");
1370
29
  // Annotate the CommonJS export names for ESM import in node:
1371
30
  0 && (module.exports = {
1372
31
  CraftForm,