@jameskabz/nextcraft-ui 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -30,31 +30,64 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ AppShell: () => AppShell,
34
+ AuthLayout: () => AuthLayout,
35
+ Breadcrumbs: () => Breadcrumbs,
36
+ Container: () => Container,
37
+ CraftBadge: () => CraftBadge,
33
38
  CraftButton: () => CraftButton,
39
+ CraftCard: () => CraftCard,
40
+ CraftCheckbox: () => CraftCheckbox,
41
+ CraftCurrencyInput: () => CraftCurrencyInput,
42
+ CraftDatePicker: () => CraftDatePicker,
43
+ CraftDrawer: () => CraftDrawer,
44
+ CraftEmptyState: () => CraftEmptyState,
34
45
  CraftInput: () => CraftInput,
35
- GlassCard: () => GlassCard
46
+ CraftModal: () => CraftModal,
47
+ CraftNumberInput: () => CraftNumberInput,
48
+ CraftSelect: () => CraftSelect,
49
+ CraftSkeleton: () => CraftSkeleton,
50
+ CraftSwitch: () => CraftSwitch,
51
+ CraftTabs: () => CraftTabs,
52
+ CraftTextarea: () => CraftTextarea,
53
+ CraftToastHost: () => CraftToastHost,
54
+ CraftTooltip: () => CraftTooltip,
55
+ GlassCard: () => GlassCard,
56
+ Grid: () => Grid,
57
+ PageHeader: () => PageHeader,
58
+ Sidebar: () => Sidebar,
59
+ ThemeProvider: () => ThemeProvider,
60
+ ThemeSwitcher: () => ThemeSwitcher,
61
+ TopNav: () => TopNav,
62
+ useCraftToast: () => useCraftToast,
63
+ useTheme: () => useTheme
36
64
  });
37
65
  module.exports = __toCommonJS(index_exports);
38
66
 
67
+ // src/utils/cn.ts
68
+ function cn(...values) {
69
+ return values.filter(Boolean).join(" ");
70
+ }
71
+
39
72
  // src/components/craft-button.tsx
40
73
  var import_jsx_runtime = require("react/jsx-runtime");
41
- var cn = (...classes) => classes.filter(Boolean).join(" ");
42
74
  var sizeClasses = {
43
75
  sm: "h-9 px-4 text-xs",
44
76
  md: "h-11 px-6 text-sm",
45
77
  lg: "h-13 px-8 text-base"
46
78
  };
47
79
  var variantClasses = {
48
- solid: "bg-gradient-to-br from-sky-400 via-blue-500 to-indigo-600 text-white shadow-lg shadow-blue-500/50 hover:shadow-xl hover:shadow-blue-500/60 hover:scale-[1.02] active:scale-[0.98]",
49
- ghost: "bg-white/5 text-white hover:bg-white/10 backdrop-blur-sm border border-white/10 hover:border-white/20",
50
- outline: "bg-transparent text-sky-400 border-2 border-sky-400/50 hover:border-sky-400 hover:bg-sky-400/10",
51
- gradient: "bg-gradient-to-r from-violet-600 via-fuchsia-500 to-pink-500 text-white shadow-lg shadow-fuchsia-500/50 hover:shadow-xl hover:shadow-fuchsia-500/60 hover:scale-[1.02] active:scale-[0.98]"
80
+ solid: "bg-gradient-to-br from-[rgb(var(--nc-accent-1))] via-[rgb(var(--nc-accent-2))] to-[rgb(var(--nc-accent-3))] text-white shadow-[0_12px_30px_rgb(var(--nc-accent-1)/0.45)] hover:shadow-[0_16px_36px_rgb(var(--nc-accent-1)/0.6)] hover:scale-[1.02] active:scale-[0.98]",
81
+ ghost: "bg-[color:rgb(var(--nc-surface)/0.12)] text-[rgb(var(--nc-fg))] hover:bg-[color:rgb(var(--nc-surface)/0.18)] backdrop-blur-sm border border-[rgb(var(--nc-border)/0.35)] hover:border-[color:rgb(var(--nc-border)/0.5)]",
82
+ outline: "bg-transparent text-[color:rgb(var(--nc-accent-1))] border-2 border-[color:rgb(var(--nc-accent-1)/0.5)] hover:border-[color:rgb(var(--nc-accent-1))] hover:bg-[color:rgb(var(--nc-accent-1)/0.1)]",
83
+ gradient: "bg-gradient-to-r from-[rgb(var(--nc-accent-1))] via-[rgb(var(--nc-accent-2))] to-[rgb(var(--nc-accent-3))] text-white shadow-[0_12px_30px_rgb(var(--nc-accent-2)/0.45)] hover:shadow-[0_16px_36px_rgb(var(--nc-accent-2)/0.6)] hover:scale-[1.02] active:scale-[0.98]"
52
84
  };
53
85
  function CraftButton({
54
86
  className,
55
87
  variant = "solid",
56
88
  size = "md",
57
89
  glow = true,
90
+ tone,
58
91
  disabled,
59
92
  ...props
60
93
  }) {
@@ -62,32 +95,21 @@ function CraftButton({
62
95
  "button",
63
96
  {
64
97
  className: cn(
65
- "relative inline-flex items-center justify-center gap-2 rounded-xl font-semibold tracking-wide transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-400 focus-visible:ring-offset-2 focus-visible:ring-offset-slate-900 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100",
98
+ "relative inline-flex items-center justify-center gap-2 rounded-xl font-semibold tracking-wide transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[rgb(var(--nc-accent-1)/0.6)] focus-visible:ring-offset-2 focus-visible:ring-offset-slate-900 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100",
66
99
  sizeClasses[size],
67
100
  variantClasses[variant],
68
- glow && (variant === "solid" || variant === "gradient") ? "before:absolute before:-inset-1 before:rounded-xl before:bg-linear-to-r before:from-sky-400/20 before:via-blue-500/20 before:to-indigo-600/20 before:blur-xl before:-z-10 before:opacity-0 hover:before:opacity-100 before:transition-opacity" : "",
101
+ glow && (variant === "solid" || variant === "gradient") ? "before:absolute before:-inset-1 before:rounded-xl before:bg-linear-to-r before:from-[rgb(var(--nc-accent-1)/0.2)] before:via-[rgb(var(--nc-accent-2)/0.2)] before:to-[rgb(var(--nc-accent-3)/0.2)] before:blur-xl before:-z-10 before:opacity-0 hover:before:opacity-100 before:transition-opacity" : "",
69
102
  className
70
103
  ),
104
+ "data-nc-theme": tone,
71
105
  disabled,
72
106
  ...props
73
107
  }
74
108
  );
75
109
  }
76
110
 
77
- // src/utils/cn.ts
78
- function cn2(...values) {
79
- return values.filter(Boolean).join(" ");
80
- }
81
-
82
111
  // src/components/glass-card.tsx
83
112
  var import_jsx_runtime2 = require("react/jsx-runtime");
84
- var cardToneClasses = {
85
- aurora: "bg-gradient-to-br from-emerald-400/15 via-teal-400/10 to-cyan-400/15 border-emerald-300/30",
86
- ember: "bg-gradient-to-br from-amber-400/15 via-orange-400/10 to-rose-400/15 border-amber-300/30",
87
- ocean: "bg-gradient-to-br from-sky-400/15 via-blue-400/10 to-indigo-400/15 border-sky-300/30",
88
- midnight: "bg-gradient-to-br from-violet-400/15 via-purple-400/10 to-fuchsia-400/15 border-violet-300/30",
89
- cosmic: "bg-gradient-to-br from-pink-400/15 via-purple-400/10 to-indigo-400/15 border-pink-300/30"
90
- };
91
113
  var intensityClasses = {
92
114
  subtle: "backdrop-blur-md bg-opacity-50",
93
115
  medium: "backdrop-blur-xl bg-opacity-70",
@@ -95,7 +117,7 @@ var intensityClasses = {
95
117
  };
96
118
  function GlassCard({
97
119
  className,
98
- tone = "ocean",
120
+ tone,
99
121
  intensity = "medium",
100
122
  bordered = true,
101
123
  children,
@@ -104,17 +126,19 @@ function GlassCard({
104
126
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
105
127
  "div",
106
128
  {
107
- className: cn2(
108
- "relative overflow-hidden rounded-3xl p-6 text-white",
129
+ className: cn(
130
+ "relative overflow-hidden rounded-3xl p-6 text-[rgb(var(--nc-fg))]",
109
131
  "shadow-[0_8px_32px_rgba(0,0,0,0.3)]",
110
132
  "transition-all duration-300",
111
133
  "hover:shadow-[0_8px_40px_rgba(0,0,0,0.4)]",
112
134
  intensityClasses[intensity],
113
- cardToneClasses[tone],
135
+ "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)]",
136
+ "border-[rgb(var(--nc-accent-1)/0.3)]",
114
137
  bordered ? "border-2" : "border-0",
115
138
  "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",
116
139
  className
117
140
  ),
141
+ "data-nc-theme": tone,
118
142
  ...props,
119
143
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "relative z-10", children })
120
144
  }
@@ -124,40 +148,35 @@ function GlassCard({
124
148
  // src/components/craft-input.tsx
125
149
  var React = __toESM(require("react"), 1);
126
150
  var import_jsx_runtime3 = require("react/jsx-runtime");
127
- var cn3 = (...classes) => classes.filter(Boolean).join(" ");
128
- var inputToneClasses = {
129
- aurora: "border-emerald-400/30 focus:border-emerald-400/80 focus:ring-emerald-400/30 placeholder:text-emerald-200/40",
130
- ember: "border-amber-400/30 focus:border-amber-400/80 focus:ring-amber-400/30 placeholder:text-amber-200/40",
131
- ocean: "border-sky-400/30 focus:border-sky-400/80 focus:ring-sky-400/30 placeholder:text-sky-200/40",
132
- midnight: "border-violet-400/30 focus:border-violet-400/80 focus:ring-violet-400/30 placeholder:text-violet-200/40"
133
- };
134
151
  var inputSizeClasses = {
135
152
  sm: "h-10 px-4 text-sm",
136
153
  md: "h-12 px-5 text-base",
137
154
  lg: "h-14 px-6 text-lg"
138
155
  };
139
156
  var CraftInput = React.forwardRef(
140
- ({ className, tone = "ocean", inputSize = "md", glow = true, icon, ...props }, ref) => {
141
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "relative w-full", children: [
142
- icon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "absolute left-4 top-1/2 -translate-y-1/2 text-white/50", children: icon }),
157
+ ({ className, tone, inputSize = "md", glow = true, icon, ...props }, ref) => {
158
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "relative w-full", "data-nc-theme": tone, children: [
159
+ icon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "absolute left-4 top-1/2 -translate-y-1/2 text-[rgb(var(--nc-fg-soft))]", children: icon }),
143
160
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
144
161
  "input",
145
162
  {
146
163
  ref,
147
- className: cn3(
148
- "w-full rounded-2xl border-2 bg-white/5 text-white backdrop-blur-xl",
164
+ className: cn(
165
+ "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
149
166
  "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
150
167
  "focus:outline-none focus:ring-4",
151
168
  "transition-all duration-300",
152
169
  "disabled:opacity-50 disabled:cursor-not-allowed",
153
170
  inputSizeClasses[inputSize],
154
- inputToneClasses[tone],
171
+ "border-[rgb(var(--nc-border)/0.35)]",
172
+ "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
173
+ "placeholder:text-[rgb(var(--nc-fg-soft))]",
155
174
  glow ? "focus:shadow-[0_0_30px_-5px_var(--glow-color)]" : "",
156
175
  icon ? "pl-12" : "",
157
176
  className
158
177
  ),
159
178
  style: {
160
- "--glow-color": tone === "aurora" ? "rgba(52,211,153,0.5)" : tone === "ember" ? "rgba(251,191,36,0.5)" : tone === "midnight" ? "rgba(167,139,250,0.5)" : "rgba(56,189,248,0.5)"
179
+ "--glow-color": "rgb(var(--nc-accent-1) / 0.5)"
161
180
  },
162
181
  ...props
163
182
  }
@@ -166,10 +185,1264 @@ var CraftInput = React.forwardRef(
166
185
  }
167
186
  );
168
187
  CraftInput.displayName = "CraftInput";
188
+
189
+ // src/components/craft-textarea.tsx
190
+ var React2 = __toESM(require("react"), 1);
191
+ var import_jsx_runtime4 = require("react/jsx-runtime");
192
+ var CraftTextarea = React2.forwardRef(
193
+ ({ className, tone, rows = 4, ...props }, ref) => {
194
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "relative w-full", "data-nc-theme": tone, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
195
+ "textarea",
196
+ {
197
+ ref,
198
+ rows,
199
+ className: cn(
200
+ "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
201
+ "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
202
+ "focus:outline-none focus:ring-4",
203
+ "transition-all duration-300",
204
+ "disabled:opacity-50 disabled:cursor-not-allowed",
205
+ "border-[rgb(var(--nc-border)/0.35)]",
206
+ "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
207
+ "placeholder:text-[rgb(var(--nc-fg-soft))]",
208
+ "px-5 py-3 text-base",
209
+ className
210
+ ),
211
+ style: {
212
+ "--glow-color": "rgb(var(--nc-accent-1) / 0.5)"
213
+ },
214
+ ...props
215
+ }
216
+ ) });
217
+ }
218
+ );
219
+ CraftTextarea.displayName = "CraftTextarea";
220
+
221
+ // src/components/craft-select.tsx
222
+ var React3 = __toESM(require("react"), 1);
223
+ var import_jsx_runtime5 = require("react/jsx-runtime");
224
+ var CraftSelect = React3.forwardRef(
225
+ ({ className, tone, children, ...props }, ref) => {
226
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative w-full", "data-nc-theme": tone, children: [
227
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
228
+ "select",
229
+ {
230
+ ref,
231
+ className: cn(
232
+ "w-full appearance-none rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
233
+ "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
234
+ "focus:outline-none focus:ring-4",
235
+ "transition-all duration-300",
236
+ "disabled:opacity-50 disabled:cursor-not-allowed",
237
+ "border-[rgb(var(--nc-border)/0.35)]",
238
+ "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
239
+ "px-5 py-3 pr-10 text-base",
240
+ className
241
+ ),
242
+ ...props,
243
+ children
244
+ }
245
+ ),
246
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
247
+ "svg",
248
+ {
249
+ className: "pointer-events-none absolute right-4 top-1/2 h-4 w-4 -translate-y-1/2 text-[rgb(var(--nc-fg-soft))]",
250
+ viewBox: "0 0 20 20",
251
+ fill: "currentColor",
252
+ "aria-hidden": "true",
253
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
254
+ "path",
255
+ {
256
+ fillRule: "evenodd",
257
+ d: "M5.23 7.21a.75.75 0 011.06.02L10 10.94l3.71-3.7a.75.75 0 111.06 1.06l-4.24 4.24a.75.75 0 01-1.06 0L5.21 8.29a.75.75 0 01.02-1.08z",
258
+ clipRule: "evenodd"
259
+ }
260
+ )
261
+ }
262
+ )
263
+ ] });
264
+ }
265
+ );
266
+ CraftSelect.displayName = "CraftSelect";
267
+
268
+ // src/components/craft-checkbox.tsx
269
+ var React4 = __toESM(require("react"), 1);
270
+ var import_jsx_runtime6 = require("react/jsx-runtime");
271
+ var CraftCheckbox = React4.forwardRef(
272
+ ({ className, tone, label, description, ...props }, ref) => {
273
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
274
+ "label",
275
+ {
276
+ className: cn(
277
+ "flex items-start gap-3 text-sm text-[rgb(var(--nc-fg))]",
278
+ props.disabled ? "opacity-60" : "cursor-pointer",
279
+ className
280
+ ),
281
+ "data-nc-theme": tone,
282
+ children: [
283
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "relative mt-0.5", children: [
284
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
285
+ "input",
286
+ {
287
+ ref,
288
+ type: "checkbox",
289
+ className: "peer sr-only",
290
+ ...props
291
+ }
292
+ ),
293
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
294
+ "span",
295
+ {
296
+ className: cn(
297
+ "flex h-5 w-5 items-center justify-center rounded-md border-2",
298
+ "border-[rgb(var(--nc-border)/0.45)] bg-[rgb(var(--nc-surface)/0.08)]",
299
+ "transition-all duration-200",
300
+ "peer-checked:border-[rgb(var(--nc-accent-1))] peer-checked:bg-[rgb(var(--nc-accent-1)/0.25)]",
301
+ "peer-focus-visible:ring-2 peer-focus-visible:ring-[rgb(var(--nc-accent-1)/0.5)]"
302
+ ),
303
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
304
+ "svg",
305
+ {
306
+ className: "h-3 w-3 text-[rgb(var(--nc-fg))] opacity-0 transition-opacity peer-checked:opacity-100",
307
+ viewBox: "0 0 20 20",
308
+ fill: "currentColor",
309
+ "aria-hidden": "true",
310
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
311
+ "path",
312
+ {
313
+ fillRule: "evenodd",
314
+ d: "M16.704 5.29a1 1 0 010 1.415l-7.2 7.2a1 1 0 01-1.415 0l-3.2-3.2a1 1 0 111.415-1.415l2.492 2.493 6.493-6.493a1 1 0 011.415 0z",
315
+ clipRule: "evenodd"
316
+ }
317
+ )
318
+ }
319
+ )
320
+ }
321
+ )
322
+ ] }),
323
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "space-y-1", children: [
324
+ label && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "block font-medium text-[rgb(var(--nc-fg))]", children: label }),
325
+ description && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "block text-xs text-[rgb(var(--nc-fg-muted))]", children: description })
326
+ ] })
327
+ ]
328
+ }
329
+ );
330
+ }
331
+ );
332
+ CraftCheckbox.displayName = "CraftCheckbox";
333
+
334
+ // src/components/craft-switch.tsx
335
+ var React5 = __toESM(require("react"), 1);
336
+ var import_jsx_runtime7 = require("react/jsx-runtime");
337
+ var CraftSwitch = React5.forwardRef(
338
+ ({ className, tone, label, ...props }, ref) => {
339
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
340
+ "label",
341
+ {
342
+ className: cn(
343
+ "inline-flex items-center gap-3 text-sm text-[rgb(var(--nc-fg))]",
344
+ props.disabled ? "opacity-60" : "cursor-pointer",
345
+ className
346
+ ),
347
+ "data-nc-theme": tone,
348
+ children: [
349
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { ref, type: "checkbox", className: "peer sr-only", ...props }),
350
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
351
+ "span",
352
+ {
353
+ className: cn(
354
+ "relative h-6 w-11 rounded-full border-2 border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.08)]",
355
+ "transition-all duration-200",
356
+ "peer-focus-visible:ring-2 peer-focus-visible:ring-[rgb(var(--nc-accent-1)/0.5)]",
357
+ "peer-checked:border-[rgb(var(--nc-accent-1)/0.6)] peer-checked:bg-[rgb(var(--nc-accent-1)/0.25)]"
358
+ ),
359
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
360
+ "span",
361
+ {
362
+ className: cn(
363
+ "absolute left-0.5 top-0.5 h-4 w-4 rounded-full bg-[rgb(var(--nc-surface-muted)/0.9)]",
364
+ "transition-all duration-200",
365
+ "peer-checked:translate-x-5 peer-checked:bg-[rgb(var(--nc-surface-muted))]"
366
+ )
367
+ }
368
+ )
369
+ }
370
+ ),
371
+ label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: label })
372
+ ]
373
+ }
374
+ );
375
+ }
376
+ );
377
+ CraftSwitch.displayName = "CraftSwitch";
378
+
379
+ // src/components/craft-badge.tsx
380
+ var import_jsx_runtime8 = require("react/jsx-runtime");
381
+ var variantClasses2 = {
382
+ solid: "bg-[color:rgb(var(--nc-accent-1))] text-white shadow-[0_10px_20px_rgb(var(--nc-accent-1)/0.35)]",
383
+ soft: "bg-[color:rgb(var(--nc-accent-1)/0.2)] text-[rgb(var(--nc-fg))]",
384
+ outline: "border border-[color:rgb(var(--nc-accent-1)/0.6)] text-[rgb(var(--nc-fg))]"
385
+ };
386
+ function CraftBadge({
387
+ className,
388
+ variant = "soft",
389
+ tone,
390
+ ...props
391
+ }) {
392
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
393
+ "span",
394
+ {
395
+ className: cn(
396
+ "inline-flex items-center rounded-full px-3 py-1 text-xs font-semibold uppercase tracking-wide",
397
+ variantClasses2[variant],
398
+ className
399
+ ),
400
+ "data-nc-theme": tone,
401
+ ...props
402
+ }
403
+ );
404
+ }
405
+
406
+ // src/components/craft-card.tsx
407
+ var import_jsx_runtime9 = require("react/jsx-runtime");
408
+ function CraftCard({ className, tone, elevated = true, ...props }) {
409
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
410
+ "div",
411
+ {
412
+ className: cn(
413
+ "rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] p-6 text-[rgb(var(--nc-fg))] backdrop-blur-xl",
414
+ elevated && "shadow-[0_18px_40px_rgba(0,0,0,0.35)]",
415
+ "transition-all duration-300",
416
+ className
417
+ ),
418
+ "data-nc-theme": tone,
419
+ ...props
420
+ }
421
+ );
422
+ }
423
+
424
+ // src/components/craft-modal.tsx
425
+ var React6 = __toESM(require("react"), 1);
426
+ var import_react_dom = require("react-dom");
427
+ var import_jsx_runtime10 = require("react/jsx-runtime");
428
+ var FOCUSABLE_SELECTORS = [
429
+ "a[href]",
430
+ "button:not([disabled])",
431
+ "textarea:not([disabled])",
432
+ "input:not([disabled])",
433
+ "select:not([disabled])",
434
+ "[tabindex]:not([tabindex='-1'])"
435
+ ].join(",");
436
+ function useFocusTrap(active) {
437
+ const ref = React6.useRef(null);
438
+ React6.useEffect(() => {
439
+ if (!active || !ref.current) return;
440
+ const root = ref.current;
441
+ const getFocusable = () => Array.from(root.querySelectorAll(FOCUSABLE_SELECTORS));
442
+ const focusables = getFocusable();
443
+ if (focusables.length) {
444
+ focusables[0].focus();
445
+ } else {
446
+ root.focus();
447
+ }
448
+ const handleKeyDown = (event) => {
449
+ if (event.key !== "Tab") return;
450
+ const items = getFocusable();
451
+ if (!items.length) return;
452
+ const first = items[0];
453
+ const last = items[items.length - 1];
454
+ const activeEl = document.activeElement;
455
+ if (event.shiftKey && activeEl === first) {
456
+ event.preventDefault();
457
+ last.focus();
458
+ } else if (!event.shiftKey && activeEl === last) {
459
+ event.preventDefault();
460
+ first.focus();
461
+ }
462
+ };
463
+ root.addEventListener("keydown", handleKeyDown);
464
+ return () => root.removeEventListener("keydown", handleKeyDown);
465
+ }, [active]);
466
+ return ref;
467
+ }
468
+ function CraftModal({
469
+ open,
470
+ defaultOpen = false,
471
+ onOpenChange,
472
+ tone,
473
+ title,
474
+ description,
475
+ children,
476
+ trigger,
477
+ footer,
478
+ className
479
+ }) {
480
+ const [uncontrolledOpen, setUncontrolledOpen] = React6.useState(defaultOpen);
481
+ const isControlled = typeof open === "boolean";
482
+ const isOpen = isControlled ? open : uncontrolledOpen;
483
+ const setOpen = React6.useCallback(
484
+ (next) => {
485
+ if (!isControlled) {
486
+ setUncontrolledOpen(next);
487
+ }
488
+ onOpenChange == null ? void 0 : onOpenChange(next);
489
+ },
490
+ [isControlled, onOpenChange]
491
+ );
492
+ React6.useEffect(() => {
493
+ if (!isOpen) return;
494
+ const handleKey = (event) => {
495
+ if (event.key === "Escape") setOpen(false);
496
+ };
497
+ document.addEventListener("keydown", handleKey);
498
+ return () => document.removeEventListener("keydown", handleKey);
499
+ }, [isOpen, setOpen]);
500
+ const ref = useFocusTrap(isOpen);
501
+ const content = isOpen ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "fixed inset-0 z-50 flex items-center justify-center px-4 py-8", children: [
502
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
503
+ "div",
504
+ {
505
+ className: "absolute inset-0 backdrop-blur-sm",
506
+ onClick: () => setOpen(false)
507
+ }
508
+ ),
509
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
510
+ "div",
511
+ {
512
+ ref,
513
+ tabIndex: -1,
514
+ className: cn(
515
+ "relative z-10 w-full max-w-lg rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] p-6 text-[rgb(var(--nc-fg))] shadow-[0_20px_60px_rgba(0,0,0,0.45)] backdrop-blur-2xl",
516
+ className
517
+ ),
518
+ "data-nc-theme": tone,
519
+ children: [
520
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-start justify-between gap-4", children: [
521
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "space-y-1", children: [
522
+ title && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { className: "text-2xl font-semibold", children: title }),
523
+ description && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-[rgb(var(--nc-fg-muted))]", children: description })
524
+ ] }),
525
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
526
+ "button",
527
+ {
528
+ 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
+ onClick: () => setOpen(false),
530
+ "aria-label": "Close",
531
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { viewBox: "0 0 20 20", className: "h-4 w-4", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.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
+ }
533
+ )
534
+ ] }),
535
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-5 space-y-4", children }),
536
+ footer && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-6", children: footer })
537
+ ]
538
+ }
539
+ )
540
+ ] }) : null;
541
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
542
+ trigger && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
543
+ "span",
544
+ {
545
+ onClick: () => setOpen(true),
546
+ onKeyDown: (event) => {
547
+ if (event.key === "Enter" || event.key === " ") setOpen(true);
548
+ },
549
+ role: "button",
550
+ tabIndex: 0,
551
+ className: "inline-flex",
552
+ children: trigger
553
+ }
554
+ ),
555
+ typeof document !== "undefined" && content ? (0, import_react_dom.createPortal)(content, document.body) : content
556
+ ] });
557
+ }
558
+
559
+ // src/components/craft-drawer.tsx
560
+ var React7 = __toESM(require("react"), 1);
561
+ var import_react_dom2 = require("react-dom");
562
+ var import_jsx_runtime11 = require("react/jsx-runtime");
563
+ function CraftDrawer({
564
+ open,
565
+ defaultOpen = false,
566
+ onOpenChange,
567
+ tone,
568
+ side = "left",
569
+ title,
570
+ children,
571
+ trigger,
572
+ footer,
573
+ className
574
+ }) {
575
+ const [uncontrolledOpen, setUncontrolledOpen] = React7.useState(defaultOpen);
576
+ const isControlled = typeof open === "boolean";
577
+ const isOpen = isControlled ? open : uncontrolledOpen;
578
+ const setOpen = React7.useCallback(
579
+ (next) => {
580
+ if (!isControlled) setUncontrolledOpen(next);
581
+ onOpenChange == null ? void 0 : onOpenChange(next);
582
+ },
583
+ [isControlled, onOpenChange]
584
+ );
585
+ React7.useEffect(() => {
586
+ if (!isOpen) return;
587
+ const handleKey = (event) => {
588
+ if (event.key === "Escape") setOpen(false);
589
+ };
590
+ document.addEventListener("keydown", handleKey);
591
+ return () => document.removeEventListener("keydown", handleKey);
592
+ }, [isOpen, setOpen]);
593
+ const content = isOpen ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "fixed inset-0 z-50 overflow-hidden", children: [
594
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
595
+ "div",
596
+ {
597
+ className: "absolute inset-0 backdrop-blur-sm",
598
+ onClick: () => setOpen(false)
599
+ }
600
+ ),
601
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
602
+ "div",
603
+ {
604
+ className: cn(
605
+ "absolute top-0 h-full w-full max-w-md border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] text-[rgb(var(--nc-fg))] shadow-[0_20px_60px_rgba(0,0,0,0.45)] backdrop-blur-2xl",
606
+ side === "right" ? "right-0" : "left-0",
607
+ className
608
+ ),
609
+ "data-nc-theme": tone,
610
+ children: [
611
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-between border-b border-[rgb(var(--nc-border)/0.3)] p-6", children: [
612
+ title && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h3", { className: "text-xl font-semibold", children: title }),
613
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
614
+ "button",
615
+ {
616
+ 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
+ onClick: () => setOpen(false),
618
+ "aria-label": "Close",
619
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { viewBox: "0 0 20 20", className: "h-4 w-4", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.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
+ }
621
+ )
622
+ ] }),
623
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "p-6 space-y-4 overflow-y-auto h-[calc(100%-5.5rem)]", children }),
624
+ footer && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "border-t border-[rgb(var(--nc-border)/0.3)] p-6", children: footer })
625
+ ]
626
+ }
627
+ )
628
+ ] }) : null;
629
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
630
+ trigger && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
631
+ "span",
632
+ {
633
+ onClick: () => setOpen(true),
634
+ onKeyDown: (event) => {
635
+ if (event.key === "Enter" || event.key === " ") setOpen(true);
636
+ },
637
+ role: "button",
638
+ tabIndex: 0,
639
+ className: "inline-flex",
640
+ children: trigger
641
+ }
642
+ ),
643
+ typeof document !== "undefined" && content ? (0, import_react_dom2.createPortal)(content, document.body) : content
644
+ ] });
645
+ }
646
+
647
+ // src/components/craft-tabs.tsx
648
+ var React8 = __toESM(require("react"), 1);
649
+ var import_jsx_runtime12 = require("react/jsx-runtime");
650
+ function CraftTabs({
651
+ value,
652
+ defaultValue,
653
+ onValueChange,
654
+ tone,
655
+ tabs,
656
+ panels,
657
+ className
658
+ }) {
659
+ var _a, _b;
660
+ const fallback = (_b = (_a = tabs[0]) == null ? void 0 : _a.value) != null ? _b : "";
661
+ const [uncontrolledValue, setUncontrolledValue] = React8.useState(
662
+ defaultValue != null ? defaultValue : fallback
663
+ );
664
+ const isControlled = value !== void 0;
665
+ const activeValue = isControlled ? value : uncontrolledValue;
666
+ const setValue = React8.useCallback(
667
+ (next) => {
668
+ if (!isControlled) setUncontrolledValue(next);
669
+ onValueChange == null ? void 0 : onValueChange(next);
670
+ },
671
+ [isControlled, onValueChange]
672
+ );
673
+ const onKeyDown = (event) => {
674
+ if (!tabs.length) return;
675
+ const currentIndex = tabs.findIndex((tab) => tab.value === activeValue);
676
+ if (event.key === "ArrowRight") {
677
+ event.preventDefault();
678
+ const next = tabs[(currentIndex + 1) % tabs.length];
679
+ setValue(next.value);
680
+ }
681
+ if (event.key === "ArrowLeft") {
682
+ event.preventDefault();
683
+ const next = tabs[(currentIndex - 1 + tabs.length) % tabs.length];
684
+ setValue(next.value);
685
+ }
686
+ };
687
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("space-y-4", className), "data-nc-theme": tone, children: [
688
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
689
+ "div",
690
+ {
691
+ 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
+ role: "tablist",
693
+ onKeyDown,
694
+ children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
695
+ "button",
696
+ {
697
+ role: "tab",
698
+ "aria-selected": activeValue === tab.value,
699
+ onClick: () => setValue(tab.value),
700
+ className: cn(
701
+ "rounded-full px-4 py-2 text-sm font-semibold transition-all",
702
+ activeValue === tab.value ? "bg-[rgb(var(--nc-accent-1)/0.65)] text-white shadow-[0_7px_5px_rgb(var(--nc-accent-1)/0.35)]" : "text-[rgb(var(--nc-fg-muted))] hover:text-[rgb(var(--nc-fg))]"
703
+ ),
704
+ children: tab.label
705
+ },
706
+ tab.value
707
+ ))
708
+ }
709
+ ),
710
+ /* @__PURE__ */ (0, import_jsx_runtime12.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
+ ] });
712
+ }
713
+
714
+ // src/components/craft-tooltip.tsx
715
+ var React9 = __toESM(require("react"), 1);
716
+ var import_jsx_runtime13 = require("react/jsx-runtime");
717
+ function CraftTooltip({ content, tone, children, side = "top" }) {
718
+ const [open, setOpen] = React9.useState(false);
719
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
720
+ "span",
721
+ {
722
+ className: "relative inline-flex",
723
+ onMouseEnter: () => setOpen(true),
724
+ onMouseLeave: () => setOpen(false),
725
+ onFocus: () => setOpen(true),
726
+ onBlur: () => setOpen(false),
727
+ children: [
728
+ children,
729
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
730
+ "span",
731
+ {
732
+ className: cn(
733
+ "pointer-events-none absolute z-20 whitespace-nowrap rounded-lg border border-white/10 bg-black/80 px-3 py-2 text-xs text-white shadow-lg transition-all",
734
+ "backdrop-blur-xl",
735
+ open ? "opacity-100 translate-y-0" : "opacity-0 translate-y-1",
736
+ side === "top" && "bottom-full left-1/2 -translate-x-1/2 -translate-y-2",
737
+ side === "bottom" && "top-full left-1/2 -translate-x-1/2 translate-y-2",
738
+ side === "left" && "right-full top-1/2 -translate-y-1/2 -translate-x-2",
739
+ side === "right" && "left-full top-1/2 -translate-y-1/2 translate-x-2"
740
+ ),
741
+ "data-nc-theme": tone,
742
+ role: "tooltip",
743
+ children: content
744
+ }
745
+ )
746
+ ]
747
+ }
748
+ );
749
+ }
750
+
751
+ // src/components/craft-toast.tsx
752
+ var React10 = __toESM(require("react"), 1);
753
+ var import_jsx_runtime14 = require("react/jsx-runtime");
754
+ var variantClasses3 = {
755
+ info: "border-[color:rgb(var(--nc-accent-1)/0.4)]",
756
+ success: "border-emerald-400/40",
757
+ warning: "border-amber-400/40",
758
+ error: "border-rose-400/40"
759
+ };
760
+ function useCraftToast() {
761
+ const [toasts, setToasts] = React10.useState([]);
762
+ const push = React10.useCallback((toast) => {
763
+ const id = `${Date.now()}-${Math.random().toString(16).slice(2)}`;
764
+ setToasts((prev) => [...prev, { ...toast, id }]);
765
+ return id;
766
+ }, []);
767
+ const remove = React10.useCallback((id) => {
768
+ setToasts((prev) => prev.filter((toast) => toast.id !== id));
769
+ }, []);
770
+ return { toasts, push, remove };
771
+ }
772
+ function CraftToastHost({ toasts, onDismiss, tone }) {
773
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
774
+ "div",
775
+ {
776
+ className: "fixed right-6 top-6 z-50 flex w-full max-w-sm flex-col gap-3",
777
+ "data-nc-theme": tone,
778
+ children: toasts.map((toast) => {
779
+ var _a;
780
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
781
+ "div",
782
+ {
783
+ className: cn(
784
+ "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
+ variantClasses3[(_a = toast.variant) != null ? _a : "info"]
786
+ ),
787
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-start justify-between gap-4", children: [
788
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
789
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm font-semibold", children: toast.title }),
790
+ toast.description && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-xs text-[rgb(var(--nc-fg-muted))]", children: toast.description })
791
+ ] }),
792
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
793
+ "button",
794
+ {
795
+ className: "text-[rgb(var(--nc-fg-soft))] hover:text-[rgb(var(--nc-fg))]",
796
+ onClick: () => onDismiss(toast.id),
797
+ children: "\u2715"
798
+ }
799
+ )
800
+ ] })
801
+ },
802
+ toast.id
803
+ );
804
+ })
805
+ }
806
+ );
807
+ }
808
+
809
+ // src/components/craft-skeleton.tsx
810
+ var import_jsx_runtime15 = require("react/jsx-runtime");
811
+ function CraftSkeleton({ className, tone, ...props }) {
812
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
813
+ "div",
814
+ {
815
+ className: cn(
816
+ "relative overflow-hidden rounded-2xl bg-[rgb(var(--nc-surface)/0.12)]",
817
+ "after:absolute after:inset-0 after:-translate-x-full after:bg-linear-to-r after:from-transparent after:via-white/20 after:to-transparent",
818
+ "after:animate-[shimmer_1.6s_infinite]",
819
+ className
820
+ ),
821
+ "data-nc-theme": tone,
822
+ ...props
823
+ }
824
+ );
825
+ }
826
+
827
+ // src/components/craft-empty-state.tsx
828
+ var import_jsx_runtime16 = require("react/jsx-runtime");
829
+ function CraftEmptyState({
830
+ className,
831
+ tone,
832
+ title,
833
+ description,
834
+ icon,
835
+ action,
836
+ ...props
837
+ }) {
838
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
839
+ "div",
840
+ {
841
+ className: cn(
842
+ "rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] p-8 text-center text-[rgb(var(--nc-fg))] backdrop-blur-xl",
843
+ "shadow-[0_18px_40px_rgba(0,0,0,0.25)]",
844
+ className
845
+ ),
846
+ "data-nc-theme": tone,
847
+ ...props,
848
+ children: [
849
+ icon && /* @__PURE__ */ (0, import_jsx_runtime16.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 }),
850
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h3", { className: "text-xl font-semibold", children: title }),
851
+ description && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "mt-2 text-sm text-[rgb(var(--nc-fg-muted))]", children: description }),
852
+ action && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "mt-6 flex justify-center", children: action })
853
+ ]
854
+ }
855
+ );
856
+ }
857
+
858
+ // src/components/craft-date-picker.tsx
859
+ var React11 = __toESM(require("react"), 1);
860
+ var import_jsx_runtime17 = require("react/jsx-runtime");
861
+ var WEEK_DAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
862
+ function formatDate(date) {
863
+ const year = date.getFullYear();
864
+ const month = `${date.getMonth() + 1}`.padStart(2, "0");
865
+ const day = `${date.getDate()}`.padStart(2, "0");
866
+ return `${year}-${month}-${day}`;
867
+ }
868
+ function parseDate(value) {
869
+ if (!value) return null;
870
+ const [year, month, day] = value.split("-").map(Number);
871
+ if (!year || !month || !day) return null;
872
+ return new Date(year, month - 1, day);
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,
888
+ tone,
889
+ min,
890
+ max,
891
+ placeholder = "Select date",
892
+ className
893
+ }) {
894
+ const [open, setOpen] = React11.useState(false);
895
+ const [uncontrolledValue, setUncontrolledValue] = React11.useState(defaultValue != null ? defaultValue : "");
896
+ const isControlled = value !== void 0;
897
+ const selectedValue = isControlled ? value != null ? value : "" : uncontrolledValue;
898
+ const selectedDate = parseDate(selectedValue);
899
+ const initialMonth = selectedDate != null ? selectedDate : /* @__PURE__ */ new Date();
900
+ const [viewDate, setViewDate] = React11.useState(initialMonth);
901
+ React11.useEffect(() => {
902
+ if (selectedDate) setViewDate(selectedDate);
903
+ }, [selectedDate]);
904
+ const wrapperRef = React11.useRef(null);
905
+ React11.useEffect(() => {
906
+ if (!open) return;
907
+ const handleClick = (event) => {
908
+ var _a;
909
+ if (!((_a = wrapperRef.current) == null ? void 0 : _a.contains(event.target))) {
910
+ setOpen(false);
911
+ }
912
+ };
913
+ const handleKey = (event) => {
914
+ if (event.key === "Escape") setOpen(false);
915
+ };
916
+ document.addEventListener("mousedown", handleClick);
917
+ document.addEventListener("keydown", handleKey);
918
+ return () => {
919
+ document.removeEventListener("mousedown", handleClick);
920
+ document.removeEventListener("keydown", handleKey);
921
+ };
922
+ }, [open]);
923
+ const setValue = React11.useCallback(
924
+ (next) => {
925
+ if (!isControlled) setUncontrolledValue(next);
926
+ onChange == null ? void 0 : onChange(next);
927
+ },
928
+ [isControlled, onChange]
929
+ );
930
+ const monthStart = new Date(viewDate.getFullYear(), viewDate.getMonth(), 1);
931
+ const monthEnd = new Date(viewDate.getFullYear(), viewDate.getMonth() + 1, 0);
932
+ const startDay = monthStart.getDay();
933
+ const daysInMonth = monthEnd.getDate();
934
+ const cells = Array.from({ length: startDay + daysInMonth }, (_, i) => {
935
+ const dayNumber = i - startDay + 1;
936
+ if (dayNumber < 1) return null;
937
+ return new Date(viewDate.getFullYear(), viewDate.getMonth(), dayNumber);
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
+ }
964
+ }
965
+ };
966
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "relative w-full", "data-nc-theme": tone, ref: wrapperRef, children: [
967
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
968
+ "button",
969
+ {
970
+ type: "button",
971
+ onClick: () => setOpen((prev) => !prev),
972
+ className: cn(
973
+ "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",
974
+ "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
975
+ "transition-all duration-300",
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
979
+ ),
980
+ children: [
981
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: selectedValue ? "text-[rgb(var(--nc-fg))]" : "text-[rgb(var(--nc-fg-soft))]", children: selectedValue || placeholder }),
982
+ /* @__PURE__ */ (0, import_jsx_runtime17.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_runtime17.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" }) })
983
+ ]
984
+ }
985
+ ),
986
+ open && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
987
+ "div",
988
+ {
989
+ className: cn(
990
+ "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
+ ),
992
+ onKeyDown: handleKeyDown,
993
+ tabIndex: -1,
994
+ children: [
995
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center justify-between", children: [
996
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
997
+ "button",
998
+ {
999
+ type: "button",
1000
+ className: "rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-1 text-sm text-[rgb(var(--nc-fg))]",
1001
+ onClick: () => setViewDate(
1002
+ new Date(viewDate.getFullYear(), viewDate.getMonth() - 1, 1)
1003
+ ),
1004
+ children: "Prev"
1005
+ }
1006
+ ),
1007
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "text-sm font-semibold", children: viewDate.toLocaleString(void 0, { month: "long", year: "numeric" }) }),
1008
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1009
+ "button",
1010
+ {
1011
+ type: "button",
1012
+ className: "rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-1 text-sm text-[rgb(var(--nc-fg))]",
1013
+ onClick: () => setViewDate(
1014
+ new Date(viewDate.getFullYear(), viewDate.getMonth() + 1, 1)
1015
+ ),
1016
+ children: "Next"
1017
+ }
1018
+ )
1019
+ ] }),
1020
+ /* @__PURE__ */ (0, import_jsx_runtime17.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_runtime17.jsx)("div", { className: "text-center", children: day }, day)) }),
1021
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "mt-2 grid grid-cols-7 gap-2", children: cells.map((date, index) => {
1022
+ if (!date) return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", {}, `empty-${index}`);
1023
+ const disabled = isOutsideRange(date, min, max);
1024
+ const selected = selectedDate && isSameDay(date, selectedDate);
1025
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1026
+ "button",
1027
+ {
1028
+ type: "button",
1029
+ onClick: () => handleDaySelect(date),
1030
+ disabled,
1031
+ className: cn(
1032
+ "rounded-lg py-2 text-sm transition-all",
1033
+ 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)]",
1034
+ disabled && "opacity-40 hover:bg-transparent"
1035
+ ),
1036
+ children: date.getDate()
1037
+ },
1038
+ date.toISOString()
1039
+ );
1040
+ }) })
1041
+ ]
1042
+ }
1043
+ )
1044
+ ] });
1045
+ }
1046
+
1047
+ // src/components/craft-number-input.tsx
1048
+ var React12 = __toESM(require("react"), 1);
1049
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1050
+ var CraftNumberInput = React12.forwardRef(({ className, tone, ...props }, ref) => {
1051
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "relative w-full", "data-nc-theme": tone, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1052
+ "input",
1053
+ {
1054
+ ref,
1055
+ type: "number",
1056
+ className: cn(
1057
+ "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
1058
+ "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
1059
+ "focus:outline-none focus:ring-4",
1060
+ "transition-all duration-300",
1061
+ "disabled:opacity-50 disabled:cursor-not-allowed",
1062
+ "border-[rgb(var(--nc-border)/0.35)]",
1063
+ "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
1064
+ "px-5 py-3 text-base",
1065
+ className
1066
+ ),
1067
+ ...props
1068
+ }
1069
+ ) });
1070
+ });
1071
+ CraftNumberInput.displayName = "CraftNumberInput";
1072
+
1073
+ // src/components/craft-currency-input.tsx
1074
+ var React13 = __toESM(require("react"), 1);
1075
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1076
+ var CraftCurrencyInput = React13.forwardRef(({ className, tone, currencySymbol = "$", ...props }, ref) => {
1077
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "relative w-full", "data-nc-theme": tone, children: [
1078
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "pointer-events-none absolute left-4 top-1/2 -translate-y-1/2 text-[rgb(var(--nc-fg-soft))]", children: currencySymbol }),
1079
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1080
+ "input",
1081
+ {
1082
+ ref,
1083
+ type: "text",
1084
+ inputMode: "decimal",
1085
+ className: cn(
1086
+ "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
1087
+ "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
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
1098
+ }
1099
+ )
1100
+ ] });
1101
+ });
1102
+ CraftCurrencyInput.displayName = "CraftCurrencyInput";
1103
+
1104
+ // src/components/layout/app-shell.tsx
1105
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1106
+ function AppShell({ className, sidebar, topNav, children, ...props }) {
1107
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1108
+ "div",
1109
+ {
1110
+ className: cn(
1111
+ "grid min-h-screen grid-cols-1 gap-6 bg-background p-6 lg:grid-cols-[260px_1fr]",
1112
+ className
1113
+ ),
1114
+ ...props,
1115
+ children: [
1116
+ sidebar && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "h-full", children: sidebar }),
1117
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-col gap-6", children: [
1118
+ topNav,
1119
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("main", { className: "flex-1", children })
1120
+ ] })
1121
+ ]
1122
+ }
1123
+ );
1124
+ }
1125
+
1126
+ // src/components/layout/sidebar.tsx
1127
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1128
+ function Sidebar({ className, title, items, footer, ...props }) {
1129
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
1130
+ "aside",
1131
+ {
1132
+ className: cn(
1133
+ "flex h-full w-full flex-col gap-6 rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] p-6 text-[rgb(var(--nc-fg))] backdrop-blur-xl",
1134
+ className
1135
+ ),
1136
+ ...props,
1137
+ children: [
1138
+ title && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-lg font-semibold", children: title }),
1139
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("nav", { className: "flex flex-col gap-2", children: items.map((item, index) => {
1140
+ var _a;
1141
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
1142
+ "a",
1143
+ {
1144
+ href: (_a = item.href) != null ? _a : "#",
1145
+ className: cn(
1146
+ "flex items-center gap-3 rounded-2xl px-3 py-2 text-sm transition",
1147
+ item.active ? "bg-[rgb(var(--nc-accent-1)/0.25)] text-[rgb(var(--nc-fg))]" : "text-[rgb(var(--nc-fg-muted))] hover:bg-[rgb(var(--nc-surface)/0.12)] hover:text-[rgb(var(--nc-fg))]"
1148
+ ),
1149
+ children: [
1150
+ item.icon,
1151
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: item.label })
1152
+ ]
1153
+ },
1154
+ `${item.label}-${index}`
1155
+ );
1156
+ }) }),
1157
+ footer && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-auto pt-4", children: footer })
1158
+ ]
1159
+ }
1160
+ );
1161
+ }
1162
+
1163
+ // src/components/layout/top-nav.tsx
1164
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1165
+ function TopNav({ className, title, actions, breadcrumb, ...props }) {
1166
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
1167
+ "header",
1168
+ {
1169
+ className: cn(
1170
+ "flex flex-wrap items-center justify-between gap-4 rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] px-6 py-4 text-[rgb(var(--nc-fg))] backdrop-blur-xl",
1171
+ className
1172
+ ),
1173
+ ...props,
1174
+ children: [
1175
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-1", children: [
1176
+ breadcrumb,
1177
+ title && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "text-xl font-semibold", children: title })
1178
+ ] }),
1179
+ actions && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex flex-wrap gap-3", children: actions })
1180
+ ]
1181
+ }
1182
+ );
1183
+ }
1184
+
1185
+ // src/components/layout/page-header.tsx
1186
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1187
+ function PageHeader({
1188
+ className,
1189
+ title,
1190
+ description,
1191
+ actions,
1192
+ ...props
1193
+ }) {
1194
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
1195
+ "div",
1196
+ {
1197
+ className: cn("flex flex-wrap items-start justify-between gap-6", className),
1198
+ ...props,
1199
+ children: [
1200
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "space-y-2", children: [
1201
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h1", { className: "text-3xl font-bold text-[rgb(var(--nc-fg))]", children: title }),
1202
+ description && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[rgb(var(--nc-fg-muted))]", children: description })
1203
+ ] }),
1204
+ actions && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex flex-wrap gap-3", children: actions })
1205
+ ]
1206
+ }
1207
+ );
1208
+ }
1209
+
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
+ // src/components/layout/auth-layout.tsx
1223
+ var import_jsx_runtime25 = require("react/jsx-runtime");
1224
+ function AuthLayout({
1225
+ className,
1226
+ title,
1227
+ description,
1228
+ footer,
1229
+ graphic,
1230
+ children,
1231
+ ...props
1232
+ }) {
1233
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1234
+ "div",
1235
+ {
1236
+ className: cn(
1237
+ "grid min-h-screen grid-cols-1 bg-background",
1238
+ "lg:grid-cols-[1.1fr_0.9fr]",
1239
+ className
1240
+ ),
1241
+ ...props,
1242
+ children: [
1243
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex flex-col justify-center px-6 py-16 sm:px-12", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "mx-auto w-full max-w-md space-y-6", children: [
1244
+ (title || description) && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "space-y-2", children: [
1245
+ title && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h1", { className: "text-3xl font-bold text-[rgb(var(--nc-fg))]", children: title }),
1246
+ description && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "text-[rgb(var(--nc-fg-muted))]", children: description })
1247
+ ] }),
1248
+ children,
1249
+ footer && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: footer })
1250
+ ] }) }),
1251
+ /* @__PURE__ */ (0, import_jsx_runtime25.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_runtime25.jsxs)("div", { className: "max-w-sm space-y-4 text-center", children: [
1252
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h2", { className: "text-2xl font-semibold", children: "Crafted experiences" }),
1253
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "text-[rgb(var(--nc-fg-muted))]", children: "Build authentication flows that feel premium and cohesive." })
1254
+ ] }) })
1255
+ ]
1256
+ }
1257
+ );
1258
+ }
1259
+
1260
+ // src/components/layout/container.tsx
1261
+ var import_jsx_runtime26 = require("react/jsx-runtime");
1262
+ var sizeClasses2 = {
1263
+ sm: "max-w-3xl",
1264
+ md: "max-w-5xl",
1265
+ lg: "max-w-6xl",
1266
+ xl: "max-w-7xl"
1267
+ };
1268
+ function Container({ className, size = "lg", ...props }) {
1269
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
1270
+ "div",
1271
+ {
1272
+ className: cn("mx-auto w-full px-4 sm:px-6 lg:px-8", sizeClasses2[size], className),
1273
+ ...props
1274
+ }
1275
+ );
1276
+ }
1277
+
1278
+ // src/components/layout/grid.tsx
1279
+ var import_jsx_runtime27 = require("react/jsx-runtime");
1280
+ var colClasses = {
1281
+ 1: "grid-cols-1",
1282
+ 2: "grid-cols-1 md:grid-cols-2",
1283
+ 3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
1284
+ 4: "grid-cols-1 md:grid-cols-2 lg:grid-cols-4",
1285
+ 5: "grid-cols-1 md:grid-cols-2 lg:grid-cols-5",
1286
+ 6: "grid-cols-1 md:grid-cols-3 lg:grid-cols-6"
1287
+ };
1288
+ var gapClasses = {
1289
+ sm: "gap-4",
1290
+ md: "gap-6",
1291
+ lg: "gap-8",
1292
+ xl: "gap-10"
1293
+ };
1294
+ function Grid({ className, columns = 3, gap = "md", ...props }) {
1295
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: cn("grid", colClasses[columns], gapClasses[gap], className), ...props });
1296
+ }
1297
+
1298
+ // src/theme/theme-context.tsx
1299
+ var React14 = __toESM(require("react"), 1);
1300
+ var import_jsx_runtime28 = require("react/jsx-runtime");
1301
+ var THEME_NAMES = [
1302
+ "aurora",
1303
+ "ember",
1304
+ "ocean",
1305
+ "midnight",
1306
+ "cosmic"
1307
+ ];
1308
+ var ThemeContext = React14.createContext(null);
1309
+ var DEFAULT_THEME_KEY = "nextcraft-theme";
1310
+ var DEFAULT_MODE_KEY = "nextcraft-mode";
1311
+ function ThemeProvider({
1312
+ children,
1313
+ defaultTheme = "ocean",
1314
+ defaultMode = "system",
1315
+ storageKeyTheme = DEFAULT_THEME_KEY,
1316
+ storageKeyMode = DEFAULT_MODE_KEY
1317
+ }) {
1318
+ const [theme, setTheme] = React14.useState(defaultTheme);
1319
+ const [mode, setMode] = React14.useState(defaultMode);
1320
+ React14.useEffect(() => {
1321
+ if (typeof window === "undefined") return;
1322
+ try {
1323
+ const storedTheme = window.localStorage.getItem(storageKeyTheme);
1324
+ const storedMode = window.localStorage.getItem(storageKeyMode);
1325
+ if (storedTheme) setTheme(storedTheme);
1326
+ if (storedMode) setMode(storedMode);
1327
+ } catch {
1328
+ }
1329
+ }, [storageKeyTheme, storageKeyMode]);
1330
+ React14.useEffect(() => {
1331
+ if (typeof window === "undefined") return;
1332
+ try {
1333
+ window.localStorage.setItem(storageKeyTheme, theme);
1334
+ window.localStorage.setItem(storageKeyMode, mode);
1335
+ } catch {
1336
+ }
1337
+ }, [theme, mode, storageKeyTheme, storageKeyMode]);
1338
+ React14.useEffect(() => {
1339
+ if (typeof document === "undefined") return;
1340
+ const root = document.documentElement;
1341
+ root.dataset.ncTheme = theme;
1342
+ if (mode !== "system") {
1343
+ root.dataset.ncMode = mode;
1344
+ return;
1345
+ }
1346
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
1347
+ const applySystem = () => {
1348
+ root.dataset.ncMode = mediaQuery.matches ? "dark" : "light";
1349
+ };
1350
+ applySystem();
1351
+ if (typeof mediaQuery.addEventListener === "function") {
1352
+ mediaQuery.addEventListener("change", applySystem);
1353
+ return () => mediaQuery.removeEventListener("change", applySystem);
1354
+ }
1355
+ mediaQuery.addListener(applySystem);
1356
+ return () => mediaQuery.removeListener(applySystem);
1357
+ }, [theme, mode]);
1358
+ const value = React14.useMemo(
1359
+ () => ({ theme, mode, setTheme, setMode }),
1360
+ [theme, mode]
1361
+ );
1362
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ThemeContext.Provider, { value, children });
1363
+ }
1364
+ function useTheme() {
1365
+ const context = React14.useContext(ThemeContext);
1366
+ if (!context) {
1367
+ throw new Error("useTheme must be used within ThemeProvider");
1368
+ }
1369
+ return context;
1370
+ }
1371
+
1372
+ // src/components/theme-switcher.tsx
1373
+ var import_jsx_runtime29 = require("react/jsx-runtime");
1374
+ var MODE_OPTIONS = ["system", "light", "dark"];
1375
+ function ThemeSwitcher({ className, showLabels = true, ...props }) {
1376
+ const { theme, mode, setTheme, setMode } = useTheme();
1377
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
1378
+ "div",
1379
+ {
1380
+ className: cn(
1381
+ "flex flex-wrap items-center gap-3 rounded-2xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] px-4 py-3 text-sm text-[rgb(var(--nc-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.06)]",
1382
+ className
1383
+ ),
1384
+ ...props,
1385
+ children: [
1386
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-2", children: [
1387
+ showLabels && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-[rgb(var(--nc-fg-muted))]", children: "Theme" }),
1388
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
1389
+ "select",
1390
+ {
1391
+ 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
+ value: theme,
1393
+ onChange: (event) => setTheme(event.target.value),
1394
+ children: THEME_NAMES.map((name) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: name, className: "text-slate-900", children: name }, name))
1395
+ }
1396
+ )
1397
+ ] }),
1398
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-2", children: [
1399
+ showLabels && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-[rgb(var(--nc-fg-muted))]", children: "Mode" }),
1400
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
1401
+ "select",
1402
+ {
1403
+ 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
+ value: mode,
1405
+ onChange: (event) => setMode(event.target.value),
1406
+ children: MODE_OPTIONS.map((value) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value, className: "text-slate-900", children: value }, value))
1407
+ }
1408
+ )
1409
+ ] })
1410
+ ]
1411
+ }
1412
+ );
1413
+ }
169
1414
  // Annotate the CommonJS export names for ESM import in node:
170
1415
  0 && (module.exports = {
1416
+ AppShell,
1417
+ AuthLayout,
1418
+ Breadcrumbs,
1419
+ Container,
1420
+ CraftBadge,
171
1421
  CraftButton,
1422
+ CraftCard,
1423
+ CraftCheckbox,
1424
+ CraftCurrencyInput,
1425
+ CraftDatePicker,
1426
+ CraftDrawer,
1427
+ CraftEmptyState,
172
1428
  CraftInput,
173
- GlassCard
1429
+ CraftModal,
1430
+ CraftNumberInput,
1431
+ CraftSelect,
1432
+ CraftSkeleton,
1433
+ CraftSwitch,
1434
+ CraftTabs,
1435
+ CraftTextarea,
1436
+ CraftToastHost,
1437
+ CraftTooltip,
1438
+ GlassCard,
1439
+ Grid,
1440
+ PageHeader,
1441
+ Sidebar,
1442
+ ThemeProvider,
1443
+ ThemeSwitcher,
1444
+ TopNav,
1445
+ useCraftToast,
1446
+ useTheme
174
1447
  });
175
1448
  //# sourceMappingURL=index.cjs.map