@jameskabz/nextcraft-ui 0.4.0 → 0.6.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/README.md +94 -0
- package/dist/chunk-6F7FN2ZF.js +671 -0
- package/dist/chunk-6F7FN2ZF.js.map +1 -0
- package/dist/chunk-7Q4Z47HT.js +657 -0
- package/dist/chunk-7Q4Z47HT.js.map +1 -0
- package/dist/chunk-7SKDTIEK.js +49 -0
- package/dist/chunk-7SKDTIEK.js.map +1 -0
- package/dist/chunk-FEFH5O5K.js +49 -0
- package/dist/chunk-FEFH5O5K.js.map +1 -0
- package/dist/chunk-M2EKVXB6.js +127 -0
- package/dist/chunk-M2EKVXB6.js.map +1 -0
- package/dist/chunk-SBLIF6UU.js +1029 -0
- package/dist/chunk-SBLIF6UU.js.map +1 -0
- package/dist/chunk-VQ6T3HIX.js +9 -0
- package/dist/chunk-VQ6T3HIX.js.map +1 -0
- package/dist/chunk-YVZL4GET.js +328 -0
- package/dist/chunk-YVZL4GET.js.map +1 -0
- package/dist/chunk-ZRV4Y374.js +582 -0
- package/dist/chunk-ZRV4Y374.js.map +1 -0
- package/dist/craft/components.cjs +1838 -0
- package/dist/craft/components.cjs.map +1 -0
- package/dist/craft/components.d.cts +369 -0
- package/dist/craft/components.d.ts +369 -0
- package/dist/craft/components.js +78 -0
- package/dist/craft/components.js.map +1 -0
- package/dist/craft/forms.cjs +1376 -0
- package/dist/craft/forms.cjs.map +1 -0
- package/dist/craft/forms.d.cts +101 -0
- package/dist/craft/forms.d.ts +101 -0
- package/dist/craft/forms.js +14 -0
- package/dist/craft/forms.js.map +1 -0
- package/dist/craft/layout.cjs +410 -0
- package/dist/craft/layout.cjs.map +1 -0
- package/dist/craft/layout.d.cts +170 -0
- package/dist/craft/layout.d.ts +170 -0
- package/dist/craft/layout.js +27 -0
- package/dist/craft/layout.js.map +1 -0
- package/dist/craft/table.cjs +662 -0
- package/dist/craft/table.cjs.map +1 -0
- package/dist/craft/table.d.cts +99 -0
- package/dist/craft/table.d.ts +99 -0
- package/dist/craft/table.js +15 -0
- package/dist/craft/table.js.map +1 -0
- package/dist/craft/theme.cjs +166 -0
- package/dist/craft/theme.cjs.map +1 -0
- package/dist/craft/theme.d.cts +10 -0
- package/dist/craft/theme.d.ts +10 -0
- package/dist/craft/theme.js +12 -0
- package/dist/craft/theme.js.map +1 -0
- package/dist/index.cjs +2374 -317
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -277
- package/dist/index.d.ts +10 -277
- package/dist/index.js +92 -1347
- package/dist/index.js.map +1 -1
- package/dist/styles.css +359 -4
- package/dist/theme-context-EVI9PfKv.d.cts +22 -0
- package/dist/theme-context-EVI9PfKv.d.ts +22 -0
- package/package.json +30 -1
package/dist/index.cjs
CHANGED
|
@@ -31,23 +31,44 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
AppShell: () => AppShell,
|
|
34
|
+
AppTemplate: () => AppTemplate,
|
|
34
35
|
AuthLayout: () => AuthLayout,
|
|
35
36
|
Breadcrumbs: () => Breadcrumbs,
|
|
36
37
|
Container: () => Container,
|
|
38
|
+
CraftAlert: () => CraftAlert,
|
|
37
39
|
CraftBadge: () => CraftBadge,
|
|
38
40
|
CraftButton: () => CraftButton,
|
|
39
41
|
CraftCard: () => CraftCard,
|
|
40
42
|
CraftCheckbox: () => CraftCheckbox,
|
|
43
|
+
CraftCommandPalette: () => CraftCommandPalette,
|
|
44
|
+
CraftConfirmDialog: () => CraftConfirmDialog,
|
|
45
|
+
CraftCreateEditDrawer: () => CraftCreateEditDrawer,
|
|
41
46
|
CraftCurrencyInput: () => CraftCurrencyInput,
|
|
47
|
+
CraftDataTable: () => CraftDataTable,
|
|
42
48
|
CraftDatePicker: () => CraftDatePicker,
|
|
43
49
|
CraftDrawer: () => CraftDrawer,
|
|
50
|
+
CraftDropdownMenu: () => CraftDropdownMenu,
|
|
44
51
|
CraftEmptyState: () => CraftEmptyState,
|
|
52
|
+
CraftErrorState: () => CraftErrorState,
|
|
53
|
+
CraftFilterBar: () => CraftFilterBar,
|
|
54
|
+
CraftForm: () => CraftForm,
|
|
55
|
+
CraftFormBuilder: () => CraftFormBuilder,
|
|
56
|
+
CraftFormField: () => CraftFormField,
|
|
57
|
+
CraftIcon: () => CraftIcon,
|
|
58
|
+
CraftIconProvider: () => CraftIconProvider,
|
|
45
59
|
CraftInput: () => CraftInput,
|
|
60
|
+
CraftLink: () => CraftLink,
|
|
61
|
+
CraftLoadingState: () => CraftLoadingState,
|
|
46
62
|
CraftModal: () => CraftModal,
|
|
47
63
|
CraftNumberInput: () => CraftNumberInput,
|
|
64
|
+
CraftPagination: () => CraftPagination,
|
|
65
|
+
CraftPopover: () => CraftPopover,
|
|
48
66
|
CraftSelect: () => CraftSelect,
|
|
49
67
|
CraftSkeleton: () => CraftSkeleton,
|
|
68
|
+
CraftStatCard: () => CraftStatCard,
|
|
69
|
+
CraftSubmitButton: () => CraftSubmitButton,
|
|
50
70
|
CraftSwitch: () => CraftSwitch,
|
|
71
|
+
CraftTableToolbar: () => CraftTableToolbar,
|
|
51
72
|
CraftTabs: () => CraftTabs,
|
|
52
73
|
CraftTextarea: () => CraftTextarea,
|
|
53
74
|
CraftToastHost: () => CraftToastHost,
|
|
@@ -59,6 +80,7 @@ __export(index_exports, {
|
|
|
59
80
|
ThemeProvider: () => ThemeProvider,
|
|
60
81
|
ThemeSwitcher: () => ThemeSwitcher,
|
|
61
82
|
TopNav: () => TopNav,
|
|
83
|
+
layoutConfigSchema: () => layoutConfigSchema,
|
|
62
84
|
useCraftToast: () => useCraftToast,
|
|
63
85
|
useTheme: () => useTheme
|
|
64
86
|
});
|
|
@@ -403,20 +425,149 @@ function CraftBadge({
|
|
|
403
425
|
);
|
|
404
426
|
}
|
|
405
427
|
|
|
406
|
-
// src/components/craft-
|
|
428
|
+
// src/components/craft-alert.tsx
|
|
407
429
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
408
|
-
|
|
409
|
-
|
|
430
|
+
var variantClasses3 = {
|
|
431
|
+
info: "border-[rgb(var(--nc-accent-1)/0.45)] bg-[rgb(var(--nc-accent-1)/0.12)]",
|
|
432
|
+
success: "border-[rgb(var(--nc-accent-2)/0.45)] bg-[rgb(var(--nc-accent-2)/0.12)]",
|
|
433
|
+
warning: "border-[rgb(var(--nc-accent-3)/0.45)] bg-[rgb(var(--nc-accent-3)/0.12)]",
|
|
434
|
+
error: "border-[rgb(var(--nc-accent-3)/0.65)] bg-[rgb(var(--nc-accent-3)/0.18)]"
|
|
435
|
+
};
|
|
436
|
+
function CraftAlert({
|
|
437
|
+
title,
|
|
438
|
+
description,
|
|
439
|
+
variant = "info",
|
|
440
|
+
icon,
|
|
441
|
+
actions,
|
|
442
|
+
tone,
|
|
443
|
+
className,
|
|
444
|
+
...props
|
|
445
|
+
}) {
|
|
446
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
447
|
+
"div",
|
|
448
|
+
{
|
|
449
|
+
className: cn(
|
|
450
|
+
"rounded-2xl border p-4 text-[rgb(var(--nc-fg))] backdrop-blur-xl",
|
|
451
|
+
variantClasses3[variant],
|
|
452
|
+
className
|
|
453
|
+
),
|
|
454
|
+
"data-nc-theme": tone,
|
|
455
|
+
...props,
|
|
456
|
+
children: [
|
|
457
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-start gap-3", children: [
|
|
458
|
+
icon && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "mt-1 text-[rgb(var(--nc-fg))]", children: icon }),
|
|
459
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "space-y-1", children: [
|
|
460
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-sm font-semibold", children: title }),
|
|
461
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: description })
|
|
462
|
+
] })
|
|
463
|
+
] }),
|
|
464
|
+
actions && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "mt-3 flex flex-wrap gap-2", children: actions })
|
|
465
|
+
]
|
|
466
|
+
}
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// src/components/craft-error-state.tsx
|
|
471
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
472
|
+
function CraftErrorState({
|
|
473
|
+
title = "Something went wrong",
|
|
474
|
+
description = "Try again or check your connection.",
|
|
475
|
+
actionLabel = "Retry",
|
|
476
|
+
onAction,
|
|
477
|
+
action,
|
|
478
|
+
tone,
|
|
479
|
+
className,
|
|
480
|
+
...props
|
|
481
|
+
}) {
|
|
482
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
483
|
+
"div",
|
|
484
|
+
{
|
|
485
|
+
className: cn(
|
|
486
|
+
"rounded-3xl border border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.12)] p-6 text-[rgb(var(--nc-fg))] shadow-[0_12px_30px_rgba(0,0,0,0.25)] backdrop-blur-xl",
|
|
487
|
+
className
|
|
488
|
+
),
|
|
489
|
+
"data-nc-theme": tone,
|
|
490
|
+
...props,
|
|
491
|
+
children: [
|
|
492
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "space-y-2", children: [
|
|
493
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { className: "text-lg font-semibold", children: title }),
|
|
494
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: description })
|
|
495
|
+
] }),
|
|
496
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-4", children: action != null ? action : onAction && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CraftButton, { size: "sm", onClick: onAction, children: actionLabel }) })
|
|
497
|
+
]
|
|
498
|
+
}
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// src/components/craft-loading-state.tsx
|
|
503
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
504
|
+
var sizeClasses2 = {
|
|
505
|
+
sm: "h-4 w-4 border-2",
|
|
506
|
+
md: "h-6 w-6 border-2",
|
|
507
|
+
lg: "h-8 w-8 border-[3px]"
|
|
508
|
+
};
|
|
509
|
+
function CraftLoadingState({
|
|
510
|
+
label = "Loading...",
|
|
511
|
+
size = "md",
|
|
512
|
+
tone,
|
|
513
|
+
className,
|
|
514
|
+
...props
|
|
515
|
+
}) {
|
|
516
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
517
|
+
"div",
|
|
518
|
+
{
|
|
519
|
+
className: cn("flex items-center gap-3 text-[rgb(var(--nc-fg))]", className),
|
|
520
|
+
"data-nc-theme": tone,
|
|
521
|
+
...props,
|
|
522
|
+
children: [
|
|
523
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
524
|
+
"span",
|
|
525
|
+
{
|
|
526
|
+
className: cn(
|
|
527
|
+
"inline-block animate-spin rounded-full border-[rgb(var(--nc-accent-1)/0.25)] border-t-[rgb(var(--nc-accent-1))]",
|
|
528
|
+
sizeClasses2[size]
|
|
529
|
+
),
|
|
530
|
+
"aria-hidden": "true"
|
|
531
|
+
}
|
|
532
|
+
),
|
|
533
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: label })
|
|
534
|
+
]
|
|
535
|
+
}
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// src/components/craft-card.tsx
|
|
540
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
541
|
+
var intensityClasses2 = {
|
|
542
|
+
subtle: "backdrop-blur-md bg-opacity-50",
|
|
543
|
+
medium: "backdrop-blur-xl bg-opacity-70",
|
|
544
|
+
strong: "backdrop-blur-2xl bg-opacity-90"
|
|
545
|
+
};
|
|
546
|
+
function CraftCard({
|
|
547
|
+
className,
|
|
548
|
+
tone,
|
|
549
|
+
elevated = true,
|
|
550
|
+
intensity = "medium",
|
|
551
|
+
bordered = true,
|
|
552
|
+
children,
|
|
553
|
+
...props
|
|
554
|
+
}) {
|
|
555
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
410
556
|
"div",
|
|
411
557
|
{
|
|
412
558
|
className: cn(
|
|
413
|
-
"
|
|
414
|
-
|
|
559
|
+
"relative overflow-hidden rounded-3xl p-6 text-[rgb(var(--nc-fg))]",
|
|
560
|
+
intensityClasses2[intensity],
|
|
561
|
+
"bg-linear-to-br from-[rgb(var(--nc-accent-1)/0.15)] via-[rgb(var(--nc-accent-2)/0.10)] to-[rgb(var(--nc-accent-3)/0.15)]",
|
|
562
|
+
bordered ? "border-2 border-[rgb(var(--nc-accent-1)/0.3)]" : "border-0",
|
|
563
|
+
elevated ? "shadow-[0_8px_32px_rgba(0,0,0,0.3)] hover:shadow-[0_8px_40px_rgba(0,0,0,0.4)]" : "shadow-none",
|
|
564
|
+
"before:absolute before:inset-0 before:bg-linear-to-br before:from-white/10 before:to-transparent before:opacity-0 hover:before:opacity-100 before:transition-opacity before:duration-300",
|
|
415
565
|
"transition-all duration-300",
|
|
416
566
|
className
|
|
417
567
|
),
|
|
418
568
|
"data-nc-theme": tone,
|
|
419
|
-
...props
|
|
569
|
+
...props,
|
|
570
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "relative z-10", children })
|
|
420
571
|
}
|
|
421
572
|
);
|
|
422
573
|
}
|
|
@@ -424,7 +575,7 @@ function CraftCard({ className, tone, elevated = true, ...props }) {
|
|
|
424
575
|
// src/components/craft-modal.tsx
|
|
425
576
|
var React6 = __toESM(require("react"), 1);
|
|
426
577
|
var import_react_dom = require("react-dom");
|
|
427
|
-
var
|
|
578
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
428
579
|
var FOCUSABLE_SELECTORS = [
|
|
429
580
|
"a[href]",
|
|
430
581
|
"button:not([disabled])",
|
|
@@ -498,48 +649,49 @@ function CraftModal({
|
|
|
498
649
|
return () => document.removeEventListener("keydown", handleKey);
|
|
499
650
|
}, [isOpen, setOpen]);
|
|
500
651
|
const ref = useFocusTrap(isOpen);
|
|
501
|
-
const content = isOpen ? /* @__PURE__ */ (0,
|
|
502
|
-
/* @__PURE__ */ (0,
|
|
652
|
+
const content = isOpen ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "fixed inset-0 z-50 flex items-center justify-center px-4 py-8", children: [
|
|
653
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
503
654
|
"div",
|
|
504
655
|
{
|
|
505
656
|
className: "absolute inset-0 backdrop-blur-sm",
|
|
506
657
|
onClick: () => setOpen(false)
|
|
507
658
|
}
|
|
508
659
|
),
|
|
509
|
-
/* @__PURE__ */ (0,
|
|
660
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
510
661
|
"div",
|
|
511
662
|
{
|
|
512
663
|
ref,
|
|
513
664
|
tabIndex: -1,
|
|
514
665
|
className: cn(
|
|
515
|
-
"relative z-10 w-full max-w-
|
|
666
|
+
"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",
|
|
667
|
+
"max-h-[calc(100vh-1rem)] overflow-y-auto",
|
|
516
668
|
className
|
|
517
669
|
),
|
|
518
670
|
"data-nc-theme": tone,
|
|
519
671
|
children: [
|
|
520
|
-
/* @__PURE__ */ (0,
|
|
521
|
-
/* @__PURE__ */ (0,
|
|
522
|
-
title && /* @__PURE__ */ (0,
|
|
523
|
-
description && /* @__PURE__ */ (0,
|
|
672
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-start justify-between gap-4", children: [
|
|
673
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "space-y-1", children: [
|
|
674
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h3", { className: "text-2xl font-semibold", children: title }),
|
|
675
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-[rgb(var(--nc-fg-muted))]", children: description })
|
|
524
676
|
] }),
|
|
525
|
-
/* @__PURE__ */ (0,
|
|
677
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
526
678
|
"button",
|
|
527
679
|
{
|
|
528
680
|
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))]",
|
|
529
681
|
onClick: () => setOpen(false),
|
|
530
682
|
"aria-label": "Close",
|
|
531
|
-
children: /* @__PURE__ */ (0,
|
|
683
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { viewBox: "0 0 20 20", className: "h-4 w-4", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime13.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" }) })
|
|
532
684
|
}
|
|
533
685
|
)
|
|
534
686
|
] }),
|
|
535
|
-
/* @__PURE__ */ (0,
|
|
536
|
-
footer && /* @__PURE__ */ (0,
|
|
687
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "mt-5 space-y-4", children }),
|
|
688
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "mt-6", children: footer })
|
|
537
689
|
]
|
|
538
690
|
}
|
|
539
691
|
)
|
|
540
692
|
] }) : null;
|
|
541
|
-
return /* @__PURE__ */ (0,
|
|
542
|
-
trigger && /* @__PURE__ */ (0,
|
|
693
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
694
|
+
trigger && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
543
695
|
"span",
|
|
544
696
|
{
|
|
545
697
|
onClick: () => setOpen(true),
|
|
@@ -559,7 +711,7 @@ function CraftModal({
|
|
|
559
711
|
// src/components/craft-drawer.tsx
|
|
560
712
|
var React7 = __toESM(require("react"), 1);
|
|
561
713
|
var import_react_dom2 = require("react-dom");
|
|
562
|
-
var
|
|
714
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
563
715
|
function CraftDrawer({
|
|
564
716
|
open,
|
|
565
717
|
defaultOpen = false,
|
|
@@ -590,15 +742,15 @@ function CraftDrawer({
|
|
|
590
742
|
document.addEventListener("keydown", handleKey);
|
|
591
743
|
return () => document.removeEventListener("keydown", handleKey);
|
|
592
744
|
}, [isOpen, setOpen]);
|
|
593
|
-
const content = isOpen ? /* @__PURE__ */ (0,
|
|
594
|
-
/* @__PURE__ */ (0,
|
|
745
|
+
const content = isOpen ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "fixed inset-0 z-50 overflow-hidden", children: [
|
|
746
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
595
747
|
"div",
|
|
596
748
|
{
|
|
597
749
|
className: "absolute inset-0 backdrop-blur-sm",
|
|
598
750
|
onClick: () => setOpen(false)
|
|
599
751
|
}
|
|
600
752
|
),
|
|
601
|
-
/* @__PURE__ */ (0,
|
|
753
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
602
754
|
"div",
|
|
603
755
|
{
|
|
604
756
|
className: cn(
|
|
@@ -608,26 +760,26 @@ function CraftDrawer({
|
|
|
608
760
|
),
|
|
609
761
|
"data-nc-theme": tone,
|
|
610
762
|
children: [
|
|
611
|
-
/* @__PURE__ */ (0,
|
|
612
|
-
title && /* @__PURE__ */ (0,
|
|
613
|
-
/* @__PURE__ */ (0,
|
|
763
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center justify-between border-b border-[rgb(var(--nc-border)/0.3)] p-6", children: [
|
|
764
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { className: "text-xl font-semibold", children: title }),
|
|
765
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
614
766
|
"button",
|
|
615
767
|
{
|
|
616
768
|
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))]",
|
|
617
769
|
onClick: () => setOpen(false),
|
|
618
770
|
"aria-label": "Close",
|
|
619
|
-
children: /* @__PURE__ */ (0,
|
|
771
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("svg", { viewBox: "0 0 20 20", className: "h-4 w-4", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime14.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" }) })
|
|
620
772
|
}
|
|
621
773
|
)
|
|
622
774
|
] }),
|
|
623
|
-
/* @__PURE__ */ (0,
|
|
624
|
-
footer && /* @__PURE__ */ (0,
|
|
775
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "p-6 space-y-4 overflow-y-auto h-[calc(100%-5.5rem)]", children }),
|
|
776
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "border-t border-[rgb(var(--nc-border)/0.3)] p-6", children: footer })
|
|
625
777
|
]
|
|
626
778
|
}
|
|
627
779
|
)
|
|
628
780
|
] }) : null;
|
|
629
|
-
return /* @__PURE__ */ (0,
|
|
630
|
-
trigger && /* @__PURE__ */ (0,
|
|
781
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
782
|
+
trigger && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
631
783
|
"span",
|
|
632
784
|
{
|
|
633
785
|
onClick: () => setOpen(true),
|
|
@@ -646,7 +798,7 @@ function CraftDrawer({
|
|
|
646
798
|
|
|
647
799
|
// src/components/craft-tabs.tsx
|
|
648
800
|
var React8 = __toESM(require("react"), 1);
|
|
649
|
-
var
|
|
801
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
650
802
|
function CraftTabs({
|
|
651
803
|
value,
|
|
652
804
|
defaultValue,
|
|
@@ -684,14 +836,14 @@ function CraftTabs({
|
|
|
684
836
|
setValue(next.value);
|
|
685
837
|
}
|
|
686
838
|
};
|
|
687
|
-
return /* @__PURE__ */ (0,
|
|
688
|
-
/* @__PURE__ */ (0,
|
|
839
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: cn("space-y-4", className), "data-nc-theme": tone, children: [
|
|
840
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
689
841
|
"div",
|
|
690
842
|
{
|
|
691
843
|
className: "inline-flex flex-wrap items-center gap-2 rounded-full border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] p-2",
|
|
692
844
|
role: "tablist",
|
|
693
845
|
onKeyDown,
|
|
694
|
-
children: tabs.map((tab) => /* @__PURE__ */ (0,
|
|
846
|
+
children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
695
847
|
"button",
|
|
696
848
|
{
|
|
697
849
|
role: "tab",
|
|
@@ -707,16 +859,16 @@ function CraftTabs({
|
|
|
707
859
|
))
|
|
708
860
|
}
|
|
709
861
|
),
|
|
710
|
-
/* @__PURE__ */ (0,
|
|
862
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "rounded-2xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] p-4 text-[rgb(var(--nc-fg))]", children: panels[activeValue] })
|
|
711
863
|
] });
|
|
712
864
|
}
|
|
713
865
|
|
|
714
866
|
// src/components/craft-tooltip.tsx
|
|
715
867
|
var React9 = __toESM(require("react"), 1);
|
|
716
|
-
var
|
|
868
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
717
869
|
function CraftTooltip({ content, tone, children, side = "top" }) {
|
|
718
870
|
const [open, setOpen] = React9.useState(false);
|
|
719
|
-
return /* @__PURE__ */ (0,
|
|
871
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
720
872
|
"span",
|
|
721
873
|
{
|
|
722
874
|
className: "relative inline-flex",
|
|
@@ -726,7 +878,7 @@ function CraftTooltip({ content, tone, children, side = "top" }) {
|
|
|
726
878
|
onBlur: () => setOpen(false),
|
|
727
879
|
children: [
|
|
728
880
|
children,
|
|
729
|
-
/* @__PURE__ */ (0,
|
|
881
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
730
882
|
"span",
|
|
731
883
|
{
|
|
732
884
|
className: cn(
|
|
@@ -750,8 +902,8 @@ function CraftTooltip({ content, tone, children, side = "top" }) {
|
|
|
750
902
|
|
|
751
903
|
// src/components/craft-toast.tsx
|
|
752
904
|
var React10 = __toESM(require("react"), 1);
|
|
753
|
-
var
|
|
754
|
-
var
|
|
905
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
906
|
+
var variantClasses4 = {
|
|
755
907
|
info: "border-[color:rgb(var(--nc-accent-1)/0.4)]",
|
|
756
908
|
success: "border-emerald-400/40",
|
|
757
909
|
warning: "border-amber-400/40",
|
|
@@ -770,26 +922,26 @@ function useCraftToast() {
|
|
|
770
922
|
return { toasts, push, remove };
|
|
771
923
|
}
|
|
772
924
|
function CraftToastHost({ toasts, onDismiss, tone }) {
|
|
773
|
-
return /* @__PURE__ */ (0,
|
|
925
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
774
926
|
"div",
|
|
775
927
|
{
|
|
776
928
|
className: "fixed right-6 top-6 z-50 flex w-full max-w-sm flex-col gap-3",
|
|
777
929
|
"data-nc-theme": tone,
|
|
778
930
|
children: toasts.map((toast) => {
|
|
779
931
|
var _a;
|
|
780
|
-
return /* @__PURE__ */ (0,
|
|
932
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
781
933
|
"div",
|
|
782
934
|
{
|
|
783
935
|
className: cn(
|
|
784
936
|
"rounded-2xl border bg-[rgb(var(--nc-surface)/0.12)] p-4 text-[rgb(var(--nc-fg))] shadow-[0_15px_35px_rgba(0,0,0,0.35)] backdrop-blur-xl",
|
|
785
|
-
|
|
937
|
+
variantClasses4[(_a = toast.variant) != null ? _a : "info"]
|
|
786
938
|
),
|
|
787
|
-
children: /* @__PURE__ */ (0,
|
|
788
|
-
/* @__PURE__ */ (0,
|
|
789
|
-
/* @__PURE__ */ (0,
|
|
790
|
-
toast.description && /* @__PURE__ */ (0,
|
|
939
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-start justify-between gap-4", children: [
|
|
940
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { children: [
|
|
941
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-sm font-semibold", children: toast.title }),
|
|
942
|
+
toast.description && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-xs text-[rgb(var(--nc-fg-muted))]", children: toast.description })
|
|
791
943
|
] }),
|
|
792
|
-
/* @__PURE__ */ (0,
|
|
944
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
793
945
|
"button",
|
|
794
946
|
{
|
|
795
947
|
className: "text-[rgb(var(--nc-fg-soft))] hover:text-[rgb(var(--nc-fg))]",
|
|
@@ -807,9 +959,9 @@ function CraftToastHost({ toasts, onDismiss, tone }) {
|
|
|
807
959
|
}
|
|
808
960
|
|
|
809
961
|
// src/components/craft-skeleton.tsx
|
|
810
|
-
var
|
|
962
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
811
963
|
function CraftSkeleton({ className, tone, ...props }) {
|
|
812
|
-
return /* @__PURE__ */ (0,
|
|
964
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
813
965
|
"div",
|
|
814
966
|
{
|
|
815
967
|
className: cn(
|
|
@@ -825,7 +977,7 @@ function CraftSkeleton({ className, tone, ...props }) {
|
|
|
825
977
|
}
|
|
826
978
|
|
|
827
979
|
// src/components/craft-empty-state.tsx
|
|
828
|
-
var
|
|
980
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
829
981
|
function CraftEmptyState({
|
|
830
982
|
className,
|
|
831
983
|
tone,
|
|
@@ -835,7 +987,7 @@ function CraftEmptyState({
|
|
|
835
987
|
action,
|
|
836
988
|
...props
|
|
837
989
|
}) {
|
|
838
|
-
return /* @__PURE__ */ (0,
|
|
990
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
839
991
|
"div",
|
|
840
992
|
{
|
|
841
993
|
className: cn(
|
|
@@ -846,69 +998,51 @@ function CraftEmptyState({
|
|
|
846
998
|
"data-nc-theme": tone,
|
|
847
999
|
...props,
|
|
848
1000
|
children: [
|
|
849
|
-
icon && /* @__PURE__ */ (0,
|
|
850
|
-
/* @__PURE__ */ (0,
|
|
851
|
-
description && /* @__PURE__ */ (0,
|
|
852
|
-
action && /* @__PURE__ */ (0,
|
|
1001
|
+
icon && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-2xl bg-[rgb(var(--nc-accent-1)/0.2)] text-[rgb(var(--nc-accent-1))]", children: icon }),
|
|
1002
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { className: "text-xl font-semibold", children: title }),
|
|
1003
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "mt-2 text-sm text-[rgb(var(--nc-fg-muted))]", children: description }),
|
|
1004
|
+
action && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "mt-6 flex justify-center", children: action })
|
|
853
1005
|
]
|
|
854
1006
|
}
|
|
855
1007
|
);
|
|
856
1008
|
}
|
|
857
1009
|
|
|
858
|
-
// src/components/craft-
|
|
1010
|
+
// src/components/craft-popover.tsx
|
|
859
1011
|
var React11 = __toESM(require("react"), 1);
|
|
860
|
-
var
|
|
861
|
-
var
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
function isSameDay(a, b) {
|
|
875
|
-
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
876
|
-
}
|
|
877
|
-
function isOutsideRange(date, min, max) {
|
|
878
|
-
const minDate = parseDate(min);
|
|
879
|
-
const maxDate = parseDate(max);
|
|
880
|
-
if (minDate && date < minDate) return true;
|
|
881
|
-
if (maxDate && date > maxDate) return true;
|
|
882
|
-
return false;
|
|
883
|
-
}
|
|
884
|
-
function CraftDatePicker({
|
|
885
|
-
value,
|
|
886
|
-
defaultValue,
|
|
887
|
-
onChange,
|
|
1012
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1013
|
+
var alignClasses = {
|
|
1014
|
+
start: "left-0",
|
|
1015
|
+
center: "left-1/2 -translate-x-1/2",
|
|
1016
|
+
end: "right-0"
|
|
1017
|
+
};
|
|
1018
|
+
function CraftPopover({
|
|
1019
|
+
open,
|
|
1020
|
+
defaultOpen = false,
|
|
1021
|
+
onOpenChange,
|
|
1022
|
+
trigger,
|
|
1023
|
+
content,
|
|
1024
|
+
align = "start",
|
|
1025
|
+
sideOffset = 10,
|
|
888
1026
|
tone,
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
placeholder = "Select date",
|
|
892
|
-
className
|
|
1027
|
+
className,
|
|
1028
|
+
contentClassName
|
|
893
1029
|
}) {
|
|
894
|
-
const [
|
|
895
|
-
const
|
|
896
|
-
const
|
|
897
|
-
const
|
|
898
|
-
const
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1030
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React11.useState(defaultOpen);
|
|
1031
|
+
const isControlled = typeof open === "boolean";
|
|
1032
|
+
const isOpen = isControlled ? open : uncontrolledOpen;
|
|
1033
|
+
const rootRef = React11.useRef(null);
|
|
1034
|
+
const setOpen = React11.useCallback(
|
|
1035
|
+
(next) => {
|
|
1036
|
+
if (!isControlled) setUncontrolledOpen(next);
|
|
1037
|
+
onOpenChange == null ? void 0 : onOpenChange(next);
|
|
1038
|
+
},
|
|
1039
|
+
[isControlled, onOpenChange]
|
|
1040
|
+
);
|
|
905
1041
|
React11.useEffect(() => {
|
|
906
|
-
if (!
|
|
1042
|
+
if (!isOpen) return;
|
|
907
1043
|
const handleClick = (event) => {
|
|
908
|
-
|
|
909
|
-
if (!
|
|
910
|
-
setOpen(false);
|
|
911
|
-
}
|
|
1044
|
+
if (!rootRef.current) return;
|
|
1045
|
+
if (!rootRef.current.contains(event.target)) setOpen(false);
|
|
912
1046
|
};
|
|
913
1047
|
const handleKey = (event) => {
|
|
914
1048
|
if (event.key === "Escape") setOpen(false);
|
|
@@ -919,81 +1053,438 @@ function CraftDatePicker({
|
|
|
919
1053
|
document.removeEventListener("mousedown", handleClick);
|
|
920
1054
|
document.removeEventListener("keydown", handleKey);
|
|
921
1055
|
};
|
|
922
|
-
}, [
|
|
923
|
-
const
|
|
924
|
-
(
|
|
925
|
-
|
|
926
|
-
|
|
1056
|
+
}, [isOpen, setOpen]);
|
|
1057
|
+
const triggerNode = React11.isValidElement(trigger) ? React11.cloneElement(trigger, {
|
|
1058
|
+
onClick: (event) => {
|
|
1059
|
+
const handler = trigger.props.onClick;
|
|
1060
|
+
handler == null ? void 0 : handler(event);
|
|
1061
|
+
if (!event.defaultPrevented) setOpen(!isOpen);
|
|
927
1062
|
},
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
const handleDaySelect = (date) => {
|
|
940
|
-
if (isOutsideRange(date, min, max)) return;
|
|
941
|
-
const next = formatDate(date);
|
|
942
|
-
setValue(next);
|
|
943
|
-
setOpen(false);
|
|
944
|
-
};
|
|
945
|
-
const handleKeyDown = (event) => {
|
|
946
|
-
if (!open) return;
|
|
947
|
-
if (!selectedDate) return;
|
|
948
|
-
const next = new Date(selectedDate);
|
|
949
|
-
if (event.key === "ArrowRight") next.setDate(next.getDate() + 1);
|
|
950
|
-
if (event.key === "ArrowLeft") next.setDate(next.getDate() - 1);
|
|
951
|
-
if (event.key === "ArrowDown") next.setDate(next.getDate() + 7);
|
|
952
|
-
if (event.key === "ArrowUp") next.setDate(next.getDate() - 7);
|
|
953
|
-
if (event.key === "Enter") {
|
|
954
|
-
event.preventDefault();
|
|
955
|
-
handleDaySelect(selectedDate);
|
|
956
|
-
return;
|
|
957
|
-
}
|
|
958
|
-
if (next.getTime() !== selectedDate.getTime()) {
|
|
959
|
-
event.preventDefault();
|
|
960
|
-
if (!isOutsideRange(next, min, max)) {
|
|
961
|
-
setValue(formatDate(next));
|
|
962
|
-
setViewDate(next);
|
|
963
|
-
}
|
|
1063
|
+
"aria-expanded": isOpen,
|
|
1064
|
+
"aria-haspopup": "dialog"
|
|
1065
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1066
|
+
"button",
|
|
1067
|
+
{
|
|
1068
|
+
type: "button",
|
|
1069
|
+
onClick: () => setOpen(!isOpen),
|
|
1070
|
+
className: "inline-flex",
|
|
1071
|
+
"aria-expanded": isOpen,
|
|
1072
|
+
"aria-haspopup": "dialog",
|
|
1073
|
+
children: trigger
|
|
964
1074
|
}
|
|
965
|
-
|
|
966
|
-
return /* @__PURE__ */ (0,
|
|
967
|
-
|
|
968
|
-
|
|
1075
|
+
);
|
|
1076
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: cn("relative inline-flex", className), ref: rootRef, children: [
|
|
1077
|
+
triggerNode,
|
|
1078
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1079
|
+
"div",
|
|
969
1080
|
{
|
|
970
|
-
type: "button",
|
|
971
|
-
onClick: () => setOpen((prev) => !prev),
|
|
972
1081
|
className: cn(
|
|
973
|
-
"
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
"border-[rgb(var(--nc-border)/0.35)]",
|
|
977
|
-
"focus:outline-none focus:ring-4 focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
|
|
978
|
-
className
|
|
1082
|
+
"absolute z-40 w-max min-w-48 rounded-2xl border border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.08)] p-3 text-[rgb(var(--nc-fg))] shadow-[0_18px_40px_rgba(0,0,0,0.35)] backdrop-blur-2xl",
|
|
1083
|
+
alignClasses[align],
|
|
1084
|
+
contentClassName
|
|
979
1085
|
),
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1086
|
+
style: { marginTop: sideOffset },
|
|
1087
|
+
role: "dialog",
|
|
1088
|
+
"data-nc-theme": tone,
|
|
1089
|
+
children: content
|
|
984
1090
|
}
|
|
985
|
-
)
|
|
986
|
-
|
|
987
|
-
|
|
1091
|
+
)
|
|
1092
|
+
] });
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
// src/components/craft-dropdown-menu.tsx
|
|
1096
|
+
var React12 = __toESM(require("react"), 1);
|
|
1097
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1098
|
+
function CraftDropdownMenu({
|
|
1099
|
+
trigger,
|
|
1100
|
+
items = [],
|
|
1101
|
+
content,
|
|
1102
|
+
open,
|
|
1103
|
+
defaultOpen = false,
|
|
1104
|
+
onOpenChange,
|
|
1105
|
+
align = "end",
|
|
1106
|
+
tone,
|
|
1107
|
+
className,
|
|
1108
|
+
menuClassName
|
|
1109
|
+
}) {
|
|
1110
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React12.useState(defaultOpen);
|
|
1111
|
+
const isControlled = typeof open === "boolean";
|
|
1112
|
+
const isOpen = isControlled ? open : uncontrolledOpen;
|
|
1113
|
+
const setOpen = React12.useCallback(
|
|
1114
|
+
(next) => {
|
|
1115
|
+
if (!isControlled) setUncontrolledOpen(next);
|
|
1116
|
+
onOpenChange == null ? void 0 : onOpenChange(next);
|
|
1117
|
+
},
|
|
1118
|
+
[isControlled, onOpenChange]
|
|
1119
|
+
);
|
|
1120
|
+
const menuContent = content != null ? content : items.length ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: cn("space-y-1", menuClassName), role: "menu", children: items.map((item, index) => {
|
|
1121
|
+
var _a;
|
|
1122
|
+
const key = (_a = item.id) != null ? _a : `${index}-${String(item.label)}`;
|
|
1123
|
+
const itemClasses = cn(
|
|
1124
|
+
"flex w-full items-start gap-3 rounded-xl px-3 py-2 text-left text-sm transition",
|
|
1125
|
+
item.disabled ? "cursor-not-allowed text-[rgb(var(--nc-fg-soft))] opacity-60" : "text-[rgb(var(--nc-fg))] hover:bg-[rgb(var(--nc-surface)/0.12)]"
|
|
1126
|
+
);
|
|
1127
|
+
const contentNode = /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
1128
|
+
item.icon && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "mt-0.5", children: item.icon }),
|
|
1129
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "flex-1", children: [
|
|
1130
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "block font-medium", children: item.label }),
|
|
1131
|
+
item.description && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "block text-xs text-[rgb(var(--nc-fg-muted))]", children: item.description })
|
|
1132
|
+
] })
|
|
1133
|
+
] });
|
|
1134
|
+
if (item.href) {
|
|
1135
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
1136
|
+
"a",
|
|
1137
|
+
{
|
|
1138
|
+
href: item.href,
|
|
1139
|
+
className: itemClasses,
|
|
1140
|
+
role: "menuitem",
|
|
1141
|
+
onClick: () => {
|
|
1142
|
+
var _a2;
|
|
1143
|
+
if (item.disabled) return;
|
|
1144
|
+
(_a2 = item.onSelect) == null ? void 0 : _a2.call(item);
|
|
1145
|
+
setOpen(false);
|
|
1146
|
+
},
|
|
1147
|
+
children: contentNode
|
|
1148
|
+
},
|
|
1149
|
+
key
|
|
1150
|
+
);
|
|
1151
|
+
}
|
|
1152
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
1153
|
+
"button",
|
|
988
1154
|
{
|
|
989
|
-
|
|
990
|
-
|
|
1155
|
+
type: "button",
|
|
1156
|
+
className: itemClasses,
|
|
1157
|
+
role: "menuitem",
|
|
1158
|
+
onClick: () => {
|
|
1159
|
+
var _a2;
|
|
1160
|
+
if (item.disabled) return;
|
|
1161
|
+
(_a2 = item.onSelect) == null ? void 0 : _a2.call(item);
|
|
1162
|
+
setOpen(false);
|
|
1163
|
+
},
|
|
1164
|
+
children: contentNode
|
|
1165
|
+
},
|
|
1166
|
+
key
|
|
1167
|
+
);
|
|
1168
|
+
}) }) : null;
|
|
1169
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
1170
|
+
CraftPopover,
|
|
1171
|
+
{
|
|
1172
|
+
trigger,
|
|
1173
|
+
content: menuContent,
|
|
1174
|
+
open: isOpen,
|
|
1175
|
+
onOpenChange: setOpen,
|
|
1176
|
+
align,
|
|
1177
|
+
tone,
|
|
1178
|
+
className
|
|
1179
|
+
}
|
|
1180
|
+
);
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
// src/components/craft-command-palette.tsx
|
|
1184
|
+
var React13 = __toESM(require("react"), 1);
|
|
1185
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1186
|
+
function CraftCommandPalette({
|
|
1187
|
+
items,
|
|
1188
|
+
open,
|
|
1189
|
+
defaultOpen = false,
|
|
1190
|
+
onOpenChange,
|
|
1191
|
+
trigger,
|
|
1192
|
+
title = "Command Palette",
|
|
1193
|
+
placeholder = "Search commands...",
|
|
1194
|
+
emptyText = "No results found.",
|
|
1195
|
+
tone,
|
|
1196
|
+
className
|
|
1197
|
+
}) {
|
|
1198
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React13.useState(defaultOpen);
|
|
1199
|
+
const isControlled = typeof open === "boolean";
|
|
1200
|
+
const isOpen = isControlled ? open : uncontrolledOpen;
|
|
1201
|
+
const [query, setQuery] = React13.useState("");
|
|
1202
|
+
const setOpen = React13.useCallback(
|
|
1203
|
+
(next) => {
|
|
1204
|
+
if (!isControlled) setUncontrolledOpen(next);
|
|
1205
|
+
onOpenChange == null ? void 0 : onOpenChange(next);
|
|
1206
|
+
},
|
|
1207
|
+
[isControlled, onOpenChange]
|
|
1208
|
+
);
|
|
1209
|
+
const filtered = React13.useMemo(() => {
|
|
1210
|
+
const q = query.trim().toLowerCase();
|
|
1211
|
+
if (!q) return items;
|
|
1212
|
+
return items.filter((item) => {
|
|
1213
|
+
var _a, _b;
|
|
1214
|
+
const haystack = [
|
|
1215
|
+
item.label,
|
|
1216
|
+
(_a = item.description) != null ? _a : "",
|
|
1217
|
+
...(_b = item.keywords) != null ? _b : []
|
|
1218
|
+
].join(" ").toLowerCase();
|
|
1219
|
+
return haystack.includes(q);
|
|
1220
|
+
});
|
|
1221
|
+
}, [items, query]);
|
|
1222
|
+
React13.useEffect(() => {
|
|
1223
|
+
if (!isOpen) setQuery("");
|
|
1224
|
+
}, [isOpen]);
|
|
1225
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1226
|
+
CraftModal,
|
|
1227
|
+
{
|
|
1228
|
+
open: isOpen,
|
|
1229
|
+
onOpenChange: setOpen,
|
|
1230
|
+
trigger,
|
|
1231
|
+
title,
|
|
1232
|
+
tone,
|
|
1233
|
+
className: cn("max-w-xl", className),
|
|
1234
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-4", children: [
|
|
1235
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1236
|
+
CraftInput,
|
|
1237
|
+
{
|
|
1238
|
+
type: "search",
|
|
1239
|
+
placeholder,
|
|
1240
|
+
value: query,
|
|
1241
|
+
onChange: (event) => setQuery(event.target.value)
|
|
1242
|
+
}
|
|
1243
|
+
),
|
|
1244
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-2", children: [
|
|
1245
|
+
filtered.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "rounded-2xl border border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.12)] p-4 text-sm text-[rgb(var(--nc-fg-muted))]", children: emptyText }),
|
|
1246
|
+
filtered.map((item) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
1247
|
+
"button",
|
|
1248
|
+
{
|
|
1249
|
+
type: "button",
|
|
1250
|
+
disabled: item.disabled,
|
|
1251
|
+
onClick: () => {
|
|
1252
|
+
var _a;
|
|
1253
|
+
if (item.disabled) return;
|
|
1254
|
+
(_a = item.onSelect) == null ? void 0 : _a.call(item);
|
|
1255
|
+
setOpen(false);
|
|
1256
|
+
},
|
|
1257
|
+
className: cn(
|
|
1258
|
+
"flex w-full items-start gap-3 rounded-2xl border border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.08)] px-4 py-3 text-left transition",
|
|
1259
|
+
item.disabled ? "cursor-not-allowed opacity-60" : "hover:bg-[rgb(var(--nc-surface)/0.16)]"
|
|
1260
|
+
),
|
|
1261
|
+
children: [
|
|
1262
|
+
item.icon && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "mt-1", children: item.icon }),
|
|
1263
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { children: [
|
|
1264
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "block text-sm font-semibold", children: item.label }),
|
|
1265
|
+
item.description && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "block text-xs text-[rgb(var(--nc-fg-muted))]", children: item.description })
|
|
1266
|
+
] })
|
|
1267
|
+
]
|
|
1268
|
+
},
|
|
1269
|
+
item.id
|
|
1270
|
+
))
|
|
1271
|
+
] })
|
|
1272
|
+
] })
|
|
1273
|
+
}
|
|
1274
|
+
);
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
// src/components/craft-link.tsx
|
|
1278
|
+
var import_link = __toESM(require("next/link"), 1);
|
|
1279
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1280
|
+
var variantClasses5 = {
|
|
1281
|
+
default: "text-[rgb(var(--nc-accent-1))] hover:text-[rgb(var(--nc-accent-1))]",
|
|
1282
|
+
muted: "text-[rgb(var(--nc-fg-muted))] hover:text-[rgb(var(--nc-fg))]",
|
|
1283
|
+
button: "inline-flex items-center rounded-xl border border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.12)] px-4 py-2 text-sm font-semibold text-[rgb(var(--nc-fg))] transition hover:bg-[rgb(var(--nc-surface)/0.2)]",
|
|
1284
|
+
ghost: "inline-flex items-center rounded-xl px-4 py-2 text-sm font-semibold text-[rgb(var(--nc-fg))] transition hover:bg-[rgb(var(--nc-surface)/0.18)]"
|
|
1285
|
+
};
|
|
1286
|
+
function CraftLink({
|
|
1287
|
+
variant = "default",
|
|
1288
|
+
underline = false,
|
|
1289
|
+
tone,
|
|
1290
|
+
className,
|
|
1291
|
+
children,
|
|
1292
|
+
...props
|
|
1293
|
+
}) {
|
|
1294
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1295
|
+
import_link.default,
|
|
1296
|
+
{
|
|
1297
|
+
className: cn(
|
|
1298
|
+
"transition-colors",
|
|
1299
|
+
variantClasses5[variant],
|
|
1300
|
+
underline && "underline underline-offset-4",
|
|
1301
|
+
className
|
|
1302
|
+
),
|
|
1303
|
+
"data-nc-theme": tone,
|
|
1304
|
+
...props,
|
|
1305
|
+
children
|
|
1306
|
+
}
|
|
1307
|
+
);
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
// src/components/craft-stat-card.tsx
|
|
1311
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1312
|
+
var trendClasses = {
|
|
1313
|
+
up: "text-emerald-300",
|
|
1314
|
+
down: "text-rose-300",
|
|
1315
|
+
neutral: "text-[rgb(var(--nc-fg-muted))]"
|
|
1316
|
+
};
|
|
1317
|
+
function CraftStatCard({
|
|
1318
|
+
label,
|
|
1319
|
+
value,
|
|
1320
|
+
delta,
|
|
1321
|
+
trend = "neutral",
|
|
1322
|
+
icon,
|
|
1323
|
+
footer,
|
|
1324
|
+
tone,
|
|
1325
|
+
className,
|
|
1326
|
+
...props
|
|
1327
|
+
}) {
|
|
1328
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
1329
|
+
CraftCard,
|
|
1330
|
+
{
|
|
1331
|
+
className: cn("space-y-3", className),
|
|
1332
|
+
tone,
|
|
1333
|
+
...props,
|
|
1334
|
+
children: [
|
|
1335
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1336
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: label }),
|
|
1337
|
+
icon && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "text-[rgb(var(--nc-fg-soft))]", children: icon })
|
|
1338
|
+
] }),
|
|
1339
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-3xl font-semibold", children: value }),
|
|
1340
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center justify-between text-xs", children: [
|
|
1341
|
+
delta && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: trendClasses[trend], children: delta }),
|
|
1342
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[rgb(var(--nc-fg-muted))]", children: footer })
|
|
1343
|
+
] })
|
|
1344
|
+
]
|
|
1345
|
+
}
|
|
1346
|
+
);
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
// src/components/craft-date-picker.tsx
|
|
1350
|
+
var React14 = __toESM(require("react"), 1);
|
|
1351
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1352
|
+
var WEEK_DAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
1353
|
+
function formatDate(date) {
|
|
1354
|
+
const year = date.getFullYear();
|
|
1355
|
+
const month = `${date.getMonth() + 1}`.padStart(2, "0");
|
|
1356
|
+
const day = `${date.getDate()}`.padStart(2, "0");
|
|
1357
|
+
return `${year}-${month}-${day}`;
|
|
1358
|
+
}
|
|
1359
|
+
function parseDate(value) {
|
|
1360
|
+
if (!value) return null;
|
|
1361
|
+
const [year, month, day] = value.split("-").map(Number);
|
|
1362
|
+
if (!year || !month || !day) return null;
|
|
1363
|
+
return new Date(year, month - 1, day);
|
|
1364
|
+
}
|
|
1365
|
+
function isSameDay(a, b) {
|
|
1366
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
1367
|
+
}
|
|
1368
|
+
function isOutsideRange(date, min, max) {
|
|
1369
|
+
const minDate = parseDate(min);
|
|
1370
|
+
const maxDate = parseDate(max);
|
|
1371
|
+
if (minDate && date < minDate) return true;
|
|
1372
|
+
if (maxDate && date > maxDate) return true;
|
|
1373
|
+
return false;
|
|
1374
|
+
}
|
|
1375
|
+
function CraftDatePicker({
|
|
1376
|
+
value,
|
|
1377
|
+
defaultValue,
|
|
1378
|
+
onChange,
|
|
1379
|
+
tone,
|
|
1380
|
+
min,
|
|
1381
|
+
max,
|
|
1382
|
+
placeholder = "Select date",
|
|
1383
|
+
className
|
|
1384
|
+
}) {
|
|
1385
|
+
const [open, setOpen] = React14.useState(false);
|
|
1386
|
+
const [uncontrolledValue, setUncontrolledValue] = React14.useState(defaultValue != null ? defaultValue : "");
|
|
1387
|
+
const isControlled = value !== void 0;
|
|
1388
|
+
const selectedValue = isControlled ? value != null ? value : "" : uncontrolledValue;
|
|
1389
|
+
const selectedDate = parseDate(selectedValue);
|
|
1390
|
+
const initialMonth = selectedDate != null ? selectedDate : /* @__PURE__ */ new Date();
|
|
1391
|
+
const [viewDate, setViewDate] = React14.useState(initialMonth);
|
|
1392
|
+
React14.useEffect(() => {
|
|
1393
|
+
if (selectedDate) setViewDate(selectedDate);
|
|
1394
|
+
}, [selectedDate]);
|
|
1395
|
+
const wrapperRef = React14.useRef(null);
|
|
1396
|
+
React14.useEffect(() => {
|
|
1397
|
+
if (!open) return;
|
|
1398
|
+
const handleClick = (event) => {
|
|
1399
|
+
var _a;
|
|
1400
|
+
if (!((_a = wrapperRef.current) == null ? void 0 : _a.contains(event.target))) {
|
|
1401
|
+
setOpen(false);
|
|
1402
|
+
}
|
|
1403
|
+
};
|
|
1404
|
+
const handleKey = (event) => {
|
|
1405
|
+
if (event.key === "Escape") setOpen(false);
|
|
1406
|
+
};
|
|
1407
|
+
document.addEventListener("mousedown", handleClick);
|
|
1408
|
+
document.addEventListener("keydown", handleKey);
|
|
1409
|
+
return () => {
|
|
1410
|
+
document.removeEventListener("mousedown", handleClick);
|
|
1411
|
+
document.removeEventListener("keydown", handleKey);
|
|
1412
|
+
};
|
|
1413
|
+
}, [open]);
|
|
1414
|
+
const setValue = React14.useCallback(
|
|
1415
|
+
(next) => {
|
|
1416
|
+
if (!isControlled) setUncontrolledValue(next);
|
|
1417
|
+
onChange == null ? void 0 : onChange(next);
|
|
1418
|
+
},
|
|
1419
|
+
[isControlled, onChange]
|
|
1420
|
+
);
|
|
1421
|
+
const monthStart = new Date(viewDate.getFullYear(), viewDate.getMonth(), 1);
|
|
1422
|
+
const monthEnd = new Date(viewDate.getFullYear(), viewDate.getMonth() + 1, 0);
|
|
1423
|
+
const startDay = monthStart.getDay();
|
|
1424
|
+
const daysInMonth = monthEnd.getDate();
|
|
1425
|
+
const cells = Array.from({ length: startDay + daysInMonth }, (_, i) => {
|
|
1426
|
+
const dayNumber = i - startDay + 1;
|
|
1427
|
+
if (dayNumber < 1) return null;
|
|
1428
|
+
return new Date(viewDate.getFullYear(), viewDate.getMonth(), dayNumber);
|
|
1429
|
+
});
|
|
1430
|
+
const handleDaySelect = (date) => {
|
|
1431
|
+
if (isOutsideRange(date, min, max)) return;
|
|
1432
|
+
const next = formatDate(date);
|
|
1433
|
+
setValue(next);
|
|
1434
|
+
setOpen(false);
|
|
1435
|
+
};
|
|
1436
|
+
const handleKeyDown = (event) => {
|
|
1437
|
+
if (!open) return;
|
|
1438
|
+
if (!selectedDate) return;
|
|
1439
|
+
const next = new Date(selectedDate);
|
|
1440
|
+
if (event.key === "ArrowRight") next.setDate(next.getDate() + 1);
|
|
1441
|
+
if (event.key === "ArrowLeft") next.setDate(next.getDate() - 1);
|
|
1442
|
+
if (event.key === "ArrowDown") next.setDate(next.getDate() + 7);
|
|
1443
|
+
if (event.key === "ArrowUp") next.setDate(next.getDate() - 7);
|
|
1444
|
+
if (event.key === "Enter") {
|
|
1445
|
+
event.preventDefault();
|
|
1446
|
+
handleDaySelect(selectedDate);
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
if (next.getTime() !== selectedDate.getTime()) {
|
|
1450
|
+
event.preventDefault();
|
|
1451
|
+
if (!isOutsideRange(next, min, max)) {
|
|
1452
|
+
setValue(formatDate(next));
|
|
1453
|
+
setViewDate(next);
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "relative w-full", "data-nc-theme": tone, ref: wrapperRef, children: [
|
|
1458
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
1459
|
+
"button",
|
|
1460
|
+
{
|
|
1461
|
+
type: "button",
|
|
1462
|
+
onClick: () => setOpen((prev) => !prev),
|
|
1463
|
+
className: cn(
|
|
1464
|
+
"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",
|
|
1465
|
+
"shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
|
|
1466
|
+
"transition-all duration-300",
|
|
1467
|
+
"border-[rgb(var(--nc-border)/0.35)]",
|
|
1468
|
+
"focus:outline-none focus:ring-4 focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
|
|
1469
|
+
className
|
|
1470
|
+
),
|
|
1471
|
+
children: [
|
|
1472
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: selectedValue ? "text-[rgb(var(--nc-fg))]" : "text-[rgb(var(--nc-fg-soft))]", children: selectedValue || placeholder }),
|
|
1473
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.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_runtime25.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" }) })
|
|
1474
|
+
]
|
|
1475
|
+
}
|
|
1476
|
+
),
|
|
1477
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
1478
|
+
"div",
|
|
1479
|
+
{
|
|
1480
|
+
className: cn(
|
|
1481
|
+
"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"
|
|
991
1482
|
),
|
|
992
1483
|
onKeyDown: handleKeyDown,
|
|
993
1484
|
tabIndex: -1,
|
|
994
1485
|
children: [
|
|
995
|
-
/* @__PURE__ */ (0,
|
|
996
|
-
/* @__PURE__ */ (0,
|
|
1486
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1487
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
997
1488
|
"button",
|
|
998
1489
|
{
|
|
999
1490
|
type: "button",
|
|
@@ -1004,8 +1495,8 @@ function CraftDatePicker({
|
|
|
1004
1495
|
children: "Prev"
|
|
1005
1496
|
}
|
|
1006
1497
|
),
|
|
1007
|
-
/* @__PURE__ */ (0,
|
|
1008
|
-
/* @__PURE__ */ (0,
|
|
1498
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "text-sm font-semibold", children: viewDate.toLocaleString(void 0, { month: "long", year: "numeric" }) }),
|
|
1499
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1009
1500
|
"button",
|
|
1010
1501
|
{
|
|
1011
1502
|
type: "button",
|
|
@@ -1017,94 +1508,1522 @@ function CraftDatePicker({
|
|
|
1017
1508
|
}
|
|
1018
1509
|
)
|
|
1019
1510
|
] }),
|
|
1020
|
-
/* @__PURE__ */ (0,
|
|
1021
|
-
/* @__PURE__ */ (0,
|
|
1022
|
-
if (!date) return /* @__PURE__ */ (0,
|
|
1023
|
-
const disabled = isOutsideRange(date, min, max);
|
|
1024
|
-
const selected = selectedDate && isSameDay(date, selectedDate);
|
|
1025
|
-
return /* @__PURE__ */ (0,
|
|
1511
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.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_runtime25.jsx)("div", { className: "text-center", children: day }, day)) }),
|
|
1512
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "mt-2 grid grid-cols-7 gap-2", children: cells.map((date, index) => {
|
|
1513
|
+
if (!date) return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", {}, `empty-${index}`);
|
|
1514
|
+
const disabled = isOutsideRange(date, min, max);
|
|
1515
|
+
const selected = selectedDate && isSameDay(date, selectedDate);
|
|
1516
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1517
|
+
"button",
|
|
1518
|
+
{
|
|
1519
|
+
type: "button",
|
|
1520
|
+
onClick: () => handleDaySelect(date),
|
|
1521
|
+
disabled,
|
|
1522
|
+
className: cn(
|
|
1523
|
+
"rounded-lg py-2 text-sm transition-all",
|
|
1524
|
+
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)]",
|
|
1525
|
+
disabled && "opacity-40 hover:bg-transparent"
|
|
1526
|
+
),
|
|
1527
|
+
children: date.getDate()
|
|
1528
|
+
},
|
|
1529
|
+
date.toISOString()
|
|
1530
|
+
);
|
|
1531
|
+
}) })
|
|
1532
|
+
]
|
|
1533
|
+
}
|
|
1534
|
+
)
|
|
1535
|
+
] });
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
// src/components/craft-icon.tsx
|
|
1539
|
+
var React15 = __toESM(require("react"), 1);
|
|
1540
|
+
var import_dynamic = require("lucide-react/dynamic");
|
|
1541
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1542
|
+
var CraftIconContext = React15.createContext(null);
|
|
1543
|
+
function CraftIconProvider({ icons, children }) {
|
|
1544
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CraftIconContext.Provider, { value: icons, children });
|
|
1545
|
+
}
|
|
1546
|
+
function CraftIcon({
|
|
1547
|
+
name,
|
|
1548
|
+
className,
|
|
1549
|
+
"aria-label": ariaLabel,
|
|
1550
|
+
icons,
|
|
1551
|
+
useLucide = true
|
|
1552
|
+
}) {
|
|
1553
|
+
const contextRegistry = React15.useContext(CraftIconContext);
|
|
1554
|
+
const registry = icons != null ? icons : contextRegistry;
|
|
1555
|
+
const icon = registry == null ? void 0 : registry[name];
|
|
1556
|
+
if (!icon) {
|
|
1557
|
+
if (!useLucide) return null;
|
|
1558
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1559
|
+
import_dynamic.DynamicIcon,
|
|
1560
|
+
{
|
|
1561
|
+
name,
|
|
1562
|
+
className,
|
|
1563
|
+
"aria-hidden": ariaLabel ? void 0 : true,
|
|
1564
|
+
"aria-label": ariaLabel
|
|
1565
|
+
}
|
|
1566
|
+
);
|
|
1567
|
+
}
|
|
1568
|
+
if (React15.isValidElement(icon)) {
|
|
1569
|
+
return React15.cloneElement(icon, {
|
|
1570
|
+
className: cn(icon.props.className, className),
|
|
1571
|
+
"aria-hidden": ariaLabel ? void 0 : true,
|
|
1572
|
+
"aria-label": ariaLabel
|
|
1573
|
+
});
|
|
1574
|
+
}
|
|
1575
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className, "aria-label": ariaLabel, children: icon });
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
// src/components/craft-number-input.tsx
|
|
1579
|
+
var React16 = __toESM(require("react"), 1);
|
|
1580
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1581
|
+
var CraftNumberInput = React16.forwardRef(({ className, tone, ...props }, ref) => {
|
|
1582
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "relative w-full", "data-nc-theme": tone, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
1583
|
+
"input",
|
|
1584
|
+
{
|
|
1585
|
+
ref,
|
|
1586
|
+
type: "number",
|
|
1587
|
+
className: cn(
|
|
1588
|
+
"w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
|
|
1589
|
+
"shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
|
|
1590
|
+
"focus:outline-none focus:ring-4",
|
|
1591
|
+
"transition-all duration-300",
|
|
1592
|
+
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1593
|
+
"border-[rgb(var(--nc-border)/0.35)]",
|
|
1594
|
+
"focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
|
|
1595
|
+
"px-5 py-3 text-base",
|
|
1596
|
+
className
|
|
1597
|
+
),
|
|
1598
|
+
...props
|
|
1599
|
+
}
|
|
1600
|
+
) });
|
|
1601
|
+
});
|
|
1602
|
+
CraftNumberInput.displayName = "CraftNumberInput";
|
|
1603
|
+
|
|
1604
|
+
// src/components/craft-currency-input.tsx
|
|
1605
|
+
var React17 = __toESM(require("react"), 1);
|
|
1606
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1607
|
+
var CraftCurrencyInput = React17.forwardRef(({ className, tone, currencySymbol = "$", ...props }, ref) => {
|
|
1608
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "relative w-full", "data-nc-theme": tone, children: [
|
|
1609
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "pointer-events-none absolute left-4 top-1/2 -translate-y-1/2 text-[rgb(var(--nc-fg-soft))]", children: currencySymbol }),
|
|
1610
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
1611
|
+
"input",
|
|
1612
|
+
{
|
|
1613
|
+
ref,
|
|
1614
|
+
type: "text",
|
|
1615
|
+
inputMode: "decimal",
|
|
1616
|
+
className: cn(
|
|
1617
|
+
"w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
|
|
1618
|
+
"shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
|
|
1619
|
+
"focus:outline-none focus:ring-4",
|
|
1620
|
+
"transition-all duration-300",
|
|
1621
|
+
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1622
|
+
"border-[rgb(var(--nc-border)/0.35)]",
|
|
1623
|
+
"focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
|
|
1624
|
+
"placeholder:text-[rgb(var(--nc-fg-soft))]",
|
|
1625
|
+
"px-5 py-3 pl-9 text-base",
|
|
1626
|
+
className
|
|
1627
|
+
),
|
|
1628
|
+
...props
|
|
1629
|
+
}
|
|
1630
|
+
)
|
|
1631
|
+
] });
|
|
1632
|
+
});
|
|
1633
|
+
CraftCurrencyInput.displayName = "CraftCurrencyInput";
|
|
1634
|
+
|
|
1635
|
+
// src/components/craft-form.tsx
|
|
1636
|
+
var React18 = __toESM(require("react"), 1);
|
|
1637
|
+
var import_react_hook_form2 = require("react-hook-form");
|
|
1638
|
+
|
|
1639
|
+
// src/components/craft-submit-button.tsx
|
|
1640
|
+
var import_react_hook_form = require("react-hook-form");
|
|
1641
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1642
|
+
function CraftSubmitButton({
|
|
1643
|
+
className,
|
|
1644
|
+
tone,
|
|
1645
|
+
loading,
|
|
1646
|
+
loadingLabel = "Submitting...",
|
|
1647
|
+
disableWhenInvalid = true,
|
|
1648
|
+
disabled,
|
|
1649
|
+
children,
|
|
1650
|
+
...props
|
|
1651
|
+
}) {
|
|
1652
|
+
var _a, _b, _c, _d;
|
|
1653
|
+
const form = (0, import_react_hook_form.useFormContext)();
|
|
1654
|
+
const isSubmitting = (_b = loading != null ? loading : (_a = form == null ? void 0 : form.formState) == null ? void 0 : _a.isSubmitting) != null ? _b : false;
|
|
1655
|
+
const isValid = (_d = (_c = form == null ? void 0 : form.formState) == null ? void 0 : _c.isValid) != null ? _d : true;
|
|
1656
|
+
const isDisabled = disabled || isSubmitting || disableWhenInvalid && !isValid;
|
|
1657
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
1658
|
+
"button",
|
|
1659
|
+
{
|
|
1660
|
+
type: "submit",
|
|
1661
|
+
className: cn(
|
|
1662
|
+
"relative inline-flex items-center justify-center gap-2 rounded-xl px-6 py-2 text-sm font-semibold",
|
|
1663
|
+
"bg-linear-to-br from-[rgb(var(--nc-accent-1))] via-[rgb(var(--nc-accent-2))] to-[rgb(var(--nc-accent-3))]",
|
|
1664
|
+
"text-white shadow-[0_12px_30px_rgb(var(--nc-accent-1)/0.35)]",
|
|
1665
|
+
"transition-all duration-200",
|
|
1666
|
+
"hover:shadow-[0_16px_36px_rgb(var(--nc-accent-1)/0.5)] hover:scale-[1.02] active:scale-[0.98]",
|
|
1667
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[rgb(var(--nc-accent-1)/0.6)]",
|
|
1668
|
+
"disabled:opacity-60 disabled:cursor-not-allowed disabled:hover:scale-100",
|
|
1669
|
+
className
|
|
1670
|
+
),
|
|
1671
|
+
"data-nc-theme": tone,
|
|
1672
|
+
disabled: isDisabled,
|
|
1673
|
+
...props,
|
|
1674
|
+
children: [
|
|
1675
|
+
isSubmitting && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "inline-flex h-4 w-4 animate-spin rounded-full border-2 border-white/60 border-t-white" }),
|
|
1676
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: isSubmitting ? loadingLabel : children })
|
|
1677
|
+
]
|
|
1678
|
+
}
|
|
1679
|
+
);
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
// src/components/craft-form.tsx
|
|
1683
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1684
|
+
function CraftForm({
|
|
1685
|
+
form,
|
|
1686
|
+
onSubmit,
|
|
1687
|
+
open,
|
|
1688
|
+
defaultOpen = false,
|
|
1689
|
+
onOpenChange,
|
|
1690
|
+
trigger,
|
|
1691
|
+
title,
|
|
1692
|
+
description,
|
|
1693
|
+
submitLabel = "Save",
|
|
1694
|
+
cancelLabel = "Cancel",
|
|
1695
|
+
tone,
|
|
1696
|
+
className,
|
|
1697
|
+
children,
|
|
1698
|
+
footer,
|
|
1699
|
+
disableSubmitWhenInvalid = true,
|
|
1700
|
+
closeOnSubmit = true,
|
|
1701
|
+
formClassName
|
|
1702
|
+
}) {
|
|
1703
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React18.useState(defaultOpen);
|
|
1704
|
+
const isControlled = typeof open === "boolean";
|
|
1705
|
+
const isOpen = isControlled ? open : uncontrolledOpen;
|
|
1706
|
+
const setOpen = React18.useCallback(
|
|
1707
|
+
(next) => {
|
|
1708
|
+
if (!isControlled) setUncontrolledOpen(next);
|
|
1709
|
+
onOpenChange == null ? void 0 : onOpenChange(next);
|
|
1710
|
+
},
|
|
1711
|
+
[isControlled, onOpenChange]
|
|
1712
|
+
);
|
|
1713
|
+
const formId = React18.useId();
|
|
1714
|
+
const handleSubmit = form.handleSubmit(async (values) => {
|
|
1715
|
+
await onSubmit(values);
|
|
1716
|
+
if (closeOnSubmit) setOpen(false);
|
|
1717
|
+
});
|
|
1718
|
+
const footerContent = footer != null ? footer : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-wrap items-center justify-end gap-3", children: [
|
|
1719
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(CraftButton, { type: "button", variant: "ghost", onClick: () => setOpen(false), children: cancelLabel }),
|
|
1720
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1721
|
+
CraftSubmitButton,
|
|
1722
|
+
{
|
|
1723
|
+
form: formId,
|
|
1724
|
+
disableWhenInvalid: disableSubmitWhenInvalid,
|
|
1725
|
+
children: submitLabel
|
|
1726
|
+
}
|
|
1727
|
+
)
|
|
1728
|
+
] });
|
|
1729
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react_hook_form2.FormProvider, { ...form, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1730
|
+
CraftModal,
|
|
1731
|
+
{
|
|
1732
|
+
open: isOpen,
|
|
1733
|
+
onOpenChange: setOpen,
|
|
1734
|
+
trigger,
|
|
1735
|
+
title,
|
|
1736
|
+
description,
|
|
1737
|
+
tone,
|
|
1738
|
+
className,
|
|
1739
|
+
footer: footerContent,
|
|
1740
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1741
|
+
"form",
|
|
1742
|
+
{
|
|
1743
|
+
id: formId,
|
|
1744
|
+
onSubmit: handleSubmit,
|
|
1745
|
+
className: cn("space-y-5", formClassName),
|
|
1746
|
+
children
|
|
1747
|
+
}
|
|
1748
|
+
)
|
|
1749
|
+
}
|
|
1750
|
+
) });
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
// src/components/craft-form-builder.tsx
|
|
1754
|
+
var React19 = __toESM(require("react"), 1);
|
|
1755
|
+
var import_react_hook_form4 = require("react-hook-form");
|
|
1756
|
+
|
|
1757
|
+
// src/components/craft-form-field.tsx
|
|
1758
|
+
var import_react_hook_form3 = require("react-hook-form");
|
|
1759
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1760
|
+
function getFieldError(errors, name) {
|
|
1761
|
+
if (!errors || typeof errors !== "object") return void 0;
|
|
1762
|
+
const segments = name.split(".");
|
|
1763
|
+
let current = errors;
|
|
1764
|
+
for (const segment of segments) {
|
|
1765
|
+
if (!current || typeof current !== "object") return void 0;
|
|
1766
|
+
current = current[segment];
|
|
1767
|
+
}
|
|
1768
|
+
return current;
|
|
1769
|
+
}
|
|
1770
|
+
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))]";
|
|
1771
|
+
function CraftFormField({
|
|
1772
|
+
name,
|
|
1773
|
+
label,
|
|
1774
|
+
description,
|
|
1775
|
+
type = "text",
|
|
1776
|
+
options = [],
|
|
1777
|
+
placeholder,
|
|
1778
|
+
tone,
|
|
1779
|
+
className,
|
|
1780
|
+
inputClassName,
|
|
1781
|
+
labelClassName,
|
|
1782
|
+
descriptionClassName,
|
|
1783
|
+
rules,
|
|
1784
|
+
disabled,
|
|
1785
|
+
fieldProps
|
|
1786
|
+
}) {
|
|
1787
|
+
const { register, control, formState } = (0, import_react_hook_form3.useFormContext)();
|
|
1788
|
+
const error = getFieldError(formState.errors, name);
|
|
1789
|
+
const errorMessage = typeof (error == null ? void 0 : error.message) === "string" ? error.message : void 0;
|
|
1790
|
+
if (type === "hidden") {
|
|
1791
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("input", { type: "hidden", ...register(name, rules) });
|
|
1792
|
+
}
|
|
1793
|
+
const labelNode = label ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1794
|
+
"label",
|
|
1795
|
+
{
|
|
1796
|
+
htmlFor: name,
|
|
1797
|
+
className: cn(
|
|
1798
|
+
"text-sm font-semibold text-[rgb(var(--nc-fg))]",
|
|
1799
|
+
labelClassName
|
|
1800
|
+
),
|
|
1801
|
+
children: label
|
|
1802
|
+
}
|
|
1803
|
+
) : null;
|
|
1804
|
+
const descriptionNode = description ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1805
|
+
"p",
|
|
1806
|
+
{
|
|
1807
|
+
className: cn(
|
|
1808
|
+
"text-xs text-[rgb(var(--nc-fg-muted))]",
|
|
1809
|
+
descriptionClassName
|
|
1810
|
+
),
|
|
1811
|
+
children: description
|
|
1812
|
+
}
|
|
1813
|
+
) : null;
|
|
1814
|
+
const errorNode = errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "text-xs text-[rgb(var(--nc-accent-3))]", children: errorMessage }) : null;
|
|
1815
|
+
const renderInput = () => {
|
|
1816
|
+
if (type === "textarea") {
|
|
1817
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1818
|
+
CraftTextarea,
|
|
1819
|
+
{
|
|
1820
|
+
id: name,
|
|
1821
|
+
placeholder,
|
|
1822
|
+
tone,
|
|
1823
|
+
className: inputClassName,
|
|
1824
|
+
disabled,
|
|
1825
|
+
...fieldProps,
|
|
1826
|
+
...register(name, rules)
|
|
1827
|
+
}
|
|
1828
|
+
);
|
|
1829
|
+
}
|
|
1830
|
+
if (type === "select" || type === "multiselect") {
|
|
1831
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
1832
|
+
CraftSelect,
|
|
1833
|
+
{
|
|
1834
|
+
id: name,
|
|
1835
|
+
tone,
|
|
1836
|
+
className: inputClassName,
|
|
1837
|
+
multiple: type === "multiselect",
|
|
1838
|
+
disabled,
|
|
1839
|
+
...fieldProps,
|
|
1840
|
+
...register(name, rules),
|
|
1841
|
+
children: [
|
|
1842
|
+
placeholder && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("option", { value: "", disabled: true, children: placeholder }),
|
|
1843
|
+
options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1844
|
+
"option",
|
|
1845
|
+
{
|
|
1846
|
+
value: option.value,
|
|
1847
|
+
disabled: option.disabled,
|
|
1848
|
+
children: option.label
|
|
1849
|
+
},
|
|
1850
|
+
option.value
|
|
1851
|
+
))
|
|
1852
|
+
]
|
|
1853
|
+
}
|
|
1854
|
+
);
|
|
1855
|
+
}
|
|
1856
|
+
if (type === "checkbox") {
|
|
1857
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1858
|
+
CraftCheckbox,
|
|
1859
|
+
{
|
|
1860
|
+
tone,
|
|
1861
|
+
label,
|
|
1862
|
+
description,
|
|
1863
|
+
disabled,
|
|
1864
|
+
...fieldProps,
|
|
1865
|
+
...register(name, rules)
|
|
1866
|
+
}
|
|
1867
|
+
);
|
|
1868
|
+
}
|
|
1869
|
+
if (type === "switch") {
|
|
1870
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1871
|
+
CraftSwitch,
|
|
1872
|
+
{
|
|
1873
|
+
tone,
|
|
1874
|
+
label,
|
|
1875
|
+
disabled,
|
|
1876
|
+
...fieldProps,
|
|
1877
|
+
...register(name, rules)
|
|
1878
|
+
}
|
|
1879
|
+
);
|
|
1880
|
+
}
|
|
1881
|
+
if (type === "date") {
|
|
1882
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1883
|
+
import_react_hook_form3.Controller,
|
|
1884
|
+
{
|
|
1885
|
+
control,
|
|
1886
|
+
name,
|
|
1887
|
+
rules,
|
|
1888
|
+
render: ({ field }) => {
|
|
1889
|
+
var _a;
|
|
1890
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1891
|
+
CraftDatePicker,
|
|
1892
|
+
{
|
|
1893
|
+
value: (_a = field.value) != null ? _a : "",
|
|
1894
|
+
onChange: field.onChange,
|
|
1895
|
+
tone,
|
|
1896
|
+
placeholder,
|
|
1897
|
+
...fieldProps
|
|
1898
|
+
}
|
|
1899
|
+
);
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
);
|
|
1903
|
+
}
|
|
1904
|
+
if (type === "number") {
|
|
1905
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1906
|
+
CraftNumberInput,
|
|
1907
|
+
{
|
|
1908
|
+
id: name,
|
|
1909
|
+
tone,
|
|
1910
|
+
placeholder,
|
|
1911
|
+
className: inputClassName,
|
|
1912
|
+
disabled,
|
|
1913
|
+
...fieldProps,
|
|
1914
|
+
...register(name, rules)
|
|
1915
|
+
}
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
if (type === "currency") {
|
|
1919
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1920
|
+
CraftCurrencyInput,
|
|
1921
|
+
{
|
|
1922
|
+
id: name,
|
|
1923
|
+
tone,
|
|
1924
|
+
placeholder,
|
|
1925
|
+
className: inputClassName,
|
|
1926
|
+
disabled,
|
|
1927
|
+
...fieldProps,
|
|
1928
|
+
...register(name, rules)
|
|
1929
|
+
}
|
|
1930
|
+
);
|
|
1931
|
+
}
|
|
1932
|
+
if (type === "radio") {
|
|
1933
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "grid gap-3", children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
1934
|
+
"label",
|
|
1935
|
+
{
|
|
1936
|
+
className: cn(
|
|
1937
|
+
"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))]",
|
|
1938
|
+
"transition-all duration-200",
|
|
1939
|
+
"focus-within:ring-2 focus-within:ring-[rgb(var(--nc-accent-1)/0.5)]",
|
|
1940
|
+
option.disabled ? "opacity-60" : "cursor-pointer"
|
|
1941
|
+
),
|
|
1942
|
+
"data-nc-theme": tone,
|
|
1943
|
+
children: [
|
|
1944
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1945
|
+
"input",
|
|
1946
|
+
{
|
|
1947
|
+
type: "radio",
|
|
1948
|
+
value: option.value,
|
|
1949
|
+
disabled: option.disabled || disabled,
|
|
1950
|
+
className: "h-4 w-4 accent-[rgb(var(--nc-accent-1))]",
|
|
1951
|
+
...fieldProps,
|
|
1952
|
+
...register(name, rules)
|
|
1953
|
+
}
|
|
1954
|
+
),
|
|
1955
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { children: option.label })
|
|
1956
|
+
]
|
|
1957
|
+
},
|
|
1958
|
+
option.value
|
|
1959
|
+
)) });
|
|
1960
|
+
}
|
|
1961
|
+
if (type === "range" || type === "slider") {
|
|
1962
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1963
|
+
"input",
|
|
1964
|
+
{
|
|
1965
|
+
id: name,
|
|
1966
|
+
type: "range",
|
|
1967
|
+
className: cn(
|
|
1968
|
+
"w-full accent-[rgb(var(--nc-accent-1))]",
|
|
1969
|
+
inputClassName
|
|
1970
|
+
),
|
|
1971
|
+
disabled,
|
|
1972
|
+
...fieldProps,
|
|
1973
|
+
...register(name, rules)
|
|
1974
|
+
}
|
|
1975
|
+
);
|
|
1976
|
+
}
|
|
1977
|
+
if (type === "file" || type === "multifile") {
|
|
1978
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1979
|
+
"input",
|
|
1980
|
+
{
|
|
1981
|
+
id: name,
|
|
1982
|
+
type: "file",
|
|
1983
|
+
multiple: type === "multifile",
|
|
1984
|
+
className: cn(
|
|
1985
|
+
baseInputClass,
|
|
1986
|
+
"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))]",
|
|
1987
|
+
inputClassName
|
|
1988
|
+
),
|
|
1989
|
+
disabled,
|
|
1990
|
+
...fieldProps,
|
|
1991
|
+
...register(name, rules)
|
|
1992
|
+
}
|
|
1993
|
+
);
|
|
1994
|
+
}
|
|
1995
|
+
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";
|
|
1996
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1997
|
+
CraftInput,
|
|
1998
|
+
{
|
|
1999
|
+
id: name,
|
|
2000
|
+
type: inputType,
|
|
2001
|
+
placeholder,
|
|
2002
|
+
tone,
|
|
2003
|
+
className: inputClassName,
|
|
2004
|
+
disabled,
|
|
2005
|
+
...fieldProps,
|
|
2006
|
+
...register(name, rules)
|
|
2007
|
+
}
|
|
2008
|
+
);
|
|
2009
|
+
};
|
|
2010
|
+
const showLabel = type !== "checkbox" && type !== "switch";
|
|
2011
|
+
const showDescriptionAbove = type !== "checkbox" && type !== "switch";
|
|
2012
|
+
const showDescriptionBelow = type === "switch";
|
|
2013
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: cn("space-y-2", className), "data-nc-theme": tone, children: [
|
|
2014
|
+
showLabel ? labelNode : null,
|
|
2015
|
+
showDescriptionAbove ? descriptionNode : null,
|
|
2016
|
+
renderInput(),
|
|
2017
|
+
showDescriptionBelow ? descriptionNode : null,
|
|
2018
|
+
errorNode
|
|
2019
|
+
] });
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
// src/components/craft-form-builder.tsx
|
|
2023
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
2024
|
+
function defaultValueForField(field) {
|
|
2025
|
+
var _a, _b, _c, _d;
|
|
2026
|
+
if (field.defaultValue !== void 0) return field.defaultValue;
|
|
2027
|
+
switch (field.type) {
|
|
2028
|
+
case "checkbox":
|
|
2029
|
+
case "switch":
|
|
2030
|
+
return false;
|
|
2031
|
+
case "number":
|
|
2032
|
+
case "slider":
|
|
2033
|
+
case "range":
|
|
2034
|
+
return (_a = field.min) != null ? _a : 0;
|
|
2035
|
+
case "multifile":
|
|
2036
|
+
return [];
|
|
2037
|
+
case "file":
|
|
2038
|
+
return null;
|
|
2039
|
+
case "multiselect":
|
|
2040
|
+
return [];
|
|
2041
|
+
case "radio":
|
|
2042
|
+
return (_d = (_c = (_b = field.options) == null ? void 0 : _b[0]) == null ? void 0 : _c.value) != null ? _d : "";
|
|
2043
|
+
default:
|
|
2044
|
+
return "";
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
function buildDefaultValues(fields, initialData) {
|
|
2048
|
+
const values = {};
|
|
2049
|
+
fields.forEach((field) => {
|
|
2050
|
+
const initialValue = initialData == null ? void 0 : initialData[field.name];
|
|
2051
|
+
if (initialValue !== void 0 && initialValue !== null) {
|
|
2052
|
+
values[field.name] = initialValue;
|
|
2053
|
+
} else {
|
|
2054
|
+
values[field.name] = defaultValueForField(field);
|
|
2055
|
+
}
|
|
2056
|
+
});
|
|
2057
|
+
return values;
|
|
2058
|
+
}
|
|
2059
|
+
function buildRules(field, getValues) {
|
|
2060
|
+
var _a;
|
|
2061
|
+
const rules = { ...field.rules };
|
|
2062
|
+
const mergeValidate = (current, next) => {
|
|
2063
|
+
if (!current) return next;
|
|
2064
|
+
if (typeof current === "function") {
|
|
2065
|
+
return (value) => {
|
|
2066
|
+
const result = current(
|
|
2067
|
+
value,
|
|
2068
|
+
getValues()
|
|
2069
|
+
);
|
|
2070
|
+
if (result !== true) return result;
|
|
2071
|
+
return next(value);
|
|
2072
|
+
};
|
|
2073
|
+
}
|
|
2074
|
+
if (typeof current === "object") {
|
|
2075
|
+
return (value) => {
|
|
2076
|
+
const entries = Object.entries(current);
|
|
2077
|
+
for (const [, validator] of entries) {
|
|
2078
|
+
const result = validator(
|
|
2079
|
+
value,
|
|
2080
|
+
getValues()
|
|
2081
|
+
);
|
|
2082
|
+
if (result !== true) return result;
|
|
2083
|
+
}
|
|
2084
|
+
return next(value);
|
|
2085
|
+
};
|
|
2086
|
+
}
|
|
2087
|
+
return next;
|
|
2088
|
+
};
|
|
2089
|
+
if (field.required && field.type !== "hidden") {
|
|
2090
|
+
if (field.type === "checkbox" || field.type === "switch") {
|
|
2091
|
+
rules.validate = mergeValidate(
|
|
2092
|
+
rules.validate,
|
|
2093
|
+
(value) => {
|
|
2094
|
+
var _a2;
|
|
2095
|
+
return value ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
|
|
2096
|
+
}
|
|
2097
|
+
);
|
|
2098
|
+
} else if (field.type === "multiselect") {
|
|
2099
|
+
rules.validate = mergeValidate(
|
|
2100
|
+
rules.validate,
|
|
2101
|
+
(value) => {
|
|
2102
|
+
var _a2;
|
|
2103
|
+
return Array.isArray(value) && value.length > 0 ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
|
|
2104
|
+
}
|
|
2105
|
+
);
|
|
2106
|
+
} else if (field.type === "file") {
|
|
2107
|
+
rules.validate = mergeValidate(
|
|
2108
|
+
rules.validate,
|
|
2109
|
+
(value) => {
|
|
2110
|
+
var _a2;
|
|
2111
|
+
return value instanceof FileList && value.length > 0 ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
|
|
2112
|
+
}
|
|
2113
|
+
);
|
|
2114
|
+
} else if (field.type === "multifile") {
|
|
2115
|
+
rules.validate = mergeValidate(
|
|
2116
|
+
rules.validate,
|
|
2117
|
+
(value) => {
|
|
2118
|
+
var _a2;
|
|
2119
|
+
return Array.isArray(value) && value.length > 0 ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
|
|
2120
|
+
}
|
|
2121
|
+
);
|
|
2122
|
+
} else {
|
|
2123
|
+
rules.required = `${String((_a = field.label) != null ? _a : field.name)} is required`;
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
if (field.min !== void 0) {
|
|
2127
|
+
rules.min = { value: field.min, message: `Min ${field.min}` };
|
|
2128
|
+
}
|
|
2129
|
+
if (field.max !== void 0) {
|
|
2130
|
+
rules.max = { value: field.max, message: `Max ${field.max}` };
|
|
2131
|
+
}
|
|
2132
|
+
if (field.type === "email") {
|
|
2133
|
+
rules.pattern = {
|
|
2134
|
+
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
2135
|
+
message: "Please enter a valid email address"
|
|
2136
|
+
};
|
|
2137
|
+
}
|
|
2138
|
+
if (field.type === "url") {
|
|
2139
|
+
rules.pattern = {
|
|
2140
|
+
value: /^https?:\/\/.+/,
|
|
2141
|
+
message: "Please enter a valid URL"
|
|
2142
|
+
};
|
|
2143
|
+
}
|
|
2144
|
+
if (field.validate) {
|
|
2145
|
+
rules.validate = mergeValidate(
|
|
2146
|
+
rules.validate,
|
|
2147
|
+
(value) => {
|
|
2148
|
+
var _a2;
|
|
2149
|
+
return (_a2 = field.validate) == null ? void 0 : _a2.call(field, value, getValues());
|
|
2150
|
+
}
|
|
2151
|
+
);
|
|
2152
|
+
}
|
|
2153
|
+
return rules;
|
|
2154
|
+
}
|
|
2155
|
+
function CraftFormBuilder({
|
|
2156
|
+
title = "Form",
|
|
2157
|
+
description,
|
|
2158
|
+
fields,
|
|
2159
|
+
initialData = null,
|
|
2160
|
+
open,
|
|
2161
|
+
defaultOpen = false,
|
|
2162
|
+
onOpenChange,
|
|
2163
|
+
trigger,
|
|
2164
|
+
submitLabel = "Submit",
|
|
2165
|
+
cancelLabel = "Cancel",
|
|
2166
|
+
resetLabel = "Reset",
|
|
2167
|
+
showReset = true,
|
|
2168
|
+
showCancel = true,
|
|
2169
|
+
tone,
|
|
2170
|
+
className,
|
|
2171
|
+
formClassName,
|
|
2172
|
+
loading = false,
|
|
2173
|
+
disableSubmitWhenInvalid = true,
|
|
2174
|
+
closeOnSubmit = true,
|
|
2175
|
+
closeOnCancel = true,
|
|
2176
|
+
onSubmit,
|
|
2177
|
+
onReset,
|
|
2178
|
+
onCancel,
|
|
2179
|
+
customValidation
|
|
2180
|
+
}) {
|
|
2181
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React19.useState(defaultOpen);
|
|
2182
|
+
const isControlled = typeof open === "boolean";
|
|
2183
|
+
const isOpen = isControlled ? open : uncontrolledOpen;
|
|
2184
|
+
const setOpen = React19.useCallback(
|
|
2185
|
+
(next) => {
|
|
2186
|
+
if (!isControlled) setUncontrolledOpen(next);
|
|
2187
|
+
onOpenChange == null ? void 0 : onOpenChange(next);
|
|
2188
|
+
},
|
|
2189
|
+
[isControlled, onOpenChange]
|
|
2190
|
+
);
|
|
2191
|
+
const defaultValues = React19.useMemo(
|
|
2192
|
+
() => buildDefaultValues(fields, initialData),
|
|
2193
|
+
[fields, initialData]
|
|
2194
|
+
);
|
|
2195
|
+
const form = (0, import_react_hook_form4.useForm)({
|
|
2196
|
+
mode: "onChange",
|
|
2197
|
+
defaultValues
|
|
2198
|
+
});
|
|
2199
|
+
const formId = React19.useId();
|
|
2200
|
+
React19.useEffect(() => {
|
|
2201
|
+
form.reset(defaultValues);
|
|
2202
|
+
}, [defaultValues, form]);
|
|
2203
|
+
const handleSubmit = form.handleSubmit(async (values) => {
|
|
2204
|
+
if (customValidation) {
|
|
2205
|
+
const customErrors = customValidation(values);
|
|
2206
|
+
if (customErrors && Object.keys(customErrors).length > 0) {
|
|
2207
|
+
Object.entries(customErrors).forEach(([key, message]) => {
|
|
2208
|
+
if (message) {
|
|
2209
|
+
form.setError(key, {
|
|
2210
|
+
type: "custom",
|
|
2211
|
+
message: String(message)
|
|
2212
|
+
});
|
|
2213
|
+
}
|
|
2214
|
+
});
|
|
2215
|
+
return;
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
await onSubmit(values);
|
|
2219
|
+
if (closeOnSubmit) setOpen(false);
|
|
2220
|
+
});
|
|
2221
|
+
const handleReset = () => {
|
|
2222
|
+
form.reset(defaultValues);
|
|
2223
|
+
onReset == null ? void 0 : onReset();
|
|
2224
|
+
};
|
|
2225
|
+
const handleCancel = () => {
|
|
2226
|
+
onCancel == null ? void 0 : onCancel();
|
|
2227
|
+
if (closeOnCancel) setOpen(false);
|
|
2228
|
+
};
|
|
2229
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react_hook_form4.FormProvider, { ...form, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
2230
|
+
CraftModal,
|
|
2231
|
+
{
|
|
2232
|
+
open: isOpen,
|
|
2233
|
+
onOpenChange: setOpen,
|
|
2234
|
+
trigger,
|
|
2235
|
+
title,
|
|
2236
|
+
description,
|
|
2237
|
+
tone,
|
|
2238
|
+
className,
|
|
2239
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-wrap items-center justify-end gap-3", children: [
|
|
2240
|
+
showReset && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
2241
|
+
CraftButton,
|
|
2242
|
+
{
|
|
2243
|
+
type: "button",
|
|
2244
|
+
variant: "outline",
|
|
2245
|
+
onClick: handleReset,
|
|
2246
|
+
disabled: loading,
|
|
2247
|
+
children: resetLabel
|
|
2248
|
+
}
|
|
2249
|
+
),
|
|
2250
|
+
showCancel && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
2251
|
+
CraftButton,
|
|
2252
|
+
{
|
|
2253
|
+
type: "button",
|
|
2254
|
+
variant: "ghost",
|
|
2255
|
+
onClick: handleCancel,
|
|
2256
|
+
disabled: loading,
|
|
2257
|
+
children: cancelLabel
|
|
2258
|
+
}
|
|
2259
|
+
),
|
|
2260
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
2261
|
+
CraftSubmitButton,
|
|
2262
|
+
{
|
|
2263
|
+
loading,
|
|
2264
|
+
disableWhenInvalid: disableSubmitWhenInvalid,
|
|
2265
|
+
form: formId,
|
|
2266
|
+
children: submitLabel
|
|
2267
|
+
}
|
|
2268
|
+
)
|
|
2269
|
+
] }),
|
|
2270
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
2271
|
+
"form",
|
|
2272
|
+
{
|
|
2273
|
+
id: formId,
|
|
2274
|
+
onSubmit: handleSubmit,
|
|
2275
|
+
className: cn("space-y-5", formClassName),
|
|
2276
|
+
children: fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "space-y-2", children: [
|
|
2277
|
+
field.helpText && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { className: "text-xs text-[rgb(var(--nc-fg-muted))]", children: field.helpText }),
|
|
2278
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
2279
|
+
CraftFormField,
|
|
2280
|
+
{
|
|
2281
|
+
name: field.name,
|
|
2282
|
+
label: field.label,
|
|
2283
|
+
description: field.description,
|
|
2284
|
+
type: field.type,
|
|
2285
|
+
placeholder: field.placeholder,
|
|
2286
|
+
options: field.options,
|
|
2287
|
+
tone,
|
|
2288
|
+
disabled: field.disabled || loading,
|
|
2289
|
+
rules: buildRules(field, form.getValues),
|
|
2290
|
+
fieldProps: {
|
|
2291
|
+
min: field.min,
|
|
2292
|
+
max: field.max,
|
|
2293
|
+
step: field.step,
|
|
2294
|
+
rows: field.rows,
|
|
2295
|
+
accept: field.accept,
|
|
2296
|
+
multiple: field.type === "multifile",
|
|
2297
|
+
...field.fieldProps
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
)
|
|
2301
|
+
] }, field.name))
|
|
2302
|
+
}
|
|
2303
|
+
)
|
|
2304
|
+
}
|
|
2305
|
+
) });
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
// src/components/craft-confirm-dialog.tsx
|
|
2309
|
+
var React20 = __toESM(require("react"), 1);
|
|
2310
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
2311
|
+
function CraftConfirmDialog({
|
|
2312
|
+
open,
|
|
2313
|
+
defaultOpen = false,
|
|
2314
|
+
onOpenChange,
|
|
2315
|
+
tone,
|
|
2316
|
+
title = "Confirm action",
|
|
2317
|
+
description,
|
|
2318
|
+
confirmLabel = "Confirm",
|
|
2319
|
+
cancelLabel = "Cancel",
|
|
2320
|
+
onConfirm,
|
|
2321
|
+
trigger,
|
|
2322
|
+
className,
|
|
2323
|
+
confirmVariant = "solid"
|
|
2324
|
+
}) {
|
|
2325
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React20.useState(defaultOpen);
|
|
2326
|
+
const isControlled = typeof open === "boolean";
|
|
2327
|
+
const isOpen = isControlled ? open : uncontrolledOpen;
|
|
2328
|
+
const setOpen = React20.useCallback(
|
|
2329
|
+
(next) => {
|
|
2330
|
+
if (!isControlled) setUncontrolledOpen(next);
|
|
2331
|
+
onOpenChange == null ? void 0 : onOpenChange(next);
|
|
2332
|
+
},
|
|
2333
|
+
[isControlled, onOpenChange]
|
|
2334
|
+
);
|
|
2335
|
+
const [isLoading, setIsLoading] = React20.useState(false);
|
|
2336
|
+
const handleConfirm = async () => {
|
|
2337
|
+
if (!onConfirm) {
|
|
2338
|
+
setOpen(false);
|
|
2339
|
+
return;
|
|
2340
|
+
}
|
|
2341
|
+
setIsLoading(true);
|
|
2342
|
+
await onConfirm();
|
|
2343
|
+
setIsLoading(false);
|
|
2344
|
+
setOpen(false);
|
|
2345
|
+
};
|
|
2346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
2347
|
+
CraftModal,
|
|
2348
|
+
{
|
|
2349
|
+
open: isOpen,
|
|
2350
|
+
onOpenChange: setOpen,
|
|
2351
|
+
trigger,
|
|
2352
|
+
title,
|
|
2353
|
+
description,
|
|
2354
|
+
tone,
|
|
2355
|
+
className: cn("max-w-md", className),
|
|
2356
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-wrap items-center justify-end gap-3", children: [
|
|
2357
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
2358
|
+
CraftButton,
|
|
2359
|
+
{
|
|
2360
|
+
type: "button",
|
|
2361
|
+
variant: "ghost",
|
|
2362
|
+
onClick: () => setOpen(false),
|
|
2363
|
+
children: cancelLabel
|
|
2364
|
+
}
|
|
2365
|
+
),
|
|
2366
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
2367
|
+
CraftButton,
|
|
2368
|
+
{
|
|
2369
|
+
type: "button",
|
|
2370
|
+
variant: confirmVariant,
|
|
2371
|
+
disabled: isLoading,
|
|
2372
|
+
onClick: handleConfirm,
|
|
2373
|
+
children: isLoading ? "Working..." : confirmLabel
|
|
2374
|
+
}
|
|
2375
|
+
)
|
|
2376
|
+
] }),
|
|
2377
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: description })
|
|
2378
|
+
}
|
|
2379
|
+
);
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2382
|
+
// src/components/craft-create-edit-drawer.tsx
|
|
2383
|
+
var React21 = __toESM(require("react"), 1);
|
|
2384
|
+
var import_react_hook_form5 = require("react-hook-form");
|
|
2385
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
2386
|
+
function CraftCreateEditDrawer({
|
|
2387
|
+
mode = "create",
|
|
2388
|
+
form,
|
|
2389
|
+
onSubmit,
|
|
2390
|
+
open,
|
|
2391
|
+
defaultOpen = false,
|
|
2392
|
+
onOpenChange,
|
|
2393
|
+
trigger,
|
|
2394
|
+
title,
|
|
2395
|
+
description,
|
|
2396
|
+
submitLabel,
|
|
2397
|
+
cancelLabel = "Cancel",
|
|
2398
|
+
tone,
|
|
2399
|
+
className,
|
|
2400
|
+
children,
|
|
2401
|
+
footer,
|
|
2402
|
+
disableSubmitWhenInvalid = true,
|
|
2403
|
+
closeOnSubmit = true,
|
|
2404
|
+
side = "right"
|
|
2405
|
+
}) {
|
|
2406
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React21.useState(defaultOpen);
|
|
2407
|
+
const isControlled = typeof open === "boolean";
|
|
2408
|
+
const isOpen = isControlled ? open : uncontrolledOpen;
|
|
2409
|
+
const setOpen = React21.useCallback(
|
|
2410
|
+
(next) => {
|
|
2411
|
+
if (!isControlled) setUncontrolledOpen(next);
|
|
2412
|
+
onOpenChange == null ? void 0 : onOpenChange(next);
|
|
2413
|
+
},
|
|
2414
|
+
[isControlled, onOpenChange]
|
|
2415
|
+
);
|
|
2416
|
+
const formId = React21.useId();
|
|
2417
|
+
const handleSubmit = form.handleSubmit(async (values) => {
|
|
2418
|
+
await onSubmit(values);
|
|
2419
|
+
if (closeOnSubmit) setOpen(false);
|
|
2420
|
+
});
|
|
2421
|
+
const resolvedTitle = title != null ? title : mode === "create" ? "Create item" : "Edit item";
|
|
2422
|
+
const resolvedSubmitLabel = submitLabel != null ? submitLabel : mode === "create" ? "Create" : "Save changes";
|
|
2423
|
+
const footerContent = footer != null ? footer : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex flex-wrap items-center justify-end gap-3", children: [
|
|
2424
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(CraftButton, { type: "button", variant: "ghost", onClick: () => setOpen(false), children: cancelLabel }),
|
|
2425
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
2426
|
+
CraftSubmitButton,
|
|
2427
|
+
{
|
|
2428
|
+
form: formId,
|
|
2429
|
+
disableWhenInvalid: disableSubmitWhenInvalid,
|
|
2430
|
+
children: resolvedSubmitLabel
|
|
2431
|
+
}
|
|
2432
|
+
)
|
|
2433
|
+
] });
|
|
2434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_hook_form5.FormProvider, { ...form, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
2435
|
+
CraftDrawer,
|
|
2436
|
+
{
|
|
2437
|
+
open: isOpen,
|
|
2438
|
+
onOpenChange: setOpen,
|
|
2439
|
+
trigger,
|
|
2440
|
+
title: resolvedTitle,
|
|
2441
|
+
tone,
|
|
2442
|
+
side,
|
|
2443
|
+
className: cn("flex flex-col", className),
|
|
2444
|
+
footer: footerContent,
|
|
2445
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("form", { id: formId, onSubmit: handleSubmit, className: "space-y-5", children: [
|
|
2446
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: description }),
|
|
2447
|
+
children
|
|
2448
|
+
] })
|
|
2449
|
+
}
|
|
2450
|
+
) });
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
// src/components/craft-filter-bar.tsx
|
|
2454
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
2455
|
+
function CraftFilterBar({
|
|
2456
|
+
title,
|
|
2457
|
+
description,
|
|
2458
|
+
searchValue,
|
|
2459
|
+
onSearchChange,
|
|
2460
|
+
searchPlaceholder = "Search...",
|
|
2461
|
+
actions,
|
|
2462
|
+
filters,
|
|
2463
|
+
tone,
|
|
2464
|
+
className
|
|
2465
|
+
}) {
|
|
2466
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
2467
|
+
"div",
|
|
2468
|
+
{
|
|
2469
|
+
className: cn(
|
|
2470
|
+
"rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] p-4 text-[rgb(var(--nc-fg))] shadow-[0_12px_36px_rgba(0,0,0,0.2)] backdrop-blur-2xl",
|
|
2471
|
+
className
|
|
2472
|
+
),
|
|
2473
|
+
"data-nc-theme": tone,
|
|
2474
|
+
children: [
|
|
2475
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-4", children: [
|
|
2476
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { children: [
|
|
2477
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h3", { className: "text-lg font-semibold", children: title }),
|
|
2478
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: description })
|
|
2479
|
+
] }),
|
|
2480
|
+
actions && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "flex items-center gap-3", children: actions })
|
|
2481
|
+
] }),
|
|
2482
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "mt-4 grid gap-4 md:grid-cols-[minmax(0,1fr)_auto]", children: [
|
|
2483
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
2484
|
+
CraftInput,
|
|
2485
|
+
{
|
|
2486
|
+
type: "search",
|
|
2487
|
+
placeholder: searchPlaceholder,
|
|
2488
|
+
value: searchValue != null ? searchValue : "",
|
|
2489
|
+
onChange: (event) => onSearchChange == null ? void 0 : onSearchChange(event.target.value),
|
|
2490
|
+
tone
|
|
2491
|
+
}
|
|
2492
|
+
),
|
|
2493
|
+
filters && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "flex flex-wrap items-center gap-3", children: filters })
|
|
2494
|
+
] })
|
|
2495
|
+
]
|
|
2496
|
+
}
|
|
2497
|
+
);
|
|
2498
|
+
}
|
|
2499
|
+
|
|
2500
|
+
// src/components/craft-table-toolbar.tsx
|
|
2501
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
2502
|
+
function CraftTableToolbar({
|
|
2503
|
+
title,
|
|
2504
|
+
description,
|
|
2505
|
+
searchValue,
|
|
2506
|
+
onSearchChange,
|
|
2507
|
+
searchPlaceholder = "Search table...",
|
|
2508
|
+
actions,
|
|
2509
|
+
filters,
|
|
2510
|
+
bulkActions,
|
|
2511
|
+
tone,
|
|
2512
|
+
className
|
|
2513
|
+
}) {
|
|
2514
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
2515
|
+
"div",
|
|
2516
|
+
{
|
|
2517
|
+
className: cn(
|
|
2518
|
+
"rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] p-4 text-[rgb(var(--nc-fg))] shadow-[0_12px_36px_rgba(0,0,0,0.2)] backdrop-blur-2xl",
|
|
2519
|
+
className
|
|
2520
|
+
),
|
|
2521
|
+
"data-nc-theme": tone,
|
|
2522
|
+
children: [
|
|
2523
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-4", children: [
|
|
2524
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { children: [
|
|
2525
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h3", { className: "text-lg font-semibold", children: title }),
|
|
2526
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: description })
|
|
2527
|
+
] }),
|
|
2528
|
+
actions && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex items-center gap-3", children: actions })
|
|
2529
|
+
] }),
|
|
2530
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "mt-4 grid gap-4 lg:grid-cols-[minmax(0,1fr)_auto]", children: [
|
|
2531
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2532
|
+
CraftInput,
|
|
2533
|
+
{
|
|
2534
|
+
type: "search",
|
|
2535
|
+
placeholder: searchPlaceholder,
|
|
2536
|
+
value: searchValue != null ? searchValue : "",
|
|
2537
|
+
onChange: (event) => onSearchChange == null ? void 0 : onSearchChange(event.target.value),
|
|
2538
|
+
tone
|
|
2539
|
+
}
|
|
2540
|
+
),
|
|
2541
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
2542
|
+
filters,
|
|
2543
|
+
bulkActions
|
|
2544
|
+
] })
|
|
2545
|
+
] })
|
|
2546
|
+
]
|
|
2547
|
+
}
|
|
2548
|
+
);
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
// src/components/craft-data-table.tsx
|
|
2552
|
+
var React22 = __toESM(require("react"), 1);
|
|
2553
|
+
|
|
2554
|
+
// src/components/craft-pagination.tsx
|
|
2555
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
2556
|
+
function getPageNumbers(pageIndex, pageCount, maxButtons = 5) {
|
|
2557
|
+
if (pageCount <= maxButtons) {
|
|
2558
|
+
return Array.from({ length: pageCount }, (_, i) => i);
|
|
2559
|
+
}
|
|
2560
|
+
const pages = [];
|
|
2561
|
+
const start = Math.max(0, pageIndex - 1);
|
|
2562
|
+
const end = Math.min(pageCount - 1, pageIndex + 1);
|
|
2563
|
+
pages.push(0);
|
|
2564
|
+
if (start > 1) pages.push("ellipsis");
|
|
2565
|
+
for (let i = start; i <= end; i += 1) {
|
|
2566
|
+
if (i !== 0 && i !== pageCount - 1) pages.push(i);
|
|
2567
|
+
}
|
|
2568
|
+
if (end < pageCount - 2) pages.push("ellipsis");
|
|
2569
|
+
pages.push(pageCount - 1);
|
|
2570
|
+
return pages;
|
|
2571
|
+
}
|
|
2572
|
+
function CraftPagination({
|
|
2573
|
+
pageIndex,
|
|
2574
|
+
pageCount,
|
|
2575
|
+
onPageChange,
|
|
2576
|
+
canPrevious = pageIndex > 0,
|
|
2577
|
+
canNext = pageIndex < pageCount - 1,
|
|
2578
|
+
pageSize,
|
|
2579
|
+
pageSizeOptions = [10, 20, 50],
|
|
2580
|
+
onPageSizeChange,
|
|
2581
|
+
tone,
|
|
2582
|
+
className
|
|
2583
|
+
}) {
|
|
2584
|
+
const pages = getPageNumbers(pageIndex, pageCount);
|
|
2585
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
2586
|
+
"div",
|
|
2587
|
+
{
|
|
2588
|
+
className: cn(
|
|
2589
|
+
"flex flex-wrap items-center justify-between gap-4",
|
|
2590
|
+
className
|
|
2591
|
+
),
|
|
2592
|
+
"data-nc-theme": tone,
|
|
2593
|
+
children: [
|
|
2594
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2595
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
2596
|
+
"button",
|
|
2597
|
+
{
|
|
2598
|
+
type: "button",
|
|
2599
|
+
className: cn(
|
|
2600
|
+
"rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-2 text-xs text-[rgb(var(--nc-fg))] transition",
|
|
2601
|
+
"hover:bg-[rgb(var(--nc-surface)/0.2)]",
|
|
2602
|
+
!canPrevious && "opacity-50 cursor-not-allowed"
|
|
2603
|
+
),
|
|
2604
|
+
onClick: () => onPageChange(Math.max(pageIndex - 1, 0)),
|
|
2605
|
+
disabled: !canPrevious,
|
|
2606
|
+
children: "Prev"
|
|
2607
|
+
}
|
|
2608
|
+
),
|
|
2609
|
+
pages.map(
|
|
2610
|
+
(page, index) => page === "ellipsis" ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "px-2 text-[rgb(var(--nc-fg-muted))]", children: "..." }, `ellipsis-${index}`) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
1026
2611
|
"button",
|
|
1027
2612
|
{
|
|
1028
2613
|
type: "button",
|
|
1029
|
-
onClick: () => handleDaySelect(date),
|
|
1030
|
-
disabled,
|
|
1031
2614
|
className: cn(
|
|
1032
|
-
"rounded-
|
|
1033
|
-
|
|
1034
|
-
disabled && "opacity-40 hover:bg-transparent"
|
|
2615
|
+
"rounded-xl border px-3 py-2 text-xs transition",
|
|
2616
|
+
page === pageIndex ? "border-[rgb(var(--nc-accent-1)/0.6)] bg-[rgb(var(--nc-accent-1)/0.2)] text-[rgb(var(--nc-fg))]" : "border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] text-[rgb(var(--nc-fg-muted))] hover:text-[rgb(var(--nc-fg))] hover:bg-[rgb(var(--nc-surface)/0.2)]"
|
|
1035
2617
|
),
|
|
1036
|
-
|
|
2618
|
+
onClick: () => onPageChange(page),
|
|
2619
|
+
children: page + 1
|
|
1037
2620
|
},
|
|
1038
|
-
|
|
1039
|
-
)
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
2621
|
+
page
|
|
2622
|
+
)
|
|
2623
|
+
),
|
|
2624
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
2625
|
+
"button",
|
|
2626
|
+
{
|
|
2627
|
+
type: "button",
|
|
2628
|
+
className: cn(
|
|
2629
|
+
"rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-2 text-xs text-[rgb(var(--nc-fg))] transition",
|
|
2630
|
+
"hover:bg-[rgb(var(--nc-surface)/0.2)]",
|
|
2631
|
+
!canNext && "opacity-50 cursor-not-allowed"
|
|
2632
|
+
),
|
|
2633
|
+
onClick: () => onPageChange(Math.min(pageIndex + 1, pageCount - 1)),
|
|
2634
|
+
disabled: !canNext,
|
|
2635
|
+
children: "Next"
|
|
2636
|
+
}
|
|
2637
|
+
)
|
|
2638
|
+
] }),
|
|
2639
|
+
onPageSizeChange && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center gap-2 text-xs text-[rgb(var(--nc-fg-muted))]", children: [
|
|
2640
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { children: "Rows" }),
|
|
2641
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
2642
|
+
"select",
|
|
2643
|
+
{
|
|
2644
|
+
className: "rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-2 py-1 text-xs text-[rgb(var(--nc-fg))]",
|
|
2645
|
+
value: pageSize,
|
|
2646
|
+
onChange: (event) => onPageSizeChange(Number(event.target.value)),
|
|
2647
|
+
children: pageSizeOptions.map((size) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("option", { value: size, children: size }, size))
|
|
2648
|
+
}
|
|
2649
|
+
)
|
|
2650
|
+
] })
|
|
2651
|
+
]
|
|
2652
|
+
}
|
|
2653
|
+
);
|
|
1045
2654
|
}
|
|
1046
2655
|
|
|
1047
|
-
// src/components/craft-
|
|
1048
|
-
var
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
2656
|
+
// src/components/craft-data-table.tsx
|
|
2657
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2658
|
+
function getColumnValue(column, row) {
|
|
2659
|
+
if (typeof column.accessor === "function") return column.accessor(row);
|
|
2660
|
+
const record = row;
|
|
2661
|
+
if (typeof column.accessor === "string") return record[column.accessor];
|
|
2662
|
+
return record[column.id];
|
|
2663
|
+
}
|
|
2664
|
+
function normalizeValue(value) {
|
|
2665
|
+
if (value === null || value === void 0) return "";
|
|
2666
|
+
if (typeof value === "number") return value;
|
|
2667
|
+
if (typeof value === "string") return value.toLowerCase();
|
|
2668
|
+
if (value instanceof Date) return value.getTime();
|
|
2669
|
+
return String(value).toLowerCase();
|
|
2670
|
+
}
|
|
2671
|
+
function CraftDataTable({
|
|
2672
|
+
data,
|
|
2673
|
+
columns,
|
|
2674
|
+
tone,
|
|
2675
|
+
className,
|
|
2676
|
+
loading = false,
|
|
2677
|
+
emptyState,
|
|
2678
|
+
toolbar,
|
|
2679
|
+
enableSorting = true,
|
|
2680
|
+
enableFiltering = true,
|
|
2681
|
+
enableColumnVisibility = true,
|
|
2682
|
+
enableRowSelection = true,
|
|
2683
|
+
enablePagination = true,
|
|
2684
|
+
showGlobalFilter,
|
|
2685
|
+
manualSorting = false,
|
|
2686
|
+
manualFiltering = false,
|
|
2687
|
+
manualPagination = false,
|
|
2688
|
+
sortBy,
|
|
2689
|
+
onSortChange,
|
|
2690
|
+
filters,
|
|
2691
|
+
onFiltersChange,
|
|
2692
|
+
globalFilter,
|
|
2693
|
+
onGlobalFilterChange,
|
|
2694
|
+
columnVisibility,
|
|
2695
|
+
onColumnVisibilityChange,
|
|
2696
|
+
selectedRowIds,
|
|
2697
|
+
onRowSelectionChange,
|
|
2698
|
+
getRowId,
|
|
2699
|
+
pageIndex,
|
|
2700
|
+
pageSize = 10,
|
|
2701
|
+
pageCount,
|
|
2702
|
+
onPageChange,
|
|
2703
|
+
onPageSizeChange
|
|
2704
|
+
}) {
|
|
2705
|
+
const [internalSort, setInternalSort] = React22.useState(null);
|
|
2706
|
+
const [internalFilters, setInternalFilters] = React22.useState({});
|
|
2707
|
+
const [internalGlobalFilter, setInternalGlobalFilter] = React22.useState("");
|
|
2708
|
+
const [internalVisibility, setInternalVisibility] = React22.useState(
|
|
2709
|
+
() => columns.reduce((acc, column) => {
|
|
2710
|
+
acc[column.id] = !column.hidden;
|
|
2711
|
+
return acc;
|
|
2712
|
+
}, {})
|
|
2713
|
+
);
|
|
2714
|
+
const [internalSelection, setInternalSelection] = React22.useState({});
|
|
2715
|
+
const [internalPageIndex, setInternalPageIndex] = React22.useState(0);
|
|
2716
|
+
const [showColumns, setShowColumns] = React22.useState(false);
|
|
2717
|
+
const resolvedSort = sortBy != null ? sortBy : internalSort;
|
|
2718
|
+
const resolvedFilters = filters != null ? filters : internalFilters;
|
|
2719
|
+
const resolvedGlobalFilter = globalFilter != null ? globalFilter : internalGlobalFilter;
|
|
2720
|
+
const resolvedVisibility = columnVisibility != null ? columnVisibility : internalVisibility;
|
|
2721
|
+
const resolvedSelection = selectedRowIds != null ? selectedRowIds : internalSelection;
|
|
2722
|
+
const resolvedPageIndex = pageIndex != null ? pageIndex : internalPageIndex;
|
|
2723
|
+
const setSort = (next) => {
|
|
2724
|
+
if (sortBy === void 0) setInternalSort(next);
|
|
2725
|
+
onSortChange == null ? void 0 : onSortChange(next);
|
|
2726
|
+
};
|
|
2727
|
+
const setFilters = (next) => {
|
|
2728
|
+
if (filters === void 0) setInternalFilters(next);
|
|
2729
|
+
onFiltersChange == null ? void 0 : onFiltersChange(next);
|
|
2730
|
+
};
|
|
2731
|
+
const setVisibility = (next) => {
|
|
2732
|
+
if (columnVisibility === void 0) setInternalVisibility(next);
|
|
2733
|
+
onColumnVisibilityChange == null ? void 0 : onColumnVisibilityChange(next);
|
|
2734
|
+
};
|
|
2735
|
+
const setSelection = (next) => {
|
|
2736
|
+
if (selectedRowIds === void 0) setInternalSelection(next);
|
|
2737
|
+
onRowSelectionChange == null ? void 0 : onRowSelectionChange(next);
|
|
2738
|
+
};
|
|
2739
|
+
const setPageIndex = React22.useCallback(
|
|
2740
|
+
(next) => {
|
|
2741
|
+
if (pageIndex === void 0) setInternalPageIndex(next);
|
|
2742
|
+
onPageChange == null ? void 0 : onPageChange(next);
|
|
2743
|
+
},
|
|
2744
|
+
[pageIndex, onPageChange]
|
|
2745
|
+
);
|
|
2746
|
+
const visibleColumns = columns.filter(
|
|
2747
|
+
(column) => resolvedVisibility[column.id] !== false
|
|
2748
|
+
);
|
|
2749
|
+
const filteredData = React22.useMemo(() => {
|
|
2750
|
+
if (manualFiltering) return data;
|
|
2751
|
+
const globalValue = resolvedGlobalFilter.trim();
|
|
2752
|
+
return data.filter((row) => {
|
|
2753
|
+
if (globalValue) {
|
|
2754
|
+
const matchesGlobal = columns.some((column) => {
|
|
2755
|
+
const value = normalizeValue(getColumnValue(column, row));
|
|
2756
|
+
return String(value).includes(globalValue.toLowerCase());
|
|
2757
|
+
});
|
|
2758
|
+
if (!matchesGlobal) return false;
|
|
2759
|
+
}
|
|
2760
|
+
return Object.entries(resolvedFilters).every(([columnId, value]) => {
|
|
2761
|
+
if (!value) return true;
|
|
2762
|
+
const column = columns.find((col) => col.id === columnId);
|
|
2763
|
+
if (!column) return true;
|
|
2764
|
+
const cellValue = normalizeValue(getColumnValue(column, row));
|
|
2765
|
+
return String(cellValue).includes(value.toLowerCase());
|
|
2766
|
+
});
|
|
2767
|
+
});
|
|
2768
|
+
}, [columns, data, manualFiltering, resolvedFilters, resolvedGlobalFilter]);
|
|
2769
|
+
const sortedData = React22.useMemo(() => {
|
|
2770
|
+
if (manualSorting || !resolvedSort) return filteredData;
|
|
2771
|
+
const column = columns.find((col) => col.id === resolvedSort.id);
|
|
2772
|
+
if (!column) return filteredData;
|
|
2773
|
+
const sorted = [...filteredData].sort((a, b) => {
|
|
2774
|
+
const valueA = normalizeValue(getColumnValue(column, a));
|
|
2775
|
+
const valueB = normalizeValue(getColumnValue(column, b));
|
|
2776
|
+
if (typeof valueA === "number" && typeof valueB === "number") {
|
|
2777
|
+
return valueA - valueB;
|
|
2778
|
+
}
|
|
2779
|
+
return String(valueA).localeCompare(String(valueB));
|
|
2780
|
+
});
|
|
2781
|
+
return resolvedSort.desc ? sorted.reverse() : sorted;
|
|
2782
|
+
}, [columns, filteredData, manualSorting, resolvedSort]);
|
|
2783
|
+
const resolvedPageCount = manualPagination ? Math.max(pageCount != null ? pageCount : 1, 1) : Math.max(Math.ceil(sortedData.length / pageSize), 1);
|
|
2784
|
+
React22.useEffect(() => {
|
|
2785
|
+
if (resolvedPageIndex > resolvedPageCount - 1) {
|
|
2786
|
+
setPageIndex(Math.max(resolvedPageCount - 1, 0));
|
|
1068
2787
|
}
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
2788
|
+
}, [resolvedPageCount, resolvedPageIndex, setPageIndex]);
|
|
2789
|
+
const pagedData = React22.useMemo(() => {
|
|
2790
|
+
if (!enablePagination || manualPagination) return sortedData;
|
|
2791
|
+
const start = resolvedPageIndex * pageSize;
|
|
2792
|
+
return sortedData.slice(start, start + pageSize);
|
|
2793
|
+
}, [enablePagination, manualPagination, pageSize, resolvedPageIndex, sortedData]);
|
|
2794
|
+
const rowIdFor = React22.useCallback(
|
|
2795
|
+
(row, index) => {
|
|
2796
|
+
var _a;
|
|
2797
|
+
return (_a = getRowId == null ? void 0 : getRowId(row, index)) != null ? _a : String(index);
|
|
2798
|
+
},
|
|
2799
|
+
[getRowId]
|
|
2800
|
+
);
|
|
2801
|
+
const pageStartIndex = enablePagination && !manualPagination ? resolvedPageIndex * pageSize : 0;
|
|
2802
|
+
const pageRowIds = pagedData.map(
|
|
2803
|
+
(row, index) => rowIdFor(row, pageStartIndex + index)
|
|
2804
|
+
);
|
|
2805
|
+
const allSelected = pageRowIds.length > 0 && pageRowIds.every((id) => resolvedSelection[id]);
|
|
2806
|
+
const someSelected = pageRowIds.some((id) => resolvedSelection[id]);
|
|
2807
|
+
const headerCheckboxRef = React22.useRef(null);
|
|
2808
|
+
React22.useEffect(() => {
|
|
2809
|
+
if (headerCheckboxRef.current) {
|
|
2810
|
+
headerCheckboxRef.current.indeterminate = someSelected && !allSelected;
|
|
2811
|
+
}
|
|
2812
|
+
}, [someSelected, allSelected]);
|
|
2813
|
+
const toggleSort = (column) => {
|
|
2814
|
+
if (!enableSorting || column.sortable === false) return;
|
|
2815
|
+
const current = resolvedSort;
|
|
2816
|
+
if (!current || current.id !== column.id) {
|
|
2817
|
+
setSort({ id: column.id, desc: false });
|
|
2818
|
+
return;
|
|
2819
|
+
}
|
|
2820
|
+
if (!current.desc) {
|
|
2821
|
+
setSort({ id: column.id, desc: true });
|
|
2822
|
+
return;
|
|
2823
|
+
}
|
|
2824
|
+
setSort(null);
|
|
2825
|
+
};
|
|
2826
|
+
const emptyContent = emptyState != null ? emptyState : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "text-center text-sm text-[rgb(var(--nc-fg-muted))]", children: "No results found." });
|
|
2827
|
+
const resolvedShowGlobalFilter = showGlobalFilter != null ? showGlobalFilter : enableFiltering && !toolbar;
|
|
2828
|
+
const setGlobalFilter = (next) => {
|
|
2829
|
+
if (globalFilter === void 0) setInternalGlobalFilter(next);
|
|
2830
|
+
onGlobalFilterChange == null ? void 0 : onGlobalFilterChange(next);
|
|
2831
|
+
};
|
|
2832
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: cn("space-y-4", className), "data-nc-theme": tone, children: [
|
|
2833
|
+
toolbar,
|
|
2834
|
+
resolvedShowGlobalFilter && /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center justify-between gap-3 rounded-2xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-2 text-sm text-[rgb(var(--nc-fg))]", children: [
|
|
2835
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-xs text-[rgb(var(--nc-fg-muted))]", children: "Global filter" }),
|
|
2836
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2837
|
+
"input",
|
|
2838
|
+
{
|
|
2839
|
+
type: "search",
|
|
2840
|
+
value: resolvedGlobalFilter,
|
|
2841
|
+
onChange: (event) => setGlobalFilter(event.target.value),
|
|
2842
|
+
placeholder: "Search all columns...",
|
|
2843
|
+
className: "w-full max-w-xs rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.18)] px-3 py-2 text-xs text-[rgb(var(--nc-fg))]"
|
|
2844
|
+
}
|
|
2845
|
+
)
|
|
2846
|
+
] }),
|
|
2847
|
+
enableColumnVisibility && /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "relative flex justify-end", children: [
|
|
2848
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2849
|
+
"button",
|
|
2850
|
+
{
|
|
2851
|
+
type: "button",
|
|
2852
|
+
className: "rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-2 text-xs text-[rgb(var(--nc-fg))] transition hover:bg-[rgb(var(--nc-surface)/0.2)]",
|
|
2853
|
+
onClick: () => setShowColumns((prev) => !prev),
|
|
2854
|
+
children: "Columns"
|
|
2855
|
+
}
|
|
2856
|
+
),
|
|
2857
|
+
showColumns && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "absolute right-0 top-10 z-20 w-48 rounded-2xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.2)] p-3 shadow-[0_12px_30px_rgba(0,0,0,0.35)] backdrop-blur-2xl", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "grid gap-2", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
2858
|
+
"label",
|
|
2859
|
+
{
|
|
2860
|
+
className: "flex items-center gap-2 text-xs text-[rgb(var(--nc-fg))]",
|
|
2861
|
+
children: [
|
|
2862
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2863
|
+
"input",
|
|
2864
|
+
{
|
|
2865
|
+
type: "checkbox",
|
|
2866
|
+
className: "h-4 w-4 accent-[rgb(var(--nc-accent-1))]",
|
|
2867
|
+
checked: resolvedVisibility[column.id] !== false,
|
|
2868
|
+
onChange: (event) => setVisibility({
|
|
2869
|
+
...resolvedVisibility,
|
|
2870
|
+
[column.id]: event.target.checked
|
|
2871
|
+
})
|
|
2872
|
+
}
|
|
2873
|
+
),
|
|
2874
|
+
column.header
|
|
2875
|
+
]
|
|
2876
|
+
},
|
|
2877
|
+
column.id
|
|
2878
|
+
)) }) })
|
|
2879
|
+
] }),
|
|
2880
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "overflow-hidden rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] shadow-[0_18px_50px_rgba(0,0,0,0.35)] backdrop-blur-2xl", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("table", { className: "w-full border-collapse text-left text-sm", children: [
|
|
2881
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("thead", { className: "bg-[rgb(var(--nc-surface)/0.12)] text-[rgb(var(--nc-fg-muted))]", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("tr", { children: [
|
|
2882
|
+
enableRowSelection && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("th", { className: "w-12 px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2883
|
+
"input",
|
|
2884
|
+
{
|
|
2885
|
+
ref: headerCheckboxRef,
|
|
2886
|
+
type: "checkbox",
|
|
2887
|
+
className: "h-4 w-4 accent-[rgb(var(--nc-accent-1))]",
|
|
2888
|
+
checked: allSelected,
|
|
2889
|
+
onChange: (event) => {
|
|
2890
|
+
const next = { ...resolvedSelection };
|
|
2891
|
+
pageRowIds.forEach((id) => {
|
|
2892
|
+
next[id] = event.target.checked;
|
|
2893
|
+
});
|
|
2894
|
+
setSelection(next);
|
|
2895
|
+
}
|
|
2896
|
+
}
|
|
2897
|
+
) }),
|
|
2898
|
+
visibleColumns.map((column) => {
|
|
2899
|
+
var _a;
|
|
2900
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
2901
|
+
"th",
|
|
2902
|
+
{
|
|
2903
|
+
className: cn(
|
|
2904
|
+
"px-4 py-3 text-xs font-semibold uppercase tracking-[0.2em]",
|
|
2905
|
+
column.headerClassName
|
|
2906
|
+
),
|
|
2907
|
+
style: { width: column.width },
|
|
2908
|
+
children: [
|
|
2909
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
2910
|
+
"button",
|
|
2911
|
+
{
|
|
2912
|
+
type: "button",
|
|
2913
|
+
className: cn(
|
|
2914
|
+
"flex items-center gap-2",
|
|
2915
|
+
enableSorting && column.sortable !== false ? "cursor-pointer" : "cursor-default"
|
|
2916
|
+
),
|
|
2917
|
+
onClick: () => toggleSort(column),
|
|
2918
|
+
children: [
|
|
2919
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { children: column.header }),
|
|
2920
|
+
(resolvedSort == null ? void 0 : resolvedSort.id) === column.id && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-[rgb(var(--nc-accent-1))]", children: resolvedSort.desc ? "\u2193" : "\u2191" })
|
|
2921
|
+
]
|
|
2922
|
+
}
|
|
2923
|
+
),
|
|
2924
|
+
enableFiltering && column.filterable !== false && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2925
|
+
"input",
|
|
2926
|
+
{
|
|
2927
|
+
type: "text",
|
|
2928
|
+
value: (_a = resolvedFilters[column.id]) != null ? _a : "",
|
|
2929
|
+
onChange: (event) => setFilters({
|
|
2930
|
+
...resolvedFilters,
|
|
2931
|
+
[column.id]: event.target.value
|
|
2932
|
+
}),
|
|
2933
|
+
placeholder: "Filter",
|
|
2934
|
+
className: "mt-2 w-full rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.18)] px-2 py-1 text-xs text-[rgb(var(--nc-fg))]"
|
|
2935
|
+
}
|
|
2936
|
+
)
|
|
2937
|
+
]
|
|
2938
|
+
},
|
|
2939
|
+
column.id
|
|
2940
|
+
);
|
|
2941
|
+
})
|
|
2942
|
+
] }) }),
|
|
2943
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("tbody", { className: "text-[rgb(var(--nc-fg))]", children: [
|
|
2944
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2945
|
+
"td",
|
|
2946
|
+
{
|
|
2947
|
+
colSpan: visibleColumns.length + (enableRowSelection ? 1 : 0),
|
|
2948
|
+
className: "px-4 py-10 text-center text-sm text-[rgb(var(--nc-fg-muted))]",
|
|
2949
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "inline-flex items-center gap-2", children: [
|
|
2950
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "h-4 w-4 animate-spin rounded-full border-2 border-[rgb(var(--nc-fg-muted))] border-t-transparent" }),
|
|
2951
|
+
"Loading data..."
|
|
2952
|
+
] })
|
|
2953
|
+
}
|
|
2954
|
+
) }),
|
|
2955
|
+
!loading && pagedData.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2956
|
+
"td",
|
|
2957
|
+
{
|
|
2958
|
+
colSpan: visibleColumns.length + (enableRowSelection ? 1 : 0),
|
|
2959
|
+
className: "px-4 py-10",
|
|
2960
|
+
children: emptyContent
|
|
2961
|
+
}
|
|
2962
|
+
) }),
|
|
2963
|
+
!loading && pagedData.map((row, rowIndex) => {
|
|
2964
|
+
const rowId = rowIdFor(row, pageStartIndex + rowIndex);
|
|
2965
|
+
const isSelected = resolvedSelection[rowId];
|
|
2966
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
2967
|
+
"tr",
|
|
2968
|
+
{
|
|
2969
|
+
className: cn(
|
|
2970
|
+
"border-t border-[rgb(var(--nc-border)/0.15)]",
|
|
2971
|
+
isSelected && "bg-[rgb(var(--nc-accent-1)/0.08)]"
|
|
2972
|
+
),
|
|
2973
|
+
children: [
|
|
2974
|
+
enableRowSelection && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("td", { className: "px-4 py-4", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2975
|
+
"input",
|
|
2976
|
+
{
|
|
2977
|
+
type: "checkbox",
|
|
2978
|
+
className: "h-4 w-4 accent-[rgb(var(--nc-accent-1))]",
|
|
2979
|
+
checked: isSelected,
|
|
2980
|
+
onChange: (event) => setSelection({
|
|
2981
|
+
...resolvedSelection,
|
|
2982
|
+
[rowId]: event.target.checked
|
|
2983
|
+
})
|
|
2984
|
+
}
|
|
2985
|
+
) }),
|
|
2986
|
+
visibleColumns.map((column) => {
|
|
2987
|
+
var _a;
|
|
2988
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2989
|
+
"td",
|
|
2990
|
+
{
|
|
2991
|
+
className: cn(
|
|
2992
|
+
"px-4 py-4",
|
|
2993
|
+
column.align === "center" && "text-center",
|
|
2994
|
+
column.align === "right" && "text-right",
|
|
2995
|
+
column.cellClassName
|
|
2996
|
+
),
|
|
2997
|
+
children: column.cell ? column.cell(row) : String((_a = getColumnValue(column, row)) != null ? _a : "")
|
|
2998
|
+
},
|
|
2999
|
+
column.id
|
|
3000
|
+
);
|
|
3001
|
+
})
|
|
3002
|
+
]
|
|
3003
|
+
},
|
|
3004
|
+
rowId
|
|
3005
|
+
);
|
|
3006
|
+
})
|
|
3007
|
+
] })
|
|
3008
|
+
] }) }),
|
|
3009
|
+
enablePagination && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
3010
|
+
CraftPagination,
|
|
1081
3011
|
{
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
"focus:outline-none focus:ring-4",
|
|
1089
|
-
"transition-all duration-300",
|
|
1090
|
-
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1091
|
-
"border-[rgb(var(--nc-border)/0.35)]",
|
|
1092
|
-
"focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
|
|
1093
|
-
"placeholder:text-[rgb(var(--nc-fg-soft))]",
|
|
1094
|
-
"px-5 py-3 pl-9 text-base",
|
|
1095
|
-
className
|
|
1096
|
-
),
|
|
1097
|
-
...props
|
|
3012
|
+
pageIndex: resolvedPageIndex,
|
|
3013
|
+
pageCount: resolvedPageCount,
|
|
3014
|
+
onPageChange: setPageIndex,
|
|
3015
|
+
pageSize,
|
|
3016
|
+
onPageSizeChange,
|
|
3017
|
+
tone
|
|
1098
3018
|
}
|
|
1099
3019
|
)
|
|
1100
3020
|
] });
|
|
1101
|
-
}
|
|
1102
|
-
CraftCurrencyInput.displayName = "CraftCurrencyInput";
|
|
3021
|
+
}
|
|
1103
3022
|
|
|
1104
3023
|
// src/components/layout/app-shell.tsx
|
|
1105
|
-
var
|
|
3024
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
1106
3025
|
function AppShell({ className, sidebar, topNav, children, ...props }) {
|
|
1107
|
-
return /* @__PURE__ */ (0,
|
|
3026
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
1108
3027
|
"div",
|
|
1109
3028
|
{
|
|
1110
3029
|
className: cn(
|
|
@@ -1113,20 +3032,35 @@ function AppShell({ className, sidebar, topNav, children, ...props }) {
|
|
|
1113
3032
|
),
|
|
1114
3033
|
...props,
|
|
1115
3034
|
children: [
|
|
1116
|
-
sidebar && /* @__PURE__ */ (0,
|
|
1117
|
-
/* @__PURE__ */ (0,
|
|
1118
|
-
topNav,
|
|
1119
|
-
/* @__PURE__ */ (0,
|
|
3035
|
+
sidebar && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "h-full lg:sticky lg:top-6 lg:self-start lg:max-h-[calc(100vh-3rem)] lg:overflow-y-auto", children: sidebar }),
|
|
3036
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-6", children: [
|
|
3037
|
+
topNav && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "lg:sticky lg:top-6 lg:z-20", children: topNav }),
|
|
3038
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("main", { className: "flex-1", children })
|
|
1120
3039
|
] })
|
|
1121
3040
|
]
|
|
1122
3041
|
}
|
|
1123
3042
|
);
|
|
1124
3043
|
}
|
|
1125
3044
|
|
|
3045
|
+
// src/components/layout/app-template.tsx
|
|
3046
|
+
var React23 = __toESM(require("react"), 1);
|
|
3047
|
+
|
|
3048
|
+
// src/components/layout/breadcrumbs.tsx
|
|
3049
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
3050
|
+
function Breadcrumbs({ className, items, ...props }) {
|
|
3051
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("nav", { className: cn("flex items-center text-sm text-[rgb(var(--nc-fg-muted))]", className), ...props, children: items.map((item, index) => {
|
|
3052
|
+
const content = item.href ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("a", { href: item.href, className: "transition hover:text-[rgb(var(--nc-fg))]", children: item.label }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "text-[rgb(var(--nc-fg))]", children: item.label });
|
|
3053
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "flex items-center", children: [
|
|
3054
|
+
content,
|
|
3055
|
+
index < items.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "mx-2 text-[rgb(var(--nc-fg-soft))]", children: "/" })
|
|
3056
|
+
] }, `${item.label}-${index}`);
|
|
3057
|
+
}) });
|
|
3058
|
+
}
|
|
3059
|
+
|
|
1126
3060
|
// src/components/layout/sidebar.tsx
|
|
1127
|
-
var
|
|
3061
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
1128
3062
|
function Sidebar({ className, title, items, footer, ...props }) {
|
|
1129
|
-
return /* @__PURE__ */ (0,
|
|
3063
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
|
|
1130
3064
|
"aside",
|
|
1131
3065
|
{
|
|
1132
3066
|
className: cn(
|
|
@@ -1135,10 +3069,10 @@ function Sidebar({ className, title, items, footer, ...props }) {
|
|
|
1135
3069
|
),
|
|
1136
3070
|
...props,
|
|
1137
3071
|
children: [
|
|
1138
|
-
title && /* @__PURE__ */ (0,
|
|
1139
|
-
/* @__PURE__ */ (0,
|
|
3072
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "text-lg font-semibold", children: title }),
|
|
3073
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("nav", { className: "flex flex-col gap-2", children: items.map((item, index) => {
|
|
1140
3074
|
var _a;
|
|
1141
|
-
return /* @__PURE__ */ (0,
|
|
3075
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
|
|
1142
3076
|
"a",
|
|
1143
3077
|
{
|
|
1144
3078
|
href: (_a = item.href) != null ? _a : "#",
|
|
@@ -1148,22 +3082,22 @@ function Sidebar({ className, title, items, footer, ...props }) {
|
|
|
1148
3082
|
),
|
|
1149
3083
|
children: [
|
|
1150
3084
|
item.icon,
|
|
1151
|
-
/* @__PURE__ */ (0,
|
|
3085
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: item.label })
|
|
1152
3086
|
]
|
|
1153
3087
|
},
|
|
1154
3088
|
`${item.label}-${index}`
|
|
1155
3089
|
);
|
|
1156
3090
|
}) }),
|
|
1157
|
-
footer && /* @__PURE__ */ (0,
|
|
3091
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "mt-auto pt-4", children: footer })
|
|
1158
3092
|
]
|
|
1159
3093
|
}
|
|
1160
3094
|
);
|
|
1161
3095
|
}
|
|
1162
3096
|
|
|
1163
3097
|
// src/components/layout/top-nav.tsx
|
|
1164
|
-
var
|
|
3098
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
1165
3099
|
function TopNav({ className, title, actions, breadcrumb, ...props }) {
|
|
1166
|
-
return /* @__PURE__ */ (0,
|
|
3100
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
1167
3101
|
"header",
|
|
1168
3102
|
{
|
|
1169
3103
|
className: cn(
|
|
@@ -1172,18 +3106,131 @@ function TopNav({ className, title, actions, breadcrumb, ...props }) {
|
|
|
1172
3106
|
),
|
|
1173
3107
|
...props,
|
|
1174
3108
|
children: [
|
|
1175
|
-
/* @__PURE__ */ (0,
|
|
3109
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "space-y-1", children: [
|
|
1176
3110
|
breadcrumb,
|
|
1177
|
-
title && /* @__PURE__ */ (0,
|
|
3111
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "text-xl font-semibold", children: title })
|
|
1178
3112
|
] }),
|
|
1179
|
-
actions && /* @__PURE__ */ (0,
|
|
3113
|
+
actions && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "flex flex-wrap gap-3", children: actions })
|
|
1180
3114
|
]
|
|
1181
3115
|
}
|
|
1182
3116
|
);
|
|
1183
3117
|
}
|
|
1184
3118
|
|
|
3119
|
+
// src/components/layout/app-template.tsx
|
|
3120
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
3121
|
+
function AppTemplate({
|
|
3122
|
+
config,
|
|
3123
|
+
headerActions,
|
|
3124
|
+
headerBreadcrumb,
|
|
3125
|
+
sidebarFooter,
|
|
3126
|
+
resolveIcon,
|
|
3127
|
+
icons,
|
|
3128
|
+
activePath,
|
|
3129
|
+
getActivePath,
|
|
3130
|
+
lucideFallback = true,
|
|
3131
|
+
children
|
|
3132
|
+
}) {
|
|
3133
|
+
const sidebarConfig = config.sidebar;
|
|
3134
|
+
const headerConfig = config.header;
|
|
3135
|
+
const resolvedActivePath = activePath != null ? activePath : getActivePath == null ? void 0 : getActivePath();
|
|
3136
|
+
const buildIcon = React23.useCallback(
|
|
3137
|
+
(name) => {
|
|
3138
|
+
if (!name) return void 0;
|
|
3139
|
+
if (resolveIcon) return resolveIcon(name);
|
|
3140
|
+
if (icons == null ? void 0 : icons[name]) return icons[name];
|
|
3141
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(CraftIcon, { name, useLucide: lucideFallback });
|
|
3142
|
+
},
|
|
3143
|
+
[icons, lucideFallback, resolveIcon]
|
|
3144
|
+
);
|
|
3145
|
+
const sidebarItems = sidebarConfig ? sidebarConfig.items.map((item) => {
|
|
3146
|
+
var _a;
|
|
3147
|
+
return {
|
|
3148
|
+
label: item.label,
|
|
3149
|
+
href: item.href,
|
|
3150
|
+
active: (_a = item.active) != null ? _a : resolvedActivePath && item.href ? item.href === resolvedActivePath : false,
|
|
3151
|
+
icon: buildIcon(item.icon)
|
|
3152
|
+
};
|
|
3153
|
+
}) : null;
|
|
3154
|
+
const breadcrumbNode = headerBreadcrumb != null ? headerBreadcrumb : (headerConfig == null ? void 0 : headerConfig.breadcrumb) ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Breadcrumbs, { items: headerConfig.breadcrumb }) : null;
|
|
3155
|
+
const sidebarFooterNode = sidebarFooter != null ? sidebarFooter : (sidebarConfig == null ? void 0 : sidebarConfig.footerText) ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "text-xs text-[rgb(var(--nc-fg-muted))]", children: sidebarConfig.footerText }) : null;
|
|
3156
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
3157
|
+
AppShell,
|
|
3158
|
+
{
|
|
3159
|
+
sidebar: sidebarConfig && sidebarItems ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
3160
|
+
Sidebar,
|
|
3161
|
+
{
|
|
3162
|
+
title: sidebarConfig.title,
|
|
3163
|
+
items: sidebarItems,
|
|
3164
|
+
footer: sidebarFooterNode
|
|
3165
|
+
}
|
|
3166
|
+
) : void 0,
|
|
3167
|
+
topNav: headerConfig ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
3168
|
+
TopNav,
|
|
3169
|
+
{
|
|
3170
|
+
title: headerConfig.title,
|
|
3171
|
+
breadcrumb: breadcrumbNode,
|
|
3172
|
+
actions: headerActions
|
|
3173
|
+
}
|
|
3174
|
+
) : void 0,
|
|
3175
|
+
children
|
|
3176
|
+
}
|
|
3177
|
+
);
|
|
3178
|
+
}
|
|
3179
|
+
|
|
3180
|
+
// src/components/layout/layout-config.ts
|
|
3181
|
+
var layoutConfigSchema = {
|
|
3182
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
3183
|
+
title: "Nextcraft UI Layout Config",
|
|
3184
|
+
type: "object",
|
|
3185
|
+
additionalProperties: false,
|
|
3186
|
+
properties: {
|
|
3187
|
+
sidebar: {
|
|
3188
|
+
type: "object",
|
|
3189
|
+
additionalProperties: false,
|
|
3190
|
+
properties: {
|
|
3191
|
+
title: { type: "string" },
|
|
3192
|
+
footerText: { type: "string" },
|
|
3193
|
+
items: {
|
|
3194
|
+
type: "array",
|
|
3195
|
+
items: {
|
|
3196
|
+
type: "object",
|
|
3197
|
+
additionalProperties: false,
|
|
3198
|
+
properties: {
|
|
3199
|
+
label: { type: "string" },
|
|
3200
|
+
href: { type: "string" },
|
|
3201
|
+
icon: { type: "string" },
|
|
3202
|
+
active: { type: "boolean" }
|
|
3203
|
+
},
|
|
3204
|
+
required: ["label"]
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
},
|
|
3208
|
+
required: ["items"]
|
|
3209
|
+
},
|
|
3210
|
+
header: {
|
|
3211
|
+
type: "object",
|
|
3212
|
+
additionalProperties: false,
|
|
3213
|
+
properties: {
|
|
3214
|
+
title: { type: "string" },
|
|
3215
|
+
breadcrumb: {
|
|
3216
|
+
type: "array",
|
|
3217
|
+
items: {
|
|
3218
|
+
type: "object",
|
|
3219
|
+
additionalProperties: false,
|
|
3220
|
+
properties: {
|
|
3221
|
+
label: { type: "string" },
|
|
3222
|
+
href: { type: "string" }
|
|
3223
|
+
},
|
|
3224
|
+
required: ["label"]
|
|
3225
|
+
}
|
|
3226
|
+
}
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
}
|
|
3230
|
+
};
|
|
3231
|
+
|
|
1185
3232
|
// src/components/layout/page-header.tsx
|
|
1186
|
-
var
|
|
3233
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
1187
3234
|
function PageHeader({
|
|
1188
3235
|
className,
|
|
1189
3236
|
title,
|
|
@@ -1191,36 +3238,24 @@ function PageHeader({
|
|
|
1191
3238
|
actions,
|
|
1192
3239
|
...props
|
|
1193
3240
|
}) {
|
|
1194
|
-
return /* @__PURE__ */ (0,
|
|
3241
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
1195
3242
|
"div",
|
|
1196
3243
|
{
|
|
1197
3244
|
className: cn("flex flex-wrap items-start justify-between gap-6", className),
|
|
1198
3245
|
...props,
|
|
1199
3246
|
children: [
|
|
1200
|
-
/* @__PURE__ */ (0,
|
|
1201
|
-
/* @__PURE__ */ (0,
|
|
1202
|
-
description && /* @__PURE__ */ (0,
|
|
3247
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "space-y-2", children: [
|
|
3248
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("h1", { className: "text-3xl font-bold text-[rgb(var(--nc-fg))]", children: title }),
|
|
3249
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "text-[rgb(var(--nc-fg-muted))]", children: description })
|
|
1203
3250
|
] }),
|
|
1204
|
-
actions && /* @__PURE__ */ (0,
|
|
3251
|
+
actions && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "flex flex-wrap gap-3", children: actions })
|
|
1205
3252
|
]
|
|
1206
3253
|
}
|
|
1207
3254
|
);
|
|
1208
3255
|
}
|
|
1209
3256
|
|
|
1210
|
-
// src/components/layout/breadcrumbs.tsx
|
|
1211
|
-
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1212
|
-
function Breadcrumbs({ className, items, ...props }) {
|
|
1213
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("nav", { className: cn("flex items-center text-sm text-[rgb(var(--nc-fg-muted))]", className), ...props, children: items.map((item, index) => {
|
|
1214
|
-
const content = item.href ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("a", { href: item.href, className: "transition hover:text-[rgb(var(--nc-fg))]", children: item.label }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[rgb(var(--nc-fg))]", children: item.label });
|
|
1215
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "flex items-center", children: [
|
|
1216
|
-
content,
|
|
1217
|
-
index < items.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "mx-2 text-[rgb(var(--nc-fg-soft))]", children: "/" })
|
|
1218
|
-
] }, `${item.label}-${index}`);
|
|
1219
|
-
}) });
|
|
1220
|
-
}
|
|
1221
|
-
|
|
1222
3257
|
// src/components/layout/auth-layout.tsx
|
|
1223
|
-
var
|
|
3258
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
1224
3259
|
function AuthLayout({
|
|
1225
3260
|
className,
|
|
1226
3261
|
title,
|
|
@@ -1230,7 +3265,7 @@ function AuthLayout({
|
|
|
1230
3265
|
children,
|
|
1231
3266
|
...props
|
|
1232
3267
|
}) {
|
|
1233
|
-
return /* @__PURE__ */ (0,
|
|
3268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
1234
3269
|
"div",
|
|
1235
3270
|
{
|
|
1236
3271
|
className: cn(
|
|
@@ -1240,17 +3275,17 @@ function AuthLayout({
|
|
|
1240
3275
|
),
|
|
1241
3276
|
...props,
|
|
1242
3277
|
children: [
|
|
1243
|
-
/* @__PURE__ */ (0,
|
|
1244
|
-
(title || description) && /* @__PURE__ */ (0,
|
|
1245
|
-
title && /* @__PURE__ */ (0,
|
|
1246
|
-
description && /* @__PURE__ */ (0,
|
|
3278
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "flex flex-col justify-center px-6 py-16 sm:px-12", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "mx-auto w-full max-w-md space-y-6", children: [
|
|
3279
|
+
(title || description) && /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "space-y-2", children: [
|
|
3280
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("h1", { className: "text-3xl font-bold text-[rgb(var(--nc-fg))]", children: title }),
|
|
3281
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "text-[rgb(var(--nc-fg-muted))]", children: description })
|
|
1247
3282
|
] }),
|
|
1248
3283
|
children,
|
|
1249
|
-
footer && /* @__PURE__ */ (0,
|
|
3284
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: footer })
|
|
1250
3285
|
] }) }),
|
|
1251
|
-
/* @__PURE__ */ (0,
|
|
1252
|
-
/* @__PURE__ */ (0,
|
|
1253
|
-
/* @__PURE__ */ (0,
|
|
3286
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "hidden items-center justify-center border-l border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] p-12 text-[rgb(var(--nc-fg))] lg:flex", children: graphic != null ? graphic : /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "max-w-sm space-y-4 text-center", children: [
|
|
3287
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("h2", { className: "text-2xl font-semibold", children: "Crafted experiences" }),
|
|
3288
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "text-[rgb(var(--nc-fg-muted))]", children: "Build authentication flows that feel premium and cohesive." })
|
|
1254
3289
|
] }) })
|
|
1255
3290
|
]
|
|
1256
3291
|
}
|
|
@@ -1258,25 +3293,25 @@ function AuthLayout({
|
|
|
1258
3293
|
}
|
|
1259
3294
|
|
|
1260
3295
|
// src/components/layout/container.tsx
|
|
1261
|
-
var
|
|
1262
|
-
var
|
|
3296
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
3297
|
+
var sizeClasses3 = {
|
|
1263
3298
|
sm: "max-w-3xl",
|
|
1264
3299
|
md: "max-w-5xl",
|
|
1265
3300
|
lg: "max-w-6xl",
|
|
1266
3301
|
xl: "max-w-7xl"
|
|
1267
3302
|
};
|
|
1268
3303
|
function Container({ className, size = "lg", ...props }) {
|
|
1269
|
-
return /* @__PURE__ */ (0,
|
|
3304
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
1270
3305
|
"div",
|
|
1271
3306
|
{
|
|
1272
|
-
className: cn("mx-auto w-full px-4 sm:px-6 lg:px-8",
|
|
3307
|
+
className: cn("mx-auto w-full px-4 sm:px-6 lg:px-8", sizeClasses3[size], className),
|
|
1273
3308
|
...props
|
|
1274
3309
|
}
|
|
1275
3310
|
);
|
|
1276
3311
|
}
|
|
1277
3312
|
|
|
1278
3313
|
// src/components/layout/grid.tsx
|
|
1279
|
-
var
|
|
3314
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
1280
3315
|
var colClasses = {
|
|
1281
3316
|
1: "grid-cols-1",
|
|
1282
3317
|
2: "grid-cols-1 md:grid-cols-2",
|
|
@@ -1292,12 +3327,12 @@ var gapClasses = {
|
|
|
1292
3327
|
xl: "gap-10"
|
|
1293
3328
|
};
|
|
1294
3329
|
function Grid({ className, columns = 3, gap = "md", ...props }) {
|
|
1295
|
-
return /* @__PURE__ */ (0,
|
|
3330
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: cn("grid", colClasses[columns], gapClasses[gap], className), ...props });
|
|
1296
3331
|
}
|
|
1297
3332
|
|
|
1298
3333
|
// src/theme/theme-context.tsx
|
|
1299
|
-
var
|
|
1300
|
-
var
|
|
3334
|
+
var React24 = __toESM(require("react"), 1);
|
|
3335
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
1301
3336
|
var THEME_NAMES = [
|
|
1302
3337
|
"aurora",
|
|
1303
3338
|
"ember",
|
|
@@ -1305,7 +3340,7 @@ var THEME_NAMES = [
|
|
|
1305
3340
|
"midnight",
|
|
1306
3341
|
"cosmic"
|
|
1307
3342
|
];
|
|
1308
|
-
var ThemeContext =
|
|
3343
|
+
var ThemeContext = React24.createContext(null);
|
|
1309
3344
|
var DEFAULT_THEME_KEY = "nextcraft-theme";
|
|
1310
3345
|
var DEFAULT_MODE_KEY = "nextcraft-mode";
|
|
1311
3346
|
function ThemeProvider({
|
|
@@ -1315,9 +3350,9 @@ function ThemeProvider({
|
|
|
1315
3350
|
storageKeyTheme = DEFAULT_THEME_KEY,
|
|
1316
3351
|
storageKeyMode = DEFAULT_MODE_KEY
|
|
1317
3352
|
}) {
|
|
1318
|
-
const [theme, setTheme] =
|
|
1319
|
-
const [mode, setMode] =
|
|
1320
|
-
|
|
3353
|
+
const [theme, setTheme] = React24.useState(defaultTheme);
|
|
3354
|
+
const [mode, setMode] = React24.useState(defaultMode);
|
|
3355
|
+
React24.useEffect(() => {
|
|
1321
3356
|
if (typeof window === "undefined") return;
|
|
1322
3357
|
try {
|
|
1323
3358
|
const storedTheme = window.localStorage.getItem(storageKeyTheme);
|
|
@@ -1327,7 +3362,7 @@ function ThemeProvider({
|
|
|
1327
3362
|
} catch {
|
|
1328
3363
|
}
|
|
1329
3364
|
}, [storageKeyTheme, storageKeyMode]);
|
|
1330
|
-
|
|
3365
|
+
React24.useEffect(() => {
|
|
1331
3366
|
if (typeof window === "undefined") return;
|
|
1332
3367
|
try {
|
|
1333
3368
|
window.localStorage.setItem(storageKeyTheme, theme);
|
|
@@ -1335,7 +3370,7 @@ function ThemeProvider({
|
|
|
1335
3370
|
} catch {
|
|
1336
3371
|
}
|
|
1337
3372
|
}, [theme, mode, storageKeyTheme, storageKeyMode]);
|
|
1338
|
-
|
|
3373
|
+
React24.useEffect(() => {
|
|
1339
3374
|
if (typeof document === "undefined") return;
|
|
1340
3375
|
const root = document.documentElement;
|
|
1341
3376
|
root.dataset.ncTheme = theme;
|
|
@@ -1355,14 +3390,14 @@ function ThemeProvider({
|
|
|
1355
3390
|
mediaQuery.addListener(applySystem);
|
|
1356
3391
|
return () => mediaQuery.removeListener(applySystem);
|
|
1357
3392
|
}, [theme, mode]);
|
|
1358
|
-
const value =
|
|
3393
|
+
const value = React24.useMemo(
|
|
1359
3394
|
() => ({ theme, mode, setTheme, setMode }),
|
|
1360
3395
|
[theme, mode]
|
|
1361
3396
|
);
|
|
1362
|
-
return /* @__PURE__ */ (0,
|
|
3397
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ThemeContext.Provider, { value, children });
|
|
1363
3398
|
}
|
|
1364
3399
|
function useTheme() {
|
|
1365
|
-
const context =
|
|
3400
|
+
const context = React24.useContext(ThemeContext);
|
|
1366
3401
|
if (!context) {
|
|
1367
3402
|
throw new Error("useTheme must be used within ThemeProvider");
|
|
1368
3403
|
}
|
|
@@ -1370,11 +3405,11 @@ function useTheme() {
|
|
|
1370
3405
|
}
|
|
1371
3406
|
|
|
1372
3407
|
// src/components/theme-switcher.tsx
|
|
1373
|
-
var
|
|
3408
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
1374
3409
|
var MODE_OPTIONS = ["system", "light", "dark"];
|
|
1375
3410
|
function ThemeSwitcher({ className, showLabels = true, ...props }) {
|
|
1376
3411
|
const { theme, mode, setTheme, setMode } = useTheme();
|
|
1377
|
-
return /* @__PURE__ */ (0,
|
|
3412
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
|
|
1378
3413
|
"div",
|
|
1379
3414
|
{
|
|
1380
3415
|
className: cn(
|
|
@@ -1383,27 +3418,27 @@ function ThemeSwitcher({ className, showLabels = true, ...props }) {
|
|
|
1383
3418
|
),
|
|
1384
3419
|
...props,
|
|
1385
3420
|
children: [
|
|
1386
|
-
/* @__PURE__ */ (0,
|
|
1387
|
-
showLabels && /* @__PURE__ */ (0,
|
|
1388
|
-
/* @__PURE__ */ (0,
|
|
3421
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("label", { className: "flex items-center gap-2", children: [
|
|
3422
|
+
showLabels && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "text-[rgb(var(--nc-fg-muted))]", children: "Theme" }),
|
|
3423
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
1389
3424
|
"select",
|
|
1390
3425
|
{
|
|
1391
3426
|
className: "rounded-lg border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-1 text-[rgb(var(--nc-fg))] outline-none focus:ring-2 focus:ring-[rgb(var(--nc-accent-1)/0.5)]",
|
|
1392
3427
|
value: theme,
|
|
1393
3428
|
onChange: (event) => setTheme(event.target.value),
|
|
1394
|
-
children: THEME_NAMES.map((name) => /* @__PURE__ */ (0,
|
|
3429
|
+
children: THEME_NAMES.map((name) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: name, className: "text-slate-900", children: name }, name))
|
|
1395
3430
|
}
|
|
1396
3431
|
)
|
|
1397
3432
|
] }),
|
|
1398
|
-
/* @__PURE__ */ (0,
|
|
1399
|
-
showLabels && /* @__PURE__ */ (0,
|
|
1400
|
-
/* @__PURE__ */ (0,
|
|
3433
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("label", { className: "flex items-center gap-2", children: [
|
|
3434
|
+
showLabels && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "text-[rgb(var(--nc-fg-muted))]", children: "Mode" }),
|
|
3435
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
1401
3436
|
"select",
|
|
1402
3437
|
{
|
|
1403
3438
|
className: "rounded-lg border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-1 text-[rgb(var(--nc-fg))] outline-none focus:ring-2 focus:ring-[rgb(var(--nc-accent-1)/0.5)]",
|
|
1404
3439
|
value: mode,
|
|
1405
3440
|
onChange: (event) => setMode(event.target.value),
|
|
1406
|
-
children: MODE_OPTIONS.map((value) => /* @__PURE__ */ (0,
|
|
3441
|
+
children: MODE_OPTIONS.map((value) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value, className: "text-slate-900", children: value }, value))
|
|
1407
3442
|
}
|
|
1408
3443
|
)
|
|
1409
3444
|
] })
|
|
@@ -1414,23 +3449,44 @@ function ThemeSwitcher({ className, showLabels = true, ...props }) {
|
|
|
1414
3449
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1415
3450
|
0 && (module.exports = {
|
|
1416
3451
|
AppShell,
|
|
3452
|
+
AppTemplate,
|
|
1417
3453
|
AuthLayout,
|
|
1418
3454
|
Breadcrumbs,
|
|
1419
3455
|
Container,
|
|
3456
|
+
CraftAlert,
|
|
1420
3457
|
CraftBadge,
|
|
1421
3458
|
CraftButton,
|
|
1422
3459
|
CraftCard,
|
|
1423
3460
|
CraftCheckbox,
|
|
3461
|
+
CraftCommandPalette,
|
|
3462
|
+
CraftConfirmDialog,
|
|
3463
|
+
CraftCreateEditDrawer,
|
|
1424
3464
|
CraftCurrencyInput,
|
|
3465
|
+
CraftDataTable,
|
|
1425
3466
|
CraftDatePicker,
|
|
1426
3467
|
CraftDrawer,
|
|
3468
|
+
CraftDropdownMenu,
|
|
1427
3469
|
CraftEmptyState,
|
|
3470
|
+
CraftErrorState,
|
|
3471
|
+
CraftFilterBar,
|
|
3472
|
+
CraftForm,
|
|
3473
|
+
CraftFormBuilder,
|
|
3474
|
+
CraftFormField,
|
|
3475
|
+
CraftIcon,
|
|
3476
|
+
CraftIconProvider,
|
|
1428
3477
|
CraftInput,
|
|
3478
|
+
CraftLink,
|
|
3479
|
+
CraftLoadingState,
|
|
1429
3480
|
CraftModal,
|
|
1430
3481
|
CraftNumberInput,
|
|
3482
|
+
CraftPagination,
|
|
3483
|
+
CraftPopover,
|
|
1431
3484
|
CraftSelect,
|
|
1432
3485
|
CraftSkeleton,
|
|
3486
|
+
CraftStatCard,
|
|
3487
|
+
CraftSubmitButton,
|
|
1433
3488
|
CraftSwitch,
|
|
3489
|
+
CraftTableToolbar,
|
|
1434
3490
|
CraftTabs,
|
|
1435
3491
|
CraftTextarea,
|
|
1436
3492
|
CraftToastHost,
|
|
@@ -1442,6 +3498,7 @@ function ThemeSwitcher({ className, showLabels = true, ...props }) {
|
|
|
1442
3498
|
ThemeProvider,
|
|
1443
3499
|
ThemeSwitcher,
|
|
1444
3500
|
TopNav,
|
|
3501
|
+
layoutConfigSchema,
|
|
1445
3502
|
useCraftToast,
|
|
1446
3503
|
useTheme
|
|
1447
3504
|
});
|