@tomny-dev/uzi 0.1.4 → 0.1.6

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,5 +1,8 @@
1
1
  "use client";
2
2
 
3
+ // src/components/button/Button.tsx
4
+ import { Slot } from "@radix-ui/react-slot";
5
+
3
6
  // src/utils/cx.ts
4
7
  function cx(...values) {
5
8
  return values.filter(Boolean).join(" ");
@@ -10,22 +13,49 @@ var button_default = {};
10
13
 
11
14
  // src/components/button/Button.tsx
12
15
  import { jsx } from "react/jsx-runtime";
16
+ var variantClass = {
17
+ default: button_default["variant-primary"],
18
+ primary: button_default["variant-primary"],
19
+ secondary: button_default["variant-secondary"],
20
+ outline: button_default["variant-outline"],
21
+ ghost: button_default["variant-ghost"],
22
+ destructive: button_default["variant-destructive"],
23
+ link: button_default["variant-link"]
24
+ };
25
+ var sizeClass = {
26
+ default: button_default["size-md"],
27
+ sm: button_default["size-sm"],
28
+ md: button_default["size-md"],
29
+ lg: button_default["size-lg"],
30
+ icon: button_default["size-icon"]
31
+ };
13
32
  function Button({
14
33
  as,
15
- variant = "primary",
16
- size = "md",
34
+ variant = "default",
35
+ size = "default",
17
36
  className,
18
37
  children,
38
+ asChild = false,
19
39
  ...rest
20
40
  }) {
21
41
  const classes = cx(
22
42
  button_default.button,
23
- button_default[`variant-${variant}`],
24
- button_default[`size-${size}`],
43
+ variantClass[variant],
44
+ sizeClass[size],
25
45
  className
26
46
  );
47
+ if (asChild) {
48
+ return /* @__PURE__ */ jsx(Slot, { className: classes, ...rest, children });
49
+ }
27
50
  if (as === "a") {
28
- return /* @__PURE__ */ jsx("a", { className: classes, ...rest, children });
51
+ return /* @__PURE__ */ jsx(
52
+ "a",
53
+ {
54
+ className: classes,
55
+ ...rest,
56
+ children
57
+ }
58
+ );
29
59
  }
30
60
  return /* @__PURE__ */ jsx(
31
61
  "button",
@@ -38,11 +68,57 @@ function Button({
38
68
  );
39
69
  }
40
70
 
71
+ // src/components/avatar/Avatar.tsx
72
+ import * as AvatarPrimitive from "@radix-ui/react-avatar";
73
+
74
+ // src/components/avatar/avatar.module.css
75
+ var avatar_default = {};
76
+
77
+ // src/components/avatar/Avatar.tsx
78
+ import { jsx as jsx2 } from "react/jsx-runtime";
79
+ function Avatar({
80
+ className,
81
+ size = "md",
82
+ ...props
83
+ }) {
84
+ return /* @__PURE__ */ jsx2(
85
+ AvatarPrimitive.Root,
86
+ {
87
+ className: cx(avatar_default.avatar, avatar_default[`size-${size}`], className),
88
+ ...props
89
+ }
90
+ );
91
+ }
92
+ function AvatarImage({
93
+ className,
94
+ ...props
95
+ }) {
96
+ return /* @__PURE__ */ jsx2(
97
+ AvatarPrimitive.Image,
98
+ {
99
+ className: cx(avatar_default.image, className),
100
+ ...props
101
+ }
102
+ );
103
+ }
104
+ function AvatarFallback({
105
+ className,
106
+ ...props
107
+ }) {
108
+ return /* @__PURE__ */ jsx2(
109
+ AvatarPrimitive.Fallback,
110
+ {
111
+ className: cx(avatar_default.fallback, className),
112
+ ...props
113
+ }
114
+ );
115
+ }
116
+
41
117
  // src/components/card/card.module.css
42
118
  var card_default = {};
43
119
 
44
120
  // src/components/card/Card.tsx
45
- import { jsx as jsx2 } from "react/jsx-runtime";
121
+ import { jsx as jsx3 } from "react/jsx-runtime";
46
122
  function Card({
47
123
  as,
48
124
  tone = "default",
@@ -61,14 +137,14 @@ function Card({
61
137
  interactive && card_default.interactive,
62
138
  className
63
139
  );
64
- return /* @__PURE__ */ jsx2(Component, { className: classes, ...rest, children });
140
+ return /* @__PURE__ */ jsx3(Component, { className: classes, ...rest, children });
65
141
  }
66
142
 
67
143
  // src/components/pill/pill.module.css
68
144
  var pill_default = {};
69
145
 
70
146
  // src/components/pill/Pill.tsx
71
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
147
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
72
148
  function Pill({
73
149
  as,
74
150
  tone = "neutral",
@@ -81,26 +157,39 @@ function Pill({
81
157
  const Component = as ?? "span";
82
158
  const classes = cx(pill_default.pill, pill_default[`tone-${tone}`], pill_default[`size-${size}`], className);
83
159
  return /* @__PURE__ */ jsxs(Component, { className: classes, ...rest, children: [
84
- icon ? /* @__PURE__ */ jsx3("span", { className: pill_default.icon, "aria-hidden": "true", children: icon }) : null,
85
- /* @__PURE__ */ jsx3("span", { className: pill_default.content, children })
160
+ icon ? /* @__PURE__ */ jsx4("span", { className: pill_default.icon, "aria-hidden": "true", children: icon }) : null,
161
+ /* @__PURE__ */ jsx4("span", { className: pill_default.content, children })
86
162
  ] });
87
163
  }
88
164
 
89
165
  // src/components/modal/Modal.tsx
90
- import { useRef } from "react";
166
+ import { useRef, useEffect } from "react";
91
167
 
92
168
  // src/components/modal/modal.module.css
93
169
  var modal_default = {};
94
170
 
95
171
  // src/components/modal/Modal.tsx
96
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
97
- function Modal({ open, onClose, title, subtitle, size = "md", children, footer }) {
172
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
173
+ function ModalOverlay({ open, onClose, className, children }) {
98
174
  const mouseDownOnBackdrop = useRef(false);
175
+ useEffect(() => {
176
+ if (!open) return;
177
+ const handleKeyDown = (e) => {
178
+ if (e.key === "Escape") {
179
+ e.stopPropagation();
180
+ onClose();
181
+ }
182
+ };
183
+ window.addEventListener("keydown", handleKeyDown, true);
184
+ return () => window.removeEventListener("keydown", handleKeyDown, true);
185
+ }, [open, onClose]);
99
186
  if (!open) return null;
100
- return /* @__PURE__ */ jsx4(
187
+ return /* @__PURE__ */ jsx5(
101
188
  "div",
102
189
  {
103
- className: modal_default.backdrop,
190
+ className: cx(modal_default.backdrop, className),
191
+ role: "dialog",
192
+ "aria-modal": "true",
104
193
  onMouseDown: (e) => {
105
194
  mouseDownOnBackdrop.current = e.target === e.currentTarget;
106
195
  },
@@ -108,30 +197,42 @@ function Modal({ open, onClose, title, subtitle, size = "md", children, footer }
108
197
  if (mouseDownOnBackdrop.current && e.target === e.currentTarget) onClose();
109
198
  mouseDownOnBackdrop.current = false;
110
199
  },
111
- children: /* @__PURE__ */ jsxs2("div", { className: cx(modal_default.modal, modal_default[`size-${size}`]), children: [
112
- /* @__PURE__ */ jsxs2("div", { className: modal_default.header, children: [
113
- /* @__PURE__ */ jsxs2("div", { className: modal_default.titles, children: [
114
- /* @__PURE__ */ jsx4("div", { className: modal_default.title, children: title }),
115
- subtitle && /* @__PURE__ */ jsx4("div", { className: modal_default.subtitle, children: subtitle })
116
- ] }),
117
- /* @__PURE__ */ jsx4("button", { className: modal_default.closeButton, onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxs2("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
118
- /* @__PURE__ */ jsx4("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
119
- /* @__PURE__ */ jsx4("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
120
- ] }) })
121
- ] }),
122
- /* @__PURE__ */ jsx4("div", { className: modal_default.body, children }),
123
- footer && /* @__PURE__ */ jsx4("div", { className: modal_default.footer, children: footer })
124
- ] })
200
+ children
125
201
  }
126
202
  );
127
203
  }
204
+ function Modal({ open, onClose, title, subtitle, size = "md", children, footer }) {
205
+ return /* @__PURE__ */ jsx5(ModalOverlay, { open, onClose, children: /* @__PURE__ */ jsxs2("div", { className: cx(modal_default.modal, modal_default[`size-${size}`]), children: [
206
+ /* @__PURE__ */ jsxs2("div", { className: modal_default.header, children: [
207
+ /* @__PURE__ */ jsxs2("div", { className: modal_default.titles, children: [
208
+ /* @__PURE__ */ jsx5("div", { className: modal_default.title, children: title }),
209
+ subtitle && /* @__PURE__ */ jsx5("div", { className: modal_default.subtitle, children: subtitle })
210
+ ] }),
211
+ /* @__PURE__ */ jsx5("button", { className: modal_default.closeButton, onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxs2("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
212
+ /* @__PURE__ */ jsx5("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
213
+ /* @__PURE__ */ jsx5("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
214
+ ] }) })
215
+ ] }),
216
+ /* @__PURE__ */ jsx5("div", { className: modal_default.body, children }),
217
+ footer && /* @__PURE__ */ jsx5("div", { className: modal_default.footer, children: footer })
218
+ ] }) });
219
+ }
220
+
221
+ // src/components/alert/alert.module.css
222
+ var alert_default = {};
223
+
224
+ // src/components/alert/Alert.tsx
225
+ import { jsx as jsx6 } from "react/jsx-runtime";
226
+ function Alert({ tone, children, className }) {
227
+ return /* @__PURE__ */ jsx6("div", { className: cx(alert_default.alert, alert_default[tone], className), role: "alert", children });
228
+ }
128
229
 
129
230
  // src/components/toast/ToastContext.tsx
130
231
  import {
131
232
  createContext,
132
233
  useCallback,
133
234
  useContext,
134
- useEffect,
235
+ useEffect as useEffect2,
135
236
  useMemo,
136
237
  useRef as useRef2,
137
238
  useState
@@ -141,7 +242,7 @@ import {
141
242
  var toast_default = {};
142
243
 
143
244
  // src/components/toast/ToastContext.tsx
144
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
245
+ import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
145
246
  var DEFAULT_CONFIG = {
146
247
  position: "top-right",
147
248
  maxToasts: 5,
@@ -201,7 +302,7 @@ function ToastProvider({
201
302
  setToasts((prev) => prev.filter((t) => t.id !== id));
202
303
  }, []);
203
304
  const dismissAll = useCallback(() => setToasts([]), []);
204
- useEffect(() => {
305
+ useEffect2(() => {
205
306
  if (!merged.pauseOnFocusLoss) return;
206
307
  const handleVisibility = () => setIsPaused(document.visibilityState !== "visible");
207
308
  document.addEventListener("visibilitychange", handleVisibility);
@@ -213,7 +314,7 @@ function ToastProvider({
213
314
  );
214
315
  return /* @__PURE__ */ jsxs3(ToastContext.Provider, { value, children: [
215
316
  children,
216
- /* @__PURE__ */ jsx5(
317
+ /* @__PURE__ */ jsx7(
217
318
  ToastContainer,
218
319
  {
219
320
  toasts,
@@ -256,14 +357,14 @@ function ToastContainer({
256
357
  return toast_default.topRight;
257
358
  }
258
359
  })();
259
- return /* @__PURE__ */ jsx5(
360
+ return /* @__PURE__ */ jsx7(
260
361
  "div",
261
362
  {
262
363
  className: cx(toast_default.stack, posClass),
263
364
  role: "presentation",
264
365
  onMouseEnter: () => pauseOnHover && onPauseChange(true),
265
366
  onMouseLeave: () => pauseOnHover && onPauseChange(false),
266
- children: toasts.map((toast) => /* @__PURE__ */ jsx5(ToastItem, { toast, isPaused, onDismiss }, toast.id))
367
+ children: toasts.map((toast) => /* @__PURE__ */ jsx7(ToastItem, { toast, isPaused, onDismiss }, toast.id))
267
368
  }
268
369
  );
269
370
  }
@@ -309,12 +410,12 @@ function ToastItem({
309
410
  },
310
411
  [triggerDismiss]
311
412
  );
312
- useEffect(() => {
413
+ useEffect2(() => {
313
414
  if (!toast.duration || toast.duration <= 0) return void 0;
314
415
  schedule(toast.duration);
315
416
  return stopTimer;
316
417
  }, [schedule, toast.duration]);
317
- useEffect(() => {
418
+ useEffect2(() => {
318
419
  if (!toast.duration || toast.duration <= 0) return;
319
420
  if (isPaused) {
320
421
  const elapsed = performance.now() - startRef.current;
@@ -326,10 +427,10 @@ function ToastItem({
326
427
  }, [isPaused, schedule, toast.duration]);
327
428
  const icon = getIcon(toast.type);
328
429
  return /* @__PURE__ */ jsxs3("div", { className: cx(toast_default.toast, exiting && toast_default.exit), style: styleVars, role: "status", "aria-live": "polite", children: [
329
- /* @__PURE__ */ jsx5("span", { className: toast_default.icon, "aria-hidden": true, children: icon }),
430
+ /* @__PURE__ */ jsx7("span", { className: toast_default.icon, "aria-hidden": true, children: icon }),
330
431
  /* @__PURE__ */ jsxs3("div", { className: toast_default.body, children: [
331
- /* @__PURE__ */ jsx5("div", { className: toast_default.message, children: toast.message }),
332
- toast.action && /* @__PURE__ */ jsx5("div", { className: toast_default.actions, children: /* @__PURE__ */ jsx5(
432
+ /* @__PURE__ */ jsx7("div", { className: toast_default.message, children: toast.message }),
433
+ toast.action && /* @__PURE__ */ jsx7("div", { className: toast_default.actions, children: /* @__PURE__ */ jsx7(
333
434
  "button",
334
435
  {
335
436
  type: "button",
@@ -342,14 +443,14 @@ function ToastItem({
342
443
  }
343
444
  ) })
344
445
  ] }),
345
- toast.dismissible !== false && /* @__PURE__ */ jsx5(
446
+ toast.dismissible !== false && /* @__PURE__ */ jsx7(
346
447
  "button",
347
448
  {
348
449
  type: "button",
349
450
  className: toast_default.closeButton,
350
451
  onClick: triggerDismiss,
351
452
  "aria-label": "Dismiss notification",
352
- children: /* @__PURE__ */ jsx5("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx5(
453
+ children: /* @__PURE__ */ jsx7("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx7(
353
454
  "path",
354
455
  {
355
456
  d: "M11 3L3 11M3 3l8 8",
@@ -421,14 +522,73 @@ function getIcon(type) {
421
522
  }
422
523
  }
423
524
 
525
+ // src/components/input/Input.tsx
526
+ import * as React from "react";
527
+
528
+ // src/components/input/input.module.css
529
+ var input_default = {};
530
+
531
+ // src/components/input/Input.tsx
532
+ import { jsx as jsx8 } from "react/jsx-runtime";
533
+ var Input = React.forwardRef(
534
+ ({ className, type, ...props }, ref) => {
535
+ return /* @__PURE__ */ jsx8(
536
+ "input",
537
+ {
538
+ ref,
539
+ type,
540
+ className: cx(input_default.input, className),
541
+ ...props
542
+ }
543
+ );
544
+ }
545
+ );
546
+ Input.displayName = "Input";
547
+
548
+ // src/components/label/Label.tsx
549
+ import * as React2 from "react";
550
+
551
+ // src/components/label/label.module.css
552
+ var label_default = {};
553
+
554
+ // src/components/label/Label.tsx
555
+ import { jsx as jsx9 } from "react/jsx-runtime";
556
+ var Label = React2.forwardRef(
557
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx9("label", { ref, className: cx(label_default.label, className), ...props })
558
+ );
559
+ Label.displayName = "Label";
560
+
561
+ // src/components/checkbox/Checkbox.tsx
562
+ import * as React3 from "react";
563
+
564
+ // src/components/checkbox/checkbox.module.css
565
+ var checkbox_default = {};
566
+
567
+ // src/components/checkbox/Checkbox.tsx
568
+ import { jsx as jsx10 } from "react/jsx-runtime";
569
+ var Checkbox = React3.forwardRef(
570
+ ({ className, ...props }, ref) => {
571
+ return /* @__PURE__ */ jsx10(
572
+ "input",
573
+ {
574
+ ref,
575
+ type: "checkbox",
576
+ className: cx(checkbox_default.checkbox, className),
577
+ ...props
578
+ }
579
+ );
580
+ }
581
+ );
582
+ Checkbox.displayName = "Checkbox";
583
+
424
584
  // src/components/dropdown/Dropdown.tsx
425
- import { useState as useState2, useRef as useRef3, useEffect as useEffect2 } from "react";
585
+ import { useState as useState2, useRef as useRef3, useEffect as useEffect3 } from "react";
426
586
 
427
587
  // src/components/dropdown/dropdown.module.css
428
588
  var dropdown_default = {};
429
589
 
430
590
  // src/components/dropdown/Dropdown.tsx
431
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
591
+ import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
432
592
  function Dropdown({
433
593
  options,
434
594
  value,
@@ -443,7 +603,7 @@ function Dropdown({
443
603
  const ref = useRef3(null);
444
604
  const selected = options.find((o) => o.value === value);
445
605
  const isActive = allowClear && value !== "";
446
- useEffect2(() => {
606
+ useEffect3(() => {
447
607
  function handleClickOutside(e) {
448
608
  if (ref.current && !ref.current.contains(e.target)) {
449
609
  setOpen(false);
@@ -463,12 +623,12 @@ function Dropdown({
463
623
  "aria-label": ariaLabel,
464
624
  children: [
465
625
  selected ? selected.label : placeholder,
466
- /* @__PURE__ */ jsx6("span", { className: cx(dropdown_default.chevron, open && dropdown_default["chevron-open"]), children: /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 10 10", fill: "none", xmlns: "http://www.w3.org/2000/svg", width: "10", height: "10", children: /* @__PURE__ */ jsx6("path", { d: "M2 3.5L5 6.5L8 3.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
626
+ /* @__PURE__ */ jsx11("span", { className: cx(dropdown_default.chevron, open && dropdown_default["chevron-open"]), children: /* @__PURE__ */ jsx11("svg", { viewBox: "0 0 10 10", fill: "none", xmlns: "http://www.w3.org/2000/svg", width: "10", height: "10", children: /* @__PURE__ */ jsx11("path", { d: "M2 3.5L5 6.5L8 3.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
467
627
  ]
468
628
  }
469
629
  ),
470
630
  open && /* @__PURE__ */ jsxs4("div", { className: dropdown_default.menu, children: [
471
- allowClear && /* @__PURE__ */ jsx6(
631
+ allowClear && /* @__PURE__ */ jsx11(
472
632
  "button",
473
633
  {
474
634
  type: "button",
@@ -480,7 +640,7 @@ function Dropdown({
480
640
  children: placeholder
481
641
  }
482
642
  ),
483
- options.map((opt) => /* @__PURE__ */ jsx6(
643
+ options.map((opt) => /* @__PURE__ */ jsx11(
484
644
  "button",
485
645
  {
486
646
  type: "button",
@@ -497,19 +657,441 @@ function Dropdown({
497
657
  ] });
498
658
  }
499
659
 
660
+ // src/components/dropdown-menu/DropdownMenu.tsx
661
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
662
+
663
+ // src/components/dropdown-menu/dropdown-menu.module.css
664
+ var dropdown_menu_default = {};
665
+
666
+ // src/components/dropdown-menu/DropdownMenu.tsx
667
+ import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
668
+ function DropdownMenu(props) {
669
+ return /* @__PURE__ */ jsx12(DropdownMenuPrimitive.Root, { ...props });
670
+ }
671
+ function DropdownMenuTrigger(props) {
672
+ return /* @__PURE__ */ jsx12(DropdownMenuPrimitive.Trigger, { ...props });
673
+ }
674
+ function DropdownMenuGroup(props) {
675
+ return /* @__PURE__ */ jsx12(DropdownMenuPrimitive.Group, { ...props });
676
+ }
677
+ function DropdownMenuPortal(props) {
678
+ return /* @__PURE__ */ jsx12(DropdownMenuPrimitive.Portal, { ...props });
679
+ }
680
+ function DropdownMenuSub(props) {
681
+ return /* @__PURE__ */ jsx12(DropdownMenuPrimitive.Sub, { ...props });
682
+ }
683
+ function DropdownMenuRadioGroup(props) {
684
+ return /* @__PURE__ */ jsx12(DropdownMenuPrimitive.RadioGroup, { ...props });
685
+ }
686
+ function DropdownMenuContent({
687
+ className,
688
+ sideOffset = 4,
689
+ ...props
690
+ }) {
691
+ return /* @__PURE__ */ jsx12(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx12(
692
+ DropdownMenuPrimitive.Content,
693
+ {
694
+ sideOffset,
695
+ className: cx(dropdown_menu_default.content, className),
696
+ ...props
697
+ }
698
+ ) });
699
+ }
700
+ function DropdownMenuItem({
701
+ className,
702
+ inset,
703
+ variant = "default",
704
+ ...props
705
+ }) {
706
+ return /* @__PURE__ */ jsx12(
707
+ DropdownMenuPrimitive.Item,
708
+ {
709
+ "data-inset": inset ? "true" : void 0,
710
+ className: cx(
711
+ dropdown_menu_default.item,
712
+ variant === "destructive" && dropdown_menu_default.destructive,
713
+ className
714
+ ),
715
+ ...props
716
+ }
717
+ );
718
+ }
719
+ function DropdownMenuCheckboxItem({
720
+ className,
721
+ children,
722
+ ...props
723
+ }) {
724
+ return /* @__PURE__ */ jsxs5(
725
+ DropdownMenuPrimitive.CheckboxItem,
726
+ {
727
+ className: cx(dropdown_menu_default.item, dropdown_menu_default.insetItem, className),
728
+ ...props,
729
+ children: [
730
+ /* @__PURE__ */ jsx12("span", { className: dropdown_menu_default.indicator, children: /* @__PURE__ */ jsx12(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx12(
731
+ "svg",
732
+ {
733
+ viewBox: "0 0 16 16",
734
+ width: "16",
735
+ height: "16",
736
+ "aria-hidden": "true",
737
+ className: dropdown_menu_default.indicatorIcon,
738
+ children: /* @__PURE__ */ jsx12(
739
+ "path",
740
+ {
741
+ d: "M3.5 8.5 6.5 11.5 12.5 4.5",
742
+ fill: "none",
743
+ stroke: "currentColor",
744
+ strokeWidth: "1.8",
745
+ strokeLinecap: "round",
746
+ strokeLinejoin: "round"
747
+ }
748
+ )
749
+ }
750
+ ) }) }),
751
+ children
752
+ ]
753
+ }
754
+ );
755
+ }
756
+ function DropdownMenuRadioItem({
757
+ className,
758
+ children,
759
+ ...props
760
+ }) {
761
+ return /* @__PURE__ */ jsxs5(
762
+ DropdownMenuPrimitive.RadioItem,
763
+ {
764
+ className: cx(dropdown_menu_default.item, dropdown_menu_default.insetItem, className),
765
+ ...props,
766
+ children: [
767
+ /* @__PURE__ */ jsx12("span", { className: dropdown_menu_default.indicator, children: /* @__PURE__ */ jsx12(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx12("span", { className: dropdown_menu_default.radioDot }) }) }),
768
+ children
769
+ ]
770
+ }
771
+ );
772
+ }
773
+ function DropdownMenuLabel({
774
+ className,
775
+ inset,
776
+ ...props
777
+ }) {
778
+ return /* @__PURE__ */ jsx12(
779
+ DropdownMenuPrimitive.Label,
780
+ {
781
+ "data-inset": inset ? "true" : void 0,
782
+ className: cx(dropdown_menu_default.label, className),
783
+ ...props
784
+ }
785
+ );
786
+ }
787
+ function DropdownMenuSeparator({
788
+ className,
789
+ ...props
790
+ }) {
791
+ return /* @__PURE__ */ jsx12(
792
+ DropdownMenuPrimitive.Separator,
793
+ {
794
+ className: cx(dropdown_menu_default.separator, className),
795
+ ...props
796
+ }
797
+ );
798
+ }
799
+ function DropdownMenuSubTrigger({
800
+ className,
801
+ inset,
802
+ children,
803
+ ...props
804
+ }) {
805
+ return /* @__PURE__ */ jsxs5(
806
+ DropdownMenuPrimitive.SubTrigger,
807
+ {
808
+ "data-inset": inset ? "true" : void 0,
809
+ className: cx(dropdown_menu_default.item, className),
810
+ ...props,
811
+ children: [
812
+ children,
813
+ /* @__PURE__ */ jsx12(
814
+ "svg",
815
+ {
816
+ viewBox: "0 0 16 16",
817
+ width: "16",
818
+ height: "16",
819
+ "aria-hidden": "true",
820
+ className: dropdown_menu_default.chevron,
821
+ children: /* @__PURE__ */ jsx12(
822
+ "path",
823
+ {
824
+ d: "M6 3.5 10.5 8 6 12.5",
825
+ fill: "none",
826
+ stroke: "currentColor",
827
+ strokeWidth: "1.6",
828
+ strokeLinecap: "round",
829
+ strokeLinejoin: "round"
830
+ }
831
+ )
832
+ }
833
+ )
834
+ ]
835
+ }
836
+ );
837
+ }
838
+ function DropdownMenuSubContent({
839
+ className,
840
+ ...props
841
+ }) {
842
+ return /* @__PURE__ */ jsx12(
843
+ DropdownMenuPrimitive.SubContent,
844
+ {
845
+ className: cx(dropdown_menu_default.content, className),
846
+ ...props
847
+ }
848
+ );
849
+ }
850
+
500
851
  // src/components/app-shell/AppShell.tsx
501
852
  import {
502
- useEffect as useEffect3,
853
+ useEffect as useEffect5,
503
854
  useId,
504
855
  useRef as useRef4,
856
+ useState as useState4
857
+ } from "react";
858
+
859
+ // src/theme/ThemeProvider.tsx
860
+ import {
861
+ createContext as createContext2,
862
+ useCallback as useCallback2,
863
+ useContext as useContext2,
864
+ useEffect as useEffect4,
865
+ useMemo as useMemo2,
505
866
  useState as useState3
506
867
  } from "react";
507
868
 
869
+ // src/theme/constants.ts
870
+ var UZI_THEMES = ["light", "dark", "system"];
871
+ var UZI_ACCENTS = ["blue", "cyan", "violet", "emerald", "amber", "rose"];
872
+ var THEME_STORAGE_KEY = "uzi-theme";
873
+ var ACCENT_STORAGE_KEY = "uzi-accent";
874
+
875
+ // src/theme/ThemeProvider.tsx
876
+ import { jsx as jsx13 } from "react/jsx-runtime";
877
+ var THEME_STORAGE_KEY2 = THEME_STORAGE_KEY;
878
+ var ACCENT_STORAGE_KEY2 = ACCENT_STORAGE_KEY;
879
+ var THEME_ATTRIBUTE = "data-uzi-theme";
880
+ var ACCENT_ATTRIBUTE = "data-uzi-accent";
881
+ var ThemeContext = createContext2(void 0);
882
+ function isTheme(value) {
883
+ return UZI_THEMES.includes(value);
884
+ }
885
+ function isAccent(value) {
886
+ return UZI_ACCENTS.includes(value);
887
+ }
888
+ function getSystemTheme() {
889
+ if (typeof window === "undefined") return "light";
890
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
891
+ }
892
+ function ThemeProvider({
893
+ children,
894
+ theme,
895
+ defaultTheme = "system",
896
+ accent,
897
+ defaultAccent = "blue",
898
+ onThemeChange,
899
+ onAccentChange,
900
+ storageKey = THEME_STORAGE_KEY2,
901
+ accentStorageKey = ACCENT_STORAGE_KEY2,
902
+ disableStorage = false
903
+ }) {
904
+ const [internalTheme, setInternalTheme] = useState3(defaultTheme);
905
+ const [internalAccent, setInternalAccent] = useState3(defaultAccent);
906
+ const [systemTheme, setSystemTheme] = useState3("light");
907
+ useEffect4(() => {
908
+ setSystemTheme(getSystemTheme());
909
+ if (!disableStorage) {
910
+ const storedTheme = window.localStorage.getItem(storageKey);
911
+ if (isTheme(storedTheme)) setInternalTheme(storedTheme);
912
+ const storedAccent = window.localStorage.getItem(accentStorageKey);
913
+ if (isAccent(storedAccent)) setInternalAccent(storedAccent);
914
+ }
915
+ }, [disableStorage, storageKey, accentStorageKey]);
916
+ const isThemeControlled = theme !== void 0;
917
+ const isAccentControlled = accent !== void 0;
918
+ const currentTheme = isThemeControlled ? theme : internalTheme;
919
+ const currentAccent = isAccentControlled ? accent : internalAccent;
920
+ const resolvedTheme = currentTheme === "system" ? systemTheme : currentTheme;
921
+ useEffect4(() => {
922
+ if (typeof window === "undefined") return;
923
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
924
+ const handleChange = () => setSystemTheme(mediaQuery.matches ? "dark" : "light");
925
+ handleChange();
926
+ mediaQuery.addEventListener("change", handleChange);
927
+ return () => mediaQuery.removeEventListener("change", handleChange);
928
+ }, []);
929
+ useEffect4(() => {
930
+ if (typeof document === "undefined") return;
931
+ const root = document.documentElement;
932
+ root.setAttribute(THEME_ATTRIBUTE, resolvedTheme);
933
+ root.setAttribute(ACCENT_ATTRIBUTE, currentAccent);
934
+ root.style.colorScheme = resolvedTheme;
935
+ root.classList.toggle("dark", resolvedTheme === "dark");
936
+ }, [currentAccent, resolvedTheme]);
937
+ const setTheme = useCallback2(
938
+ (nextTheme) => {
939
+ if (!isThemeControlled) setInternalTheme(nextTheme);
940
+ if (!disableStorage && typeof window !== "undefined") {
941
+ window.localStorage.setItem(storageKey, nextTheme);
942
+ }
943
+ onThemeChange?.(nextTheme);
944
+ },
945
+ [disableStorage, isThemeControlled, onThemeChange, storageKey]
946
+ );
947
+ const setAccent = useCallback2(
948
+ (nextAccent) => {
949
+ if (!isAccentControlled) setInternalAccent(nextAccent);
950
+ if (!disableStorage && typeof window !== "undefined") {
951
+ window.localStorage.setItem(accentStorageKey, nextAccent);
952
+ }
953
+ onAccentChange?.(nextAccent);
954
+ },
955
+ [accentStorageKey, disableStorage, isAccentControlled, onAccentChange]
956
+ );
957
+ const toggleTheme = useCallback2(() => {
958
+ setTheme(resolvedTheme === "dark" ? "light" : "dark");
959
+ }, [resolvedTheme, setTheme]);
960
+ const value = useMemo2(
961
+ () => ({
962
+ theme: currentTheme,
963
+ resolvedTheme,
964
+ accent: currentAccent,
965
+ setTheme,
966
+ setAccent,
967
+ toggleTheme
968
+ }),
969
+ [currentAccent, currentTheme, resolvedTheme, setAccent, setTheme, toggleTheme]
970
+ );
971
+ return /* @__PURE__ */ jsx13(ThemeContext.Provider, { value, children });
972
+ }
973
+ function useTheme() {
974
+ const context = useContext2(ThemeContext);
975
+ if (!context) throw new Error("useTheme must be used within a ThemeProvider");
976
+ return context;
977
+ }
978
+
979
+ // src/components/theme-toggle-button/theme-toggle-button.module.css
980
+ var theme_toggle_button_default = {};
981
+
982
+ // src/components/theme-toggle-button/ThemeToggleButton.tsx
983
+ import { jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
984
+ function MoonIcon() {
985
+ return /* @__PURE__ */ jsx14("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", width: "16", height: "16", fill: "none", children: /* @__PURE__ */ jsx14(
986
+ "path",
987
+ {
988
+ d: "M20 15.2A8.5 8.5 0 0 1 8.8 4 9 9 0 1 0 20 15.2Z",
989
+ stroke: "currentColor",
990
+ strokeWidth: "1.8",
991
+ strokeLinecap: "round",
992
+ strokeLinejoin: "round"
993
+ }
994
+ ) });
995
+ }
996
+ function SunIcon() {
997
+ return /* @__PURE__ */ jsxs6("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", width: "16", height: "16", fill: "none", children: [
998
+ /* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "4", stroke: "currentColor", strokeWidth: "1.8" }),
999
+ /* @__PURE__ */ jsx14(
1000
+ "path",
1001
+ {
1002
+ d: "M12 2.75v2.5M12 18.75v2.5M21.25 12h-2.5M5.25 12h-2.5M18.54 5.46l-1.77 1.77M7.23 16.77l-1.77 1.77M18.54 18.54l-1.77-1.77M7.23 7.23 5.46 5.46",
1003
+ stroke: "currentColor",
1004
+ strokeWidth: "1.8",
1005
+ strokeLinecap: "round"
1006
+ }
1007
+ )
1008
+ ] });
1009
+ }
1010
+ function ThemeToggleButton({
1011
+ showLabel = false,
1012
+ lightLabel = "Light mode",
1013
+ darkLabel = "Dark mode",
1014
+ className,
1015
+ onClick,
1016
+ ...rest
1017
+ }) {
1018
+ const { resolvedTheme, toggleTheme } = useTheme();
1019
+ const nextThemeLabel = resolvedTheme === "dark" ? lightLabel : darkLabel;
1020
+ return /* @__PURE__ */ jsxs6(
1021
+ Button,
1022
+ {
1023
+ type: "button",
1024
+ variant: "ghost",
1025
+ size: showLabel ? "sm" : "icon",
1026
+ className: cx(showLabel && theme_toggle_button_default.withLabel, className),
1027
+ "aria-label": `Switch to ${nextThemeLabel.toLowerCase()}`,
1028
+ title: `Switch to ${nextThemeLabel.toLowerCase()}`,
1029
+ onClick: (event) => {
1030
+ onClick?.(event);
1031
+ if (!event.defaultPrevented) toggleTheme();
1032
+ },
1033
+ ...rest,
1034
+ children: [
1035
+ resolvedTheme === "dark" ? /* @__PURE__ */ jsx14(SunIcon, {}) : /* @__PURE__ */ jsx14(MoonIcon, {}),
1036
+ showLabel && /* @__PURE__ */ jsx14("span", { children: nextThemeLabel })
1037
+ ]
1038
+ }
1039
+ );
1040
+ }
1041
+
1042
+ // src/components/top-bar/top-bar.module.css
1043
+ var top_bar_default = {};
1044
+
1045
+ // src/components/top-bar/TopBar.tsx
1046
+ import { jsx as jsx15, jsxs as jsxs7 } from "react/jsx-runtime";
1047
+ function TopBar({
1048
+ leading,
1049
+ brand,
1050
+ brandHref,
1051
+ brandingLocation = "left",
1052
+ start,
1053
+ center,
1054
+ actions,
1055
+ showThemeToggle = false,
1056
+ themeToggleProps,
1057
+ className,
1058
+ innerClassName,
1059
+ isSticky,
1060
+ sticky = true,
1061
+ children,
1062
+ ...rest
1063
+ }) {
1064
+ const shouldStick = isSticky ?? sticky;
1065
+ const brandNode = !brand ? null : brandHref ? /* @__PURE__ */ jsx15("a", { href: brandHref, className: top_bar_default.topBarBrand, children: /* @__PURE__ */ jsx15("span", { className: top_bar_default.topBarBrandContent, children: brand }) }) : /* @__PURE__ */ jsx15("div", { className: top_bar_default.topBarBrand, children: /* @__PURE__ */ jsx15("span", { className: top_bar_default.topBarBrandContent, children: brand }) });
1066
+ return /* @__PURE__ */ jsx15(
1067
+ "header",
1068
+ {
1069
+ className: cx(top_bar_default.topBar, !shouldStick && top_bar_default.topBarStatic, className),
1070
+ ...rest,
1071
+ children: /* @__PURE__ */ jsxs7("div", { className: cx(top_bar_default.topBarInner, innerClassName), children: [
1072
+ /* @__PURE__ */ jsxs7("div", { className: top_bar_default.topBarStart, children: [
1073
+ leading,
1074
+ brandingLocation === "left" && brandNode,
1075
+ start
1076
+ ] }),
1077
+ brandNode && brandingLocation === "center" || center || children ? /* @__PURE__ */ jsx15("div", { className: top_bar_default.topBarCenter, children: /* @__PURE__ */ jsxs7("div", { className: top_bar_default.topBarCenterGroup, children: [
1078
+ brandingLocation === "center" && brandNode,
1079
+ center ?? children
1080
+ ] }) }) : null,
1081
+ /* @__PURE__ */ jsxs7("div", { className: top_bar_default.topBarActions, children: [
1082
+ showThemeToggle && /* @__PURE__ */ jsx15(ThemeToggleButton, { ...themeToggleProps }),
1083
+ actions
1084
+ ] })
1085
+ ] })
1086
+ }
1087
+ );
1088
+ }
1089
+
508
1090
  // src/components/app-shell/app-shell.module.css
509
1091
  var app_shell_default = {};
510
1092
 
511
1093
  // src/components/app-shell/AppShell.tsx
512
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1094
+ import { jsx as jsx16, jsxs as jsxs8 } from "react/jsx-runtime";
513
1095
  var DESKTOP_BREAKPOINT = 960;
514
1096
  function getIsDesktop() {
515
1097
  if (typeof window === "undefined") return false;
@@ -522,6 +1104,9 @@ function AppShell({
522
1104
  brandHref,
523
1105
  topbarStart,
524
1106
  topbarEnd,
1107
+ showThemeToggle = false,
1108
+ themeToggleProps,
1109
+ topBarBrandingLocation = "left",
525
1110
  className,
526
1111
  sidebarClassName,
527
1112
  topbarClassName,
@@ -531,19 +1116,23 @@ function AppShell({
531
1116
  hamburgerLabel = "Toggle navigation",
532
1117
  onSidebarToggle
533
1118
  }) {
534
- const [isDesktop, setIsDesktop] = useState3(false);
535
- const [sidebarOpen, setSidebarOpen] = useState3(false);
1119
+ const [isDesktop, setIsDesktop] = useState4(false);
1120
+ const [sidebarOpen, setSidebarOpen] = useState4(false);
1121
+ const [transitionsReady, setTransitionsReady] = useState4(false);
536
1122
  const prevIsDesktopRef = useRef4(false);
537
1123
  const closeKeyRef = useRef4(closeSidebarOnChangeKey);
538
1124
  const sidebarRef = useRef4(null);
539
1125
  const hamburgerRef = useRef4(null);
540
1126
  const mainRef = useRef4(null);
541
1127
  const sidebarId = useId();
542
- useEffect3(() => {
1128
+ useEffect5(() => {
543
1129
  const desktop = getIsDesktop();
544
1130
  setIsDesktop(desktop);
545
1131
  setSidebarOpen(desktop);
546
1132
  prevIsDesktopRef.current = desktop;
1133
+ const transitionFrame = window.requestAnimationFrame(() => {
1134
+ setTransitionsReady(true);
1135
+ });
547
1136
  const handleResize = () => {
548
1137
  const nowDesktop = getIsDesktop();
549
1138
  setIsDesktop(nowDesktop);
@@ -553,9 +1142,12 @@ function AppShell({
553
1142
  }
554
1143
  };
555
1144
  window.addEventListener("resize", handleResize);
556
- return () => window.removeEventListener("resize", handleResize);
1145
+ return () => {
1146
+ window.cancelAnimationFrame(transitionFrame);
1147
+ window.removeEventListener("resize", handleResize);
1148
+ };
557
1149
  }, []);
558
- useEffect3(() => {
1150
+ useEffect5(() => {
559
1151
  if (isDesktop || !sidebarOpen) return;
560
1152
  const mainElement = mainRef.current;
561
1153
  const closeSidebar = () => setSidebarOpen(false);
@@ -580,25 +1172,26 @@ function AppShell({
580
1172
  document.removeEventListener("touchmove", closeSidebar);
581
1173
  };
582
1174
  }, [sidebarOpen, isDesktop]);
583
- useEffect3(() => {
1175
+ useEffect5(() => {
584
1176
  if (!isDesktop && closeKeyRef.current !== closeSidebarOnChangeKey) {
585
1177
  setSidebarOpen(false);
586
1178
  }
587
1179
  closeKeyRef.current = closeSidebarOnChangeKey;
588
1180
  }, [closeSidebarOnChangeKey, isDesktop]);
589
- useEffect3(() => {
1181
+ useEffect5(() => {
590
1182
  onSidebarToggle?.(sidebarOpen);
591
1183
  }, [sidebarOpen, onSidebarToggle]);
592
1184
  const toggleSidebar = () => setSidebarOpen((open) => !open);
593
1185
  const sidebarWidthValue = sidebarWidth === void 0 ? void 0 : typeof sidebarWidth === "number" ? `${sidebarWidth}px` : sidebarWidth;
594
1186
  const shellStyle = sidebarWidthValue ? { ["--app-shell-sidebar-width"]: sidebarWidthValue } : void 0;
595
1187
  const shellClasses = cx(
596
- app_shell_default.shell,
597
- sidebarOpen ? app_shell_default.sidebarOpen : app_shell_default.sidebarCollapsed,
1188
+ app_shell_default.appShell,
1189
+ transitionsReady && app_shell_default.appShellAnimated,
1190
+ sidebarOpen ? app_shell_default.appShellOpen : app_shell_default.appShellCollapsed,
598
1191
  className
599
1192
  );
600
- const sidebarClasses = cx(app_shell_default.sidebar, sidebarOpen && app_shell_default.open, sidebarClassName);
601
- return /* @__PURE__ */ jsxs5(
1193
+ const sidebarClasses = cx(app_shell_default.appShellSidebar, sidebarOpen && app_shell_default.appShellSidebarOpen, sidebarClassName);
1194
+ return /* @__PURE__ */ jsxs8(
602
1195
  "div",
603
1196
  {
604
1197
  className: shellClasses,
@@ -607,29 +1200,35 @@ function AppShell({
607
1200
  "data-desktop": isDesktop ? "true" : "false",
608
1201
  "data-sidebar-open": sidebarOpen ? "true" : "false",
609
1202
  children: [
610
- /* @__PURE__ */ jsxs5("header", { className: cx(app_shell_default.topbar, topbarClassName), children: [
611
- /* @__PURE__ */ jsxs5("div", { className: app_shell_default.topbarLeft, children: [
612
- /* @__PURE__ */ jsx7(
1203
+ /* @__PURE__ */ jsx16(
1204
+ TopBar,
1205
+ {
1206
+ className: cx(app_shell_default.appShellTopbar, topbarClassName),
1207
+ leading: /* @__PURE__ */ jsx16(
613
1208
  "button",
614
1209
  {
615
1210
  ref: hamburgerRef,
616
1211
  type: "button",
617
- className: app_shell_default.hamburger,
1212
+ className: app_shell_default.appShellHamburger,
618
1213
  onClick: toggleSidebar,
619
1214
  "aria-label": hamburgerLabel,
620
1215
  "aria-expanded": sidebarOpen,
621
1216
  "aria-controls": sidebarId,
622
- children: /* @__PURE__ */ jsx7("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "M3 6h18M3 12h18M3 18h18", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }) })
1217
+ children: /* @__PURE__ */ jsx16("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx16("path", { d: "M3 6h18M3 12h18M3 18h18", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }) })
623
1218
  }
624
1219
  ),
625
- brand && (brandHref ? /* @__PURE__ */ jsx7("a", { className: app_shell_default.brand, href: brandHref, children: brand }) : /* @__PURE__ */ jsx7("div", { className: app_shell_default.brand, children: brand })),
626
- topbarStart && /* @__PURE__ */ jsx7("div", { className: app_shell_default.topbarStart, children: topbarStart })
627
- ] }),
628
- /* @__PURE__ */ jsx7("div", { className: app_shell_default.topbarRight, children: topbarEnd })
629
- ] }),
630
- !isDesktop && sidebarOpen && /* @__PURE__ */ jsx7("div", { className: app_shell_default.backdrop, onClick: () => setSidebarOpen(false), onTouchStart: () => setSidebarOpen(false), "aria-hidden": "true" }),
631
- /* @__PURE__ */ jsx7("aside", { ref: sidebarRef, id: sidebarId, className: sidebarClasses, "aria-label": "Sidebar navigation", children: sidebar }),
632
- /* @__PURE__ */ jsx7("main", { ref: mainRef, className: cx(app_shell_default.main, mainClassName), children })
1220
+ brand,
1221
+ brandHref,
1222
+ brandingLocation: topBarBrandingLocation,
1223
+ start: topbarStart,
1224
+ actions: topbarEnd,
1225
+ showThemeToggle,
1226
+ themeToggleProps
1227
+ }
1228
+ ),
1229
+ !isDesktop && sidebarOpen && /* @__PURE__ */ jsx16("div", { className: app_shell_default.appShellBackdrop, onClick: () => setSidebarOpen(false), onTouchStart: () => setSidebarOpen(false), "aria-hidden": "true" }),
1230
+ /* @__PURE__ */ jsx16("aside", { ref: sidebarRef, id: sidebarId, className: sidebarClasses, "aria-label": "Sidebar navigation", children: sidebar }),
1231
+ /* @__PURE__ */ jsx16("main", { ref: mainRef, className: cx(app_shell_default.appShellMain, mainClassName), children })
633
1232
  ]
634
1233
  }
635
1234
  );
@@ -639,56 +1238,175 @@ function AppShell({
639
1238
  var sidebar_nav_default = {};
640
1239
 
641
1240
  // src/components/sidebar-nav/SidebarNav.tsx
642
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1241
+ import { Fragment, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
643
1242
  var defaultIsActive = (item, path) => {
644
1243
  if (item.active !== void 0) return item.active;
1244
+ if (!item.href) return false;
645
1245
  if (!path) return false;
646
1246
  if (item.href === "/") return path === "/";
647
1247
  return path.startsWith(item.href);
648
1248
  };
649
1249
  function SidebarNav({
650
- items,
1250
+ items = [],
1251
+ sections,
651
1252
  currentPath,
652
1253
  getIsActive = defaultIsActive,
653
1254
  onItemClick,
1255
+ header,
1256
+ footer,
1257
+ ariaLabel = "Sidebar navigation",
1258
+ collapsed = false,
1259
+ iconSize,
654
1260
  className,
655
- itemClassName
1261
+ itemClassName,
1262
+ sectionClassName
656
1263
  }) {
657
- return /* @__PURE__ */ jsx8("nav", { className: cx(sidebar_nav_default.nav, className), "aria-label": "Sidebar navigation", children: items.map((item) => {
658
- const active = getIsActive(item, currentPath);
659
- const rel = item.rel ?? (item.target === "_blank" ? "noreferrer" : void 0);
660
- return /* @__PURE__ */ jsxs6(
661
- "a",
1264
+ const resolvedSections = sections?.length ? sections : [{ id: "default", items }];
1265
+ const style = iconSize !== void 0 ? {
1266
+ ["--sidebar-nav-icon-size"]: typeof iconSize === "number" ? `${iconSize}px` : iconSize
1267
+ } : void 0;
1268
+ return /* @__PURE__ */ jsxs9(
1269
+ "nav",
1270
+ {
1271
+ className: cx(sidebar_nav_default.uziSidebarNav, collapsed && sidebar_nav_default.uziSidebarNavCollapsed, className),
1272
+ "aria-label": ariaLabel,
1273
+ style,
1274
+ children: [
1275
+ header ? /* @__PURE__ */ jsx17("div", { className: sidebar_nav_default.uziSidebarNavHeader, children: header }) : null,
1276
+ /* @__PURE__ */ jsx17("div", { className: sidebar_nav_default.uziSidebarNavSections, children: resolvedSections.map((section, sectionIndex) => /* @__PURE__ */ jsxs9(
1277
+ "div",
1278
+ {
1279
+ className: cx(sidebar_nav_default.uziSidebarNavSection, sectionClassName),
1280
+ children: [
1281
+ section.label && !collapsed ? /* @__PURE__ */ jsx17("div", { className: sidebar_nav_default.uziSidebarNavSectionLabel, children: section.label }) : null,
1282
+ /* @__PURE__ */ jsx17("div", { className: sidebar_nav_default.uziSidebarNavSectionItems, children: section.items.map((item, itemIndex) => /* @__PURE__ */ jsx17(
1283
+ SidebarNavEntry,
1284
+ {
1285
+ item,
1286
+ active: getIsActive(item, currentPath),
1287
+ collapsed,
1288
+ itemClassName,
1289
+ onItemClick
1290
+ },
1291
+ `${section.id ?? sectionIndex}-${item.href ?? item.title ?? itemIndex}`
1292
+ )) })
1293
+ ]
1294
+ },
1295
+ section.id ?? `section-${sectionIndex}`
1296
+ )) }),
1297
+ footer ? /* @__PURE__ */ jsx17("div", { className: sidebar_nav_default.uziSidebarNavFooter, children: footer }) : null
1298
+ ]
1299
+ }
1300
+ );
1301
+ }
1302
+ function SidebarNavEntry({
1303
+ item,
1304
+ active,
1305
+ collapsed,
1306
+ itemClassName,
1307
+ onItemClick
1308
+ }) {
1309
+ const rel = item.rel ?? (item.target === "_blank" ? "noreferrer" : void 0);
1310
+ const title = item.title ?? (typeof item.label === "string" ? item.label : void 0);
1311
+ const classes = cx(
1312
+ sidebar_nav_default.uziSidebarNavItem,
1313
+ active && sidebar_nav_default.uziSidebarNavItemActive,
1314
+ collapsed && sidebar_nav_default.uziSidebarNavItemCollapsed,
1315
+ item.disabled && sidebar_nav_default.uziSidebarNavItemDisabled,
1316
+ itemClassName
1317
+ );
1318
+ const content = /* @__PURE__ */ jsxs9(Fragment, { children: [
1319
+ item.icon && /* @__PURE__ */ jsx17("span", { className: sidebar_nav_default.uziSidebarNavIcon, children: item.icon }),
1320
+ !collapsed ? /* @__PURE__ */ jsxs9("span", { className: sidebar_nav_default.uziSidebarNavItemBody, children: [
1321
+ /* @__PURE__ */ jsxs9("span", { className: sidebar_nav_default.uziSidebarNavLabelRow, children: [
1322
+ /* @__PURE__ */ jsx17("span", { className: sidebar_nav_default.uziSidebarNavLabel, children: item.label }),
1323
+ item.badge && /* @__PURE__ */ jsx17("span", { className: sidebar_nav_default.uziSidebarNavBadge, children: item.badge })
1324
+ ] }),
1325
+ item.description ? /* @__PURE__ */ jsx17("span", { className: sidebar_nav_default.uziSidebarNavDescription, children: item.description }) : null
1326
+ ] }) : null
1327
+ ] });
1328
+ const handleClick = () => {
1329
+ if (item.disabled) return;
1330
+ item.onClick?.();
1331
+ onItemClick?.(item);
1332
+ };
1333
+ if (!item.href) {
1334
+ return /* @__PURE__ */ jsx17(
1335
+ "button",
662
1336
  {
663
- className: cx(sidebar_nav_default.item, active && sidebar_nav_default.active, itemClassName),
664
- href: item.href,
665
- target: item.target,
666
- rel,
1337
+ type: "button",
1338
+ className: classes,
667
1339
  "aria-current": active ? "page" : void 0,
668
- onClick: () => {
669
- item.onClick?.();
670
- onItemClick?.(item);
671
- },
672
- children: [
673
- item.icon && /* @__PURE__ */ jsx8("span", { className: sidebar_nav_default.icon, children: item.icon }),
674
- /* @__PURE__ */ jsx8("span", { className: sidebar_nav_default.label, children: item.label }),
675
- item.badge && /* @__PURE__ */ jsx8("span", { className: sidebar_nav_default.badge, children: item.badge })
676
- ]
677
- },
678
- item.href
1340
+ "aria-disabled": item.disabled ? "true" : void 0,
1341
+ disabled: item.disabled,
1342
+ title: collapsed ? title : void 0,
1343
+ onClick: handleClick,
1344
+ children: content
1345
+ }
679
1346
  );
680
- }) });
1347
+ }
1348
+ if (item.disabled) {
1349
+ return /* @__PURE__ */ jsx17(
1350
+ "div",
1351
+ {
1352
+ className: classes,
1353
+ "aria-current": active ? "page" : void 0,
1354
+ "aria-disabled": "true",
1355
+ title: collapsed ? title : void 0,
1356
+ children: content
1357
+ }
1358
+ );
1359
+ }
1360
+ return /* @__PURE__ */ jsx17(
1361
+ "a",
1362
+ {
1363
+ className: classes,
1364
+ href: item.href,
1365
+ target: item.target,
1366
+ rel,
1367
+ "aria-current": active ? "page" : void 0,
1368
+ title: collapsed ? title : void 0,
1369
+ onClick: handleClick,
1370
+ children: content
1371
+ }
1372
+ );
681
1373
  }
682
1374
  export {
1375
+ Alert,
683
1376
  AppShell,
1377
+ Avatar,
1378
+ AvatarFallback,
1379
+ AvatarImage,
684
1380
  Button,
685
1381
  Card,
1382
+ Checkbox,
686
1383
  Dropdown,
1384
+ DropdownMenu,
1385
+ DropdownMenuCheckboxItem,
1386
+ DropdownMenuContent,
1387
+ DropdownMenuGroup,
1388
+ DropdownMenuItem,
1389
+ DropdownMenuLabel,
1390
+ DropdownMenuPortal,
1391
+ DropdownMenuRadioGroup,
1392
+ DropdownMenuRadioItem,
1393
+ DropdownMenuSeparator,
1394
+ DropdownMenuSub,
1395
+ DropdownMenuSubContent,
1396
+ DropdownMenuSubTrigger,
1397
+ DropdownMenuTrigger,
1398
+ Input,
1399
+ Label,
687
1400
  Modal,
1401
+ ModalOverlay,
688
1402
  Pill,
689
1403
  SidebarNav,
1404
+ ThemeProvider,
1405
+ ThemeToggleButton,
690
1406
  ToastProvider,
1407
+ TopBar,
691
1408
  cx,
1409
+ useTheme,
692
1410
  useToast
693
1411
  };
694
1412
  //# sourceMappingURL=index.js.map