@kjaniec-dev/ui 0.6.0 → 0.7.1

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;
@@ -527,14 +587,17 @@ var TabsList = React17__namespace.forwardRef(
527
587
  ref,
528
588
  role: "tablist",
529
589
  onKeyDown: handleKeyDown,
530
- className: cn("flex gap-1 border-b border-border", className),
590
+ className: cn(
591
+ "flex gap-1 border-b border-border overflow-x-auto whitespace-nowrap [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
592
+ className
593
+ ),
531
594
  ...props
532
595
  }
533
596
  );
534
597
  }
535
598
  );
536
599
  TabsList.displayName = "TabsList";
537
- var TabsTrigger = React17__namespace.forwardRef(
600
+ var TabsTrigger = React18__namespace.forwardRef(
538
601
  ({ className, value, children, ...props }, ref) => {
539
602
  const { value: current, setValue } = useTabs();
540
603
  const active = current === value;
@@ -550,7 +613,7 @@ var TabsTrigger = React17__namespace.forwardRef(
550
613
  tabIndex: active ? 0 : -1,
551
614
  onClick: () => setValue(value),
552
615
  className: cn(
553
- "relative px-[0.9rem] py-2.5 text-sm font-semibold cursor-pointer transition-colors duration-150 outline-none",
616
+ "relative px-[0.9rem] py-2.5 text-sm font-semibold cursor-pointer transition-colors duration-150 outline-none shrink-0 whitespace-nowrap",
554
617
  "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:rounded-sm",
555
618
  "after:content-[''] after:absolute after:left-[0.9rem] after:right-[0.9rem] after:-bottom-px after:h-0.5 after:rounded-sm after:transition-colors",
556
619
  active ? "text-foreground after:bg-primary" : "text-muted-foreground hover:text-foreground after:bg-transparent",
@@ -563,7 +626,7 @@ var TabsTrigger = React17__namespace.forwardRef(
563
626
  }
564
627
  );
565
628
  TabsTrigger.displayName = "TabsTrigger";
566
- var TabsContent = React17__namespace.forwardRef(
629
+ var TabsContent = React18__namespace.forwardRef(
567
630
  ({ className, value, ...props }, ref) => {
568
631
  const { value: current } = useTabs();
569
632
  const active = current === value;
@@ -583,10 +646,10 @@ var TabsContent = React17__namespace.forwardRef(
583
646
  }
584
647
  );
585
648
  TabsContent.displayName = "TabsContent";
586
- var AccordionContext = React17__namespace.createContext(null);
649
+ var AccordionContext = React18__namespace.createContext(null);
587
650
  function Accordion({ type = "single", defaultValue = [], className, children, ...props }) {
588
- const [open, setOpen] = React17__namespace.useState(defaultValue);
589
- const toggle = React17__namespace.useCallback(
651
+ const [open, setOpen] = React18__namespace.useState(defaultValue);
652
+ const toggle = React18__namespace.useCallback(
590
653
  (v) => {
591
654
  setOpen((prev) => {
592
655
  const isOpen = prev.includes(v);
@@ -598,15 +661,15 @@ function Accordion({ type = "single", defaultValue = [], className, children, ..
598
661
  );
599
662
  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
663
  }
601
- var ItemContext = React17__namespace.createContext("");
602
- var AccordionItem = React17__namespace.forwardRef(
664
+ var ItemContext = React18__namespace.createContext("");
665
+ var AccordionItem = React18__namespace.forwardRef(
603
666
  ({ 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
667
  );
605
668
  AccordionItem.displayName = "AccordionItem";
606
- var AccordionTrigger = React17__namespace.forwardRef(
669
+ var AccordionTrigger = React18__namespace.forwardRef(
607
670
  ({ className, children, ...props }, ref) => {
608
- const ctx = React17__namespace.useContext(AccordionContext);
609
- const value = React17__namespace.useContext(ItemContext);
671
+ const ctx = React18__namespace.useContext(AccordionContext);
672
+ const value = React18__namespace.useContext(ItemContext);
610
673
  const isOpen = ctx.open.includes(value);
611
674
  return /* @__PURE__ */ jsxRuntime.jsxs(
612
675
  "button",
@@ -643,10 +706,10 @@ var AccordionTrigger = React17__namespace.forwardRef(
643
706
  }
644
707
  );
645
708
  AccordionTrigger.displayName = "AccordionTrigger";
646
- var AccordionContent = React17__namespace.forwardRef(
709
+ var AccordionContent = React18__namespace.forwardRef(
647
710
  ({ className, children, ...props }, ref) => {
648
- const ctx = React17__namespace.useContext(AccordionContext);
649
- const value = React17__namespace.useContext(ItemContext);
711
+ const ctx = React18__namespace.useContext(AccordionContext);
712
+ const value = React18__namespace.useContext(ItemContext);
650
713
  const isOpen = ctx.open.includes(value);
651
714
  return /* @__PURE__ */ jsxRuntime.jsx(
652
715
  "div",
@@ -660,11 +723,11 @@ var AccordionContent = React17__namespace.forwardRef(
660
723
  }
661
724
  );
662
725
  AccordionContent.displayName = "AccordionContent";
663
- var MenuContext = React17__namespace.createContext(null);
726
+ var MenuContext = React18__namespace.createContext(null);
664
727
  function DropdownMenu({ children, className }) {
665
- const [open, setOpen] = React17__namespace.useState(false);
666
- const ref = React17__namespace.useRef(null);
667
- React17__namespace.useEffect(() => {
728
+ const [open, setOpen] = React18__namespace.useState(false);
729
+ const ref = React18__namespace.useRef(null);
730
+ React18__namespace.useEffect(() => {
668
731
  if (!open) return;
669
732
  const onDoc = (e) => {
670
733
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -679,11 +742,11 @@ function DropdownMenu({ children, className }) {
679
742
  }, [open]);
680
743
  return /* @__PURE__ */ jsxRuntime.jsx(MenuContext.Provider, { value: { open, setOpen }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("relative inline-block", className), children }) });
681
744
  }
682
- var DropdownMenuTrigger = React17__namespace.forwardRef(({ onClick, asChild, ...props }, ref) => {
683
- const ctx = React17__namespace.useContext(MenuContext);
745
+ var DropdownMenuTrigger = React18__namespace.forwardRef(({ onClick, asChild, ...props }, ref) => {
746
+ const ctx = React18__namespace.useContext(MenuContext);
684
747
  if (asChild) {
685
- const child = React17__namespace.Children.only(props.children);
686
- return React17__namespace.cloneElement(child, {
748
+ const child = React18__namespace.Children.only(props.children);
749
+ return React18__namespace.cloneElement(child, {
687
750
  ref,
688
751
  ...props,
689
752
  ...child.props,
@@ -713,9 +776,9 @@ var DropdownMenuTrigger = React17__namespace.forwardRef(({ onClick, asChild, ...
713
776
  });
714
777
  DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
715
778
  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(() => {
779
+ const ctx = React18__namespace.useContext(MenuContext);
780
+ const ref = React18__namespace.useRef(null);
781
+ React18__namespace.useEffect(() => {
719
782
  if (!ctx.open) return;
720
783
  const container = ref.current;
721
784
  if (container) {
@@ -762,9 +825,9 @@ function DropdownMenuContent({ className, align = "start", children, ...props })
762
825
  }
763
826
  );
764
827
  }
765
- var DropdownMenuItem = React17__namespace.forwardRef(
828
+ var DropdownMenuItem = React18__namespace.forwardRef(
766
829
  ({ className, danger, icon, children, onClick, ...props }, ref) => {
767
- const ctx = React17__namespace.useContext(MenuContext);
830
+ const ctx = React18__namespace.useContext(MenuContext);
768
831
  return /* @__PURE__ */ jsxRuntime.jsxs(
769
832
  "button",
770
833
  {
@@ -794,11 +857,11 @@ DropdownMenuItem.displayName = "DropdownMenuItem";
794
857
  function DropdownMenuSeparator({ className }) {
795
858
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("h-px bg-border my-1.5", className), role: "separator" });
796
859
  }
797
- var Breadcrumb = React17__namespace.forwardRef(
860
+ var Breadcrumb = React18__namespace.forwardRef(
798
861
  ({ 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
862
  );
800
863
  Breadcrumb.displayName = "Breadcrumb";
801
- var BreadcrumbItem = React17__namespace.forwardRef(
864
+ var BreadcrumbItem = React18__namespace.forwardRef(
802
865
  ({ className, current, children, ...props }, ref) => {
803
866
  if (current) {
804
867
  return /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-current": "page", className: cn("text-foreground font-semibold", className), children });
@@ -845,27 +908,99 @@ function Pagination({ page, pageCount, onPageChange, className }) {
845
908
  /* @__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
909
  ] });
847
910
  }
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 })
911
+ var BottomNavigation = React18__namespace.forwardRef(
912
+ ({ className, items, showLabels = "always", fixed = true, ...props }, ref) => {
913
+ return /* @__PURE__ */ jsxRuntime.jsx(
914
+ "nav",
915
+ {
916
+ ref,
917
+ className: cn(
918
+ "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",
919
+ fixed ? "fixed bottom-0 left-0 right-0 z-40 backdrop-blur-md" : "relative w-full",
920
+ className
921
+ ),
922
+ ...props,
923
+ children: items.map((item) => {
924
+ const isActive = item.active;
925
+ const showLabel = showLabels !== "never" && (showLabels === "always" || isActive);
926
+ const content = /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-col items-center justify-center gap-1 w-full relative", children: [
927
+ /* @__PURE__ */ jsxRuntime.jsxs(
928
+ "span",
929
+ {
930
+ className: cn(
931
+ "relative flex items-center justify-center p-1 rounded-full transition-all duration-200",
932
+ isActive ? "text-primary scale-110" : "text-muted-foreground group-hover:text-foreground group-active:scale-95"
933
+ ),
934
+ children: [
935
+ item.icon,
936
+ 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 })
937
+ ]
938
+ }
939
+ ),
940
+ /* @__PURE__ */ jsxRuntime.jsx(
941
+ "span",
942
+ {
943
+ className: cn(
944
+ "text-[10px] font-semibold tracking-wide transition-all duration-200 select-none",
945
+ showLabel ? "opacity-100 scale-100 h-auto" : "opacity-0 scale-75 h-0 overflow-hidden",
946
+ isActive ? "text-primary font-bold" : "text-muted-foreground group-hover:text-foreground"
947
+ ),
948
+ children: item.label
949
+ }
950
+ ),
951
+ isActive && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -bottom-1.5 w-1 h-1 rounded-full bg-primary animate-fade-in" })
952
+ ] });
953
+ const itemClass = "group flex-1 flex flex-col items-center justify-center py-1 cursor-pointer transition-all duration-150 relative focus:outline-none";
954
+ if (item.href) {
955
+ return /* @__PURE__ */ jsxRuntime.jsx(
956
+ "a",
957
+ {
958
+ href: item.href,
959
+ className: itemClass,
960
+ "aria-current": isActive ? "page" : void 0,
961
+ children: content
962
+ },
963
+ item.id
964
+ );
965
+ }
966
+ return /* @__PURE__ */ jsxRuntime.jsx(
967
+ "button",
968
+ {
969
+ type: "button",
970
+ onClick: item.onClick,
971
+ className: itemClass,
972
+ "aria-pressed": isActive,
973
+ children: content
974
+ },
975
+ item.id
976
+ );
977
+ })
978
+ }
979
+ );
980
+ }
981
+ );
982
+ BottomNavigation.displayName = "BottomNavigation";
983
+ var TableWrap = React18__namespace.forwardRef(
984
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("border border-border rounded-kj-lg overflow-x-auto w-full", className), ...props })
850
985
  );
851
986
  TableWrap.displayName = "TableWrap";
852
- var Table = React17__namespace.forwardRef(
987
+ var Table = React18__namespace.forwardRef(
853
988
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("table", { ref, className: cn("w-full border-collapse text-[0.85rem]", className), ...props })
854
989
  );
855
990
  Table.displayName = "Table";
856
- var TableHeader = React17__namespace.forwardRef(
991
+ var TableHeader = React18__namespace.forwardRef(
857
992
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("thead", { ref, className, ...props })
858
993
  );
859
994
  TableHeader.displayName = "TableHeader";
860
- var TableBody = React17__namespace.forwardRef(
995
+ var TableBody = React18__namespace.forwardRef(
861
996
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tbody", { ref, className, ...props })
862
997
  );
863
998
  TableBody.displayName = "TableBody";
864
- var TableRow = React17__namespace.forwardRef(
999
+ var TableRow = React18__namespace.forwardRef(
865
1000
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tr", { ref, className: cn("transition-colors hover:bg-muted/50", className), ...props })
866
1001
  );
867
1002
  TableRow.displayName = "TableRow";
868
- var TableHead = React17__namespace.forwardRef(
1003
+ var TableHead = React18__namespace.forwardRef(
869
1004
  ({ className, numeric, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
870
1005
  "th",
871
1006
  {
@@ -880,7 +1015,7 @@ var TableHead = React17__namespace.forwardRef(
880
1015
  )
881
1016
  );
882
1017
  TableHead.displayName = "TableHead";
883
- var TableCell = React17__namespace.forwardRef(
1018
+ var TableCell = React18__namespace.forwardRef(
884
1019
  ({ className, numeric, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
885
1020
  "td",
886
1021
  {
@@ -913,13 +1048,13 @@ function Tooltip({ content, children, className }) {
913
1048
  )
914
1049
  ] });
915
1050
  }
916
- var ModalContext = React17__namespace.createContext(null);
1051
+ var ModalContext = React18__namespace.createContext(null);
917
1052
  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(() => {
1053
+ const titleId = React18__namespace.useId();
1054
+ const descId = React18__namespace.useId();
1055
+ const containerRef = React18__namespace.useRef(null);
1056
+ const lastActiveElement = React18__namespace.useRef(null);
1057
+ React18__namespace.useEffect(() => {
923
1058
  if (!open) {
924
1059
  if (lastActiveElement.current) {
925
1060
  lastActiveElement.current.focus();
@@ -1021,19 +1156,19 @@ function Modal({ open, onClose, children, width = 440, className, showClose = tr
1021
1156
  );
1022
1157
  }
1023
1158
  function ModalTitle({ className, id, ...props }) {
1024
- const ctx = React17__namespace.useContext(ModalContext);
1159
+ const ctx = React18__namespace.useContext(ModalContext);
1025
1160
  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
1161
  }
1027
1162
  function ModalDescription({ className, id, ...props }) {
1028
- const ctx = React17__namespace.useContext(ModalContext);
1163
+ const ctx = React18__namespace.useContext(ModalContext);
1029
1164
  return /* @__PURE__ */ jsxRuntime.jsx("p", { id: id ?? ctx?.descId, className: cn("m-0 text-[0.9rem] text-muted-foreground", className), ...props });
1030
1165
  }
1031
1166
  function ModalActions({ className, ...props }) {
1032
1167
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex gap-2.5 justify-end mt-6", className), ...props });
1033
1168
  }
1034
- var ToastContext = React17__namespace.createContext(null);
1169
+ var ToastContext = React18__namespace.createContext(null);
1035
1170
  function useToast() {
1036
- const ctx = React17__namespace.useContext(ToastContext);
1171
+ const ctx = React18__namespace.useContext(ToastContext);
1037
1172
  if (!ctx) throw new Error("useToast must be used within <ToastProvider>");
1038
1173
  return ctx;
1039
1174
  }
@@ -1054,13 +1189,13 @@ var toneBorder = {
1054
1189
  danger: "border-l-danger"
1055
1190
  };
1056
1191
  function ToastProvider({ children }) {
1057
- const [items, setItems] = React17__namespace.useState([]);
1058
- const idRef = React17__namespace.useRef(0);
1059
- const remove = React17__namespace.useCallback((id) => {
1192
+ const [items, setItems] = React18__namespace.useState([]);
1193
+ const idRef = React18__namespace.useRef(0);
1194
+ const remove = React18__namespace.useCallback((id) => {
1060
1195
  setItems((prev) => prev.map((t) => t.id === id ? { ...t, leaving: true } : t));
1061
1196
  setTimeout(() => setItems((prev) => prev.filter((t) => t.id !== id)), 250);
1062
1197
  }, []);
1063
- const toast = React17__namespace.useCallback(
1198
+ const toast = React18__namespace.useCallback(
1064
1199
  ({ message, tone = "default", duration = 3200 }) => {
1065
1200
  const id = ++idRef.current;
1066
1201
  setItems((prev) => [...prev, { id, message, tone, duration }]);
@@ -1090,7 +1225,7 @@ function ToastProvider({ children }) {
1090
1225
  )) })
1091
1226
  ] });
1092
1227
  }
1093
- var PageHeader = React17__namespace.forwardRef(
1228
+ var PageHeader = React18__namespace.forwardRef(
1094
1229
  ({ 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
1230
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 max-w-2xl", children: [
1096
1231
  eyebrow && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-mono text-xs font-bold uppercase tracking-[0.2em] text-primary", children: eyebrow }),
@@ -1101,7 +1236,7 @@ var PageHeader = React17__namespace.forwardRef(
1101
1236
  ] }) })
1102
1237
  );
1103
1238
  PageHeader.displayName = "PageHeader";
1104
- var EmptyState = React17__namespace.forwardRef(
1239
+ var EmptyState = React18__namespace.forwardRef(
1105
1240
  ({ className, icon, title, description, action, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
1106
1241
  "div",
1107
1242
  {
@@ -1121,7 +1256,7 @@ var EmptyState = React17__namespace.forwardRef(
1121
1256
  )
1122
1257
  );
1123
1258
  EmptyState.displayName = "EmptyState";
1124
- var MetricCard = React17__namespace.forwardRef(
1259
+ var MetricCard = React18__namespace.forwardRef(
1125
1260
  ({ className, title, value, trend, trendDirection = "neutral", description, icon, ...props }, ref) => {
1126
1261
  const trendColor = {
1127
1262
  up: "text-success bg-success-surface border-success/20",
@@ -1151,54 +1286,171 @@ function DataTable({
1151
1286
  emptyTitle = "No data available",
1152
1287
  emptyDescription = "There are no records to display at this time.",
1153
1288
  emptyAction,
1289
+ getRowKey,
1290
+ onRowClick,
1291
+ toolbar,
1292
+ pagination,
1293
+ selectedRows,
1294
+ onSelectionChange,
1295
+ sortBy,
1296
+ sortDirection,
1297
+ onSort,
1154
1298
  ...props
1155
1299
  }) {
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)) })
1300
+ const getRowId = React18__namespace.useCallback(
1301
+ (row, index) => getRowKey ? getRowKey(row, index) : index,
1302
+ [getRowKey]
1303
+ );
1304
+ const isSelectionActive = selectedRows !== void 0 && onSelectionChange !== void 0;
1305
+ const allSelected = React18__namespace.useMemo(() => {
1306
+ if (!isSelectionActive || data.length === 0) return false;
1307
+ return data.every((row, idx) => selectedRows.has(getRowId(row, idx)));
1308
+ }, [isSelectionActive, data, selectedRows, getRowId]);
1309
+ const someSelected = React18__namespace.useMemo(() => {
1310
+ if (!isSelectionActive || data.length === 0) return false;
1311
+ const selectedCount = data.filter((row, idx) => selectedRows.has(getRowId(row, idx))).length;
1312
+ return selectedCount > 0 && selectedCount < data.length;
1313
+ }, [isSelectionActive, data, selectedRows, getRowId]);
1314
+ const headerCheckboxRef = React18__namespace.useRef(null);
1315
+ React18__namespace.useEffect(() => {
1316
+ if (headerCheckboxRef.current) {
1317
+ headerCheckboxRef.current.indeterminate = someSelected;
1318
+ }
1319
+ }, [someSelected]);
1320
+ const handleSelectAll = (e) => {
1321
+ if (!onSelectionChange) return;
1322
+ const checked = e.target.checked;
1323
+ const next = new Set(selectedRows);
1324
+ data.forEach((row, idx) => {
1325
+ const id = getRowId(row, idx);
1326
+ if (checked) {
1327
+ next.add(id);
1328
+ } else {
1329
+ next.delete(id);
1330
+ }
1331
+ });
1332
+ onSelectionChange(next);
1333
+ };
1334
+ const handleSelectRow = (row, idx, checked) => {
1335
+ if (!onSelectionChange || !selectedRows) return;
1336
+ const id = getRowId(row, idx);
1337
+ const next = new Set(selectedRows);
1338
+ if (checked) {
1339
+ next.add(id);
1340
+ } else {
1341
+ next.delete(id);
1342
+ }
1343
+ onSelectionChange(next);
1344
+ };
1345
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-4 w-full", className), children: [
1346
+ toolbar && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-3", children: toolbar }),
1347
+ /* @__PURE__ */ jsxRuntime.jsxs(TableWrap, { className: "relative overflow-hidden", ...props, children: [
1348
+ /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
1349
+ /* @__PURE__ */ jsxRuntime.jsx(TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { children: [
1350
+ 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(
1351
+ "input",
1352
+ {
1353
+ type: "checkbox",
1354
+ ref: headerCheckboxRef,
1355
+ checked: allSelected,
1356
+ onChange: handleSelectAll,
1357
+ "aria-label": "Select all rows",
1358
+ className: "h-4 w-4 rounded border-input text-primary focus:ring-ring"
1359
+ }
1360
+ ) }) }),
1361
+ columns.map((col, idx) => {
1362
+ const alignClass = {
1363
+ left: "text-left",
1364
+ center: "text-center",
1365
+ right: "text-right"
1366
+ }[col.align || "left"];
1367
+ const isSortable = col.sortable && onSort && col.sortKey;
1368
+ const isSortedActive = sortBy && col.sortKey === sortBy;
1369
+ return /* @__PURE__ */ jsxRuntime.jsx(
1370
+ TableHead,
1371
+ {
1372
+ className: cn(
1373
+ alignClass,
1374
+ isSortable && "cursor-pointer select-none hover:bg-muted/30 transition-colors",
1375
+ col.className
1376
+ ),
1377
+ onClick: () => {
1378
+ if (!isSortable || !col.sortKey) return;
1379
+ const nextDirection = isSortedActive && sortDirection === "asc" ? "desc" : "asc";
1380
+ onSort(col.sortKey, nextDirection);
1381
+ },
1382
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("inline-flex items-center gap-1.5", alignClass === "text-right" && "justify-end w-full"), children: [
1383
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: col.header }),
1384
+ isSortable && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground shrink-0 select-none", children: isSortedActive ? sortDirection === "asc" ? "\u25B2" : "\u25BC" : "\u21C5" })
1385
+ ] })
1386
+ },
1387
+ idx
1388
+ );
1389
+ })
1390
+ ] }) }),
1391
+ /* @__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: [
1392
+ /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 32 }),
1393
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Loading dataset..." })
1394
+ ] }) }) }) : 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(
1395
+ EmptyState,
1396
+ {
1397
+ title: emptyTitle,
1398
+ description: emptyDescription,
1399
+ action: emptyAction,
1400
+ className: "border-none bg-transparent rounded-none py-16"
1401
+ }
1402
+ ) }) }) : data.map((row, rowIdx) => {
1403
+ const rowKey = getRowId(row, rowIdx);
1404
+ const isSelected = isSelectionActive && selectedRows.has(rowKey);
1405
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1406
+ TableRow,
1407
+ {
1408
+ onClick: () => onRowClick && onRowClick(row),
1409
+ className: cn(
1410
+ onRowClick && "cursor-pointer hover:bg-muted/40 transition-colors",
1411
+ isSelected && "bg-primary/5 hover:bg-primary/10"
1412
+ ),
1413
+ children: [
1414
+ isSelectionActive && /* @__PURE__ */ jsxRuntime.jsx(
1415
+ TableCell,
1416
+ {
1417
+ className: "w-12 px-4 text-center",
1418
+ onClick: (e) => {
1419
+ e.stopPropagation();
1420
+ },
1421
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
1422
+ "input",
1423
+ {
1424
+ type: "checkbox",
1425
+ checked: isSelected,
1426
+ onChange: (e) => handleSelectRow(row, rowIdx, e.target.checked),
1427
+ "aria-label": `Select row ${rowIdx + 1}`,
1428
+ className: "h-4 w-4 rounded border-input text-primary focus:ring-ring"
1429
+ }
1430
+ ) })
1431
+ }
1432
+ ),
1433
+ columns.map((col, colIdx) => {
1434
+ const alignClass = {
1435
+ left: "text-left",
1436
+ center: "text-center",
1437
+ right: "text-right"
1438
+ }[col.align || "left"];
1439
+ return /* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: cn(alignClass, col.className), children: col.accessor(row) }, colIdx);
1440
+ })
1441
+ ]
1442
+ },
1443
+ rowKey
1444
+ );
1445
+ }) })
1446
+ ] }),
1447
+ 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
1448
  ] }),
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 }) })
1449
+ pagination && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-end w-full", children: pagination })
1173
1450
  ] });
1174
1451
  }
1175
1452
  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(
1453
+ var ErrorState = React18__namespace.forwardRef(
1202
1454
  ({ className, title = "Wyst\u0105pi\u0142 b\u0142\u0105d", message, onRetry, retryLabel = "Spr\xF3buj ponownie", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
1203
1455
  "div",
1204
1456
  {
@@ -1218,7 +1470,7 @@ var ErrorState = React17__namespace.forwardRef(
1218
1470
  )
1219
1471
  );
1220
1472
  ErrorState.displayName = "ErrorState";
1221
- var Skeleton = React17__namespace.forwardRef(
1473
+ var Skeleton = React18__namespace.forwardRef(
1222
1474
  ({ className, variant = "rectangular", width, height, style, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1223
1475
  "div",
1224
1476
  {
@@ -1240,27 +1492,549 @@ var Skeleton = React17__namespace.forwardRef(
1240
1492
  )
1241
1493
  );
1242
1494
  Skeleton.displayName = "Skeleton";
1243
- var DashboardShell = React17__namespace.forwardRef(
1244
- ({ className, sidebar, topbar, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
1495
+ var DashboardShell = React18__namespace.forwardRef(
1496
+ ({
1497
+ className,
1498
+ sidebar,
1499
+ topbar,
1500
+ children,
1501
+ sidebarWidth = "md:w-64",
1502
+ contentWidth = "default",
1503
+ stickyTopbar = true,
1504
+ mobileSidebar,
1505
+ ...props
1506
+ }, ref) => {
1507
+ const [mobileOpen, setMobileOpen] = React18__namespace.useState(false);
1508
+ const contentWidthClass = {
1509
+ default: "max-w-7xl w-full mx-auto",
1510
+ wide: "max-w-screen-2xl w-full mx-auto",
1511
+ full: "max-w-none w-full"
1512
+ }[contentWidth];
1513
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1514
+ "div",
1515
+ {
1516
+ ref,
1517
+ className: cn(
1518
+ "min-h-screen bg-canvas text-foreground flex flex-col md:flex-row",
1519
+ className
1520
+ ),
1521
+ ...props,
1522
+ children: [
1523
+ sidebar && /* @__PURE__ */ jsxRuntime.jsx(
1524
+ "aside",
1525
+ {
1526
+ className: cn(
1527
+ "border-r border-border bg-surface shrink-0 z-20",
1528
+ mobileSidebar ? "hidden md:flex" : "w-full md:flex",
1529
+ sidebarWidth
1530
+ ),
1531
+ 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 })
1532
+ }
1533
+ ),
1534
+ mobileSidebar && mobileOpen && /* @__PURE__ */ jsxRuntime.jsx(
1535
+ "div",
1536
+ {
1537
+ onClick: () => setMobileOpen(false),
1538
+ className: "fixed inset-0 z-50 md:hidden bg-[color-mix(in_oklch,#09090b_45%,transparent)] backdrop-blur-[2px] transition-opacity duration-300",
1539
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1540
+ "aside",
1541
+ {
1542
+ onClick: (e) => e.stopPropagation(),
1543
+ className: "w-72 h-full bg-surface border-r border-border flex flex-col shadow-kj-lg",
1544
+ children: [
1545
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-4 border-b border-border", children: [
1546
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-bold uppercase tracking-wider text-muted-foreground", children: "Navigation" }),
1547
+ /* @__PURE__ */ jsxRuntime.jsx(
1548
+ "button",
1549
+ {
1550
+ type: "button",
1551
+ onClick: () => setMobileOpen(false),
1552
+ className: "p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted transition-colors cursor-pointer",
1553
+ 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" }) })
1554
+ }
1555
+ )
1556
+ ] }),
1557
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto", children: mobileSidebar })
1558
+ ]
1559
+ }
1560
+ )
1561
+ }
1562
+ ),
1563
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col min-w-0", children: [
1564
+ topbar && /* @__PURE__ */ jsxRuntime.jsxs(
1565
+ "header",
1566
+ {
1567
+ className: cn(
1568
+ "h-14 border-b border-border bg-surface flex items-center px-6 z-10 shrink-0 gap-4",
1569
+ stickyTopbar && "sticky top-0"
1570
+ ),
1571
+ children: [
1572
+ mobileSidebar && /* @__PURE__ */ jsxRuntime.jsx(
1573
+ "button",
1574
+ {
1575
+ type: "button",
1576
+ onClick: () => setMobileOpen(true),
1577
+ 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",
1578
+ "aria-label": "Open navigation",
1579
+ 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: [
1580
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "12", x2: "21", y2: "12" }),
1581
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "6", x2: "21", y2: "6" }),
1582
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "18", x2: "21", y2: "18" })
1583
+ ] })
1584
+ }
1585
+ ),
1586
+ topbar
1587
+ ]
1588
+ }
1589
+ ),
1590
+ /* @__PURE__ */ jsxRuntime.jsx("main", { className: cn("flex-1 p-6 md:p-8", contentWidthClass), children })
1591
+ ] })
1592
+ ]
1593
+ }
1594
+ );
1595
+ }
1596
+ );
1597
+ DashboardShell.displayName = "DashboardShell";
1598
+ var SettingsLayout = React18__namespace.forwardRef(
1599
+ ({ className, sidebar, children, title, description, ...props }, ref) => {
1600
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("space-y-6 w-full", className), ...props, children: [
1601
+ (title || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-border pb-4", children: [
1602
+ title && /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold tracking-tight text-foreground", children: title }),
1603
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mt-1", children: description })
1604
+ ] }),
1605
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col lg:flex-row gap-8", children: [
1606
+ /* @__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 }) }),
1607
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 max-w-3xl", children })
1608
+ ] })
1609
+ ] });
1610
+ }
1611
+ );
1612
+ SettingsLayout.displayName = "SettingsLayout";
1613
+ var DetailPageLayout = React18__namespace.forwardRef(
1614
+ ({ className, title, description, backHref, backLabel = "Back", onBackClick, actions, aside, children, ...props }, ref) => {
1615
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("space-y-6 w-full", className), ...props, children: [
1616
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
1617
+ (backHref || onBackClick) && /* @__PURE__ */ jsxRuntime.jsx("div", { children: backHref ? /* @__PURE__ */ jsxRuntime.jsxs(
1618
+ "a",
1619
+ {
1620
+ href: backHref,
1621
+ className: cn(
1622
+ buttonVariants({ variant: "ghost", size: "sm" }),
1623
+ "-ml-3 h-8 text-muted-foreground hover:text-foreground inline-flex items-center gap-1.5"
1624
+ ),
1625
+ children: [
1626
+ /* @__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" }) }),
1627
+ backLabel
1628
+ ]
1629
+ }
1630
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
1631
+ Button,
1632
+ {
1633
+ variant: "ghost",
1634
+ size: "sm",
1635
+ className: "-ml-3 h-8 text-muted-foreground hover:text-foreground",
1636
+ onClick: onBackClick,
1637
+ children: [
1638
+ /* @__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" }) }),
1639
+ backLabel
1640
+ ]
1641
+ }
1642
+ ) }),
1643
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col md:flex-row md:items-center md:justify-between gap-4", children: [
1644
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
1645
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold tracking-tight text-foreground", children: title }),
1646
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: description })
1647
+ ] }),
1648
+ actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 shrink-0", children: actions })
1649
+ ] })
1650
+ ] }),
1651
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-3 gap-8 items-start", children: [
1652
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-6", aside ? "lg:col-span-2" : "lg:col-span-3"), children }),
1653
+ 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 })
1654
+ ] })
1655
+ ] });
1656
+ }
1657
+ );
1658
+ DetailPageLayout.displayName = "DetailPageLayout";
1659
+ var TableToolbar = React18__namespace.forwardRef(
1660
+ ({ className, searchQuery, onSearchChange, searchPlaceholder = "Search...", actions, filters, ...props }, ref) => {
1661
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1662
+ "div",
1663
+ {
1664
+ ref,
1665
+ className: cn(
1666
+ "flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-3 w-full pb-1",
1667
+ className
1668
+ ),
1669
+ ...props,
1670
+ children: [
1671
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col sm:flex-row items-stretch sm:items-center gap-2 max-w-xl", children: [
1672
+ onSearchChange && /* @__PURE__ */ jsxRuntime.jsx(
1673
+ Input,
1674
+ {
1675
+ type: "search",
1676
+ placeholder: searchPlaceholder,
1677
+ value: searchQuery,
1678
+ onChange: (e) => onSearchChange(e.target.value),
1679
+ className: "sm:w-64",
1680
+ 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" }) })
1681
+ }
1682
+ ),
1683
+ filters && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: filters })
1684
+ ] }),
1685
+ actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 shrink-0 justify-end", children: actions })
1686
+ ]
1687
+ }
1688
+ );
1689
+ }
1690
+ );
1691
+ TableToolbar.displayName = "TableToolbar";
1692
+ function ConfirmDialog({
1693
+ open,
1694
+ onClose,
1695
+ onConfirm,
1696
+ title,
1697
+ description,
1698
+ confirmLabel = "Confirm",
1699
+ cancelLabel = "Cancel",
1700
+ tone = "primary",
1701
+ loading = false
1702
+ }) {
1703
+ const toneButtonVariant = {
1704
+ danger: "danger",
1705
+ primary: "primary",
1706
+ success: "secondary"
1707
+ // standard secondary in our system is teal (success-aligned)
1708
+ }[tone];
1709
+ return /* @__PURE__ */ jsxRuntime.jsxs(Modal, { open, onClose, width: 400, showClose: !loading, children: [
1710
+ /* @__PURE__ */ jsxRuntime.jsx(ModalTitle, { children: title }),
1711
+ /* @__PURE__ */ jsxRuntime.jsx(ModalDescription, { children: description }),
1712
+ /* @__PURE__ */ jsxRuntime.jsxs(ModalActions, { children: [
1713
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", onClick: onClose, disabled: loading, children: cancelLabel }),
1714
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: toneButtonVariant, onClick: onConfirm, loading, children: confirmLabel })
1715
+ ] })
1716
+ ] });
1717
+ }
1718
+ ConfirmDialog.displayName = "ConfirmDialog";
1719
+ function Drawer({
1720
+ open,
1721
+ onClose,
1722
+ children,
1723
+ title,
1724
+ description,
1725
+ width = "max-w-md",
1726
+ side = "right"
1727
+ }) {
1728
+ const containerRef = React18__namespace.useRef(null);
1729
+ const lastActiveElement = React18__namespace.useRef(null);
1730
+ React18__namespace.useEffect(() => {
1731
+ if (!open) {
1732
+ if (lastActiveElement.current) {
1733
+ lastActiveElement.current.focus();
1734
+ lastActiveElement.current = null;
1735
+ }
1736
+ return;
1737
+ }
1738
+ lastActiveElement.current = document.activeElement;
1739
+ const container = containerRef.current;
1740
+ if (container) {
1741
+ const focusables = container.querySelectorAll(
1742
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1743
+ );
1744
+ if (focusables.length > 0) {
1745
+ setTimeout(() => focusables[0].focus(), 50);
1746
+ } else {
1747
+ container.focus();
1748
+ }
1749
+ }
1750
+ const handleKeyDown = (e) => {
1751
+ if (e.key === "Escape") {
1752
+ onClose();
1753
+ return;
1754
+ }
1755
+ if (e.key === "Tab") {
1756
+ const container2 = containerRef.current;
1757
+ if (!container2) return;
1758
+ const focusables = Array.from(
1759
+ container2.querySelectorAll(
1760
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1761
+ )
1762
+ );
1763
+ if (focusables.length === 0) {
1764
+ e.preventDefault();
1765
+ return;
1766
+ }
1767
+ const first = focusables[0];
1768
+ const last = focusables[focusables.length - 1];
1769
+ if (e.shiftKey) {
1770
+ if (document.activeElement === first || document.activeElement === container2) {
1771
+ last.focus();
1772
+ e.preventDefault();
1773
+ }
1774
+ } else {
1775
+ if (document.activeElement === last) {
1776
+ first.focus();
1777
+ e.preventDefault();
1778
+ }
1779
+ }
1780
+ }
1781
+ };
1782
+ document.addEventListener("keydown", handleKeyDown);
1783
+ document.body.style.overflow = "hidden";
1784
+ return () => {
1785
+ document.removeEventListener("keydown", handleKeyDown);
1786
+ document.body.style.overflow = "";
1787
+ };
1788
+ }, [open, onClose]);
1789
+ const sideClasses = {
1790
+ right: cn(
1791
+ "right-0 h-full border-l",
1792
+ open ? "translate-x-0" : "translate-x-full"
1793
+ ),
1794
+ left: cn(
1795
+ "left-0 h-full border-r",
1796
+ open ? "translate-x-0" : "-translate-x-full"
1797
+ )
1798
+ }[side];
1799
+ return /* @__PURE__ */ jsxRuntime.jsx(
1245
1800
  "div",
1246
1801
  {
1247
- ref,
1802
+ onClick: (e) => e.target === e.currentTarget && onClose(),
1248
1803
  className: cn(
1249
- "min-h-screen bg-canvas text-foreground flex flex-col md:flex-row",
1250
- className
1804
+ "fixed inset-0 z-[100] transition-opacity duration-300 backdrop-blur-[2px]",
1805
+ "bg-[color-mix(in_oklch,#09090b_45%,transparent)]",
1806
+ open ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"
1251
1807
  ),
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
- ]
1808
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1809
+ "div",
1810
+ {
1811
+ ref: containerRef,
1812
+ role: "dialog",
1813
+ "aria-modal": "true",
1814
+ "aria-label": !title ? "Drawer" : void 0,
1815
+ "aria-labelledby": title ? "drawer-title" : void 0,
1816
+ "aria-describedby": description ? "drawer-description" : void 0,
1817
+ tabIndex: -1,
1818
+ className: cn(
1819
+ "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",
1820
+ width,
1821
+ sideClasses
1822
+ ),
1823
+ children: [
1824
+ (title || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-6 border-b border-border", children: [
1825
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
1826
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { id: "drawer-title", className: "text-lg font-bold tracking-tight text-foreground", children: title }),
1827
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { id: "drawer-description", className: "text-xs text-muted-foreground", children: description })
1828
+ ] }),
1829
+ /* @__PURE__ */ jsxRuntime.jsx(
1830
+ "button",
1831
+ {
1832
+ type: "button",
1833
+ onClick: onClose,
1834
+ "aria-label": "Close",
1835
+ className: "p-1.5 rounded-kj-sm text-muted-foreground hover:text-foreground hover:bg-muted transition-colors cursor-pointer",
1836
+ 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" }) })
1837
+ }
1838
+ )
1839
+ ] }),
1840
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto p-6", children })
1841
+ ]
1842
+ }
1843
+ )
1260
1844
  }
1261
- )
1262
- );
1263
- DashboardShell.displayName = "DashboardShell";
1845
+ );
1846
+ }
1847
+ Drawer.displayName = "Drawer";
1848
+ function CommandPalette({ open, onClose, items, placeholder = "Type a command or search..." }) {
1849
+ const [search, setSearch] = React18__namespace.useState("");
1850
+ const [activeIndex, setActiveIndex] = React18__namespace.useState(0);
1851
+ const containerRef = React18__namespace.useRef(null);
1852
+ const listRef = React18__namespace.useRef(null);
1853
+ React18__namespace.useEffect(() => {
1854
+ if (open) {
1855
+ setSearch("");
1856
+ setActiveIndex(0);
1857
+ document.body.style.overflow = "hidden";
1858
+ } else {
1859
+ document.body.style.overflow = "";
1860
+ }
1861
+ }, [open]);
1862
+ const filteredItems = React18__namespace.useMemo(() => {
1863
+ if (!search) return items;
1864
+ const cleanSearch = search.toLowerCase();
1865
+ return items.filter(
1866
+ (item) => item.title.toLowerCase().includes(cleanSearch) || item.subtitle?.toLowerCase().includes(cleanSearch) || item.category?.toLowerCase().includes(cleanSearch)
1867
+ );
1868
+ }, [search, items]);
1869
+ React18__namespace.useEffect(() => {
1870
+ setActiveIndex(0);
1871
+ }, [filteredItems]);
1872
+ React18__namespace.useEffect(() => {
1873
+ if (!open) return;
1874
+ const handleKeyDown = (e) => {
1875
+ if (e.key === "Escape") {
1876
+ onClose();
1877
+ return;
1878
+ }
1879
+ if (e.key === "ArrowDown") {
1880
+ e.preventDefault();
1881
+ setActiveIndex((prev) => filteredItems.length === 0 ? 0 : (prev + 1) % filteredItems.length);
1882
+ } else if (e.key === "ArrowUp") {
1883
+ e.preventDefault();
1884
+ setActiveIndex((prev) => filteredItems.length === 0 ? 0 : (prev - 1 + filteredItems.length) % filteredItems.length);
1885
+ } else if (e.key === "Enter") {
1886
+ e.preventDefault();
1887
+ if (filteredItems[activeIndex]) {
1888
+ filteredItems[activeIndex].action();
1889
+ onClose();
1890
+ }
1891
+ }
1892
+ };
1893
+ document.addEventListener("keydown", handleKeyDown);
1894
+ return () => document.removeEventListener("keydown", handleKeyDown);
1895
+ }, [open, filteredItems, activeIndex, onClose]);
1896
+ React18__namespace.useEffect(() => {
1897
+ if (listRef.current) {
1898
+ const activeEl = listRef.current.children[activeIndex];
1899
+ if (activeEl) {
1900
+ activeEl.scrollIntoView({ block: "nearest" });
1901
+ }
1902
+ }
1903
+ }, [activeIndex]);
1904
+ if (!open) return null;
1905
+ const groups = {};
1906
+ filteredItems.forEach((item) => {
1907
+ const cat = item.category || "General";
1908
+ if (!groups[cat]) groups[cat] = [];
1909
+ groups[cat].push(item);
1910
+ });
1911
+ let absoluteItemIndex = 0;
1912
+ return /* @__PURE__ */ jsxRuntime.jsx(
1913
+ "div",
1914
+ {
1915
+ onClick: (e) => e.target === e.currentTarget && onClose(),
1916
+ 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)]",
1917
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1918
+ "div",
1919
+ {
1920
+ ref: containerRef,
1921
+ 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]",
1922
+ children: [
1923
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 border-b border-border flex items-center gap-2", children: [
1924
+ /* @__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" }) }),
1925
+ /* @__PURE__ */ jsxRuntime.jsx(
1926
+ "input",
1927
+ {
1928
+ type: "text",
1929
+ placeholder,
1930
+ value: search,
1931
+ onChange: (e) => setSearch(e.target.value),
1932
+ className: "flex-1 font-sans text-[0.95rem] bg-transparent text-foreground placeholder:text-muted-foreground outline-none border-none focus:ring-0",
1933
+ autoFocus: true
1934
+ }
1935
+ )
1936
+ ] }),
1937
+ /* @__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: [
1938
+ 'No results found for "',
1939
+ search,
1940
+ '"'
1941
+ ] }) : /* @__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: [
1942
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-1 text-[0.65rem] font-bold uppercase tracking-wider text-muted-foreground", children: cat }),
1943
+ itemsInCat.map((item) => {
1944
+ const currentIdx = absoluteItemIndex++;
1945
+ const isActive = currentIdx === activeIndex;
1946
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1947
+ "div",
1948
+ {
1949
+ onClick: () => {
1950
+ item.action();
1951
+ onClose();
1952
+ },
1953
+ className: cn(
1954
+ "flex items-center justify-between gap-3 px-3 py-2.5 rounded-kj-md cursor-pointer select-none transition-colors",
1955
+ isActive ? "bg-primary/10 text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
1956
+ ),
1957
+ children: [
1958
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
1959
+ item.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground [&_svg]:h-[1.1rem] [&_svg]:w-[1.1rem]", children: item.icon }),
1960
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex flex-col", children: [
1961
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[0.85rem] font-semibold", isActive ? "text-primary" : "text-foreground"), children: item.title }),
1962
+ item.subtitle && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.75rem] text-muted-foreground truncate", children: item.subtitle })
1963
+ ] })
1964
+ ] }),
1965
+ item.shortcut && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: item.shortcut.map((sc, scIdx) => /* @__PURE__ */ jsxRuntime.jsx(
1966
+ "kbd",
1967
+ {
1968
+ 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",
1969
+ children: sc
1970
+ },
1971
+ scIdx
1972
+ )) })
1973
+ ]
1974
+ },
1975
+ item.id
1976
+ );
1977
+ })
1978
+ ] }, cat)) }) }),
1979
+ /* @__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: [
1980
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1981
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
1982
+ /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "font-mono text-[9px] px-1 border rounded bg-surface", children: "\u2191\u2193" }),
1983
+ " Navigate"
1984
+ ] }),
1985
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
1986
+ /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "font-mono text-[9px] px-1 border rounded bg-surface", children: "Enter" }),
1987
+ " Select"
1988
+ ] })
1989
+ ] }),
1990
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1991
+ /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "font-mono text-[9px] px-1 border rounded bg-surface", children: "Esc" }),
1992
+ " Close"
1993
+ ] })
1994
+ ] })
1995
+ ]
1996
+ }
1997
+ )
1998
+ }
1999
+ );
2000
+ }
2001
+ CommandPalette.displayName = "CommandPalette";
2002
+ function SidebarNav({ className, groups, currentHref, ...props }) {
2003
+ 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: [
2004
+ group.title && /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "px-3 text-[10px] font-bold uppercase tracking-widest text-muted-foreground/85", children: group.title }),
2005
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-0.5", children: group.items.map((item) => {
2006
+ const isActive = item.active || item.href && currentHref && currentHref === item.href;
2007
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2008
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2.5 min-w-0", children: [
2009
+ item.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
2010
+ "[&_svg]:h-[1.1rem] [&_svg]:w-[1.1rem] shrink-0",
2011
+ isActive ? "text-primary" : "text-muted-foreground group-hover:text-foreground"
2012
+ ), children: item.icon }),
2013
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: item.label })
2014
+ ] }),
2015
+ item.badge && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 flex items-center justify-center", children: item.badge })
2016
+ ] });
2017
+ const itemClass = cn(
2018
+ "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",
2019
+ 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"
2020
+ );
2021
+ if (item.href) {
2022
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.href, className: itemClass, children: content }, item.id);
2023
+ }
2024
+ return /* @__PURE__ */ jsxRuntime.jsx(
2025
+ "button",
2026
+ {
2027
+ type: "button",
2028
+ onClick: item.onClick,
2029
+ className: itemClass,
2030
+ children: content
2031
+ },
2032
+ item.id
2033
+ );
2034
+ }) })
2035
+ ] }, groupIdx)) });
2036
+ }
2037
+ SidebarNav.displayName = "SidebarNav";
1264
2038
 
1265
2039
  exports.Accordion = Accordion;
1266
2040
  exports.AccordionContent = AccordionContent;
@@ -1270,6 +2044,7 @@ exports.Alert = Alert;
1270
2044
  exports.Avatar = Avatar;
1271
2045
  exports.AvatarGroup = AvatarGroup;
1272
2046
  exports.Badge = Badge;
2047
+ exports.BottomNavigation = BottomNavigation;
1273
2048
  exports.Breadcrumb = Breadcrumb;
1274
2049
  exports.BreadcrumbItem = BreadcrumbItem;
1275
2050
  exports.BreadcrumbSeparator = BreadcrumbSeparator;
@@ -1281,8 +2056,13 @@ exports.CardFooter = CardFooter;
1281
2056
  exports.CardHeader = CardHeader;
1282
2057
  exports.CardTitle = CardTitle;
1283
2058
  exports.Checkbox = Checkbox;
2059
+ exports.CheckboxField = CheckboxField;
2060
+ exports.CommandPalette = CommandPalette;
2061
+ exports.ConfirmDialog = ConfirmDialog;
1284
2062
  exports.DashboardShell = DashboardShell;
1285
2063
  exports.DataTable = DataTable;
2064
+ exports.DetailPageLayout = DetailPageLayout;
2065
+ exports.Drawer = Drawer;
1286
2066
  exports.DropdownMenu = DropdownMenu;
1287
2067
  exports.DropdownMenuContent = DropdownMenuContent;
1288
2068
  exports.DropdownMenuItem = DropdownMenuItem;
@@ -1306,6 +2086,9 @@ exports.Progress = Progress;
1306
2086
  exports.Radio = Radio;
1307
2087
  exports.Segmented = Segmented;
1308
2088
  exports.Select = Select;
2089
+ exports.SelectField = SelectField;
2090
+ exports.SettingsLayout = SettingsLayout;
2091
+ exports.SidebarNav = SidebarNav;
1309
2092
  exports.Skeleton = Skeleton;
1310
2093
  exports.Slider = Slider;
1311
2094
  exports.Spinner = Spinner;
@@ -1317,11 +2100,13 @@ exports.TableCell = TableCell;
1317
2100
  exports.TableHead = TableHead;
1318
2101
  exports.TableHeader = TableHeader;
1319
2102
  exports.TableRow = TableRow;
2103
+ exports.TableToolbar = TableToolbar;
1320
2104
  exports.TableWrap = TableWrap;
1321
2105
  exports.Tabs = Tabs;
1322
2106
  exports.TabsContent = TabsContent;
1323
2107
  exports.TabsList = TabsList;
1324
2108
  exports.TabsTrigger = TabsTrigger;
2109
+ exports.TextField = TextField;
1325
2110
  exports.Textarea = Textarea;
1326
2111
  exports.ToastProvider = ToastProvider;
1327
2112
  exports.Tooltip = Tooltip;