@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.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { clsx } from 'clsx';
2
2
  import { twMerge } from 'tailwind-merge';
3
- import * as React17 from 'react';
3
+ import * as React18 from 'react';
4
4
  import { cva } from 'class-variance-authority';
5
- import { jsxs, jsx } from 'react/jsx-runtime';
5
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
6
 
7
7
  // src/lib/cn.ts
8
8
  function cn(...inputs) {
@@ -38,7 +38,7 @@ var buttonVariants = cva(
38
38
  defaultVariants: { variant: "primary", size: "md" }
39
39
  }
40
40
  );
41
- var Button = React17.forwardRef(
41
+ var Button = React18.forwardRef(
42
42
  ({ className, variant, size, loading, leadingIcon, trailingIcon, children, disabled, ...props }, ref) => {
43
43
  return /* @__PURE__ */ jsxs(
44
44
  "button",
@@ -85,7 +85,7 @@ var badgeVariants = cva(
85
85
  defaultVariants: { variant: "neutral" }
86
86
  }
87
87
  );
88
- var Badge = React17.forwardRef(
88
+ var Badge = React18.forwardRef(
89
89
  ({ className, variant, dot, children, ...props }, ref) => /* @__PURE__ */ jsxs("span", { ref, className: cn(badgeVariants({ variant }), className), ...props, children: [
90
90
  dot && /* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-current", "aria-hidden": true }),
91
91
  children
@@ -112,7 +112,7 @@ var iconColor = {
112
112
  warning: "text-warning",
113
113
  danger: "text-danger"
114
114
  };
115
- var Alert = React17.forwardRef(
115
+ var Alert = React18.forwardRef(
116
116
  ({ className, variant = "info", icon, title, children, ...props }, ref) => /* @__PURE__ */ jsxs("div", { ref, role: "alert", className: cn(alertVariants({ variant }), className), ...props, children: [
117
117
  icon && /* @__PURE__ */ jsx("span", { className: cn("shrink-0 mt-0.5 [&_svg]:h-[1.15rem] [&_svg]:w-[1.15rem]", iconColor[variant ?? "info"]), children: icon }),
118
118
  /* @__PURE__ */ jsxs("div", { className: "text-foreground", children: [
@@ -122,7 +122,7 @@ var Alert = React17.forwardRef(
122
122
  ] })
123
123
  );
124
124
  Alert.displayName = "Alert";
125
- var Spinner = React17.forwardRef(
125
+ var Spinner = React18.forwardRef(
126
126
  ({ className, size = 24, style, ...props }, ref) => /* @__PURE__ */ jsx(
127
127
  "span",
128
128
  {
@@ -139,7 +139,7 @@ var Spinner = React17.forwardRef(
139
139
  )
140
140
  );
141
141
  Spinner.displayName = "Spinner";
142
- var Progress = React17.forwardRef(
142
+ var Progress = React18.forwardRef(
143
143
  ({ className, value = 0, tone = "primary", barClassName, ...props }, ref) => {
144
144
  const pct = Math.max(0, Math.min(100, value));
145
145
  return /* @__PURE__ */ jsx(
@@ -169,8 +169,55 @@ var Progress = React17.forwardRef(
169
169
  }
170
170
  );
171
171
  Progress.displayName = "Progress";
172
+ var Label = React18.forwardRef(
173
+ ({ className, required, children, ...props }, ref) => /* @__PURE__ */ jsxs("label", { ref, className: cn("text-[0.8rem] font-semibold text-foreground", className), ...props, children: [
174
+ children,
175
+ required && /* @__PURE__ */ jsx("span", { className: "text-danger", children: " *" })
176
+ ] })
177
+ );
178
+ Label.displayName = "Label";
179
+ var Hint = React18.forwardRef(
180
+ ({ className, error, ...props }, ref) => /* @__PURE__ */ jsx(
181
+ "span",
182
+ {
183
+ ref,
184
+ className: cn("text-[0.76rem]", error ? "text-danger" : "text-muted-foreground", className),
185
+ ...props
186
+ }
187
+ )
188
+ );
189
+ Hint.displayName = "Hint";
190
+ var Field = React18.forwardRef(
191
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex flex-col gap-1.5", className), ...props })
192
+ );
193
+ Field.displayName = "Field";
194
+ var FormField = React18.forwardRef(
195
+ ({ className, label, hint, error, required, children, ...props }, ref) => {
196
+ const id = React18.useId();
197
+ const hintId = `${id}-hint`;
198
+ const errorId = `${id}-error`;
199
+ const child = React18.Children.only(children);
200
+ const clonedChild = React18.cloneElement(child, {
201
+ id: child.props.id ?? id,
202
+ "aria-describedby": cn(
203
+ hint && hintId,
204
+ error && errorId,
205
+ child.props["aria-describedby"]
206
+ ) || void 0,
207
+ "aria-invalid": error ? "true" : void 0,
208
+ required: child.props.required ?? required
209
+ });
210
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex flex-col gap-1.5 w-full", className), ...props, children: [
211
+ /* @__PURE__ */ jsx(Label, { htmlFor: id, required, children: label }),
212
+ clonedChild,
213
+ hint && !error && /* @__PURE__ */ jsx(Hint, { id: hintId, children: hint }),
214
+ error && /* @__PURE__ */ jsx(Hint, { id: errorId, error: true, children: error })
215
+ ] });
216
+ }
217
+ );
218
+ FormField.displayName = "FormField";
172
219
  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";
173
- var Input = React17.forwardRef(
220
+ var Input = React18.forwardRef(
174
221
  ({ className, error, leadingIcon, style, ...props }, ref) => {
175
222
  const field = /* @__PURE__ */ jsx(
176
223
  "input",
@@ -195,7 +242,7 @@ var Input = React17.forwardRef(
195
242
  }
196
243
  );
197
244
  Input.displayName = "Input";
198
- var Textarea = React17.forwardRef(
245
+ var Textarea = React18.forwardRef(
199
246
  ({ className, error, ...props }, ref) => /* @__PURE__ */ jsx(
200
247
  "textarea",
201
248
  {
@@ -212,30 +259,14 @@ var Textarea = React17.forwardRef(
212
259
  )
213
260
  );
214
261
  Textarea.displayName = "Textarea";
215
- var Label = React17.forwardRef(
216
- ({ className, required, children, ...props }, ref) => /* @__PURE__ */ jsxs("label", { ref, className: cn("text-[0.8rem] font-semibold text-foreground", className), ...props, children: [
217
- children,
218
- required && /* @__PURE__ */ jsx("span", { className: "text-danger", children: " *" })
219
- ] })
220
- );
221
- Label.displayName = "Label";
222
- var Hint = React17.forwardRef(
223
- ({ className, error, ...props }, ref) => /* @__PURE__ */ jsx(
224
- "span",
225
- {
226
- ref,
227
- className: cn("text-[0.76rem]", error ? "text-danger" : "text-muted-foreground", className),
228
- ...props
229
- }
230
- )
231
- );
232
- Hint.displayName = "Hint";
233
- var Field = React17.forwardRef(
234
- ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex flex-col gap-1.5", className), ...props })
262
+ var TextField = React18.forwardRef(
263
+ ({ label, hint, error, required, className, ...props }, ref) => {
264
+ return /* @__PURE__ */ jsx(FormField, { label, hint, error, required, className, children: /* @__PURE__ */ jsx(Input, { ref, error: !!error, ...props }) });
265
+ }
235
266
  );
236
- Field.displayName = "Field";
267
+ TextField.displayName = "TextField";
237
268
  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";
238
- var Select = React17.forwardRef(
269
+ var Select = React18.forwardRef(
239
270
  ({ className, error, style, children, ...props }, ref) => /* @__PURE__ */ jsx(
240
271
  "select",
241
272
  {
@@ -263,9 +294,15 @@ var Select = React17.forwardRef(
263
294
  )
264
295
  );
265
296
  Select.displayName = "Select";
266
- var Checkbox = React17.forwardRef(
297
+ var SelectField = React18.forwardRef(
298
+ ({ label, hint, error, required, className, children, ...props }, ref) => {
299
+ return /* @__PURE__ */ jsx(FormField, { label, hint, error, required, className, children: /* @__PURE__ */ jsx(Select, { ref, error: !!error, ...props, children }) });
300
+ }
301
+ );
302
+ SelectField.displayName = "SelectField";
303
+ var Checkbox = React18.forwardRef(
267
304
  ({ className, label, id, ...props }, ref) => {
268
- const autoId = React17.useId();
305
+ const autoId = React18.useId();
269
306
  const inputId = id ?? autoId;
270
307
  return /* @__PURE__ */ jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
271
308
  /* @__PURE__ */ jsx("input", { ref, id: inputId, type: "checkbox", className: "peer sr-only", ...props }),
@@ -275,9 +312,9 @@ var Checkbox = React17.forwardRef(
275
312
  }
276
313
  );
277
314
  Checkbox.displayName = "Checkbox";
278
- var Radio = React17.forwardRef(
315
+ var Radio = React18.forwardRef(
279
316
  ({ className, label, id, ...props }, ref) => {
280
- const autoId = React17.useId();
317
+ const autoId = React18.useId();
281
318
  const inputId = id ?? autoId;
282
319
  return /* @__PURE__ */ jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
283
320
  /* @__PURE__ */ jsx("input", { ref, id: inputId, type: "radio", className: "peer sr-only", ...props }),
@@ -287,9 +324,32 @@ var Radio = React17.forwardRef(
287
324
  }
288
325
  );
289
326
  Radio.displayName = "Radio";
290
- var Switch = React17.forwardRef(
327
+ var CheckboxField = React18.forwardRef(
328
+ ({ label, hint, error, className, ...props }, ref) => {
329
+ const id = React18.useId();
330
+ const hintId = `${id}-hint`;
331
+ const errorId = `${id}-error`;
332
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1 w-full", className), children: [
333
+ /* @__PURE__ */ jsx(
334
+ Checkbox,
335
+ {
336
+ ref,
337
+ id,
338
+ label,
339
+ "aria-describedby": cn(hint && hintId, error && errorId) || void 0,
340
+ "aria-invalid": error ? "true" : void 0,
341
+ ...props
342
+ }
343
+ ),
344
+ hint && !error && /* @__PURE__ */ jsx(Hint, { id: hintId, className: "pl-[1.8rem]", children: hint }),
345
+ error && /* @__PURE__ */ jsx(Hint, { id: errorId, error: true, className: "pl-[1.8rem]", children: error })
346
+ ] });
347
+ }
348
+ );
349
+ CheckboxField.displayName = "CheckboxField";
350
+ var Switch = React18.forwardRef(
291
351
  ({ className, label, id, ...props }, ref) => {
292
- const autoId = React17.useId();
352
+ const autoId = React18.useId();
293
353
  const inputId = id ?? autoId;
294
354
  return /* @__PURE__ */ jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
295
355
  /* @__PURE__ */ jsx("input", { ref, id: inputId, type: "checkbox", role: "switch", className: "peer sr-only", ...props }),
@@ -299,7 +359,7 @@ var Switch = React17.forwardRef(
299
359
  }
300
360
  );
301
361
  Switch.displayName = "Switch";
302
- var Slider = React17.forwardRef(
362
+ var Slider = React18.forwardRef(
303
363
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
304
364
  "input",
305
365
  {
@@ -352,7 +412,7 @@ function Segmented({
352
412
  }
353
413
  );
354
414
  }
355
- var Card = React17.forwardRef(
415
+ var Card = React18.forwardRef(
356
416
  ({ as: Tag = "div", className, elevated, interactive, ...props }, ref) => /* @__PURE__ */ jsx(
357
417
  Tag,
358
418
  {
@@ -368,23 +428,23 @@ var Card = React17.forwardRef(
368
428
  )
369
429
  );
370
430
  Card.displayName = "Card";
371
- var CardHeader = React17.forwardRef(
431
+ var CardHeader = React18.forwardRef(
372
432
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-[1.35rem] flex flex-col gap-1", className), ...props })
373
433
  );
374
434
  CardHeader.displayName = "CardHeader";
375
- var CardTitle = React17.forwardRef(
435
+ var CardTitle = React18.forwardRef(
376
436
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx("h3", { ref, className: cn("m-0 text-base font-bold tracking-[-0.01em]", className), ...props })
377
437
  );
378
438
  CardTitle.displayName = "CardTitle";
379
- var CardDescription = React17.forwardRef(
439
+ var CardDescription = React18.forwardRef(
380
440
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx("p", { ref, className: cn("m-0 text-[0.85rem] text-muted-foreground", className), ...props })
381
441
  );
382
442
  CardDescription.displayName = "CardDescription";
383
- var CardContent = React17.forwardRef(
443
+ var CardContent = React18.forwardRef(
384
444
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("px-[1.35rem] pb-[1.35rem]", className), ...props })
385
445
  );
386
446
  CardContent.displayName = "CardContent";
387
- var CardFooter = React17.forwardRef(
447
+ var CardFooter = React18.forwardRef(
388
448
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
389
449
  "div",
390
450
  {
@@ -395,7 +455,7 @@ var CardFooter = React17.forwardRef(
395
455
  )
396
456
  );
397
457
  CardFooter.displayName = "CardFooter";
398
- var Stat = React17.forwardRef(
458
+ var Stat = React18.forwardRef(
399
459
  ({ className, label, value, delta, trend, ...props }, ref) => /* @__PURE__ */ jsxs(Card, { ref, className: cn("p-[1.35rem] flex flex-col gap-2", className), ...props, children: [
400
460
  /* @__PURE__ */ jsx("span", { className: "text-[0.78rem] font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: label }),
401
461
  /* @__PURE__ */ jsx("span", { className: "text-[2rem] font-bold tracking-[-0.03em] tabular-nums leading-none", children: value }),
@@ -435,7 +495,7 @@ var avatarVariants = cva(
435
495
  defaultVariants: { size: "md", tone: "secondary" }
436
496
  }
437
497
  );
438
- var Avatar = React17.forwardRef(
498
+ var Avatar = React18.forwardRef(
439
499
  ({ className, size, tone, src, alt, status, children, ...props }, ref) => {
440
500
  const node = /* @__PURE__ */ jsx("span", { ref, className: cn(avatarVariants({ size, tone }), "overflow-hidden", className), ...props, children: src ? /* @__PURE__ */ jsx("img", { src, alt, className: "h-full w-full object-cover" }) : children });
441
501
  if (!status) return node;
@@ -446,20 +506,20 @@ var Avatar = React17.forwardRef(
446
506
  }
447
507
  );
448
508
  Avatar.displayName = "Avatar";
449
- var AvatarGroup = React17.forwardRef(
509
+ var AvatarGroup = React18.forwardRef(
450
510
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex [&>*:not(:first-child)]:-ml-2.5", className), ...props })
451
511
  );
452
512
  AvatarGroup.displayName = "AvatarGroup";
453
- var TabsContext = React17.createContext(null);
513
+ var TabsContext = React18.createContext(null);
454
514
  function useTabs() {
455
- const ctx = React17.useContext(TabsContext);
515
+ const ctx = React18.useContext(TabsContext);
456
516
  if (!ctx) throw new Error("Tabs.* must be used within <Tabs>");
457
517
  return ctx;
458
518
  }
459
519
  function Tabs({ value, defaultValue, onValueChange, className, children, ...props }) {
460
- const [internal, setInternal] = React17.useState(defaultValue ?? "");
520
+ const [internal, setInternal] = React18.useState(defaultValue ?? "");
461
521
  const current = value ?? internal;
462
- const setValue = React17.useCallback(
522
+ const setValue = React18.useCallback(
463
523
  (v) => {
464
524
  if (value === void 0) setInternal(v);
465
525
  onValueChange?.(v);
@@ -468,7 +528,7 @@ function Tabs({ value, defaultValue, onValueChange, className, children, ...prop
468
528
  );
469
529
  return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { value: current, setValue }, children: /* @__PURE__ */ jsx("div", { className, ...props, children }) });
470
530
  }
471
- var TabsList = React17.forwardRef(
531
+ var TabsList = React18.forwardRef(
472
532
  ({ className, onKeyDown, ...props }, ref) => {
473
533
  const handleKeyDown = (e) => {
474
534
  const container = e.currentTarget;
@@ -512,7 +572,7 @@ var TabsList = React17.forwardRef(
512
572
  }
513
573
  );
514
574
  TabsList.displayName = "TabsList";
515
- var TabsTrigger = React17.forwardRef(
575
+ var TabsTrigger = React18.forwardRef(
516
576
  ({ className, value, children, ...props }, ref) => {
517
577
  const { value: current, setValue } = useTabs();
518
578
  const active = current === value;
@@ -541,7 +601,7 @@ var TabsTrigger = React17.forwardRef(
541
601
  }
542
602
  );
543
603
  TabsTrigger.displayName = "TabsTrigger";
544
- var TabsContent = React17.forwardRef(
604
+ var TabsContent = React18.forwardRef(
545
605
  ({ className, value, ...props }, ref) => {
546
606
  const { value: current } = useTabs();
547
607
  const active = current === value;
@@ -561,10 +621,10 @@ var TabsContent = React17.forwardRef(
561
621
  }
562
622
  );
563
623
  TabsContent.displayName = "TabsContent";
564
- var AccordionContext = React17.createContext(null);
624
+ var AccordionContext = React18.createContext(null);
565
625
  function Accordion({ type = "single", defaultValue = [], className, children, ...props }) {
566
- const [open, setOpen] = React17.useState(defaultValue);
567
- const toggle = React17.useCallback(
626
+ const [open, setOpen] = React18.useState(defaultValue);
627
+ const toggle = React18.useCallback(
568
628
  (v) => {
569
629
  setOpen((prev) => {
570
630
  const isOpen = prev.includes(v);
@@ -576,15 +636,15 @@ function Accordion({ type = "single", defaultValue = [], className, children, ..
576
636
  );
577
637
  return /* @__PURE__ */ jsx(AccordionContext.Provider, { value: { open, toggle }, children: /* @__PURE__ */ jsx("div", { className: cn("border border-border rounded-kj-lg overflow-hidden", className), ...props, children }) });
578
638
  }
579
- var ItemContext = React17.createContext("");
580
- var AccordionItem = React17.forwardRef(
639
+ var ItemContext = React18.createContext("");
640
+ var AccordionItem = React18.forwardRef(
581
641
  ({ className, value, ...props }, ref) => /* @__PURE__ */ jsx(ItemContext.Provider, { value, children: /* @__PURE__ */ jsx("div", { ref, className: cn("border-t border-border first:border-t-0", className), ...props }) })
582
642
  );
583
643
  AccordionItem.displayName = "AccordionItem";
584
- var AccordionTrigger = React17.forwardRef(
644
+ var AccordionTrigger = React18.forwardRef(
585
645
  ({ className, children, ...props }, ref) => {
586
- const ctx = React17.useContext(AccordionContext);
587
- const value = React17.useContext(ItemContext);
646
+ const ctx = React18.useContext(AccordionContext);
647
+ const value = React18.useContext(ItemContext);
588
648
  const isOpen = ctx.open.includes(value);
589
649
  return /* @__PURE__ */ jsxs(
590
650
  "button",
@@ -621,10 +681,10 @@ var AccordionTrigger = React17.forwardRef(
621
681
  }
622
682
  );
623
683
  AccordionTrigger.displayName = "AccordionTrigger";
624
- var AccordionContent = React17.forwardRef(
684
+ var AccordionContent = React18.forwardRef(
625
685
  ({ className, children, ...props }, ref) => {
626
- const ctx = React17.useContext(AccordionContext);
627
- const value = React17.useContext(ItemContext);
686
+ const ctx = React18.useContext(AccordionContext);
687
+ const value = React18.useContext(ItemContext);
628
688
  const isOpen = ctx.open.includes(value);
629
689
  return /* @__PURE__ */ jsx(
630
690
  "div",
@@ -638,11 +698,11 @@ var AccordionContent = React17.forwardRef(
638
698
  }
639
699
  );
640
700
  AccordionContent.displayName = "AccordionContent";
641
- var MenuContext = React17.createContext(null);
701
+ var MenuContext = React18.createContext(null);
642
702
  function DropdownMenu({ children, className }) {
643
- const [open, setOpen] = React17.useState(false);
644
- const ref = React17.useRef(null);
645
- React17.useEffect(() => {
703
+ const [open, setOpen] = React18.useState(false);
704
+ const ref = React18.useRef(null);
705
+ React18.useEffect(() => {
646
706
  if (!open) return;
647
707
  const onDoc = (e) => {
648
708
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -657,11 +717,11 @@ function DropdownMenu({ children, className }) {
657
717
  }, [open]);
658
718
  return /* @__PURE__ */ jsx(MenuContext.Provider, { value: { open, setOpen }, children: /* @__PURE__ */ jsx("div", { ref, className: cn("relative inline-block", className), children }) });
659
719
  }
660
- var DropdownMenuTrigger = React17.forwardRef(({ onClick, asChild, ...props }, ref) => {
661
- const ctx = React17.useContext(MenuContext);
720
+ var DropdownMenuTrigger = React18.forwardRef(({ onClick, asChild, ...props }, ref) => {
721
+ const ctx = React18.useContext(MenuContext);
662
722
  if (asChild) {
663
- const child = React17.Children.only(props.children);
664
- return React17.cloneElement(child, {
723
+ const child = React18.Children.only(props.children);
724
+ return React18.cloneElement(child, {
665
725
  ref,
666
726
  ...props,
667
727
  ...child.props,
@@ -691,9 +751,9 @@ var DropdownMenuTrigger = React17.forwardRef(({ onClick, asChild, ...props }, re
691
751
  });
692
752
  DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
693
753
  function DropdownMenuContent({ className, align = "start", children, ...props }) {
694
- const ctx = React17.useContext(MenuContext);
695
- const ref = React17.useRef(null);
696
- React17.useEffect(() => {
754
+ const ctx = React18.useContext(MenuContext);
755
+ const ref = React18.useRef(null);
756
+ React18.useEffect(() => {
697
757
  if (!ctx.open) return;
698
758
  const container = ref.current;
699
759
  if (container) {
@@ -740,9 +800,9 @@ function DropdownMenuContent({ className, align = "start", children, ...props })
740
800
  }
741
801
  );
742
802
  }
743
- var DropdownMenuItem = React17.forwardRef(
803
+ var DropdownMenuItem = React18.forwardRef(
744
804
  ({ className, danger, icon, children, onClick, ...props }, ref) => {
745
- const ctx = React17.useContext(MenuContext);
805
+ const ctx = React18.useContext(MenuContext);
746
806
  return /* @__PURE__ */ jsxs(
747
807
  "button",
748
808
  {
@@ -772,11 +832,11 @@ DropdownMenuItem.displayName = "DropdownMenuItem";
772
832
  function DropdownMenuSeparator({ className }) {
773
833
  return /* @__PURE__ */ jsx("div", { className: cn("h-px bg-border my-1.5", className), role: "separator" });
774
834
  }
775
- var Breadcrumb = React17.forwardRef(
835
+ var Breadcrumb = React18.forwardRef(
776
836
  ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx("nav", { ref, "aria-label": "Breadcrumb", className: cn("flex items-center gap-1.5 text-[0.85rem] text-muted-foreground", className), ...props, children })
777
837
  );
778
838
  Breadcrumb.displayName = "Breadcrumb";
779
- var BreadcrumbItem = React17.forwardRef(
839
+ var BreadcrumbItem = React18.forwardRef(
780
840
  ({ className, current, children, ...props }, ref) => {
781
841
  if (current) {
782
842
  return /* @__PURE__ */ jsx("span", { "aria-current": "page", className: cn("text-foreground font-semibold", className), children });
@@ -823,27 +883,99 @@ function Pagination({ page, pageCount, onPageChange, className }) {
823
883
  /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Next", disabled: page >= pageCount, onClick: () => onPageChange(page + 1), children: /* @__PURE__ */ jsx(Chevron, { dir: "right" }) })
824
884
  ] });
825
885
  }
826
- var TableWrap = React17.forwardRef(
827
- ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("border border-border rounded-kj-lg overflow-hidden", className), ...props })
886
+ var BottomNavigation = React18.forwardRef(
887
+ ({ className, items, showLabels = "always", fixed = true, ...props }, ref) => {
888
+ return /* @__PURE__ */ jsx(
889
+ "nav",
890
+ {
891
+ ref,
892
+ className: cn(
893
+ "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",
894
+ fixed ? "fixed bottom-0 left-0 right-0 z-40 backdrop-blur-md" : "relative w-full",
895
+ className
896
+ ),
897
+ ...props,
898
+ children: items.map((item) => {
899
+ const isActive = item.active;
900
+ const showLabel = showLabels !== "never" && (showLabels === "always" || isActive);
901
+ const content = /* @__PURE__ */ jsxs("span", { className: "flex flex-col items-center justify-center gap-1 w-full relative", children: [
902
+ /* @__PURE__ */ jsxs(
903
+ "span",
904
+ {
905
+ className: cn(
906
+ "relative flex items-center justify-center p-1 rounded-full transition-all duration-200",
907
+ isActive ? "text-primary scale-110" : "text-muted-foreground group-hover:text-foreground group-active:scale-95"
908
+ ),
909
+ children: [
910
+ item.icon,
911
+ item.badge !== void 0 && item.badge !== null && /* @__PURE__ */ 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 })
912
+ ]
913
+ }
914
+ ),
915
+ /* @__PURE__ */ jsx(
916
+ "span",
917
+ {
918
+ className: cn(
919
+ "text-[10px] font-semibold tracking-wide transition-all duration-200 select-none",
920
+ showLabel ? "opacity-100 scale-100 h-auto" : "opacity-0 scale-75 h-0 overflow-hidden",
921
+ isActive ? "text-primary font-bold" : "text-muted-foreground group-hover:text-foreground"
922
+ ),
923
+ children: item.label
924
+ }
925
+ ),
926
+ isActive && /* @__PURE__ */ jsx("span", { className: "absolute -bottom-1.5 w-1 h-1 rounded-full bg-primary animate-fade-in" })
927
+ ] });
928
+ const itemClass = "group flex-1 flex flex-col items-center justify-center py-1 cursor-pointer transition-all duration-150 relative focus:outline-none";
929
+ if (item.href) {
930
+ return /* @__PURE__ */ jsx(
931
+ "a",
932
+ {
933
+ href: item.href,
934
+ className: itemClass,
935
+ "aria-current": isActive ? "page" : void 0,
936
+ children: content
937
+ },
938
+ item.id
939
+ );
940
+ }
941
+ return /* @__PURE__ */ jsx(
942
+ "button",
943
+ {
944
+ type: "button",
945
+ onClick: item.onClick,
946
+ className: itemClass,
947
+ "aria-pressed": isActive,
948
+ children: content
949
+ },
950
+ item.id
951
+ );
952
+ })
953
+ }
954
+ );
955
+ }
956
+ );
957
+ BottomNavigation.displayName = "BottomNavigation";
958
+ var TableWrap = React18.forwardRef(
959
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("border border-border rounded-kj-lg overflow-x-auto w-full", className), ...props })
828
960
  );
829
961
  TableWrap.displayName = "TableWrap";
830
- var Table = React17.forwardRef(
962
+ var Table = React18.forwardRef(
831
963
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx("table", { ref, className: cn("w-full border-collapse text-[0.85rem]", className), ...props })
832
964
  );
833
965
  Table.displayName = "Table";
834
- var TableHeader = React17.forwardRef(
966
+ var TableHeader = React18.forwardRef(
835
967
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", { ref, className, ...props })
836
968
  );
837
969
  TableHeader.displayName = "TableHeader";
838
- var TableBody = React17.forwardRef(
970
+ var TableBody = React18.forwardRef(
839
971
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx("tbody", { ref, className, ...props })
840
972
  );
841
973
  TableBody.displayName = "TableBody";
842
- var TableRow = React17.forwardRef(
974
+ var TableRow = React18.forwardRef(
843
975
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx("tr", { ref, className: cn("transition-colors hover:bg-muted/50", className), ...props })
844
976
  );
845
977
  TableRow.displayName = "TableRow";
846
- var TableHead = React17.forwardRef(
978
+ var TableHead = React18.forwardRef(
847
979
  ({ className, numeric, ...props }, ref) => /* @__PURE__ */ jsx(
848
980
  "th",
849
981
  {
@@ -858,7 +990,7 @@ var TableHead = React17.forwardRef(
858
990
  )
859
991
  );
860
992
  TableHead.displayName = "TableHead";
861
- var TableCell = React17.forwardRef(
993
+ var TableCell = React18.forwardRef(
862
994
  ({ className, numeric, ...props }, ref) => /* @__PURE__ */ jsx(
863
995
  "td",
864
996
  {
@@ -891,13 +1023,13 @@ function Tooltip({ content, children, className }) {
891
1023
  )
892
1024
  ] });
893
1025
  }
894
- var ModalContext = React17.createContext(null);
1026
+ var ModalContext = React18.createContext(null);
895
1027
  function Modal({ open, onClose, children, width = 440, className, showClose = true }) {
896
- const titleId = React17.useId();
897
- const descId = React17.useId();
898
- const containerRef = React17.useRef(null);
899
- const lastActiveElement = React17.useRef(null);
900
- React17.useEffect(() => {
1028
+ const titleId = React18.useId();
1029
+ const descId = React18.useId();
1030
+ const containerRef = React18.useRef(null);
1031
+ const lastActiveElement = React18.useRef(null);
1032
+ React18.useEffect(() => {
901
1033
  if (!open) {
902
1034
  if (lastActiveElement.current) {
903
1035
  lastActiveElement.current.focus();
@@ -999,19 +1131,19 @@ function Modal({ open, onClose, children, width = 440, className, showClose = tr
999
1131
  );
1000
1132
  }
1001
1133
  function ModalTitle({ className, id, ...props }) {
1002
- const ctx = React17.useContext(ModalContext);
1134
+ const ctx = React18.useContext(ModalContext);
1003
1135
  return /* @__PURE__ */ jsx("h3", { id: id ?? ctx?.titleId, className: cn("m-0 mb-2 text-[1.15rem] font-bold tracking-[-0.01em]", className), ...props });
1004
1136
  }
1005
1137
  function ModalDescription({ className, id, ...props }) {
1006
- const ctx = React17.useContext(ModalContext);
1138
+ const ctx = React18.useContext(ModalContext);
1007
1139
  return /* @__PURE__ */ jsx("p", { id: id ?? ctx?.descId, className: cn("m-0 text-[0.9rem] text-muted-foreground", className), ...props });
1008
1140
  }
1009
1141
  function ModalActions({ className, ...props }) {
1010
1142
  return /* @__PURE__ */ jsx("div", { className: cn("flex gap-2.5 justify-end mt-6", className), ...props });
1011
1143
  }
1012
- var ToastContext = React17.createContext(null);
1144
+ var ToastContext = React18.createContext(null);
1013
1145
  function useToast() {
1014
- const ctx = React17.useContext(ToastContext);
1146
+ const ctx = React18.useContext(ToastContext);
1015
1147
  if (!ctx) throw new Error("useToast must be used within <ToastProvider>");
1016
1148
  return ctx;
1017
1149
  }
@@ -1032,13 +1164,13 @@ var toneBorder = {
1032
1164
  danger: "border-l-danger"
1033
1165
  };
1034
1166
  function ToastProvider({ children }) {
1035
- const [items, setItems] = React17.useState([]);
1036
- const idRef = React17.useRef(0);
1037
- const remove = React17.useCallback((id) => {
1167
+ const [items, setItems] = React18.useState([]);
1168
+ const idRef = React18.useRef(0);
1169
+ const remove = React18.useCallback((id) => {
1038
1170
  setItems((prev) => prev.map((t) => t.id === id ? { ...t, leaving: true } : t));
1039
1171
  setTimeout(() => setItems((prev) => prev.filter((t) => t.id !== id)), 250);
1040
1172
  }, []);
1041
- const toast = React17.useCallback(
1173
+ const toast = React18.useCallback(
1042
1174
  ({ message, tone = "default", duration = 3200 }) => {
1043
1175
  const id = ++idRef.current;
1044
1176
  setItems((prev) => [...prev, { id, message, tone, duration }]);
@@ -1068,7 +1200,7 @@ function ToastProvider({ children }) {
1068
1200
  )) })
1069
1201
  ] });
1070
1202
  }
1071
- var PageHeader = React17.forwardRef(
1203
+ var PageHeader = React18.forwardRef(
1072
1204
  ({ eyebrow, title, description, actions }, ref) => /* @__PURE__ */ jsx("header", { ref, className: "py-12 md:py-16", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6 md:flex-row md:items-end md:justify-between", children: [
1073
1205
  /* @__PURE__ */ jsxs("div", { className: "space-y-3 max-w-2xl", children: [
1074
1206
  eyebrow && /* @__PURE__ */ jsx("p", { className: "font-mono text-xs font-bold uppercase tracking-[0.2em] text-primary", children: eyebrow }),
@@ -1079,7 +1211,7 @@ var PageHeader = React17.forwardRef(
1079
1211
  ] }) })
1080
1212
  );
1081
1213
  PageHeader.displayName = "PageHeader";
1082
- var EmptyState = React17.forwardRef(
1214
+ var EmptyState = React18.forwardRef(
1083
1215
  ({ className, icon, title, description, action, ...props }, ref) => /* @__PURE__ */ jsxs(
1084
1216
  "div",
1085
1217
  {
@@ -1099,7 +1231,7 @@ var EmptyState = React17.forwardRef(
1099
1231
  )
1100
1232
  );
1101
1233
  EmptyState.displayName = "EmptyState";
1102
- var MetricCard = React17.forwardRef(
1234
+ var MetricCard = React18.forwardRef(
1103
1235
  ({ className, title, value, trend, trendDirection = "neutral", description, icon, ...props }, ref) => {
1104
1236
  const trendColor = {
1105
1237
  up: "text-success bg-success-surface border-success/20",
@@ -1129,54 +1261,171 @@ function DataTable({
1129
1261
  emptyTitle = "No data available",
1130
1262
  emptyDescription = "There are no records to display at this time.",
1131
1263
  emptyAction,
1264
+ getRowKey,
1265
+ onRowClick,
1266
+ toolbar,
1267
+ pagination,
1268
+ selectedRows,
1269
+ onSelectionChange,
1270
+ sortBy,
1271
+ sortDirection,
1272
+ onSort,
1132
1273
  ...props
1133
1274
  }) {
1134
- return /* @__PURE__ */ jsxs(TableWrap, { className: cn("relative overflow-hidden", className), ...props, children: [
1135
- /* @__PURE__ */ jsxs(Table, { children: [
1136
- /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsx(TableRow, { children: columns.map((col, idx) => /* @__PURE__ */ jsx(TableHead, { className: col.className, children: col.header }, idx)) }) }),
1137
- /* @__PURE__ */ jsx(TableBody, { children: loading && data.length === 0 ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length, className: "h-64 text-center", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-3", children: [
1138
- /* @__PURE__ */ jsx(Spinner, { size: 32 }),
1139
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Loading dataset..." })
1140
- ] }) }) }) : error ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length, className: "p-8", children: /* @__PURE__ */ jsx(Alert, { variant: "danger", title: "Error loading data", children: error }) }) }) : data.length === 0 ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length, className: "p-0", children: /* @__PURE__ */ jsx(
1141
- EmptyState,
1142
- {
1143
- title: emptyTitle,
1144
- description: emptyDescription,
1145
- action: emptyAction,
1146
- className: "border-none bg-transparent rounded-none py-16"
1147
- }
1148
- ) }) }) : data.map((row, rowIdx) => /* @__PURE__ */ jsx(TableRow, { children: columns.map((col, colIdx) => /* @__PURE__ */ jsx(TableCell, { className: col.className, children: col.accessor(row) }, colIdx)) }, rowIdx)) })
1275
+ const getRowId = React18.useCallback(
1276
+ (row, index) => getRowKey ? getRowKey(row, index) : index,
1277
+ [getRowKey]
1278
+ );
1279
+ const isSelectionActive = selectedRows !== void 0 && onSelectionChange !== void 0;
1280
+ const allSelected = React18.useMemo(() => {
1281
+ if (!isSelectionActive || data.length === 0) return false;
1282
+ return data.every((row, idx) => selectedRows.has(getRowId(row, idx)));
1283
+ }, [isSelectionActive, data, selectedRows, getRowId]);
1284
+ const someSelected = React18.useMemo(() => {
1285
+ if (!isSelectionActive || data.length === 0) return false;
1286
+ const selectedCount = data.filter((row, idx) => selectedRows.has(getRowId(row, idx))).length;
1287
+ return selectedCount > 0 && selectedCount < data.length;
1288
+ }, [isSelectionActive, data, selectedRows, getRowId]);
1289
+ const headerCheckboxRef = React18.useRef(null);
1290
+ React18.useEffect(() => {
1291
+ if (headerCheckboxRef.current) {
1292
+ headerCheckboxRef.current.indeterminate = someSelected;
1293
+ }
1294
+ }, [someSelected]);
1295
+ const handleSelectAll = (e) => {
1296
+ if (!onSelectionChange) return;
1297
+ const checked = e.target.checked;
1298
+ const next = new Set(selectedRows);
1299
+ data.forEach((row, idx) => {
1300
+ const id = getRowId(row, idx);
1301
+ if (checked) {
1302
+ next.add(id);
1303
+ } else {
1304
+ next.delete(id);
1305
+ }
1306
+ });
1307
+ onSelectionChange(next);
1308
+ };
1309
+ const handleSelectRow = (row, idx, checked) => {
1310
+ if (!onSelectionChange || !selectedRows) return;
1311
+ const id = getRowId(row, idx);
1312
+ const next = new Set(selectedRows);
1313
+ if (checked) {
1314
+ next.add(id);
1315
+ } else {
1316
+ next.delete(id);
1317
+ }
1318
+ onSelectionChange(next);
1319
+ };
1320
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-4 w-full", className), children: [
1321
+ toolbar && /* @__PURE__ */ jsx("div", { className: "flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-3", children: toolbar }),
1322
+ /* @__PURE__ */ jsxs(TableWrap, { className: "relative overflow-hidden", ...props, children: [
1323
+ /* @__PURE__ */ jsxs(Table, { children: [
1324
+ /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
1325
+ isSelectionActive && /* @__PURE__ */ jsx(TableHead, { className: "w-12 px-4 text-center", children: /* @__PURE__ */ jsx("div", { className: "inline-flex items-center justify-center", children: /* @__PURE__ */ jsx(
1326
+ "input",
1327
+ {
1328
+ type: "checkbox",
1329
+ ref: headerCheckboxRef,
1330
+ checked: allSelected,
1331
+ onChange: handleSelectAll,
1332
+ "aria-label": "Select all rows",
1333
+ className: "h-4 w-4 rounded border-input text-primary focus:ring-ring"
1334
+ }
1335
+ ) }) }),
1336
+ columns.map((col, idx) => {
1337
+ const alignClass = {
1338
+ left: "text-left",
1339
+ center: "text-center",
1340
+ right: "text-right"
1341
+ }[col.align || "left"];
1342
+ const isSortable = col.sortable && onSort && col.sortKey;
1343
+ const isSortedActive = sortBy && col.sortKey === sortBy;
1344
+ return /* @__PURE__ */ jsx(
1345
+ TableHead,
1346
+ {
1347
+ className: cn(
1348
+ alignClass,
1349
+ isSortable && "cursor-pointer select-none hover:bg-muted/30 transition-colors",
1350
+ col.className
1351
+ ),
1352
+ onClick: () => {
1353
+ if (!isSortable || !col.sortKey) return;
1354
+ const nextDirection = isSortedActive && sortDirection === "asc" ? "desc" : "asc";
1355
+ onSort(col.sortKey, nextDirection);
1356
+ },
1357
+ children: /* @__PURE__ */ jsxs("div", { className: cn("inline-flex items-center gap-1.5", alignClass === "text-right" && "justify-end w-full"), children: [
1358
+ /* @__PURE__ */ jsx("span", { children: col.header }),
1359
+ isSortable && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground shrink-0 select-none", children: isSortedActive ? sortDirection === "asc" ? "\u25B2" : "\u25BC" : "\u21C5" })
1360
+ ] })
1361
+ },
1362
+ idx
1363
+ );
1364
+ })
1365
+ ] }) }),
1366
+ /* @__PURE__ */ jsx(TableBody, { children: loading && data.length === 0 ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length + (isSelectionActive ? 1 : 0), className: "h-64 text-center", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-3", children: [
1367
+ /* @__PURE__ */ jsx(Spinner, { size: 32 }),
1368
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Loading dataset..." })
1369
+ ] }) }) }) : error ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length + (isSelectionActive ? 1 : 0), className: "p-8", children: /* @__PURE__ */ jsx(Alert, { variant: "danger", title: "Error loading data", children: error }) }) }) : data.length === 0 ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length + (isSelectionActive ? 1 : 0), className: "p-0", children: /* @__PURE__ */ jsx(
1370
+ EmptyState,
1371
+ {
1372
+ title: emptyTitle,
1373
+ description: emptyDescription,
1374
+ action: emptyAction,
1375
+ className: "border-none bg-transparent rounded-none py-16"
1376
+ }
1377
+ ) }) }) : data.map((row, rowIdx) => {
1378
+ const rowKey = getRowId(row, rowIdx);
1379
+ const isSelected = isSelectionActive && selectedRows.has(rowKey);
1380
+ return /* @__PURE__ */ jsxs(
1381
+ TableRow,
1382
+ {
1383
+ onClick: () => onRowClick && onRowClick(row),
1384
+ className: cn(
1385
+ onRowClick && "cursor-pointer hover:bg-muted/40 transition-colors",
1386
+ isSelected && "bg-primary/5 hover:bg-primary/10"
1387
+ ),
1388
+ children: [
1389
+ isSelectionActive && /* @__PURE__ */ jsx(
1390
+ TableCell,
1391
+ {
1392
+ className: "w-12 px-4 text-center",
1393
+ onClick: (e) => {
1394
+ e.stopPropagation();
1395
+ },
1396
+ children: /* @__PURE__ */ jsx("div", { className: "inline-flex items-center justify-center", children: /* @__PURE__ */ jsx(
1397
+ "input",
1398
+ {
1399
+ type: "checkbox",
1400
+ checked: isSelected,
1401
+ onChange: (e) => handleSelectRow(row, rowIdx, e.target.checked),
1402
+ "aria-label": `Select row ${rowIdx + 1}`,
1403
+ className: "h-4 w-4 rounded border-input text-primary focus:ring-ring"
1404
+ }
1405
+ ) })
1406
+ }
1407
+ ),
1408
+ columns.map((col, colIdx) => {
1409
+ const alignClass = {
1410
+ left: "text-left",
1411
+ center: "text-center",
1412
+ right: "text-right"
1413
+ }[col.align || "left"];
1414
+ return /* @__PURE__ */ jsx(TableCell, { className: cn(alignClass, col.className), children: col.accessor(row) }, colIdx);
1415
+ })
1416
+ ]
1417
+ },
1418
+ rowKey
1419
+ );
1420
+ }) })
1421
+ ] }),
1422
+ loading && data.length > 0 && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-background/50 backdrop-blur-[1px] grid place-items-center z-10 transition-opacity duration-150", children: /* @__PURE__ */ jsx(Spinner, { size: 36 }) })
1149
1423
  ] }),
1150
- loading && data.length > 0 && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-background/50 backdrop-blur-[1px] grid place-items-center z-10 transition-opacity duration-150", children: /* @__PURE__ */ jsx(Spinner, { size: 36 }) })
1424
+ pagination && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end w-full", children: pagination })
1151
1425
  ] });
1152
1426
  }
1153
1427
  DataTable.displayName = "DataTable";
1154
- var FormField = React17.forwardRef(
1155
- ({ className, label, hint, error, required, children, ...props }, ref) => {
1156
- const id = React17.useId();
1157
- const hintId = `${id}-hint`;
1158
- const errorId = `${id}-error`;
1159
- const child = React17.Children.only(children);
1160
- const clonedChild = React17.cloneElement(child, {
1161
- id: child.props.id ?? id,
1162
- "aria-describedby": cn(
1163
- hint && hintId,
1164
- error && errorId,
1165
- child.props["aria-describedby"]
1166
- ) || void 0,
1167
- "aria-invalid": error ? "true" : void 0,
1168
- required: child.props.required ?? required
1169
- });
1170
- return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex flex-col gap-1.5 w-full", className), ...props, children: [
1171
- /* @__PURE__ */ jsx(Label, { htmlFor: id, required, children: label }),
1172
- clonedChild,
1173
- hint && !error && /* @__PURE__ */ jsx(Hint, { id: hintId, children: hint }),
1174
- error && /* @__PURE__ */ jsx(Hint, { id: errorId, error: true, children: error })
1175
- ] });
1176
- }
1177
- );
1178
- FormField.displayName = "FormField";
1179
- var ErrorState = React17.forwardRef(
1428
+ var ErrorState = React18.forwardRef(
1180
1429
  ({ className, title = "Wyst\u0105pi\u0142 b\u0142\u0105d", message, onRetry, retryLabel = "Spr\xF3buj ponownie", ...props }, ref) => /* @__PURE__ */ jsxs(
1181
1430
  "div",
1182
1431
  {
@@ -1196,7 +1445,7 @@ var ErrorState = React17.forwardRef(
1196
1445
  )
1197
1446
  );
1198
1447
  ErrorState.displayName = "ErrorState";
1199
- var Skeleton = React17.forwardRef(
1448
+ var Skeleton = React18.forwardRef(
1200
1449
  ({ className, variant = "rectangular", width, height, style, ...props }, ref) => /* @__PURE__ */ jsx(
1201
1450
  "div",
1202
1451
  {
@@ -1218,28 +1467,550 @@ var Skeleton = React17.forwardRef(
1218
1467
  )
1219
1468
  );
1220
1469
  Skeleton.displayName = "Skeleton";
1221
- var DashboardShell = React17.forwardRef(
1222
- ({ className, sidebar, topbar, children, ...props }, ref) => /* @__PURE__ */ jsxs(
1470
+ var DashboardShell = React18.forwardRef(
1471
+ ({
1472
+ className,
1473
+ sidebar,
1474
+ topbar,
1475
+ children,
1476
+ sidebarWidth = "md:w-64",
1477
+ contentWidth = "default",
1478
+ stickyTopbar = true,
1479
+ mobileSidebar,
1480
+ ...props
1481
+ }, ref) => {
1482
+ const [mobileOpen, setMobileOpen] = React18.useState(false);
1483
+ const contentWidthClass = {
1484
+ default: "max-w-7xl w-full mx-auto",
1485
+ wide: "max-w-screen-2xl w-full mx-auto",
1486
+ full: "max-w-none w-full"
1487
+ }[contentWidth];
1488
+ return /* @__PURE__ */ jsxs(
1489
+ "div",
1490
+ {
1491
+ ref,
1492
+ className: cn(
1493
+ "min-h-screen bg-canvas text-foreground flex flex-col md:flex-row",
1494
+ className
1495
+ ),
1496
+ ...props,
1497
+ children: [
1498
+ sidebar && /* @__PURE__ */ jsx(
1499
+ "aside",
1500
+ {
1501
+ className: cn(
1502
+ "border-r border-border bg-surface shrink-0 z-20",
1503
+ mobileSidebar ? "hidden md:flex" : "w-full md:flex",
1504
+ sidebarWidth
1505
+ ),
1506
+ children: /* @__PURE__ */ jsx("div", { className: cn("sticky top-0 w-full flex flex-col", mobileSidebar ? "h-screen" : "h-auto md:h-screen"), children: sidebar })
1507
+ }
1508
+ ),
1509
+ mobileSidebar && mobileOpen && /* @__PURE__ */ jsx(
1510
+ "div",
1511
+ {
1512
+ onClick: () => setMobileOpen(false),
1513
+ className: "fixed inset-0 z-50 md:hidden bg-[color-mix(in_oklch,#09090b_45%,transparent)] backdrop-blur-[2px] transition-opacity duration-300",
1514
+ children: /* @__PURE__ */ jsxs(
1515
+ "aside",
1516
+ {
1517
+ onClick: (e) => e.stopPropagation(),
1518
+ className: "w-72 h-full bg-surface border-r border-border flex flex-col shadow-kj-lg",
1519
+ children: [
1520
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-4 border-b border-border", children: [
1521
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-bold uppercase tracking-wider text-muted-foreground", children: "Navigation" }),
1522
+ /* @__PURE__ */ jsx(
1523
+ "button",
1524
+ {
1525
+ type: "button",
1526
+ onClick: () => setMobileOpen(false),
1527
+ className: "p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted transition-colors cursor-pointer",
1528
+ children: /* @__PURE__ */ jsx("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
1529
+ }
1530
+ )
1531
+ ] }),
1532
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: mobileSidebar })
1533
+ ]
1534
+ }
1535
+ )
1536
+ }
1537
+ ),
1538
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col min-w-0", children: [
1539
+ topbar && /* @__PURE__ */ jsxs(
1540
+ "header",
1541
+ {
1542
+ className: cn(
1543
+ "h-14 border-b border-border bg-surface flex items-center px-6 z-10 shrink-0 gap-4",
1544
+ stickyTopbar && "sticky top-0"
1545
+ ),
1546
+ children: [
1547
+ mobileSidebar && /* @__PURE__ */ jsx(
1548
+ "button",
1549
+ {
1550
+ type: "button",
1551
+ onClick: () => setMobileOpen(true),
1552
+ 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",
1553
+ "aria-label": "Open navigation",
1554
+ children: /* @__PURE__ */ jsxs("svg", { width: 20, height: 20, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: [
1555
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "12", x2: "21", y2: "12" }),
1556
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "6", x2: "21", y2: "6" }),
1557
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "18", x2: "21", y2: "18" })
1558
+ ] })
1559
+ }
1560
+ ),
1561
+ topbar
1562
+ ]
1563
+ }
1564
+ ),
1565
+ /* @__PURE__ */ jsx("main", { className: cn("flex-1 p-6 md:p-8", contentWidthClass), children })
1566
+ ] })
1567
+ ]
1568
+ }
1569
+ );
1570
+ }
1571
+ );
1572
+ DashboardShell.displayName = "DashboardShell";
1573
+ var SettingsLayout = React18.forwardRef(
1574
+ ({ className, sidebar, children, title, description, ...props }, ref) => {
1575
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("space-y-6 w-full", className), ...props, children: [
1576
+ (title || description) && /* @__PURE__ */ jsxs("div", { className: "border-b border-border pb-4", children: [
1577
+ title && /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold tracking-tight text-foreground", children: title }),
1578
+ description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: description })
1579
+ ] }),
1580
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col lg:flex-row gap-8", children: [
1581
+ /* @__PURE__ */ jsx("aside", { className: "lg:w-1/4 shrink-0", children: /* @__PURE__ */ 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 }) }),
1582
+ /* @__PURE__ */ jsx("div", { className: "flex-1 max-w-3xl", children })
1583
+ ] })
1584
+ ] });
1585
+ }
1586
+ );
1587
+ SettingsLayout.displayName = "SettingsLayout";
1588
+ var DetailPageLayout = React18.forwardRef(
1589
+ ({ className, title, description, backHref, backLabel = "Back", onBackClick, actions, aside, children, ...props }, ref) => {
1590
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("space-y-6 w-full", className), ...props, children: [
1591
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
1592
+ (backHref || onBackClick) && /* @__PURE__ */ jsx("div", { children: backHref ? /* @__PURE__ */ jsxs(
1593
+ "a",
1594
+ {
1595
+ href: backHref,
1596
+ className: cn(
1597
+ buttonVariants({ variant: "ghost", size: "sm" }),
1598
+ "-ml-3 h-8 text-muted-foreground hover:text-foreground inline-flex items-center gap-1.5"
1599
+ ),
1600
+ children: [
1601
+ /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", className: "h-4 w-4", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.75 19.5 8.25 12l7.5-7.5" }) }),
1602
+ backLabel
1603
+ ]
1604
+ }
1605
+ ) : /* @__PURE__ */ jsxs(
1606
+ Button,
1607
+ {
1608
+ variant: "ghost",
1609
+ size: "sm",
1610
+ className: "-ml-3 h-8 text-muted-foreground hover:text-foreground",
1611
+ onClick: onBackClick,
1612
+ children: [
1613
+ /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", className: "h-4 w-4 mr-1.5", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.75 19.5 8.25 12l7.5-7.5" }) }),
1614
+ backLabel
1615
+ ]
1616
+ }
1617
+ ) }),
1618
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col md:flex-row md:items-center md:justify-between gap-4", children: [
1619
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1620
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold tracking-tight text-foreground", children: title }),
1621
+ description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: description })
1622
+ ] }),
1623
+ actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 shrink-0", children: actions })
1624
+ ] })
1625
+ ] }),
1626
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-3 gap-8 items-start", children: [
1627
+ /* @__PURE__ */ jsx("div", { className: cn("space-y-6", aside ? "lg:col-span-2" : "lg:col-span-3"), children }),
1628
+ aside && /* @__PURE__ */ 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 })
1629
+ ] })
1630
+ ] });
1631
+ }
1632
+ );
1633
+ DetailPageLayout.displayName = "DetailPageLayout";
1634
+ var TableToolbar = React18.forwardRef(
1635
+ ({ className, searchQuery, onSearchChange, searchPlaceholder = "Search...", actions, filters, ...props }, ref) => {
1636
+ return /* @__PURE__ */ jsxs(
1637
+ "div",
1638
+ {
1639
+ ref,
1640
+ className: cn(
1641
+ "flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-3 w-full pb-1",
1642
+ className
1643
+ ),
1644
+ ...props,
1645
+ children: [
1646
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col sm:flex-row items-stretch sm:items-center gap-2 max-w-xl", children: [
1647
+ onSearchChange && /* @__PURE__ */ jsx(
1648
+ Input,
1649
+ {
1650
+ type: "search",
1651
+ placeholder: searchPlaceholder,
1652
+ value: searchQuery,
1653
+ onChange: (e) => onSearchChange(e.target.value),
1654
+ className: "sm:w-64",
1655
+ leadingIcon: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", className: "h-4 w-4", children: /* @__PURE__ */ 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" }) })
1656
+ }
1657
+ ),
1658
+ filters && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: filters })
1659
+ ] }),
1660
+ actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 shrink-0 justify-end", children: actions })
1661
+ ]
1662
+ }
1663
+ );
1664
+ }
1665
+ );
1666
+ TableToolbar.displayName = "TableToolbar";
1667
+ function ConfirmDialog({
1668
+ open,
1669
+ onClose,
1670
+ onConfirm,
1671
+ title,
1672
+ description,
1673
+ confirmLabel = "Confirm",
1674
+ cancelLabel = "Cancel",
1675
+ tone = "primary",
1676
+ loading = false
1677
+ }) {
1678
+ const toneButtonVariant = {
1679
+ danger: "danger",
1680
+ primary: "primary",
1681
+ success: "secondary"
1682
+ // standard secondary in our system is teal (success-aligned)
1683
+ }[tone];
1684
+ return /* @__PURE__ */ jsxs(Modal, { open, onClose, width: 400, showClose: !loading, children: [
1685
+ /* @__PURE__ */ jsx(ModalTitle, { children: title }),
1686
+ /* @__PURE__ */ jsx(ModalDescription, { children: description }),
1687
+ /* @__PURE__ */ jsxs(ModalActions, { children: [
1688
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onClose, disabled: loading, children: cancelLabel }),
1689
+ /* @__PURE__ */ jsx(Button, { variant: toneButtonVariant, onClick: onConfirm, loading, children: confirmLabel })
1690
+ ] })
1691
+ ] });
1692
+ }
1693
+ ConfirmDialog.displayName = "ConfirmDialog";
1694
+ function Drawer({
1695
+ open,
1696
+ onClose,
1697
+ children,
1698
+ title,
1699
+ description,
1700
+ width = "max-w-md",
1701
+ side = "right"
1702
+ }) {
1703
+ const containerRef = React18.useRef(null);
1704
+ const lastActiveElement = React18.useRef(null);
1705
+ React18.useEffect(() => {
1706
+ if (!open) {
1707
+ if (lastActiveElement.current) {
1708
+ lastActiveElement.current.focus();
1709
+ lastActiveElement.current = null;
1710
+ }
1711
+ return;
1712
+ }
1713
+ lastActiveElement.current = document.activeElement;
1714
+ const container = containerRef.current;
1715
+ if (container) {
1716
+ const focusables = container.querySelectorAll(
1717
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1718
+ );
1719
+ if (focusables.length > 0) {
1720
+ setTimeout(() => focusables[0].focus(), 50);
1721
+ } else {
1722
+ container.focus();
1723
+ }
1724
+ }
1725
+ const handleKeyDown = (e) => {
1726
+ if (e.key === "Escape") {
1727
+ onClose();
1728
+ return;
1729
+ }
1730
+ if (e.key === "Tab") {
1731
+ const container2 = containerRef.current;
1732
+ if (!container2) return;
1733
+ const focusables = Array.from(
1734
+ container2.querySelectorAll(
1735
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1736
+ )
1737
+ );
1738
+ if (focusables.length === 0) {
1739
+ e.preventDefault();
1740
+ return;
1741
+ }
1742
+ const first = focusables[0];
1743
+ const last = focusables[focusables.length - 1];
1744
+ if (e.shiftKey) {
1745
+ if (document.activeElement === first || document.activeElement === container2) {
1746
+ last.focus();
1747
+ e.preventDefault();
1748
+ }
1749
+ } else {
1750
+ if (document.activeElement === last) {
1751
+ first.focus();
1752
+ e.preventDefault();
1753
+ }
1754
+ }
1755
+ }
1756
+ };
1757
+ document.addEventListener("keydown", handleKeyDown);
1758
+ document.body.style.overflow = "hidden";
1759
+ return () => {
1760
+ document.removeEventListener("keydown", handleKeyDown);
1761
+ document.body.style.overflow = "";
1762
+ };
1763
+ }, [open, onClose]);
1764
+ const sideClasses = {
1765
+ right: cn(
1766
+ "right-0 h-full border-l",
1767
+ open ? "translate-x-0" : "translate-x-full"
1768
+ ),
1769
+ left: cn(
1770
+ "left-0 h-full border-r",
1771
+ open ? "translate-x-0" : "-translate-x-full"
1772
+ )
1773
+ }[side];
1774
+ return /* @__PURE__ */ jsx(
1223
1775
  "div",
1224
1776
  {
1225
- ref,
1777
+ onClick: (e) => e.target === e.currentTarget && onClose(),
1226
1778
  className: cn(
1227
- "min-h-screen bg-canvas text-foreground flex flex-col md:flex-row",
1228
- className
1779
+ "fixed inset-0 z-[100] transition-opacity duration-300 backdrop-blur-[2px]",
1780
+ "bg-[color-mix(in_oklch,#09090b_45%,transparent)]",
1781
+ open ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"
1229
1782
  ),
1230
- ...props,
1231
- children: [
1232
- sidebar && /* @__PURE__ */ jsx("aside", { className: "w-full md:w-64 border-r border-border bg-surface shrink-0 z-20", children: /* @__PURE__ */ jsx("div", { className: "sticky top-0 h-auto md:h-screen flex flex-col", children: sidebar }) }),
1233
- /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col min-w-0", children: [
1234
- topbar && /* @__PURE__ */ 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 }),
1235
- /* @__PURE__ */ jsx("main", { className: "flex-1 p-6 md:p-8 max-w-7xl w-full mx-auto", children })
1236
- ] })
1237
- ]
1783
+ children: /* @__PURE__ */ jsxs(
1784
+ "div",
1785
+ {
1786
+ ref: containerRef,
1787
+ role: "dialog",
1788
+ "aria-modal": "true",
1789
+ "aria-label": !title ? "Drawer" : void 0,
1790
+ "aria-labelledby": title ? "drawer-title" : void 0,
1791
+ "aria-describedby": description ? "drawer-description" : void 0,
1792
+ tabIndex: -1,
1793
+ className: cn(
1794
+ "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",
1795
+ width,
1796
+ sideClasses
1797
+ ),
1798
+ children: [
1799
+ (title || description) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-6 border-b border-border", children: [
1800
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1801
+ title && /* @__PURE__ */ jsx("h2", { id: "drawer-title", className: "text-lg font-bold tracking-tight text-foreground", children: title }),
1802
+ description && /* @__PURE__ */ jsx("p", { id: "drawer-description", className: "text-xs text-muted-foreground", children: description })
1803
+ ] }),
1804
+ /* @__PURE__ */ jsx(
1805
+ "button",
1806
+ {
1807
+ type: "button",
1808
+ onClick: onClose,
1809
+ "aria-label": "Close",
1810
+ className: "p-1.5 rounded-kj-sm text-muted-foreground hover:text-foreground hover:bg-muted transition-colors cursor-pointer",
1811
+ children: /* @__PURE__ */ jsx("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
1812
+ }
1813
+ )
1814
+ ] }),
1815
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto p-6", children })
1816
+ ]
1817
+ }
1818
+ )
1238
1819
  }
1239
- )
1240
- );
1241
- DashboardShell.displayName = "DashboardShell";
1820
+ );
1821
+ }
1822
+ Drawer.displayName = "Drawer";
1823
+ function CommandPalette({ open, onClose, items, placeholder = "Type a command or search..." }) {
1824
+ const [search, setSearch] = React18.useState("");
1825
+ const [activeIndex, setActiveIndex] = React18.useState(0);
1826
+ const containerRef = React18.useRef(null);
1827
+ const listRef = React18.useRef(null);
1828
+ React18.useEffect(() => {
1829
+ if (open) {
1830
+ setSearch("");
1831
+ setActiveIndex(0);
1832
+ document.body.style.overflow = "hidden";
1833
+ } else {
1834
+ document.body.style.overflow = "";
1835
+ }
1836
+ }, [open]);
1837
+ const filteredItems = React18.useMemo(() => {
1838
+ if (!search) return items;
1839
+ const cleanSearch = search.toLowerCase();
1840
+ return items.filter(
1841
+ (item) => item.title.toLowerCase().includes(cleanSearch) || item.subtitle?.toLowerCase().includes(cleanSearch) || item.category?.toLowerCase().includes(cleanSearch)
1842
+ );
1843
+ }, [search, items]);
1844
+ React18.useEffect(() => {
1845
+ setActiveIndex(0);
1846
+ }, [filteredItems]);
1847
+ React18.useEffect(() => {
1848
+ if (!open) return;
1849
+ const handleKeyDown = (e) => {
1850
+ if (e.key === "Escape") {
1851
+ onClose();
1852
+ return;
1853
+ }
1854
+ if (e.key === "ArrowDown") {
1855
+ e.preventDefault();
1856
+ setActiveIndex((prev) => filteredItems.length === 0 ? 0 : (prev + 1) % filteredItems.length);
1857
+ } else if (e.key === "ArrowUp") {
1858
+ e.preventDefault();
1859
+ setActiveIndex((prev) => filteredItems.length === 0 ? 0 : (prev - 1 + filteredItems.length) % filteredItems.length);
1860
+ } else if (e.key === "Enter") {
1861
+ e.preventDefault();
1862
+ if (filteredItems[activeIndex]) {
1863
+ filteredItems[activeIndex].action();
1864
+ onClose();
1865
+ }
1866
+ }
1867
+ };
1868
+ document.addEventListener("keydown", handleKeyDown);
1869
+ return () => document.removeEventListener("keydown", handleKeyDown);
1870
+ }, [open, filteredItems, activeIndex, onClose]);
1871
+ React18.useEffect(() => {
1872
+ if (listRef.current) {
1873
+ const activeEl = listRef.current.children[activeIndex];
1874
+ if (activeEl) {
1875
+ activeEl.scrollIntoView({ block: "nearest" });
1876
+ }
1877
+ }
1878
+ }, [activeIndex]);
1879
+ if (!open) return null;
1880
+ const groups = {};
1881
+ filteredItems.forEach((item) => {
1882
+ const cat = item.category || "General";
1883
+ if (!groups[cat]) groups[cat] = [];
1884
+ groups[cat].push(item);
1885
+ });
1886
+ let absoluteItemIndex = 0;
1887
+ return /* @__PURE__ */ jsx(
1888
+ "div",
1889
+ {
1890
+ onClick: (e) => e.target === e.currentTarget && onClose(),
1891
+ 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)]",
1892
+ children: /* @__PURE__ */ jsxs(
1893
+ "div",
1894
+ {
1895
+ ref: containerRef,
1896
+ 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]",
1897
+ children: [
1898
+ /* @__PURE__ */ jsxs("div", { className: "p-4 border-b border-border flex items-center gap-2", children: [
1899
+ /* @__PURE__ */ 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__ */ 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" }) }),
1900
+ /* @__PURE__ */ jsx(
1901
+ "input",
1902
+ {
1903
+ type: "text",
1904
+ placeholder,
1905
+ value: search,
1906
+ onChange: (e) => setSearch(e.target.value),
1907
+ className: "flex-1 font-sans text-[0.95rem] bg-transparent text-foreground placeholder:text-muted-foreground outline-none border-none focus:ring-0",
1908
+ autoFocus: true
1909
+ }
1910
+ )
1911
+ ] }),
1912
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto p-2 min-h-[150px]", children: filteredItems.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "py-12 text-center text-sm text-muted-foreground", children: [
1913
+ 'No results found for "',
1914
+ search,
1915
+ '"'
1916
+ ] }) : /* @__PURE__ */ jsx("div", { ref: listRef, className: "space-y-4", children: Object.entries(groups).map(([cat, itemsInCat]) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1917
+ /* @__PURE__ */ jsx("div", { className: "px-3 py-1 text-[0.65rem] font-bold uppercase tracking-wider text-muted-foreground", children: cat }),
1918
+ itemsInCat.map((item) => {
1919
+ const currentIdx = absoluteItemIndex++;
1920
+ const isActive = currentIdx === activeIndex;
1921
+ return /* @__PURE__ */ jsxs(
1922
+ "div",
1923
+ {
1924
+ onClick: () => {
1925
+ item.action();
1926
+ onClose();
1927
+ },
1928
+ className: cn(
1929
+ "flex items-center justify-between gap-3 px-3 py-2.5 rounded-kj-md cursor-pointer select-none transition-colors",
1930
+ isActive ? "bg-primary/10 text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
1931
+ ),
1932
+ children: [
1933
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
1934
+ item.icon && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground [&_svg]:h-[1.1rem] [&_svg]:w-[1.1rem]", children: item.icon }),
1935
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex flex-col", children: [
1936
+ /* @__PURE__ */ jsx("span", { className: cn("text-[0.85rem] font-semibold", isActive ? "text-primary" : "text-foreground"), children: item.title }),
1937
+ item.subtitle && /* @__PURE__ */ jsx("span", { className: "text-[0.75rem] text-muted-foreground truncate", children: item.subtitle })
1938
+ ] })
1939
+ ] }),
1940
+ item.shortcut && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: item.shortcut.map((sc, scIdx) => /* @__PURE__ */ jsx(
1941
+ "kbd",
1942
+ {
1943
+ 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",
1944
+ children: sc
1945
+ },
1946
+ scIdx
1947
+ )) })
1948
+ ]
1949
+ },
1950
+ item.id
1951
+ );
1952
+ })
1953
+ ] }, cat)) }) }),
1954
+ /* @__PURE__ */ 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: [
1955
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1956
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
1957
+ /* @__PURE__ */ jsx("kbd", { className: "font-mono text-[9px] px-1 border rounded bg-surface", children: "\u2191\u2193" }),
1958
+ " Navigate"
1959
+ ] }),
1960
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
1961
+ /* @__PURE__ */ jsx("kbd", { className: "font-mono text-[9px] px-1 border rounded bg-surface", children: "Enter" }),
1962
+ " Select"
1963
+ ] })
1964
+ ] }),
1965
+ /* @__PURE__ */ jsxs("div", { children: [
1966
+ /* @__PURE__ */ jsx("kbd", { className: "font-mono text-[9px] px-1 border rounded bg-surface", children: "Esc" }),
1967
+ " Close"
1968
+ ] })
1969
+ ] })
1970
+ ]
1971
+ }
1972
+ )
1973
+ }
1974
+ );
1975
+ }
1976
+ CommandPalette.displayName = "CommandPalette";
1977
+ function SidebarNav({ className, groups, currentHref, ...props }) {
1978
+ return /* @__PURE__ */ jsx("div", { className: cn("space-y-6 py-4 px-3 w-full", className), ...props, children: groups.map((group, groupIdx) => /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
1979
+ group.title && /* @__PURE__ */ jsx("h4", { className: "px-3 text-[10px] font-bold uppercase tracking-widest text-muted-foreground/85", children: group.title }),
1980
+ /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: group.items.map((item) => {
1981
+ const isActive = item.active || item.href && currentHref && currentHref === item.href;
1982
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
1983
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2.5 min-w-0", children: [
1984
+ item.icon && /* @__PURE__ */ jsx("span", { className: cn(
1985
+ "[&_svg]:h-[1.1rem] [&_svg]:w-[1.1rem] shrink-0",
1986
+ isActive ? "text-primary" : "text-muted-foreground group-hover:text-foreground"
1987
+ ), children: item.icon }),
1988
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: item.label })
1989
+ ] }),
1990
+ item.badge && /* @__PURE__ */ jsx("span", { className: "shrink-0 flex items-center justify-center", children: item.badge })
1991
+ ] });
1992
+ const itemClass = cn(
1993
+ "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",
1994
+ 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"
1995
+ );
1996
+ if (item.href) {
1997
+ return /* @__PURE__ */ jsx("a", { href: item.href, className: itemClass, children: content }, item.id);
1998
+ }
1999
+ return /* @__PURE__ */ jsx(
2000
+ "button",
2001
+ {
2002
+ type: "button",
2003
+ onClick: item.onClick,
2004
+ className: itemClass,
2005
+ children: content
2006
+ },
2007
+ item.id
2008
+ );
2009
+ }) })
2010
+ ] }, groupIdx)) });
2011
+ }
2012
+ SidebarNav.displayName = "SidebarNav";
1242
2013
 
1243
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, Avatar, AvatarGroup, Badge, Breadcrumb, BreadcrumbItem, BreadcrumbSeparator, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, DashboardShell, DataTable, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, EmptyState, ErrorState, Field, FormField, Hint, Input, Label, MetricCard, Modal, ModalActions, ModalDescription, ModalTitle, PageHeader, Pagination, Progress, Radio, Segmented, Select, Skeleton, Slider, Spinner, Stat, Switch, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, TableWrap, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ToastProvider, Tooltip, badgeVariants, buttonVariants, cn, sliderThumbCSS, useToast };
2014
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, Avatar, AvatarGroup, Badge, BottomNavigation, Breadcrumb, BreadcrumbItem, BreadcrumbSeparator, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, CheckboxField, CommandPalette, ConfirmDialog, DashboardShell, DataTable, DetailPageLayout, Drawer, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, EmptyState, ErrorState, Field, FormField, Hint, Input, Label, MetricCard, Modal, ModalActions, ModalDescription, ModalTitle, PageHeader, Pagination, Progress, Radio, Segmented, Select, SelectField, SettingsLayout, SidebarNav, Skeleton, Slider, Spinner, Stat, Switch, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, TableToolbar, TableWrap, Tabs, TabsContent, TabsList, TabsTrigger, TextField, Textarea, ToastProvider, Tooltip, badgeVariants, buttonVariants, cn, sliderThumbCSS, useToast };
1244
2015
  //# sourceMappingURL=index.js.map
1245
2016
  //# sourceMappingURL=index.js.map