@kjaniec-dev/ui 0.6.0 → 0.7.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
@@ -2,7 +2,7 @@
2
2
 
3
3
  var clsx = require('clsx');
4
4
  var tailwindMerge = require('tailwind-merge');
5
- var React17 = require('react');
5
+ var React18 = require('react');
6
6
  var classVarianceAuthority = require('class-variance-authority');
7
7
  var jsxRuntime = require('react/jsx-runtime');
8
8
 
@@ -24,7 +24,7 @@ function _interopNamespace(e) {
24
24
  return Object.freeze(n);
25
25
  }
26
26
 
27
- var React17__namespace = /*#__PURE__*/_interopNamespace(React17);
27
+ var React18__namespace = /*#__PURE__*/_interopNamespace(React18);
28
28
 
29
29
  // src/lib/cn.ts
30
30
  function cn(...inputs) {
@@ -60,7 +60,7 @@ var buttonVariants = classVarianceAuthority.cva(
60
60
  defaultVariants: { variant: "primary", size: "md" }
61
61
  }
62
62
  );
63
- var Button = React17__namespace.forwardRef(
63
+ var Button = React18__namespace.forwardRef(
64
64
  ({ className, variant, size, loading, leadingIcon, trailingIcon, children, disabled, ...props }, ref) => {
65
65
  return /* @__PURE__ */ jsxRuntime.jsxs(
66
66
  "button",
@@ -107,7 +107,7 @@ var badgeVariants = classVarianceAuthority.cva(
107
107
  defaultVariants: { variant: "neutral" }
108
108
  }
109
109
  );
110
- var Badge = React17__namespace.forwardRef(
110
+ var Badge = React18__namespace.forwardRef(
111
111
  ({ className, variant, dot, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, className: cn(badgeVariants({ variant }), className), ...props, children: [
112
112
  dot && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-current", "aria-hidden": true }),
113
113
  children
@@ -134,7 +134,7 @@ var iconColor = {
134
134
  warning: "text-warning",
135
135
  danger: "text-danger"
136
136
  };
137
- var Alert = React17__namespace.forwardRef(
137
+ var Alert = React18__namespace.forwardRef(
138
138
  ({ className, variant = "info", icon, title, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, role: "alert", className: cn(alertVariants({ variant }), className), ...props, children: [
139
139
  icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("shrink-0 mt-0.5 [&_svg]:h-[1.15rem] [&_svg]:w-[1.15rem]", iconColor[variant ?? "info"]), children: icon }),
140
140
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-foreground", children: [
@@ -144,7 +144,7 @@ var Alert = React17__namespace.forwardRef(
144
144
  ] })
145
145
  );
146
146
  Alert.displayName = "Alert";
147
- var Spinner = React17__namespace.forwardRef(
147
+ var Spinner = React18__namespace.forwardRef(
148
148
  ({ className, size = 24, style, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
149
149
  "span",
150
150
  {
@@ -161,7 +161,7 @@ var Spinner = React17__namespace.forwardRef(
161
161
  )
162
162
  );
163
163
  Spinner.displayName = "Spinner";
164
- var Progress = React17__namespace.forwardRef(
164
+ var Progress = React18__namespace.forwardRef(
165
165
  ({ className, value = 0, tone = "primary", barClassName, ...props }, ref) => {
166
166
  const pct = Math.max(0, Math.min(100, value));
167
167
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -191,8 +191,55 @@ var Progress = React17__namespace.forwardRef(
191
191
  }
192
192
  );
193
193
  Progress.displayName = "Progress";
194
+ var Label = React18__namespace.forwardRef(
195
+ ({ className, required, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs("label", { ref, className: cn("text-[0.8rem] font-semibold text-foreground", className), ...props, children: [
196
+ children,
197
+ required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-danger", children: " *" })
198
+ ] })
199
+ );
200
+ Label.displayName = "Label";
201
+ var Hint = React18__namespace.forwardRef(
202
+ ({ className, error, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
203
+ "span",
204
+ {
205
+ ref,
206
+ className: cn("text-[0.76rem]", error ? "text-danger" : "text-muted-foreground", className),
207
+ ...props
208
+ }
209
+ )
210
+ );
211
+ Hint.displayName = "Hint";
212
+ var Field = React18__namespace.forwardRef(
213
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex flex-col gap-1.5", className), ...props })
214
+ );
215
+ Field.displayName = "Field";
216
+ var FormField = React18__namespace.forwardRef(
217
+ ({ className, label, hint, error, required, children, ...props }, ref) => {
218
+ const id = React18__namespace.useId();
219
+ const hintId = `${id}-hint`;
220
+ const errorId = `${id}-error`;
221
+ const child = React18__namespace.Children.only(children);
222
+ const clonedChild = React18__namespace.cloneElement(child, {
223
+ id: child.props.id ?? id,
224
+ "aria-describedby": cn(
225
+ hint && hintId,
226
+ error && errorId,
227
+ child.props["aria-describedby"]
228
+ ) || void 0,
229
+ "aria-invalid": error ? "true" : void 0,
230
+ required: child.props.required ?? required
231
+ });
232
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("flex flex-col gap-1.5 w-full", className), ...props, children: [
233
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: id, required, children: label }),
234
+ clonedChild,
235
+ hint && !error && /* @__PURE__ */ jsxRuntime.jsx(Hint, { id: hintId, children: hint }),
236
+ error && /* @__PURE__ */ jsxRuntime.jsx(Hint, { id: errorId, error: true, children: error })
237
+ ] });
238
+ }
239
+ );
240
+ FormField.displayName = "FormField";
194
241
  var baseField = "w-full font-sans text-sm text-foreground bg-surface border rounded-kj-md px-[0.85rem] transition-[border-color,box-shadow] duration-150 placeholder:text-muted-foreground focus:outline-none focus:border-ring focus:ring-[3px] focus:ring-ring/30 disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed";
195
- var Input = React17__namespace.forwardRef(
242
+ var Input = React18__namespace.forwardRef(
196
243
  ({ className, error, leadingIcon, style, ...props }, ref) => {
197
244
  const field = /* @__PURE__ */ jsxRuntime.jsx(
198
245
  "input",
@@ -217,7 +264,7 @@ var Input = React17__namespace.forwardRef(
217
264
  }
218
265
  );
219
266
  Input.displayName = "Input";
220
- var Textarea = React17__namespace.forwardRef(
267
+ var Textarea = React18__namespace.forwardRef(
221
268
  ({ className, error, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
222
269
  "textarea",
223
270
  {
@@ -234,30 +281,14 @@ var Textarea = React17__namespace.forwardRef(
234
281
  )
235
282
  );
236
283
  Textarea.displayName = "Textarea";
237
- var Label = React17__namespace.forwardRef(
238
- ({ className, required, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs("label", { ref, className: cn("text-[0.8rem] font-semibold text-foreground", className), ...props, children: [
239
- children,
240
- required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-danger", children: " *" })
241
- ] })
242
- );
243
- Label.displayName = "Label";
244
- var Hint = React17__namespace.forwardRef(
245
- ({ className, error, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
246
- "span",
247
- {
248
- ref,
249
- className: cn("text-[0.76rem]", error ? "text-danger" : "text-muted-foreground", className),
250
- ...props
251
- }
252
- )
253
- );
254
- Hint.displayName = "Hint";
255
- var Field = React17__namespace.forwardRef(
256
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex flex-col gap-1.5", className), ...props })
284
+ var TextField = React18__namespace.forwardRef(
285
+ ({ label, hint, error, required, className, ...props }, ref) => {
286
+ return /* @__PURE__ */ jsxRuntime.jsx(FormField, { label, hint, error, required, className, children: /* @__PURE__ */ jsxRuntime.jsx(Input, { ref, error: !!error, ...props }) });
287
+ }
257
288
  );
258
- Field.displayName = "Field";
289
+ TextField.displayName = "TextField";
259
290
  var chevron = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E";
260
- var Select = React17__namespace.forwardRef(
291
+ var Select = React18__namespace.forwardRef(
261
292
  ({ className, error, style, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
262
293
  "select",
263
294
  {
@@ -285,9 +316,15 @@ var Select = React17__namespace.forwardRef(
285
316
  )
286
317
  );
287
318
  Select.displayName = "Select";
288
- var Checkbox = React17__namespace.forwardRef(
319
+ var SelectField = React18__namespace.forwardRef(
320
+ ({ label, hint, error, required, className, children, ...props }, ref) => {
321
+ return /* @__PURE__ */ jsxRuntime.jsx(FormField, { label, hint, error, required, className, children: /* @__PURE__ */ jsxRuntime.jsx(Select, { ref, error: !!error, ...props, children }) });
322
+ }
323
+ );
324
+ SelectField.displayName = "SelectField";
325
+ var Checkbox = React18__namespace.forwardRef(
289
326
  ({ className, label, id, ...props }, ref) => {
290
- const autoId = React17__namespace.useId();
327
+ const autoId = React18__namespace.useId();
291
328
  const inputId = id ?? autoId;
292
329
  return /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
293
330
  /* @__PURE__ */ jsxRuntime.jsx("input", { ref, id: inputId, type: "checkbox", className: "peer sr-only", ...props }),
@@ -297,9 +334,9 @@ var Checkbox = React17__namespace.forwardRef(
297
334
  }
298
335
  );
299
336
  Checkbox.displayName = "Checkbox";
300
- var Radio = React17__namespace.forwardRef(
337
+ var Radio = React18__namespace.forwardRef(
301
338
  ({ className, label, id, ...props }, ref) => {
302
- const autoId = React17__namespace.useId();
339
+ const autoId = React18__namespace.useId();
303
340
  const inputId = id ?? autoId;
304
341
  return /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
305
342
  /* @__PURE__ */ jsxRuntime.jsx("input", { ref, id: inputId, type: "radio", className: "peer sr-only", ...props }),
@@ -309,9 +346,32 @@ var Radio = React17__namespace.forwardRef(
309
346
  }
310
347
  );
311
348
  Radio.displayName = "Radio";
312
- var Switch = React17__namespace.forwardRef(
349
+ var CheckboxField = React18__namespace.forwardRef(
350
+ ({ label, hint, error, className, ...props }, ref) => {
351
+ const id = React18__namespace.useId();
352
+ const hintId = `${id}-hint`;
353
+ const errorId = `${id}-error`;
354
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-1 w-full", className), children: [
355
+ /* @__PURE__ */ jsxRuntime.jsx(
356
+ Checkbox,
357
+ {
358
+ ref,
359
+ id,
360
+ label,
361
+ "aria-describedby": cn(hint && hintId, error && errorId) || void 0,
362
+ "aria-invalid": error ? "true" : void 0,
363
+ ...props
364
+ }
365
+ ),
366
+ hint && !error && /* @__PURE__ */ jsxRuntime.jsx(Hint, { id: hintId, className: "pl-[1.8rem]", children: hint }),
367
+ error && /* @__PURE__ */ jsxRuntime.jsx(Hint, { id: errorId, error: true, className: "pl-[1.8rem]", children: error })
368
+ ] });
369
+ }
370
+ );
371
+ CheckboxField.displayName = "CheckboxField";
372
+ var Switch = React18__namespace.forwardRef(
313
373
  ({ className, label, id, ...props }, ref) => {
314
- const autoId = React17__namespace.useId();
374
+ const autoId = React18__namespace.useId();
315
375
  const inputId = id ?? autoId;
316
376
  return /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
317
377
  /* @__PURE__ */ jsxRuntime.jsx("input", { ref, id: inputId, type: "checkbox", role: "switch", className: "peer sr-only", ...props }),
@@ -321,7 +381,7 @@ var Switch = React17__namespace.forwardRef(
321
381
  }
322
382
  );
323
383
  Switch.displayName = "Switch";
324
- var Slider = React17__namespace.forwardRef(
384
+ var Slider = React18__namespace.forwardRef(
325
385
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
326
386
  "input",
327
387
  {
@@ -374,7 +434,7 @@ function Segmented({
374
434
  }
375
435
  );
376
436
  }
377
- var Card = React17__namespace.forwardRef(
437
+ var Card = React18__namespace.forwardRef(
378
438
  ({ as: Tag = "div", className, elevated, interactive, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
379
439
  Tag,
380
440
  {
@@ -390,23 +450,23 @@ var Card = React17__namespace.forwardRef(
390
450
  )
391
451
  );
392
452
  Card.displayName = "Card";
393
- var CardHeader = React17__namespace.forwardRef(
453
+ var CardHeader = React18__namespace.forwardRef(
394
454
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("p-[1.35rem] flex flex-col gap-1", className), ...props })
395
455
  );
396
456
  CardHeader.displayName = "CardHeader";
397
- var CardTitle = React17__namespace.forwardRef(
457
+ var CardTitle = React18__namespace.forwardRef(
398
458
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("h3", { ref, className: cn("m-0 text-base font-bold tracking-[-0.01em]", className), ...props })
399
459
  );
400
460
  CardTitle.displayName = "CardTitle";
401
- var CardDescription = React17__namespace.forwardRef(
461
+ var CardDescription = React18__namespace.forwardRef(
402
462
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("p", { ref, className: cn("m-0 text-[0.85rem] text-muted-foreground", className), ...props })
403
463
  );
404
464
  CardDescription.displayName = "CardDescription";
405
- var CardContent = React17__namespace.forwardRef(
465
+ var CardContent = React18__namespace.forwardRef(
406
466
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("px-[1.35rem] pb-[1.35rem]", className), ...props })
407
467
  );
408
468
  CardContent.displayName = "CardContent";
409
- var CardFooter = React17__namespace.forwardRef(
469
+ var CardFooter = React18__namespace.forwardRef(
410
470
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
411
471
  "div",
412
472
  {
@@ -417,7 +477,7 @@ var CardFooter = React17__namespace.forwardRef(
417
477
  )
418
478
  );
419
479
  CardFooter.displayName = "CardFooter";
420
- var Stat = React17__namespace.forwardRef(
480
+ var Stat = React18__namespace.forwardRef(
421
481
  ({ className, label, value, delta, trend, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(Card, { ref, className: cn("p-[1.35rem] flex flex-col gap-2", className), ...props, children: [
422
482
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.78rem] font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: label }),
423
483
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[2rem] font-bold tracking-[-0.03em] tabular-nums leading-none", children: value }),
@@ -457,7 +517,7 @@ var avatarVariants = classVarianceAuthority.cva(
457
517
  defaultVariants: { size: "md", tone: "secondary" }
458
518
  }
459
519
  );
460
- var Avatar = React17__namespace.forwardRef(
520
+ var Avatar = React18__namespace.forwardRef(
461
521
  ({ className, size, tone, src, alt, status, children, ...props }, ref) => {
462
522
  const node = /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn(avatarVariants({ size, tone }), "overflow-hidden", className), ...props, children: src ? /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt, className: "h-full w-full object-cover" }) : children });
463
523
  if (!status) return node;
@@ -468,20 +528,20 @@ var Avatar = React17__namespace.forwardRef(
468
528
  }
469
529
  );
470
530
  Avatar.displayName = "Avatar";
471
- var AvatarGroup = React17__namespace.forwardRef(
531
+ var AvatarGroup = React18__namespace.forwardRef(
472
532
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex [&>*:not(:first-child)]:-ml-2.5", className), ...props })
473
533
  );
474
534
  AvatarGroup.displayName = "AvatarGroup";
475
- var TabsContext = React17__namespace.createContext(null);
535
+ var TabsContext = React18__namespace.createContext(null);
476
536
  function useTabs() {
477
- const ctx = React17__namespace.useContext(TabsContext);
537
+ const ctx = React18__namespace.useContext(TabsContext);
478
538
  if (!ctx) throw new Error("Tabs.* must be used within <Tabs>");
479
539
  return ctx;
480
540
  }
481
541
  function Tabs({ value, defaultValue, onValueChange, className, children, ...props }) {
482
- const [internal, setInternal] = React17__namespace.useState(defaultValue ?? "");
542
+ const [internal, setInternal] = React18__namespace.useState(defaultValue ?? "");
483
543
  const current = value ?? internal;
484
- const setValue = React17__namespace.useCallback(
544
+ const setValue = React18__namespace.useCallback(
485
545
  (v) => {
486
546
  if (value === void 0) setInternal(v);
487
547
  onValueChange?.(v);
@@ -490,7 +550,7 @@ function Tabs({ value, defaultValue, onValueChange, className, children, ...prop
490
550
  );
491
551
  return /* @__PURE__ */ jsxRuntime.jsx(TabsContext.Provider, { value: { value: current, setValue }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, ...props, children }) });
492
552
  }
493
- var TabsList = React17__namespace.forwardRef(
553
+ var TabsList = React18__namespace.forwardRef(
494
554
  ({ className, onKeyDown, ...props }, ref) => {
495
555
  const handleKeyDown = (e) => {
496
556
  const container = e.currentTarget;
@@ -534,7 +594,7 @@ var TabsList = React17__namespace.forwardRef(
534
594
  }
535
595
  );
536
596
  TabsList.displayName = "TabsList";
537
- var TabsTrigger = React17__namespace.forwardRef(
597
+ var TabsTrigger = React18__namespace.forwardRef(
538
598
  ({ className, value, children, ...props }, ref) => {
539
599
  const { value: current, setValue } = useTabs();
540
600
  const active = current === value;
@@ -563,7 +623,7 @@ var TabsTrigger = React17__namespace.forwardRef(
563
623
  }
564
624
  );
565
625
  TabsTrigger.displayName = "TabsTrigger";
566
- var TabsContent = React17__namespace.forwardRef(
626
+ var TabsContent = React18__namespace.forwardRef(
567
627
  ({ className, value, ...props }, ref) => {
568
628
  const { value: current } = useTabs();
569
629
  const active = current === value;
@@ -583,10 +643,10 @@ var TabsContent = React17__namespace.forwardRef(
583
643
  }
584
644
  );
585
645
  TabsContent.displayName = "TabsContent";
586
- var AccordionContext = React17__namespace.createContext(null);
646
+ var AccordionContext = React18__namespace.createContext(null);
587
647
  function Accordion({ type = "single", defaultValue = [], className, children, ...props }) {
588
- const [open, setOpen] = React17__namespace.useState(defaultValue);
589
- const toggle = React17__namespace.useCallback(
648
+ const [open, setOpen] = React18__namespace.useState(defaultValue);
649
+ const toggle = React18__namespace.useCallback(
590
650
  (v) => {
591
651
  setOpen((prev) => {
592
652
  const isOpen = prev.includes(v);
@@ -598,15 +658,15 @@ function Accordion({ type = "single", defaultValue = [], className, children, ..
598
658
  );
599
659
  return /* @__PURE__ */ jsxRuntime.jsx(AccordionContext.Provider, { value: { open, toggle }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("border border-border rounded-kj-lg overflow-hidden", className), ...props, children }) });
600
660
  }
601
- var ItemContext = React17__namespace.createContext("");
602
- var AccordionItem = React17__namespace.forwardRef(
661
+ var ItemContext = React18__namespace.createContext("");
662
+ var AccordionItem = React18__namespace.forwardRef(
603
663
  ({ className, value, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(ItemContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("border-t border-border first:border-t-0", className), ...props }) })
604
664
  );
605
665
  AccordionItem.displayName = "AccordionItem";
606
- var AccordionTrigger = React17__namespace.forwardRef(
666
+ var AccordionTrigger = React18__namespace.forwardRef(
607
667
  ({ className, children, ...props }, ref) => {
608
- const ctx = React17__namespace.useContext(AccordionContext);
609
- const value = React17__namespace.useContext(ItemContext);
668
+ const ctx = React18__namespace.useContext(AccordionContext);
669
+ const value = React18__namespace.useContext(ItemContext);
610
670
  const isOpen = ctx.open.includes(value);
611
671
  return /* @__PURE__ */ jsxRuntime.jsxs(
612
672
  "button",
@@ -643,10 +703,10 @@ var AccordionTrigger = React17__namespace.forwardRef(
643
703
  }
644
704
  );
645
705
  AccordionTrigger.displayName = "AccordionTrigger";
646
- var AccordionContent = React17__namespace.forwardRef(
706
+ var AccordionContent = React18__namespace.forwardRef(
647
707
  ({ className, children, ...props }, ref) => {
648
- const ctx = React17__namespace.useContext(AccordionContext);
649
- const value = React17__namespace.useContext(ItemContext);
708
+ const ctx = React18__namespace.useContext(AccordionContext);
709
+ const value = React18__namespace.useContext(ItemContext);
650
710
  const isOpen = ctx.open.includes(value);
651
711
  return /* @__PURE__ */ jsxRuntime.jsx(
652
712
  "div",
@@ -660,11 +720,11 @@ var AccordionContent = React17__namespace.forwardRef(
660
720
  }
661
721
  );
662
722
  AccordionContent.displayName = "AccordionContent";
663
- var MenuContext = React17__namespace.createContext(null);
723
+ var MenuContext = React18__namespace.createContext(null);
664
724
  function DropdownMenu({ children, className }) {
665
- const [open, setOpen] = React17__namespace.useState(false);
666
- const ref = React17__namespace.useRef(null);
667
- React17__namespace.useEffect(() => {
725
+ const [open, setOpen] = React18__namespace.useState(false);
726
+ const ref = React18__namespace.useRef(null);
727
+ React18__namespace.useEffect(() => {
668
728
  if (!open) return;
669
729
  const onDoc = (e) => {
670
730
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -679,11 +739,11 @@ function DropdownMenu({ children, className }) {
679
739
  }, [open]);
680
740
  return /* @__PURE__ */ jsxRuntime.jsx(MenuContext.Provider, { value: { open, setOpen }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("relative inline-block", className), children }) });
681
741
  }
682
- var DropdownMenuTrigger = React17__namespace.forwardRef(({ onClick, asChild, ...props }, ref) => {
683
- const ctx = React17__namespace.useContext(MenuContext);
742
+ var DropdownMenuTrigger = React18__namespace.forwardRef(({ onClick, asChild, ...props }, ref) => {
743
+ const ctx = React18__namespace.useContext(MenuContext);
684
744
  if (asChild) {
685
- const child = React17__namespace.Children.only(props.children);
686
- return React17__namespace.cloneElement(child, {
745
+ const child = React18__namespace.Children.only(props.children);
746
+ return React18__namespace.cloneElement(child, {
687
747
  ref,
688
748
  ...props,
689
749
  ...child.props,
@@ -713,9 +773,9 @@ var DropdownMenuTrigger = React17__namespace.forwardRef(({ onClick, asChild, ...
713
773
  });
714
774
  DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
715
775
  function DropdownMenuContent({ className, align = "start", children, ...props }) {
716
- const ctx = React17__namespace.useContext(MenuContext);
717
- const ref = React17__namespace.useRef(null);
718
- React17__namespace.useEffect(() => {
776
+ const ctx = React18__namespace.useContext(MenuContext);
777
+ const ref = React18__namespace.useRef(null);
778
+ React18__namespace.useEffect(() => {
719
779
  if (!ctx.open) return;
720
780
  const container = ref.current;
721
781
  if (container) {
@@ -762,9 +822,9 @@ function DropdownMenuContent({ className, align = "start", children, ...props })
762
822
  }
763
823
  );
764
824
  }
765
- var DropdownMenuItem = React17__namespace.forwardRef(
825
+ var DropdownMenuItem = React18__namespace.forwardRef(
766
826
  ({ className, danger, icon, children, onClick, ...props }, ref) => {
767
- const ctx = React17__namespace.useContext(MenuContext);
827
+ const ctx = React18__namespace.useContext(MenuContext);
768
828
  return /* @__PURE__ */ jsxRuntime.jsxs(
769
829
  "button",
770
830
  {
@@ -794,11 +854,11 @@ DropdownMenuItem.displayName = "DropdownMenuItem";
794
854
  function DropdownMenuSeparator({ className }) {
795
855
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("h-px bg-border my-1.5", className), role: "separator" });
796
856
  }
797
- var Breadcrumb = React17__namespace.forwardRef(
857
+ var Breadcrumb = React18__namespace.forwardRef(
798
858
  ({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("nav", { ref, "aria-label": "Breadcrumb", className: cn("flex items-center gap-1.5 text-[0.85rem] text-muted-foreground", className), ...props, children })
799
859
  );
800
860
  Breadcrumb.displayName = "Breadcrumb";
801
- var BreadcrumbItem = React17__namespace.forwardRef(
861
+ var BreadcrumbItem = React18__namespace.forwardRef(
802
862
  ({ className, current, children, ...props }, ref) => {
803
863
  if (current) {
804
864
  return /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-current": "page", className: cn("text-foreground font-semibold", className), children });
@@ -845,27 +905,99 @@ function Pagination({ page, pageCount, onPageChange, className }) {
845
905
  /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Next", disabled: page >= pageCount, onClick: () => onPageChange(page + 1), children: /* @__PURE__ */ jsxRuntime.jsx(Chevron, { dir: "right" }) })
846
906
  ] });
847
907
  }
848
- var TableWrap = React17__namespace.forwardRef(
849
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("border border-border rounded-kj-lg overflow-hidden", className), ...props })
908
+ var BottomNavigation = React18__namespace.forwardRef(
909
+ ({ className, items, showLabels = "always", fixed = true, ...props }, ref) => {
910
+ return /* @__PURE__ */ jsxRuntime.jsx(
911
+ "nav",
912
+ {
913
+ ref,
914
+ className: cn(
915
+ "bg-surface/90 border-t border-border flex items-center justify-around px-4 pt-2 pb-[calc(0.75rem+env(safe-area-inset-bottom,0))] shadow-kj-lg",
916
+ fixed ? "fixed bottom-0 left-0 right-0 z-40 backdrop-blur-md" : "relative w-full",
917
+ className
918
+ ),
919
+ ...props,
920
+ children: items.map((item) => {
921
+ const isActive = item.active;
922
+ const showLabel = showLabels !== "never" && (showLabels === "always" || isActive);
923
+ const content = /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-col items-center justify-center gap-1 w-full relative", children: [
924
+ /* @__PURE__ */ jsxRuntime.jsxs(
925
+ "span",
926
+ {
927
+ className: cn(
928
+ "relative flex items-center justify-center p-1 rounded-full transition-all duration-200",
929
+ isActive ? "text-primary scale-110" : "text-muted-foreground group-hover:text-foreground group-active:scale-95"
930
+ ),
931
+ children: [
932
+ item.icon,
933
+ item.badge !== void 0 && item.badge !== null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-1 -right-1.5 min-w-[16px] h-[16px] px-1 rounded-full bg-primary text-primary-foreground text-[9px] font-bold flex items-center justify-center ring-2 ring-surface", children: item.badge })
934
+ ]
935
+ }
936
+ ),
937
+ /* @__PURE__ */ jsxRuntime.jsx(
938
+ "span",
939
+ {
940
+ className: cn(
941
+ "text-[10px] font-semibold tracking-wide transition-all duration-200 select-none",
942
+ showLabel ? "opacity-100 scale-100 h-auto" : "opacity-0 scale-75 h-0 overflow-hidden",
943
+ isActive ? "text-primary font-bold" : "text-muted-foreground group-hover:text-foreground"
944
+ ),
945
+ children: item.label
946
+ }
947
+ ),
948
+ isActive && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -bottom-1.5 w-1 h-1 rounded-full bg-primary animate-fade-in" })
949
+ ] });
950
+ const itemClass = "group flex-1 flex flex-col items-center justify-center py-1 cursor-pointer transition-all duration-150 relative focus:outline-none";
951
+ if (item.href) {
952
+ return /* @__PURE__ */ jsxRuntime.jsx(
953
+ "a",
954
+ {
955
+ href: item.href,
956
+ className: itemClass,
957
+ "aria-current": isActive ? "page" : void 0,
958
+ children: content
959
+ },
960
+ item.id
961
+ );
962
+ }
963
+ return /* @__PURE__ */ jsxRuntime.jsx(
964
+ "button",
965
+ {
966
+ type: "button",
967
+ onClick: item.onClick,
968
+ className: itemClass,
969
+ "aria-pressed": isActive,
970
+ children: content
971
+ },
972
+ item.id
973
+ );
974
+ })
975
+ }
976
+ );
977
+ }
978
+ );
979
+ BottomNavigation.displayName = "BottomNavigation";
980
+ var TableWrap = React18__namespace.forwardRef(
981
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("border border-border rounded-kj-lg overflow-x-auto w-full", className), ...props })
850
982
  );
851
983
  TableWrap.displayName = "TableWrap";
852
- var Table = React17__namespace.forwardRef(
984
+ var Table = React18__namespace.forwardRef(
853
985
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("table", { ref, className: cn("w-full border-collapse text-[0.85rem]", className), ...props })
854
986
  );
855
987
  Table.displayName = "Table";
856
- var TableHeader = React17__namespace.forwardRef(
988
+ var TableHeader = React18__namespace.forwardRef(
857
989
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("thead", { ref, className, ...props })
858
990
  );
859
991
  TableHeader.displayName = "TableHeader";
860
- var TableBody = React17__namespace.forwardRef(
992
+ var TableBody = React18__namespace.forwardRef(
861
993
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tbody", { ref, className, ...props })
862
994
  );
863
995
  TableBody.displayName = "TableBody";
864
- var TableRow = React17__namespace.forwardRef(
996
+ var TableRow = React18__namespace.forwardRef(
865
997
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tr", { ref, className: cn("transition-colors hover:bg-muted/50", className), ...props })
866
998
  );
867
999
  TableRow.displayName = "TableRow";
868
- var TableHead = React17__namespace.forwardRef(
1000
+ var TableHead = React18__namespace.forwardRef(
869
1001
  ({ className, numeric, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
870
1002
  "th",
871
1003
  {
@@ -880,7 +1012,7 @@ var TableHead = React17__namespace.forwardRef(
880
1012
  )
881
1013
  );
882
1014
  TableHead.displayName = "TableHead";
883
- var TableCell = React17__namespace.forwardRef(
1015
+ var TableCell = React18__namespace.forwardRef(
884
1016
  ({ className, numeric, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
885
1017
  "td",
886
1018
  {
@@ -913,13 +1045,13 @@ function Tooltip({ content, children, className }) {
913
1045
  )
914
1046
  ] });
915
1047
  }
916
- var ModalContext = React17__namespace.createContext(null);
1048
+ var ModalContext = React18__namespace.createContext(null);
917
1049
  function Modal({ open, onClose, children, width = 440, className, showClose = true }) {
918
- const titleId = React17__namespace.useId();
919
- const descId = React17__namespace.useId();
920
- const containerRef = React17__namespace.useRef(null);
921
- const lastActiveElement = React17__namespace.useRef(null);
922
- React17__namespace.useEffect(() => {
1050
+ const titleId = React18__namespace.useId();
1051
+ const descId = React18__namespace.useId();
1052
+ const containerRef = React18__namespace.useRef(null);
1053
+ const lastActiveElement = React18__namespace.useRef(null);
1054
+ React18__namespace.useEffect(() => {
923
1055
  if (!open) {
924
1056
  if (lastActiveElement.current) {
925
1057
  lastActiveElement.current.focus();
@@ -1021,19 +1153,19 @@ function Modal({ open, onClose, children, width = 440, className, showClose = tr
1021
1153
  );
1022
1154
  }
1023
1155
  function ModalTitle({ className, id, ...props }) {
1024
- const ctx = React17__namespace.useContext(ModalContext);
1156
+ const ctx = React18__namespace.useContext(ModalContext);
1025
1157
  return /* @__PURE__ */ jsxRuntime.jsx("h3", { id: id ?? ctx?.titleId, className: cn("m-0 mb-2 text-[1.15rem] font-bold tracking-[-0.01em]", className), ...props });
1026
1158
  }
1027
1159
  function ModalDescription({ className, id, ...props }) {
1028
- const ctx = React17__namespace.useContext(ModalContext);
1160
+ const ctx = React18__namespace.useContext(ModalContext);
1029
1161
  return /* @__PURE__ */ jsxRuntime.jsx("p", { id: id ?? ctx?.descId, className: cn("m-0 text-[0.9rem] text-muted-foreground", className), ...props });
1030
1162
  }
1031
1163
  function ModalActions({ className, ...props }) {
1032
1164
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex gap-2.5 justify-end mt-6", className), ...props });
1033
1165
  }
1034
- var ToastContext = React17__namespace.createContext(null);
1166
+ var ToastContext = React18__namespace.createContext(null);
1035
1167
  function useToast() {
1036
- const ctx = React17__namespace.useContext(ToastContext);
1168
+ const ctx = React18__namespace.useContext(ToastContext);
1037
1169
  if (!ctx) throw new Error("useToast must be used within <ToastProvider>");
1038
1170
  return ctx;
1039
1171
  }
@@ -1054,13 +1186,13 @@ var toneBorder = {
1054
1186
  danger: "border-l-danger"
1055
1187
  };
1056
1188
  function ToastProvider({ children }) {
1057
- const [items, setItems] = React17__namespace.useState([]);
1058
- const idRef = React17__namespace.useRef(0);
1059
- const remove = React17__namespace.useCallback((id) => {
1189
+ const [items, setItems] = React18__namespace.useState([]);
1190
+ const idRef = React18__namespace.useRef(0);
1191
+ const remove = React18__namespace.useCallback((id) => {
1060
1192
  setItems((prev) => prev.map((t) => t.id === id ? { ...t, leaving: true } : t));
1061
1193
  setTimeout(() => setItems((prev) => prev.filter((t) => t.id !== id)), 250);
1062
1194
  }, []);
1063
- const toast = React17__namespace.useCallback(
1195
+ const toast = React18__namespace.useCallback(
1064
1196
  ({ message, tone = "default", duration = 3200 }) => {
1065
1197
  const id = ++idRef.current;
1066
1198
  setItems((prev) => [...prev, { id, message, tone, duration }]);
@@ -1090,7 +1222,7 @@ function ToastProvider({ children }) {
1090
1222
  )) })
1091
1223
  ] });
1092
1224
  }
1093
- var PageHeader = React17__namespace.forwardRef(
1225
+ var PageHeader = React18__namespace.forwardRef(
1094
1226
  ({ eyebrow, title, description, actions }, ref) => /* @__PURE__ */ jsxRuntime.jsx("header", { ref, className: "py-12 md:py-16", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6 md:flex-row md:items-end md:justify-between", children: [
1095
1227
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 max-w-2xl", children: [
1096
1228
  eyebrow && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-mono text-xs font-bold uppercase tracking-[0.2em] text-primary", children: eyebrow }),
@@ -1101,7 +1233,7 @@ var PageHeader = React17__namespace.forwardRef(
1101
1233
  ] }) })
1102
1234
  );
1103
1235
  PageHeader.displayName = "PageHeader";
1104
- var EmptyState = React17__namespace.forwardRef(
1236
+ var EmptyState = React18__namespace.forwardRef(
1105
1237
  ({ className, icon, title, description, action, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
1106
1238
  "div",
1107
1239
  {
@@ -1121,7 +1253,7 @@ var EmptyState = React17__namespace.forwardRef(
1121
1253
  )
1122
1254
  );
1123
1255
  EmptyState.displayName = "EmptyState";
1124
- var MetricCard = React17__namespace.forwardRef(
1256
+ var MetricCard = React18__namespace.forwardRef(
1125
1257
  ({ className, title, value, trend, trendDirection = "neutral", description, icon, ...props }, ref) => {
1126
1258
  const trendColor = {
1127
1259
  up: "text-success bg-success-surface border-success/20",
@@ -1151,54 +1283,171 @@ function DataTable({
1151
1283
  emptyTitle = "No data available",
1152
1284
  emptyDescription = "There are no records to display at this time.",
1153
1285
  emptyAction,
1286
+ getRowKey,
1287
+ onRowClick,
1288
+ toolbar,
1289
+ pagination,
1290
+ selectedRows,
1291
+ onSelectionChange,
1292
+ sortBy,
1293
+ sortDirection,
1294
+ onSort,
1154
1295
  ...props
1155
1296
  }) {
1156
- return /* @__PURE__ */ jsxRuntime.jsxs(TableWrap, { className: cn("relative overflow-hidden", className), ...props, children: [
1157
- /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
1158
- /* @__PURE__ */ jsxRuntime.jsx(TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(TableRow, { children: columns.map((col, idx) => /* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: col.className, children: col.header }, idx)) }) }),
1159
- /* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: loading && data.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(TableRow, { children: /* @__PURE__ */ jsxRuntime.jsx(TableCell, { colSpan: columns.length, className: "h-64 text-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center gap-3", children: [
1160
- /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 32 }),
1161
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Loading dataset..." })
1162
- ] }) }) }) : error ? /* @__PURE__ */ jsxRuntime.jsx(TableRow, { children: /* @__PURE__ */ jsxRuntime.jsx(TableCell, { colSpan: columns.length, className: "p-8", children: /* @__PURE__ */ jsxRuntime.jsx(Alert, { variant: "danger", title: "Error loading data", children: error }) }) }) : data.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(TableRow, { children: /* @__PURE__ */ jsxRuntime.jsx(TableCell, { colSpan: columns.length, className: "p-0", children: /* @__PURE__ */ jsxRuntime.jsx(
1163
- EmptyState,
1164
- {
1165
- title: emptyTitle,
1166
- description: emptyDescription,
1167
- action: emptyAction,
1168
- className: "border-none bg-transparent rounded-none py-16"
1169
- }
1170
- ) }) }) : data.map((row, rowIdx) => /* @__PURE__ */ jsxRuntime.jsx(TableRow, { children: columns.map((col, colIdx) => /* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: col.className, children: col.accessor(row) }, colIdx)) }, rowIdx)) })
1297
+ const getRowId = React18__namespace.useCallback(
1298
+ (row, index) => getRowKey ? getRowKey(row, index) : index,
1299
+ [getRowKey]
1300
+ );
1301
+ const isSelectionActive = selectedRows !== void 0 && onSelectionChange !== void 0;
1302
+ const allSelected = React18__namespace.useMemo(() => {
1303
+ if (!isSelectionActive || data.length === 0) return false;
1304
+ return data.every((row, idx) => selectedRows.has(getRowId(row, idx)));
1305
+ }, [isSelectionActive, data, selectedRows, getRowId]);
1306
+ const someSelected = React18__namespace.useMemo(() => {
1307
+ if (!isSelectionActive || data.length === 0) return false;
1308
+ const selectedCount = data.filter((row, idx) => selectedRows.has(getRowId(row, idx))).length;
1309
+ return selectedCount > 0 && selectedCount < data.length;
1310
+ }, [isSelectionActive, data, selectedRows, getRowId]);
1311
+ const headerCheckboxRef = React18__namespace.useRef(null);
1312
+ React18__namespace.useEffect(() => {
1313
+ if (headerCheckboxRef.current) {
1314
+ headerCheckboxRef.current.indeterminate = someSelected;
1315
+ }
1316
+ }, [someSelected]);
1317
+ const handleSelectAll = (e) => {
1318
+ if (!onSelectionChange) return;
1319
+ const checked = e.target.checked;
1320
+ const next = new Set(selectedRows);
1321
+ data.forEach((row, idx) => {
1322
+ const id = getRowId(row, idx);
1323
+ if (checked) {
1324
+ next.add(id);
1325
+ } else {
1326
+ next.delete(id);
1327
+ }
1328
+ });
1329
+ onSelectionChange(next);
1330
+ };
1331
+ const handleSelectRow = (row, idx, checked) => {
1332
+ if (!onSelectionChange || !selectedRows) return;
1333
+ const id = getRowId(row, idx);
1334
+ const next = new Set(selectedRows);
1335
+ if (checked) {
1336
+ next.add(id);
1337
+ } else {
1338
+ next.delete(id);
1339
+ }
1340
+ onSelectionChange(next);
1341
+ };
1342
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-4 w-full", className), children: [
1343
+ toolbar && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-3", children: toolbar }),
1344
+ /* @__PURE__ */ jsxRuntime.jsxs(TableWrap, { className: "relative overflow-hidden", ...props, children: [
1345
+ /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
1346
+ /* @__PURE__ */ jsxRuntime.jsx(TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { children: [
1347
+ isSelectionActive && /* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "w-12 px-4 text-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
1348
+ "input",
1349
+ {
1350
+ type: "checkbox",
1351
+ ref: headerCheckboxRef,
1352
+ checked: allSelected,
1353
+ onChange: handleSelectAll,
1354
+ "aria-label": "Select all rows",
1355
+ className: "h-4 w-4 rounded border-input text-primary focus:ring-ring"
1356
+ }
1357
+ ) }) }),
1358
+ columns.map((col, idx) => {
1359
+ const alignClass = {
1360
+ left: "text-left",
1361
+ center: "text-center",
1362
+ right: "text-right"
1363
+ }[col.align || "left"];
1364
+ const isSortable = col.sortable && onSort && col.sortKey;
1365
+ const isSortedActive = sortBy && col.sortKey === sortBy;
1366
+ return /* @__PURE__ */ jsxRuntime.jsx(
1367
+ TableHead,
1368
+ {
1369
+ className: cn(
1370
+ alignClass,
1371
+ isSortable && "cursor-pointer select-none hover:bg-muted/30 transition-colors",
1372
+ col.className
1373
+ ),
1374
+ onClick: () => {
1375
+ if (!isSortable || !col.sortKey) return;
1376
+ const nextDirection = isSortedActive && sortDirection === "asc" ? "desc" : "asc";
1377
+ onSort(col.sortKey, nextDirection);
1378
+ },
1379
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("inline-flex items-center gap-1.5", alignClass === "text-right" && "justify-end w-full"), children: [
1380
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: col.header }),
1381
+ isSortable && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground shrink-0 select-none", children: isSortedActive ? sortDirection === "asc" ? "\u25B2" : "\u25BC" : "\u21C5" })
1382
+ ] })
1383
+ },
1384
+ idx
1385
+ );
1386
+ })
1387
+ ] }) }),
1388
+ /* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: loading && data.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(TableRow, { children: /* @__PURE__ */ jsxRuntime.jsx(TableCell, { colSpan: columns.length + (isSelectionActive ? 1 : 0), className: "h-64 text-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center gap-3", children: [
1389
+ /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 32 }),
1390
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Loading dataset..." })
1391
+ ] }) }) }) : error ? /* @__PURE__ */ jsxRuntime.jsx(TableRow, { children: /* @__PURE__ */ jsxRuntime.jsx(TableCell, { colSpan: columns.length + (isSelectionActive ? 1 : 0), className: "p-8", children: /* @__PURE__ */ jsxRuntime.jsx(Alert, { variant: "danger", title: "Error loading data", children: error }) }) }) : data.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(TableRow, { children: /* @__PURE__ */ jsxRuntime.jsx(TableCell, { colSpan: columns.length + (isSelectionActive ? 1 : 0), className: "p-0", children: /* @__PURE__ */ jsxRuntime.jsx(
1392
+ EmptyState,
1393
+ {
1394
+ title: emptyTitle,
1395
+ description: emptyDescription,
1396
+ action: emptyAction,
1397
+ className: "border-none bg-transparent rounded-none py-16"
1398
+ }
1399
+ ) }) }) : data.map((row, rowIdx) => {
1400
+ const rowKey = getRowId(row, rowIdx);
1401
+ const isSelected = isSelectionActive && selectedRows.has(rowKey);
1402
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1403
+ TableRow,
1404
+ {
1405
+ onClick: () => onRowClick && onRowClick(row),
1406
+ className: cn(
1407
+ onRowClick && "cursor-pointer hover:bg-muted/40 transition-colors",
1408
+ isSelected && "bg-primary/5 hover:bg-primary/10"
1409
+ ),
1410
+ children: [
1411
+ isSelectionActive && /* @__PURE__ */ jsxRuntime.jsx(
1412
+ TableCell,
1413
+ {
1414
+ className: "w-12 px-4 text-center",
1415
+ onClick: (e) => {
1416
+ e.stopPropagation();
1417
+ },
1418
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
1419
+ "input",
1420
+ {
1421
+ type: "checkbox",
1422
+ checked: isSelected,
1423
+ onChange: (e) => handleSelectRow(row, rowIdx, e.target.checked),
1424
+ "aria-label": `Select row ${rowIdx + 1}`,
1425
+ className: "h-4 w-4 rounded border-input text-primary focus:ring-ring"
1426
+ }
1427
+ ) })
1428
+ }
1429
+ ),
1430
+ columns.map((col, colIdx) => {
1431
+ const alignClass = {
1432
+ left: "text-left",
1433
+ center: "text-center",
1434
+ right: "text-right"
1435
+ }[col.align || "left"];
1436
+ return /* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: cn(alignClass, col.className), children: col.accessor(row) }, colIdx);
1437
+ })
1438
+ ]
1439
+ },
1440
+ rowKey
1441
+ );
1442
+ }) })
1443
+ ] }),
1444
+ loading && data.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-background/50 backdrop-blur-[1px] grid place-items-center z-10 transition-opacity duration-150", children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 36 }) })
1171
1445
  ] }),
1172
- loading && data.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-background/50 backdrop-blur-[1px] grid place-items-center z-10 transition-opacity duration-150", children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 36 }) })
1446
+ pagination && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-end w-full", children: pagination })
1173
1447
  ] });
1174
1448
  }
1175
1449
  DataTable.displayName = "DataTable";
1176
- var FormField = React17__namespace.forwardRef(
1177
- ({ className, label, hint, error, required, children, ...props }, ref) => {
1178
- const id = React17__namespace.useId();
1179
- const hintId = `${id}-hint`;
1180
- const errorId = `${id}-error`;
1181
- const child = React17__namespace.Children.only(children);
1182
- const clonedChild = React17__namespace.cloneElement(child, {
1183
- id: child.props.id ?? id,
1184
- "aria-describedby": cn(
1185
- hint && hintId,
1186
- error && errorId,
1187
- child.props["aria-describedby"]
1188
- ) || void 0,
1189
- "aria-invalid": error ? "true" : void 0,
1190
- required: child.props.required ?? required
1191
- });
1192
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("flex flex-col gap-1.5 w-full", className), ...props, children: [
1193
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: id, required, children: label }),
1194
- clonedChild,
1195
- hint && !error && /* @__PURE__ */ jsxRuntime.jsx(Hint, { id: hintId, children: hint }),
1196
- error && /* @__PURE__ */ jsxRuntime.jsx(Hint, { id: errorId, error: true, children: error })
1197
- ] });
1198
- }
1199
- );
1200
- FormField.displayName = "FormField";
1201
- var ErrorState = React17__namespace.forwardRef(
1450
+ var ErrorState = React18__namespace.forwardRef(
1202
1451
  ({ className, title = "Wyst\u0105pi\u0142 b\u0142\u0105d", message, onRetry, retryLabel = "Spr\xF3buj ponownie", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
1203
1452
  "div",
1204
1453
  {
@@ -1218,7 +1467,7 @@ var ErrorState = React17__namespace.forwardRef(
1218
1467
  )
1219
1468
  );
1220
1469
  ErrorState.displayName = "ErrorState";
1221
- var Skeleton = React17__namespace.forwardRef(
1470
+ var Skeleton = React18__namespace.forwardRef(
1222
1471
  ({ className, variant = "rectangular", width, height, style, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1223
1472
  "div",
1224
1473
  {
@@ -1240,27 +1489,549 @@ var Skeleton = React17__namespace.forwardRef(
1240
1489
  )
1241
1490
  );
1242
1491
  Skeleton.displayName = "Skeleton";
1243
- var DashboardShell = React17__namespace.forwardRef(
1244
- ({ className, sidebar, topbar, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
1492
+ var DashboardShell = React18__namespace.forwardRef(
1493
+ ({
1494
+ className,
1495
+ sidebar,
1496
+ topbar,
1497
+ children,
1498
+ sidebarWidth = "md:w-64",
1499
+ contentWidth = "default",
1500
+ stickyTopbar = true,
1501
+ mobileSidebar,
1502
+ ...props
1503
+ }, ref) => {
1504
+ const [mobileOpen, setMobileOpen] = React18__namespace.useState(false);
1505
+ const contentWidthClass = {
1506
+ default: "max-w-7xl w-full mx-auto",
1507
+ wide: "max-w-screen-2xl w-full mx-auto",
1508
+ full: "max-w-none w-full"
1509
+ }[contentWidth];
1510
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1511
+ "div",
1512
+ {
1513
+ ref,
1514
+ className: cn(
1515
+ "min-h-screen bg-canvas text-foreground flex flex-col md:flex-row",
1516
+ className
1517
+ ),
1518
+ ...props,
1519
+ children: [
1520
+ sidebar && /* @__PURE__ */ jsxRuntime.jsx(
1521
+ "aside",
1522
+ {
1523
+ className: cn(
1524
+ "border-r border-border bg-surface shrink-0 z-20",
1525
+ mobileSidebar ? "hidden md:flex" : "w-full md:flex",
1526
+ sidebarWidth
1527
+ ),
1528
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("sticky top-0 w-full flex flex-col", mobileSidebar ? "h-screen" : "h-auto md:h-screen"), children: sidebar })
1529
+ }
1530
+ ),
1531
+ mobileSidebar && mobileOpen && /* @__PURE__ */ jsxRuntime.jsx(
1532
+ "div",
1533
+ {
1534
+ onClick: () => setMobileOpen(false),
1535
+ className: "fixed inset-0 z-50 md:hidden bg-[color-mix(in_oklch,#09090b_45%,transparent)] backdrop-blur-[2px] transition-opacity duration-300",
1536
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1537
+ "aside",
1538
+ {
1539
+ onClick: (e) => e.stopPropagation(),
1540
+ className: "w-72 h-full bg-surface border-r border-border flex flex-col shadow-kj-lg",
1541
+ children: [
1542
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-4 border-b border-border", children: [
1543
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-bold uppercase tracking-wider text-muted-foreground", children: "Navigation" }),
1544
+ /* @__PURE__ */ jsxRuntime.jsx(
1545
+ "button",
1546
+ {
1547
+ type: "button",
1548
+ onClick: () => setMobileOpen(false),
1549
+ className: "p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted transition-colors cursor-pointer",
1550
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
1551
+ }
1552
+ )
1553
+ ] }),
1554
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto", children: mobileSidebar })
1555
+ ]
1556
+ }
1557
+ )
1558
+ }
1559
+ ),
1560
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col min-w-0", children: [
1561
+ topbar && /* @__PURE__ */ jsxRuntime.jsxs(
1562
+ "header",
1563
+ {
1564
+ className: cn(
1565
+ "h-14 border-b border-border bg-surface flex items-center px-6 z-10 shrink-0 gap-4",
1566
+ stickyTopbar && "sticky top-0"
1567
+ ),
1568
+ children: [
1569
+ mobileSidebar && /* @__PURE__ */ jsxRuntime.jsx(
1570
+ "button",
1571
+ {
1572
+ type: "button",
1573
+ onClick: () => setMobileOpen(true),
1574
+ className: "md:hidden p-1.5 -ml-1.5 rounded-kj-sm text-muted-foreground hover:text-foreground hover:bg-muted transition-colors cursor-pointer",
1575
+ "aria-label": "Open navigation",
1576
+ children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: 20, height: 20, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: [
1577
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "12", x2: "21", y2: "12" }),
1578
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "6", x2: "21", y2: "6" }),
1579
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "18", x2: "21", y2: "18" })
1580
+ ] })
1581
+ }
1582
+ ),
1583
+ topbar
1584
+ ]
1585
+ }
1586
+ ),
1587
+ /* @__PURE__ */ jsxRuntime.jsx("main", { className: cn("flex-1 p-6 md:p-8", contentWidthClass), children })
1588
+ ] })
1589
+ ]
1590
+ }
1591
+ );
1592
+ }
1593
+ );
1594
+ DashboardShell.displayName = "DashboardShell";
1595
+ var SettingsLayout = React18__namespace.forwardRef(
1596
+ ({ className, sidebar, children, title, description, ...props }, ref) => {
1597
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("space-y-6 w-full", className), ...props, children: [
1598
+ (title || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-border pb-4", children: [
1599
+ title && /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold tracking-tight text-foreground", children: title }),
1600
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mt-1", children: description })
1601
+ ] }),
1602
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col lg:flex-row gap-8", children: [
1603
+ /* @__PURE__ */ jsxRuntime.jsx("aside", { className: "lg:w-1/4 shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "flex flex-row lg:flex-col gap-1 overflow-x-auto lg:overflow-x-visible pb-2 lg:pb-0", children: sidebar }) }),
1604
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 max-w-3xl", children })
1605
+ ] })
1606
+ ] });
1607
+ }
1608
+ );
1609
+ SettingsLayout.displayName = "SettingsLayout";
1610
+ var DetailPageLayout = React18__namespace.forwardRef(
1611
+ ({ className, title, description, backHref, backLabel = "Back", onBackClick, actions, aside, children, ...props }, ref) => {
1612
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("space-y-6 w-full", className), ...props, children: [
1613
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
1614
+ (backHref || onBackClick) && /* @__PURE__ */ jsxRuntime.jsx("div", { children: backHref ? /* @__PURE__ */ jsxRuntime.jsxs(
1615
+ "a",
1616
+ {
1617
+ href: backHref,
1618
+ className: cn(
1619
+ buttonVariants({ variant: "ghost", size: "sm" }),
1620
+ "-ml-3 h-8 text-muted-foreground hover:text-foreground inline-flex items-center gap-1.5"
1621
+ ),
1622
+ children: [
1623
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", className: "h-4 w-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.75 19.5 8.25 12l7.5-7.5" }) }),
1624
+ backLabel
1625
+ ]
1626
+ }
1627
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
1628
+ Button,
1629
+ {
1630
+ variant: "ghost",
1631
+ size: "sm",
1632
+ className: "-ml-3 h-8 text-muted-foreground hover:text-foreground",
1633
+ onClick: onBackClick,
1634
+ children: [
1635
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", className: "h-4 w-4 mr-1.5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.75 19.5 8.25 12l7.5-7.5" }) }),
1636
+ backLabel
1637
+ ]
1638
+ }
1639
+ ) }),
1640
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col md:flex-row md:items-center md:justify-between gap-4", children: [
1641
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
1642
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold tracking-tight text-foreground", children: title }),
1643
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: description })
1644
+ ] }),
1645
+ actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 shrink-0", children: actions })
1646
+ ] })
1647
+ ] }),
1648
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-3 gap-8 items-start", children: [
1649
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-6", aside ? "lg:col-span-2" : "lg:col-span-3"), children }),
1650
+ aside && /* @__PURE__ */ jsxRuntime.jsx("aside", { className: "space-y-6 lg:col-span-1 bg-surface border border-border rounded-kj-xl p-6 shadow-kj-xs", children: aside })
1651
+ ] })
1652
+ ] });
1653
+ }
1654
+ );
1655
+ DetailPageLayout.displayName = "DetailPageLayout";
1656
+ var TableToolbar = React18__namespace.forwardRef(
1657
+ ({ className, searchQuery, onSearchChange, searchPlaceholder = "Search...", actions, filters, ...props }, ref) => {
1658
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1659
+ "div",
1660
+ {
1661
+ ref,
1662
+ className: cn(
1663
+ "flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-3 w-full pb-1",
1664
+ className
1665
+ ),
1666
+ ...props,
1667
+ children: [
1668
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col sm:flex-row items-stretch sm:items-center gap-2 max-w-xl", children: [
1669
+ onSearchChange && /* @__PURE__ */ jsxRuntime.jsx(
1670
+ Input,
1671
+ {
1672
+ type: "search",
1673
+ placeholder: searchPlaceholder,
1674
+ value: searchQuery,
1675
+ onChange: (e) => onSearchChange(e.target.value),
1676
+ className: "sm:w-64",
1677
+ leadingIcon: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", className: "h-4 w-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" }) })
1678
+ }
1679
+ ),
1680
+ filters && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: filters })
1681
+ ] }),
1682
+ actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 shrink-0 justify-end", children: actions })
1683
+ ]
1684
+ }
1685
+ );
1686
+ }
1687
+ );
1688
+ TableToolbar.displayName = "TableToolbar";
1689
+ function ConfirmDialog({
1690
+ open,
1691
+ onClose,
1692
+ onConfirm,
1693
+ title,
1694
+ description,
1695
+ confirmLabel = "Confirm",
1696
+ cancelLabel = "Cancel",
1697
+ tone = "primary",
1698
+ loading = false
1699
+ }) {
1700
+ const toneButtonVariant = {
1701
+ danger: "danger",
1702
+ primary: "primary",
1703
+ success: "secondary"
1704
+ // standard secondary in our system is teal (success-aligned)
1705
+ }[tone];
1706
+ return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { open, onClose, width: 400, showClose: !loading, children: [
1707
+ /* @__PURE__ */ jsxRuntime.jsx(ModalTitle, { children: title }),
1708
+ /* @__PURE__ */ jsxRuntime.jsx(ModalDescription, { children: description }),
1709
+ /* @__PURE__ */ jsxRuntime.jsxs(ModalActions, { children: [
1710
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", onClick: onClose, disabled: loading, children: cancelLabel }),
1711
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: toneButtonVariant, onClick: onConfirm, loading, children: confirmLabel })
1712
+ ] })
1713
+ ] });
1714
+ }
1715
+ ConfirmDialog.displayName = "ConfirmDialog";
1716
+ function Drawer({
1717
+ open,
1718
+ onClose,
1719
+ children,
1720
+ title,
1721
+ description,
1722
+ width = "max-w-md",
1723
+ side = "right"
1724
+ }) {
1725
+ const containerRef = React18__namespace.useRef(null);
1726
+ const lastActiveElement = React18__namespace.useRef(null);
1727
+ React18__namespace.useEffect(() => {
1728
+ if (!open) {
1729
+ if (lastActiveElement.current) {
1730
+ lastActiveElement.current.focus();
1731
+ lastActiveElement.current = null;
1732
+ }
1733
+ return;
1734
+ }
1735
+ lastActiveElement.current = document.activeElement;
1736
+ const container = containerRef.current;
1737
+ if (container) {
1738
+ const focusables = container.querySelectorAll(
1739
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1740
+ );
1741
+ if (focusables.length > 0) {
1742
+ setTimeout(() => focusables[0].focus(), 50);
1743
+ } else {
1744
+ container.focus();
1745
+ }
1746
+ }
1747
+ const handleKeyDown = (e) => {
1748
+ if (e.key === "Escape") {
1749
+ onClose();
1750
+ return;
1751
+ }
1752
+ if (e.key === "Tab") {
1753
+ const container2 = containerRef.current;
1754
+ if (!container2) return;
1755
+ const focusables = Array.from(
1756
+ container2.querySelectorAll(
1757
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1758
+ )
1759
+ );
1760
+ if (focusables.length === 0) {
1761
+ e.preventDefault();
1762
+ return;
1763
+ }
1764
+ const first = focusables[0];
1765
+ const last = focusables[focusables.length - 1];
1766
+ if (e.shiftKey) {
1767
+ if (document.activeElement === first || document.activeElement === container2) {
1768
+ last.focus();
1769
+ e.preventDefault();
1770
+ }
1771
+ } else {
1772
+ if (document.activeElement === last) {
1773
+ first.focus();
1774
+ e.preventDefault();
1775
+ }
1776
+ }
1777
+ }
1778
+ };
1779
+ document.addEventListener("keydown", handleKeyDown);
1780
+ document.body.style.overflow = "hidden";
1781
+ return () => {
1782
+ document.removeEventListener("keydown", handleKeyDown);
1783
+ document.body.style.overflow = "";
1784
+ };
1785
+ }, [open, onClose]);
1786
+ const sideClasses = {
1787
+ right: cn(
1788
+ "right-0 h-full border-l",
1789
+ open ? "translate-x-0" : "translate-x-full"
1790
+ ),
1791
+ left: cn(
1792
+ "left-0 h-full border-r",
1793
+ open ? "translate-x-0" : "-translate-x-full"
1794
+ )
1795
+ }[side];
1796
+ return /* @__PURE__ */ jsxRuntime.jsx(
1245
1797
  "div",
1246
1798
  {
1247
- ref,
1799
+ onClick: (e) => e.target === e.currentTarget && onClose(),
1248
1800
  className: cn(
1249
- "min-h-screen bg-canvas text-foreground flex flex-col md:flex-row",
1250
- className
1801
+ "fixed inset-0 z-[100] transition-opacity duration-300 backdrop-blur-[2px]",
1802
+ "bg-[color-mix(in_oklch,#09090b_45%,transparent)]",
1803
+ open ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"
1251
1804
  ),
1252
- ...props,
1253
- children: [
1254
- sidebar && /* @__PURE__ */ jsxRuntime.jsx("aside", { className: "w-full md:w-64 border-r border-border bg-surface shrink-0 z-20", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-0 h-auto md:h-screen flex flex-col", children: sidebar }) }),
1255
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col min-w-0", children: [
1256
- topbar && /* @__PURE__ */ jsxRuntime.jsx("header", { className: "sticky top-0 h-14 border-b border-border bg-surface flex items-center px-6 z-10 shrink-0", children: topbar }),
1257
- /* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex-1 p-6 md:p-8 max-w-7xl w-full mx-auto", children })
1258
- ] })
1259
- ]
1805
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1806
+ "div",
1807
+ {
1808
+ ref: containerRef,
1809
+ role: "dialog",
1810
+ "aria-modal": "true",
1811
+ "aria-label": !title ? "Drawer" : void 0,
1812
+ "aria-labelledby": title ? "drawer-title" : void 0,
1813
+ "aria-describedby": description ? "drawer-description" : void 0,
1814
+ tabIndex: -1,
1815
+ className: cn(
1816
+ "fixed top-0 bottom-0 bg-surface border-border flex flex-col w-full shadow-kj-lg transition-transform duration-300 ease-spring outline-none",
1817
+ width,
1818
+ sideClasses
1819
+ ),
1820
+ children: [
1821
+ (title || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-6 border-b border-border", children: [
1822
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
1823
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { id: "drawer-title", className: "text-lg font-bold tracking-tight text-foreground", children: title }),
1824
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { id: "drawer-description", className: "text-xs text-muted-foreground", children: description })
1825
+ ] }),
1826
+ /* @__PURE__ */ jsxRuntime.jsx(
1827
+ "button",
1828
+ {
1829
+ type: "button",
1830
+ onClick: onClose,
1831
+ "aria-label": "Close",
1832
+ className: "p-1.5 rounded-kj-sm text-muted-foreground hover:text-foreground hover:bg-muted transition-colors cursor-pointer",
1833
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
1834
+ }
1835
+ )
1836
+ ] }),
1837
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto p-6", children })
1838
+ ]
1839
+ }
1840
+ )
1260
1841
  }
1261
- )
1262
- );
1263
- DashboardShell.displayName = "DashboardShell";
1842
+ );
1843
+ }
1844
+ Drawer.displayName = "Drawer";
1845
+ function CommandPalette({ open, onClose, items, placeholder = "Type a command or search..." }) {
1846
+ const [search, setSearch] = React18__namespace.useState("");
1847
+ const [activeIndex, setActiveIndex] = React18__namespace.useState(0);
1848
+ const containerRef = React18__namespace.useRef(null);
1849
+ const listRef = React18__namespace.useRef(null);
1850
+ React18__namespace.useEffect(() => {
1851
+ if (open) {
1852
+ setSearch("");
1853
+ setActiveIndex(0);
1854
+ document.body.style.overflow = "hidden";
1855
+ } else {
1856
+ document.body.style.overflow = "";
1857
+ }
1858
+ }, [open]);
1859
+ const filteredItems = React18__namespace.useMemo(() => {
1860
+ if (!search) return items;
1861
+ const cleanSearch = search.toLowerCase();
1862
+ return items.filter(
1863
+ (item) => item.title.toLowerCase().includes(cleanSearch) || item.subtitle?.toLowerCase().includes(cleanSearch) || item.category?.toLowerCase().includes(cleanSearch)
1864
+ );
1865
+ }, [search, items]);
1866
+ React18__namespace.useEffect(() => {
1867
+ setActiveIndex(0);
1868
+ }, [filteredItems]);
1869
+ React18__namespace.useEffect(() => {
1870
+ if (!open) return;
1871
+ const handleKeyDown = (e) => {
1872
+ if (e.key === "Escape") {
1873
+ onClose();
1874
+ return;
1875
+ }
1876
+ if (e.key === "ArrowDown") {
1877
+ e.preventDefault();
1878
+ setActiveIndex((prev) => filteredItems.length === 0 ? 0 : (prev + 1) % filteredItems.length);
1879
+ } else if (e.key === "ArrowUp") {
1880
+ e.preventDefault();
1881
+ setActiveIndex((prev) => filteredItems.length === 0 ? 0 : (prev - 1 + filteredItems.length) % filteredItems.length);
1882
+ } else if (e.key === "Enter") {
1883
+ e.preventDefault();
1884
+ if (filteredItems[activeIndex]) {
1885
+ filteredItems[activeIndex].action();
1886
+ onClose();
1887
+ }
1888
+ }
1889
+ };
1890
+ document.addEventListener("keydown", handleKeyDown);
1891
+ return () => document.removeEventListener("keydown", handleKeyDown);
1892
+ }, [open, filteredItems, activeIndex, onClose]);
1893
+ React18__namespace.useEffect(() => {
1894
+ if (listRef.current) {
1895
+ const activeEl = listRef.current.children[activeIndex];
1896
+ if (activeEl) {
1897
+ activeEl.scrollIntoView({ block: "nearest" });
1898
+ }
1899
+ }
1900
+ }, [activeIndex]);
1901
+ if (!open) return null;
1902
+ const groups = {};
1903
+ filteredItems.forEach((item) => {
1904
+ const cat = item.category || "General";
1905
+ if (!groups[cat]) groups[cat] = [];
1906
+ groups[cat].push(item);
1907
+ });
1908
+ let absoluteItemIndex = 0;
1909
+ return /* @__PURE__ */ jsxRuntime.jsx(
1910
+ "div",
1911
+ {
1912
+ onClick: (e) => e.target === e.currentTarget && onClose(),
1913
+ className: "fixed inset-0 z-[100] grid place-items-start justify-center p-6 md:p-24 backdrop-blur-[3px] bg-[color-mix(in_oklch,#09090b_60%,transparent)]",
1914
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1915
+ "div",
1916
+ {
1917
+ ref: containerRef,
1918
+ className: "w-[95vw] max-w-lg bg-surface border border-border rounded-kj-xl shadow-kj-lg flex flex-col overflow-hidden max-h-[500px]",
1919
+ children: [
1920
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 border-b border-border flex items-center gap-2", children: [
1921
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", className: "h-5 w-5 text-muted-foreground shrink-0 ml-1", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" }) }),
1922
+ /* @__PURE__ */ jsxRuntime.jsx(
1923
+ "input",
1924
+ {
1925
+ type: "text",
1926
+ placeholder,
1927
+ value: search,
1928
+ onChange: (e) => setSearch(e.target.value),
1929
+ className: "flex-1 font-sans text-[0.95rem] bg-transparent text-foreground placeholder:text-muted-foreground outline-none border-none focus:ring-0",
1930
+ autoFocus: true
1931
+ }
1932
+ )
1933
+ ] }),
1934
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto p-2 min-h-[150px]", children: filteredItems.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-12 text-center text-sm text-muted-foreground", children: [
1935
+ 'No results found for "',
1936
+ search,
1937
+ '"'
1938
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { ref: listRef, className: "space-y-4", children: Object.entries(groups).map(([cat, itemsInCat]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
1939
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-1 text-[0.65rem] font-bold uppercase tracking-wider text-muted-foreground", children: cat }),
1940
+ itemsInCat.map((item) => {
1941
+ const currentIdx = absoluteItemIndex++;
1942
+ const isActive = currentIdx === activeIndex;
1943
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1944
+ "div",
1945
+ {
1946
+ onClick: () => {
1947
+ item.action();
1948
+ onClose();
1949
+ },
1950
+ className: cn(
1951
+ "flex items-center justify-between gap-3 px-3 py-2.5 rounded-kj-md cursor-pointer select-none transition-colors",
1952
+ isActive ? "bg-primary/10 text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
1953
+ ),
1954
+ children: [
1955
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
1956
+ item.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground [&_svg]:h-[1.1rem] [&_svg]:w-[1.1rem]", children: item.icon }),
1957
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex flex-col", children: [
1958
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[0.85rem] font-semibold", isActive ? "text-primary" : "text-foreground"), children: item.title }),
1959
+ item.subtitle && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.75rem] text-muted-foreground truncate", children: item.subtitle })
1960
+ ] })
1961
+ ] }),
1962
+ item.shortcut && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: item.shortcut.map((sc, scIdx) => /* @__PURE__ */ jsxRuntime.jsx(
1963
+ "kbd",
1964
+ {
1965
+ className: "px-1.5 py-0.5 rounded border border-border bg-subtle text-[10px] font-mono leading-none shadow-kj-xs text-muted-foreground",
1966
+ children: sc
1967
+ },
1968
+ scIdx
1969
+ )) })
1970
+ ]
1971
+ },
1972
+ item.id
1973
+ );
1974
+ })
1975
+ ] }, cat)) }) }),
1976
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-2.5 border-t border-border bg-subtle flex items-center justify-between text-[11px] text-muted-foreground font-medium", children: [
1977
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1978
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
1979
+ /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "font-mono text-[9px] px-1 border rounded bg-surface", children: "\u2191\u2193" }),
1980
+ " Navigate"
1981
+ ] }),
1982
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
1983
+ /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "font-mono text-[9px] px-1 border rounded bg-surface", children: "Enter" }),
1984
+ " Select"
1985
+ ] })
1986
+ ] }),
1987
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1988
+ /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "font-mono text-[9px] px-1 border rounded bg-surface", children: "Esc" }),
1989
+ " Close"
1990
+ ] })
1991
+ ] })
1992
+ ]
1993
+ }
1994
+ )
1995
+ }
1996
+ );
1997
+ }
1998
+ CommandPalette.displayName = "CommandPalette";
1999
+ function SidebarNav({ className, groups, currentHref, ...props }) {
2000
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-6 py-4 px-3 w-full", className), ...props, children: groups.map((group, groupIdx) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
2001
+ group.title && /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "px-3 text-[10px] font-bold uppercase tracking-widest text-muted-foreground/85", children: group.title }),
2002
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-0.5", children: group.items.map((item) => {
2003
+ const isActive = item.active || item.href && currentHref && currentHref === item.href;
2004
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2005
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2.5 min-w-0", children: [
2006
+ item.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
2007
+ "[&_svg]:h-[1.1rem] [&_svg]:w-[1.1rem] shrink-0",
2008
+ isActive ? "text-primary" : "text-muted-foreground group-hover:text-foreground"
2009
+ ), children: item.icon }),
2010
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: item.label })
2011
+ ] }),
2012
+ item.badge && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 flex items-center justify-center", children: item.badge })
2013
+ ] });
2014
+ const itemClass = cn(
2015
+ "group flex items-center justify-between gap-3 px-3 py-2 rounded-kj-md text-[0.85rem] font-semibold select-none cursor-pointer transition-all duration-150",
2016
+ isActive ? "bg-primary/10 text-primary border-l-2 border-primary rounded-l-none pl-2.5" : "text-muted-foreground hover:bg-muted hover:text-foreground border-l-2 border-transparent"
2017
+ );
2018
+ if (item.href) {
2019
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.href, className: itemClass, children: content }, item.id);
2020
+ }
2021
+ return /* @__PURE__ */ jsxRuntime.jsx(
2022
+ "button",
2023
+ {
2024
+ type: "button",
2025
+ onClick: item.onClick,
2026
+ className: itemClass,
2027
+ children: content
2028
+ },
2029
+ item.id
2030
+ );
2031
+ }) })
2032
+ ] }, groupIdx)) });
2033
+ }
2034
+ SidebarNav.displayName = "SidebarNav";
1264
2035
 
1265
2036
  exports.Accordion = Accordion;
1266
2037
  exports.AccordionContent = AccordionContent;
@@ -1270,6 +2041,7 @@ exports.Alert = Alert;
1270
2041
  exports.Avatar = Avatar;
1271
2042
  exports.AvatarGroup = AvatarGroup;
1272
2043
  exports.Badge = Badge;
2044
+ exports.BottomNavigation = BottomNavigation;
1273
2045
  exports.Breadcrumb = Breadcrumb;
1274
2046
  exports.BreadcrumbItem = BreadcrumbItem;
1275
2047
  exports.BreadcrumbSeparator = BreadcrumbSeparator;
@@ -1281,8 +2053,13 @@ exports.CardFooter = CardFooter;
1281
2053
  exports.CardHeader = CardHeader;
1282
2054
  exports.CardTitle = CardTitle;
1283
2055
  exports.Checkbox = Checkbox;
2056
+ exports.CheckboxField = CheckboxField;
2057
+ exports.CommandPalette = CommandPalette;
2058
+ exports.ConfirmDialog = ConfirmDialog;
1284
2059
  exports.DashboardShell = DashboardShell;
1285
2060
  exports.DataTable = DataTable;
2061
+ exports.DetailPageLayout = DetailPageLayout;
2062
+ exports.Drawer = Drawer;
1286
2063
  exports.DropdownMenu = DropdownMenu;
1287
2064
  exports.DropdownMenuContent = DropdownMenuContent;
1288
2065
  exports.DropdownMenuItem = DropdownMenuItem;
@@ -1306,6 +2083,9 @@ exports.Progress = Progress;
1306
2083
  exports.Radio = Radio;
1307
2084
  exports.Segmented = Segmented;
1308
2085
  exports.Select = Select;
2086
+ exports.SelectField = SelectField;
2087
+ exports.SettingsLayout = SettingsLayout;
2088
+ exports.SidebarNav = SidebarNav;
1309
2089
  exports.Skeleton = Skeleton;
1310
2090
  exports.Slider = Slider;
1311
2091
  exports.Spinner = Spinner;
@@ -1317,11 +2097,13 @@ exports.TableCell = TableCell;
1317
2097
  exports.TableHead = TableHead;
1318
2098
  exports.TableHeader = TableHeader;
1319
2099
  exports.TableRow = TableRow;
2100
+ exports.TableToolbar = TableToolbar;
1320
2101
  exports.TableWrap = TableWrap;
1321
2102
  exports.Tabs = Tabs;
1322
2103
  exports.TabsContent = TabsContent;
1323
2104
  exports.TabsList = TabsList;
1324
2105
  exports.TabsTrigger = TabsTrigger;
2106
+ exports.TextField = TextField;
1325
2107
  exports.Textarea = Textarea;
1326
2108
  exports.ToastProvider = ToastProvider;
1327
2109
  exports.Tooltip = Tooltip;