@tradalab/lyra 1.0.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -83,6 +83,47 @@ declare function SidebarMenuSubButton({ asChild, size, isActive, className, ...p
83
83
  isActive?: boolean;
84
84
  }): React.JSX.Element;
85
85
 
86
+ type AccountMenuUser = {
87
+ name?: string | null;
88
+ email?: string | null;
89
+ image?: string | null;
90
+ };
91
+ type AccountMenuLabels = {
92
+ account: string;
93
+ guest: string;
94
+ signIn: string;
95
+ switchAccount: string;
96
+ signOut: string;
97
+ };
98
+ /** Default English labels — spread + override, or reference directly. */
99
+ declare const defaultAccountMenuLabels: AccountMenuLabels;
100
+ interface AccountMenuProps {
101
+ /** Current user, or `null`/`undefined` for a guest. */
102
+ user?: AccountMenuUser | null;
103
+ /** Override labels — pass translated strings if your app is localized. */
104
+ labels?: Partial<AccountMenuLabels>;
105
+ /** Sign-out handler (signed-in only). Item hidden if omitted. */
106
+ onSignOut?: () => void;
107
+ /** Switch-account handler (signed-in only). Item hidden if omitted. */
108
+ onSwitchAccount?: () => void;
109
+ /** Sign-in handler (guest only). Item hidden if omitted. */
110
+ onSignIn?: () => void;
111
+ /** Dropdown alignment. Default `"end"`. */
112
+ align?: "start" | "center" | "end";
113
+ /** Extra menu content (e.g. theme/language submenus) above the account actions. */
114
+ children?: React.ReactNode;
115
+ }
116
+ /**
117
+ * Account dropdown built on lyra's standardized session shape. Signed-in users
118
+ * get an avatar trigger + switch-account / sign-out; guests get a neutral icon +
119
+ * sign-in. All actions are callbacks and all labels are props, so the component
120
+ * stays framework- and i18n-agnostic. Use `children` to inject app preferences
121
+ * (theme, language, …) above the account actions.
122
+ */
123
+ declare function AccountMenu({ user, labels, onSignOut, onSwitchAccount, onSignIn, align, children, }: AccountMenuProps): React.JSX.Element;
124
+ /** Two-letter avatar fallback from a name or email. Shared with shell NavUser. */
125
+ declare function initialsOf(value?: string | null): string;
126
+
86
127
  declare function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">): React.JSX.Element;
87
128
  declare function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">): React.JSX.Element;
88
129
  declare function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">): React.JSX.Element;
@@ -93,4 +134,4 @@ declare function BreadcrumbPage({ className, ...props }: React.ComponentProps<"s
93
134
  declare function BreadcrumbSeparator({ children, className, ...props }: React.ComponentProps<"li">): React.JSX.Element;
94
135
  declare function BreadcrumbEllipsis({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
95
136
 
96
- export { SidebarMenuSubItem as A, Breadcrumb as B, SidebarRail as C, SidebarSeparator as D, SidebarTrigger as E, TooltipContent as F, TooltipProvider as G, TooltipTrigger as H, Input as I, buttonVariants as J, useSidebar as K, SidebarProvider as S, Tooltip as T, SidebarInset as a, Button as b, Separator as c, BreadcrumbEllipsis as d, BreadcrumbItem as e, BreadcrumbLink as f, BreadcrumbList as g, BreadcrumbPage as h, BreadcrumbSeparator as i, Sidebar as j, SidebarContent as k, SidebarFooter as l, SidebarGroup as m, SidebarGroupAction as n, SidebarGroupContent as o, SidebarGroupLabel as p, SidebarHeader as q, SidebarInput as r, SidebarMenu as s, SidebarMenuAction as t, SidebarMenuBadge as u, SidebarMenuButton as v, SidebarMenuItem as w, SidebarMenuSkeleton as x, SidebarMenuSub as y, SidebarMenuSubButton as z };
137
+ export { type AccountMenuUser as A, Breadcrumb as B, SidebarMenuSkeleton as C, SidebarMenuSub as D, SidebarMenuSubButton as E, SidebarMenuSubItem as F, SidebarRail as G, SidebarSeparator as H, Input as I, SidebarTrigger as J, TooltipContent as K, TooltipProvider as L, TooltipTrigger as M, buttonVariants as N, defaultAccountMenuLabels as O, initialsOf as P, useSidebar as Q, SidebarProvider as S, Tooltip as T, SidebarInset as a, Sidebar as b, type AccountMenuLabels as c, Button as d, Separator as e, AccountMenu as f, type AccountMenuProps as g, BreadcrumbEllipsis as h, BreadcrumbItem as i, BreadcrumbLink as j, BreadcrumbList as k, BreadcrumbPage as l, BreadcrumbSeparator as m, SidebarContent as n, SidebarFooter as o, SidebarGroup as p, SidebarGroupAction as q, SidebarGroupContent as r, SidebarGroupLabel as s, SidebarHeader as t, SidebarInput as u, SidebarMenu as v, SidebarMenuAction as w, SidebarMenuBadge as x, SidebarMenuButton as y, SidebarMenuItem as z };
@@ -1,12 +1,108 @@
1
1
  import { useMobile } from './chunk-QYA2HGKW.js';
2
+ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuItem } from './chunk-VEWKPOMS.js';
2
3
  import { Button } from './chunk-KFQOYZ64.js';
3
4
  import { cn } from './chunk-XH55BHUU.js';
4
- import * as React6 from 'react';
5
- import { Slot, Separator as Separator$1, Dialog, Tooltip as Tooltip$1 } from 'radix-ui';
6
- import { ChevronRightIcon, MoreHorizontalIcon, XIcon, PanelLeftIcon } from 'lucide-react';
7
- import { jsx, jsxs } from 'react/jsx-runtime';
5
+ import * as React9 from 'react';
6
+ import { Avatar as Avatar$1, Slot, Separator as Separator$1, ContextMenu as ContextMenu$1, ScrollArea as ScrollArea$1, Dialog, Tooltip as Tooltip$1 } from 'radix-ui';
7
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
+ import { ChevronRightIcon, MoreHorizontalIcon, CheckIcon, XIcon, PanelLeftIcon, CircleUser, Users, LogOut, LogIn } from 'lucide-react';
8
9
  import { cva } from 'class-variance-authority';
9
10
 
11
+ function Avatar({
12
+ className,
13
+ size = "default",
14
+ ...props
15
+ }) {
16
+ return /* @__PURE__ */ jsx(
17
+ Avatar$1.Root,
18
+ {
19
+ "data-slot": "avatar",
20
+ "data-size": size,
21
+ className: cn(
22
+ "group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten",
23
+ className
24
+ ),
25
+ ...props
26
+ }
27
+ );
28
+ }
29
+ function AvatarImage({
30
+ className,
31
+ ...props
32
+ }) {
33
+ return /* @__PURE__ */ jsx(
34
+ Avatar$1.Image,
35
+ {
36
+ "data-slot": "avatar-image",
37
+ className: cn(
38
+ "aspect-square size-full rounded-full object-cover",
39
+ className
40
+ ),
41
+ ...props
42
+ }
43
+ );
44
+ }
45
+ function AvatarFallback({
46
+ className,
47
+ ...props
48
+ }) {
49
+ return /* @__PURE__ */ jsx(
50
+ Avatar$1.Fallback,
51
+ {
52
+ "data-slot": "avatar-fallback",
53
+ className: cn(
54
+ "flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs",
55
+ className
56
+ ),
57
+ ...props
58
+ }
59
+ );
60
+ }
61
+ function AvatarBadge({ className, ...props }) {
62
+ return /* @__PURE__ */ jsx(
63
+ "span",
64
+ {
65
+ "data-slot": "avatar-badge",
66
+ className: cn(
67
+ "absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none",
68
+ "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden",
69
+ "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2",
70
+ "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2",
71
+ className
72
+ ),
73
+ ...props
74
+ }
75
+ );
76
+ }
77
+ function AvatarGroup({ className, ...props }) {
78
+ return /* @__PURE__ */ jsx(
79
+ "div",
80
+ {
81
+ "data-slot": "avatar-group",
82
+ className: cn(
83
+ "group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background",
84
+ className
85
+ ),
86
+ ...props
87
+ }
88
+ );
89
+ }
90
+ function AvatarGroupCount({
91
+ className,
92
+ ...props
93
+ }) {
94
+ return /* @__PURE__ */ jsx(
95
+ "div",
96
+ {
97
+ "data-slot": "avatar-group-count",
98
+ className: cn(
99
+ "relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-xs text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3",
100
+ className
101
+ ),
102
+ ...props
103
+ }
104
+ );
105
+ }
10
106
  function Breadcrumb({ className, ...props }) {
11
107
  return /* @__PURE__ */ jsx(
12
108
  "nav",
@@ -145,6 +241,224 @@ function Input({ className, type, ...props }) {
145
241
  }
146
242
  );
147
243
  }
244
+ function ContextMenu({ ...props }) {
245
+ return /* @__PURE__ */ jsx(ContextMenu$1.Root, { "data-slot": "context-menu", ...props });
246
+ }
247
+ function ContextMenuTrigger({ className, ...props }) {
248
+ return /* @__PURE__ */ jsx(ContextMenu$1.Trigger, { "data-slot": "context-menu-trigger", className: cn("select-none", className), ...props });
249
+ }
250
+ function ContextMenuGroup({ ...props }) {
251
+ return /* @__PURE__ */ jsx(ContextMenu$1.Group, { "data-slot": "context-menu-group", ...props });
252
+ }
253
+ function ContextMenuPortal({ ...props }) {
254
+ return /* @__PURE__ */ jsx(ContextMenu$1.Portal, { "data-slot": "context-menu-portal", ...props });
255
+ }
256
+ function ContextMenuSub({ ...props }) {
257
+ return /* @__PURE__ */ jsx(ContextMenu$1.Sub, { "data-slot": "context-menu-sub", ...props });
258
+ }
259
+ function ContextMenuRadioGroup({ ...props }) {
260
+ return /* @__PURE__ */ jsx(ContextMenu$1.RadioGroup, { "data-slot": "context-menu-radio-group", ...props });
261
+ }
262
+ function ContextMenuContent({
263
+ className,
264
+ ...props
265
+ }) {
266
+ return /* @__PURE__ */ jsx(ContextMenu$1.Portal, { children: /* @__PURE__ */ jsx(
267
+ ContextMenu$1.Content,
268
+ {
269
+ "data-slot": "context-menu-content",
270
+ className: cn(
271
+ "z-50 max-h-(--radix-context-menu-content-available-height) min-w-36 origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-none bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
272
+ className
273
+ ),
274
+ ...props
275
+ }
276
+ ) });
277
+ }
278
+ function ContextMenuItem({
279
+ className,
280
+ inset,
281
+ variant = "default",
282
+ ...props
283
+ }) {
284
+ return /* @__PURE__ */ jsx(
285
+ ContextMenu$1.Item,
286
+ {
287
+ "data-slot": "context-menu-item",
288
+ "data-inset": inset,
289
+ "data-variant": variant,
290
+ className: cn(
291
+ "group/context-menu-item relative flex cursor-default items-center gap-2 rounded-none px-2 py-2 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 focus:*:[svg]:text-accent-foreground data-[variant=destructive]:*:[svg]:text-destructive",
292
+ className
293
+ ),
294
+ ...props
295
+ }
296
+ );
297
+ }
298
+ function ContextMenuSubTrigger({
299
+ className,
300
+ inset,
301
+ children,
302
+ ...props
303
+ }) {
304
+ return /* @__PURE__ */ jsxs(
305
+ ContextMenu$1.SubTrigger,
306
+ {
307
+ "data-slot": "context-menu-sub-trigger",
308
+ "data-inset": inset,
309
+ className: cn(
310
+ "flex cursor-default items-center gap-2 rounded-none px-2 py-2 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
311
+ className
312
+ ),
313
+ ...props,
314
+ children: [
315
+ children,
316
+ /* @__PURE__ */ jsx(ChevronRightIcon, { className: "ml-auto" })
317
+ ]
318
+ }
319
+ );
320
+ }
321
+ function ContextMenuSubContent({ className, ...props }) {
322
+ return /* @__PURE__ */ jsx(
323
+ ContextMenu$1.SubContent,
324
+ {
325
+ "data-slot": "context-menu-sub-content",
326
+ className: cn(
327
+ "z-50 min-w-32 origin-(--radix-context-menu-content-transform-origin) overflow-hidden rounded-none border bg-popover text-popover-foreground shadow-lg duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
328
+ className
329
+ ),
330
+ ...props
331
+ }
332
+ );
333
+ }
334
+ function ContextMenuCheckboxItem({
335
+ className,
336
+ children,
337
+ checked,
338
+ inset,
339
+ ...props
340
+ }) {
341
+ return /* @__PURE__ */ jsxs(
342
+ ContextMenu$1.CheckboxItem,
343
+ {
344
+ "data-slot": "context-menu-checkbox-item",
345
+ "data-inset": inset,
346
+ className: cn(
347
+ "relative flex cursor-default items-center gap-2 rounded-none py-2 pr-8 pl-2 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
348
+ className
349
+ ),
350
+ checked,
351
+ ...props,
352
+ children: [
353
+ /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute right-2", children: /* @__PURE__ */ jsx(ContextMenu$1.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, {}) }) }),
354
+ children
355
+ ]
356
+ }
357
+ );
358
+ }
359
+ function ContextMenuRadioItem({
360
+ className,
361
+ children,
362
+ inset,
363
+ ...props
364
+ }) {
365
+ return /* @__PURE__ */ jsxs(
366
+ ContextMenu$1.RadioItem,
367
+ {
368
+ "data-slot": "context-menu-radio-item",
369
+ "data-inset": inset,
370
+ className: cn(
371
+ "relative flex cursor-default items-center gap-2 rounded-none py-2 pr-8 pl-2 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
372
+ className
373
+ ),
374
+ ...props,
375
+ children: [
376
+ /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute right-2", children: /* @__PURE__ */ jsx(ContextMenu$1.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, {}) }) }),
377
+ children
378
+ ]
379
+ }
380
+ );
381
+ }
382
+ function ContextMenuLabel({
383
+ className,
384
+ inset,
385
+ ...props
386
+ }) {
387
+ return /* @__PURE__ */ jsx(
388
+ ContextMenu$1.Label,
389
+ {
390
+ "data-slot": "context-menu-label",
391
+ "data-inset": inset,
392
+ className: cn("px-2 py-2 text-xs text-muted-foreground data-inset:pl-7", className),
393
+ ...props
394
+ }
395
+ );
396
+ }
397
+ function ContextMenuSeparator({ className, ...props }) {
398
+ return /* @__PURE__ */ jsx(ContextMenu$1.Separator, { "data-slot": "context-menu-separator", className: cn("-mx-1 h-px bg-border", className), ...props });
399
+ }
400
+ function ContextMenuShortcut({ className, ...props }) {
401
+ return /* @__PURE__ */ jsx(
402
+ "span",
403
+ {
404
+ "data-slot": "context-menu-shortcut",
405
+ className: cn("ml-auto text-xs tracking-widest text-muted-foreground group-focus/context-menu-item:text-accent-foreground", className),
406
+ ...props
407
+ }
408
+ );
409
+ }
410
+ function ScrollArea({
411
+ className,
412
+ children,
413
+ ...props
414
+ }) {
415
+ return /* @__PURE__ */ jsxs(
416
+ ScrollArea$1.Root,
417
+ {
418
+ "data-slot": "scroll-area",
419
+ className: cn("relative", className),
420
+ ...props,
421
+ children: [
422
+ /* @__PURE__ */ jsx(
423
+ ScrollArea$1.Viewport,
424
+ {
425
+ "data-slot": "scroll-area-viewport",
426
+ className: "size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1",
427
+ children
428
+ }
429
+ ),
430
+ /* @__PURE__ */ jsx(ScrollBar, {}),
431
+ /* @__PURE__ */ jsx(ScrollArea$1.Corner, {})
432
+ ]
433
+ }
434
+ );
435
+ }
436
+ function ScrollBar({
437
+ className,
438
+ orientation = "vertical",
439
+ ...props
440
+ }) {
441
+ return /* @__PURE__ */ jsx(
442
+ ScrollArea$1.ScrollAreaScrollbar,
443
+ {
444
+ "data-slot": "scroll-area-scrollbar",
445
+ "data-orientation": orientation,
446
+ orientation,
447
+ className: cn(
448
+ "flex touch-none p-px transition-colors select-none data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent",
449
+ className
450
+ ),
451
+ ...props,
452
+ children: /* @__PURE__ */ jsx(
453
+ ScrollArea$1.ScrollAreaThumb,
454
+ {
455
+ "data-slot": "scroll-area-thumb",
456
+ className: "relative flex-1 rounded-none bg-border"
457
+ }
458
+ )
459
+ }
460
+ );
461
+ }
148
462
  function Sheet({ ...props }) {
149
463
  return /* @__PURE__ */ jsx(Dialog.Root, { "data-slot": "sheet", ...props });
150
464
  }
@@ -331,9 +645,9 @@ var SIDEBAR_WIDTH = "16rem";
331
645
  var SIDEBAR_WIDTH_MOBILE = "18rem";
332
646
  var SIDEBAR_WIDTH_ICON = "3rem";
333
647
  var SIDEBAR_KEYBOARD_SHORTCUT = "b";
334
- var SidebarContext = React6.createContext(null);
648
+ var SidebarContext = React9.createContext(null);
335
649
  function useSidebar() {
336
- const context = React6.useContext(SidebarContext);
650
+ const context = React9.useContext(SidebarContext);
337
651
  if (!context) {
338
652
  throw new Error("useSidebar must be used within a SidebarProvider.");
339
653
  }
@@ -349,10 +663,10 @@ function SidebarProvider({
349
663
  ...props
350
664
  }) {
351
665
  const isMobile = useMobile();
352
- const [openMobile, setOpenMobile] = React6.useState(false);
353
- const [_open, _setOpen] = React6.useState(defaultOpen);
666
+ const [openMobile, setOpenMobile] = React9.useState(false);
667
+ const [_open, _setOpen] = React9.useState(defaultOpen);
354
668
  const open = openProp ?? _open;
355
- const setOpen = React6.useCallback(
669
+ const setOpen = React9.useCallback(
356
670
  (value) => {
357
671
  const openState = typeof value === "function" ? value(open) : value;
358
672
  if (setOpenProp) {
@@ -364,10 +678,10 @@ function SidebarProvider({
364
678
  },
365
679
  [setOpenProp, open]
366
680
  );
367
- const toggleSidebar = React6.useCallback(() => {
681
+ const toggleSidebar = React9.useCallback(() => {
368
682
  return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
369
683
  }, [isMobile, setOpen, setOpenMobile]);
370
- React6.useEffect(() => {
684
+ React9.useEffect(() => {
371
685
  const handleKeyDown = (event) => {
372
686
  if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
373
687
  event.preventDefault();
@@ -378,7 +692,7 @@ function SidebarProvider({
378
692
  return () => window.removeEventListener("keydown", handleKeyDown);
379
693
  }, [toggleSidebar]);
380
694
  const state = open ? "expanded" : "collapsed";
381
- const contextValue = React6.useMemo(
695
+ const contextValue = React9.useMemo(
382
696
  () => ({
383
697
  state,
384
698
  open,
@@ -822,7 +1136,7 @@ function SidebarMenuSkeleton({
822
1136
  showIcon = false,
823
1137
  ...props
824
1138
  }) {
825
- const [width] = React6.useState(() => {
1139
+ const [width] = React9.useState(() => {
826
1140
  return `${Math.floor(Math.random() * 40) + 50}%`;
827
1141
  });
828
1142
  return /* @__PURE__ */ jsxs(
@@ -905,7 +1219,92 @@ function SidebarMenuSubButton({
905
1219
  }
906
1220
  );
907
1221
  }
1222
+ var defaultAccountMenuLabels = {
1223
+ account: "Account",
1224
+ guest: "Guest",
1225
+ signIn: "Sign in",
1226
+ switchAccount: "Switch account",
1227
+ signOut: "Sign out"
1228
+ };
1229
+ function AccountMenu({
1230
+ user,
1231
+ labels,
1232
+ onSignOut,
1233
+ onSwitchAccount,
1234
+ onSignIn,
1235
+ align = "end",
1236
+ children
1237
+ }) {
1238
+ const l = { ...defaultAccountMenuLabels, ...labels };
1239
+ const displayName = user?.name ?? user?.email ?? l.account;
1240
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
1241
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: user ? /* @__PURE__ */ jsxs(
1242
+ "button",
1243
+ {
1244
+ type: "button",
1245
+ "aria-label": l.account,
1246
+ className: cn(
1247
+ "focus-visible:ring-ring flex items-center gap-3 rounded-none outline-none focus-visible:ring-2"
1248
+ ),
1249
+ children: [
1250
+ /* @__PURE__ */ jsxs("span", { className: "hidden text-right leading-tight sm:flex sm:flex-col", children: [
1251
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: user.name ?? "\u2014" }),
1252
+ user.email ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-xs", children: user.email }) : null
1253
+ ] }),
1254
+ /* @__PURE__ */ jsxs(Avatar, { children: [
1255
+ user.image ? /* @__PURE__ */ jsx(AvatarImage, { src: user.image, alt: displayName }) : null,
1256
+ /* @__PURE__ */ jsx(AvatarFallback, { children: initialsOf(user.name ?? user.email) })
1257
+ ] })
1258
+ ]
1259
+ }
1260
+ ) : /* @__PURE__ */ jsxs(
1261
+ "button",
1262
+ {
1263
+ type: "button",
1264
+ "aria-label": l.account,
1265
+ className: cn(
1266
+ "focus-visible:ring-ring text-muted-foreground flex items-center gap-2 rounded-none outline-none focus-visible:ring-2"
1267
+ ),
1268
+ children: [
1269
+ /* @__PURE__ */ jsx("span", { className: "hidden text-sm sm:inline", children: l.guest }),
1270
+ /* @__PURE__ */ jsx(CircleUser, { className: "size-7" })
1271
+ ]
1272
+ }
1273
+ ) }),
1274
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align, className: "w-56", children: [
1275
+ user ? /* @__PURE__ */ jsxs(DropdownMenuLabel, { className: "flex flex-col gap-0.5", children: [
1276
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium leading-tight", children: user.name ?? "\u2014" }),
1277
+ user.email ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-xs font-normal leading-tight", children: user.email }) : null
1278
+ ] }) : /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "text-muted-foreground font-normal", children: l.guest }),
1279
+ children ? /* @__PURE__ */ jsxs(Fragment, { children: [
1280
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
1281
+ children
1282
+ ] }) : null,
1283
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
1284
+ user ? /* @__PURE__ */ jsxs(Fragment, { children: [
1285
+ onSwitchAccount ? /* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: onSwitchAccount, children: [
1286
+ /* @__PURE__ */ jsx(Users, { className: "mr-2" }),
1287
+ l.switchAccount
1288
+ ] }) : null,
1289
+ onSignOut ? /* @__PURE__ */ jsxs(DropdownMenuItem, { variant: "destructive", onSelect: onSignOut, children: [
1290
+ /* @__PURE__ */ jsx(LogOut, { className: "mr-2" }),
1291
+ l.signOut
1292
+ ] }) : null
1293
+ ] }) : onSignIn ? /* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: onSignIn, children: [
1294
+ /* @__PURE__ */ jsx(LogIn, { className: "mr-2" }),
1295
+ l.signIn
1296
+ ] }) : null
1297
+ ] })
1298
+ ] });
1299
+ }
1300
+ function initialsOf(value) {
1301
+ if (!value) return "?";
1302
+ const base = value.includes("@") ? value.split("@")[0] ?? value : value;
1303
+ const parts = base.split(/[\s._-]+/).filter(Boolean);
1304
+ const letters = (parts[0]?.[0] ?? "") + (parts[1]?.[0] ?? "");
1305
+ return (letters || base.slice(0, 2)).toUpperCase();
1306
+ }
908
1307
 
909
- export { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Input, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, useSidebar };
910
- //# sourceMappingURL=chunk-E2QCV5QI.js.map
911
- //# sourceMappingURL=chunk-E2QCV5QI.js.map
1308
+ export { AccountMenu, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, Input, ScrollArea, ScrollBar, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, defaultAccountMenuLabels, initialsOf, useSidebar };
1309
+ //# sourceMappingURL=chunk-5UAFV75V.js.map
1310
+ //# sourceMappingURL=chunk-5UAFV75V.js.map