@caffeinebounce/ui 0.62.2

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.
Files changed (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -0
  3. package/dist/FinancialStatementTable-BNUrdTU4.d.cts +249 -0
  4. package/dist/FinancialStatementTable-BNUrdTU4.d.ts +249 -0
  5. package/dist/NewsletterSignup-BPreFi5W.d.cts +37 -0
  6. package/dist/NewsletterSignup-BPreFi5W.d.ts +37 -0
  7. package/dist/TestimonialsSection-DtPu2OeR.d.ts +736 -0
  8. package/dist/TestimonialsSection-z-yotRfv.d.cts +736 -0
  9. package/dist/UnifiedTableControls-CG299y9h.d.ts +1233 -0
  10. package/dist/UnifiedTableControls-CIjRpNhy.d.cts +1233 -0
  11. package/dist/blog.d.cts +99 -0
  12. package/dist/blog.d.ts +99 -0
  13. package/dist/blog.js +292 -0
  14. package/dist/blog.mjs +279 -0
  15. package/dist/button-BHnoRUkF.d.cts +34 -0
  16. package/dist/button-BHnoRUkF.d.ts +34 -0
  17. package/dist/charts.d.cts +80 -0
  18. package/dist/charts.d.ts +80 -0
  19. package/dist/charts.js +19 -0
  20. package/dist/charts.mjs +2 -0
  21. package/dist/chunk-33JR5SYE.js +44 -0
  22. package/dist/chunk-3NDB4YPC.js +247 -0
  23. package/dist/chunk-5RW4PYZ6.js +1504 -0
  24. package/dist/chunk-5THF4YP6.mjs +155 -0
  25. package/dist/chunk-6BUBNZPG.mjs +164 -0
  26. package/dist/chunk-6DVWMJ3H.mjs +7029 -0
  27. package/dist/chunk-6TGV2DNP.js +120 -0
  28. package/dist/chunk-72JGQ7IJ.mjs +1498 -0
  29. package/dist/chunk-7DHKQODW.mjs +2932 -0
  30. package/dist/chunk-7IKHZKAC.js +160 -0
  31. package/dist/chunk-ADIDI7AJ.js +11 -0
  32. package/dist/chunk-BFWX5GJZ.mjs +940 -0
  33. package/dist/chunk-BMFQG6RA.mjs +5537 -0
  34. package/dist/chunk-C4UT5V3P.js +65 -0
  35. package/dist/chunk-CC4KUIKC.js +2004 -0
  36. package/dist/chunk-D3QXPL47.mjs +1814 -0
  37. package/dist/chunk-DQWHYBV2.js +36 -0
  38. package/dist/chunk-E42B4GSB.js +993 -0
  39. package/dist/chunk-ESZ7CBA2.js +1007 -0
  40. package/dist/chunk-EYJJQVV4.js +111 -0
  41. package/dist/chunk-FRRS2YZH.mjs +129 -0
  42. package/dist/chunk-G5TQWWQA.mjs +37 -0
  43. package/dist/chunk-GAIQJCAZ.js +5612 -0
  44. package/dist/chunk-GMBGWOCR.mjs +48 -0
  45. package/dist/chunk-GUSTCU2W.mjs +105 -0
  46. package/dist/chunk-HBLKVQIQ.mjs +23 -0
  47. package/dist/chunk-HMAMMC72.js +26 -0
  48. package/dist/chunk-IMKLN273.mjs +9 -0
  49. package/dist/chunk-J6OLBSZR.js +250 -0
  50. package/dist/chunk-JAE45W2T.js +28 -0
  51. package/dist/chunk-JORVSG52.js +606 -0
  52. package/dist/chunk-KB7UXIQZ.mjs +984 -0
  53. package/dist/chunk-KGGQ5NZV.js +186 -0
  54. package/dist/chunk-KHCC5UKW.mjs +22 -0
  55. package/dist/chunk-KRRIRS6A.mjs +1945 -0
  56. package/dist/chunk-LQCVRWVF.js +48 -0
  57. package/dist/chunk-MHZXUOGN.mjs +168 -0
  58. package/dist/chunk-MPZFPU4X.js +349 -0
  59. package/dist/chunk-MVYRNJA6.js +74 -0
  60. package/dist/chunk-N6AFNFZR.mjs +565 -0
  61. package/dist/chunk-OFQLWSUR.mjs +214 -0
  62. package/dist/chunk-OLAAXLXY.mjs +219 -0
  63. package/dist/chunk-OZZWDIOY.js +1859 -0
  64. package/dist/chunk-PZRI43EZ.js +111 -0
  65. package/dist/chunk-Q256HRYD.js +176 -0
  66. package/dist/chunk-Q52ZEL62.mjs +223 -0
  67. package/dist/chunk-R26Y7LGJ.js +142 -0
  68. package/dist/chunk-RBUYW6QQ.js +39 -0
  69. package/dist/chunk-RVEFPVZF.mjs +43 -0
  70. package/dist/chunk-SORWLKOK.js +96 -0
  71. package/dist/chunk-STEP6C4C.mjs +33 -0
  72. package/dist/chunk-T5R6HUDG.mjs +22 -0
  73. package/dist/chunk-T6ZBA6VJ.js +7109 -0
  74. package/dist/chunk-UM7WMXIU.js +2995 -0
  75. package/dist/chunk-VBD4Q5LL.mjs +117 -0
  76. package/dist/chunk-WOITB4JL.js +195 -0
  77. package/dist/chunk-YKZEKJMZ.mjs +71 -0
  78. package/dist/chunk-YL7RZRHM.mjs +103 -0
  79. package/dist/chunk-YSLD2HLP.mjs +346 -0
  80. package/dist/chunk-ZFLZA7UP.mjs +140 -0
  81. package/dist/chunk-ZKUIUE7W.mjs +26 -0
  82. package/dist/chunk-ZOA7B32D.js +248 -0
  83. package/dist/data-table.d.cts +46 -0
  84. package/dist/data-table.d.ts +46 -0
  85. package/dist/data-table.js +270 -0
  86. package/dist/data-table.mjs +13 -0
  87. package/dist/editor.d.cts +89 -0
  88. package/dist/editor.d.ts +89 -0
  89. package/dist/editor.js +10 -0
  90. package/dist/editor.mjs +1 -0
  91. package/dist/forms.d.cts +142 -0
  92. package/dist/forms.d.ts +142 -0
  93. package/dist/forms.js +24 -0
  94. package/dist/forms.mjs +11 -0
  95. package/dist/hooks-8ORd7T1A.d.cts +751 -0
  96. package/dist/hooks-B2jU1GVT.d.ts +751 -0
  97. package/dist/hooks.d.cts +6 -0
  98. package/dist/hooks.d.ts +6 -0
  99. package/dist/hooks.js +99 -0
  100. package/dist/hooks.mjs +10 -0
  101. package/dist/index.d.cts +3141 -0
  102. package/dist/index.d.ts +3141 -0
  103. package/dist/index.js +7332 -0
  104. package/dist/index.mjs +5876 -0
  105. package/dist/layouts-DPfDDF53.d.cts +1001 -0
  106. package/dist/layouts-DPfDDF53.d.ts +1001 -0
  107. package/dist/layouts.d.cts +4 -0
  108. package/dist/layouts.d.ts +4 -0
  109. package/dist/layouts.js +100 -0
  110. package/dist/layouts.mjs +11 -0
  111. package/dist/marketing-3d.d.cts +51 -0
  112. package/dist/marketing-3d.d.ts +51 -0
  113. package/dist/marketing-3d.js +553 -0
  114. package/dist/marketing-3d.mjs +526 -0
  115. package/dist/marketing.d.cts +583 -0
  116. package/dist/marketing.d.ts +583 -0
  117. package/dist/marketing.js +299 -0
  118. package/dist/marketing.mjs +10 -0
  119. package/dist/media.d.cts +29 -0
  120. package/dist/media.d.ts +29 -0
  121. package/dist/media.js +189 -0
  122. package/dist/media.mjs +182 -0
  123. package/dist/navigation.d.cts +591 -0
  124. package/dist/navigation.d.ts +591 -0
  125. package/dist/navigation.js +108 -0
  126. package/dist/navigation.mjs +15 -0
  127. package/dist/portal.d.cts +58 -0
  128. package/dist/portal.d.ts +58 -0
  129. package/dist/portal.js +403 -0
  130. package/dist/portal.mjs +395 -0
  131. package/dist/primitives.d.cts +508 -0
  132. package/dist/primitives.d.ts +508 -0
  133. package/dist/primitives.js +295 -0
  134. package/dist/primitives.mjs +14 -0
  135. package/dist/settings.d.cts +216 -0
  136. package/dist/settings.d.ts +216 -0
  137. package/dist/settings.js +34 -0
  138. package/dist/settings.mjs +9 -0
  139. package/dist/shared-Dqn36QHZ.d.cts +4 -0
  140. package/dist/shared-Dqn36QHZ.d.ts +4 -0
  141. package/dist/styles.css +1213 -0
  142. package/package.json +189 -0
  143. package/styles.css +1 -0
@@ -0,0 +1,1814 @@
1
+ import { NewsletterSignup } from './chunk-ZFLZA7UP.mjs';
2
+ import { Container } from './chunk-RVEFPVZF.mjs';
3
+ import { SidebarMenu, SidebarMenuItem, SidebarMenuButton, KeyboardShortcut, useSidebar, Avatar, AvatarImage, AvatarFallback, UserAvatarMenu } from './chunk-BFWX5GJZ.mjs';
4
+ import { Separator } from './chunk-ZKUIUE7W.mjs';
5
+ import { Spinner } from './chunk-HBLKVQIQ.mjs';
6
+ import { useScrollDirection } from './chunk-G5TQWWQA.mjs';
7
+ import { Button } from './chunk-VBD4Q5LL.mjs';
8
+ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator } from './chunk-OFQLWSUR.mjs';
9
+ import { Tooltip, TooltipTrigger, TooltipContent } from './chunk-YKZEKJMZ.mjs';
10
+ import { Input } from './chunk-STEP6C4C.mjs';
11
+ import { getAvatarGradient } from './chunk-MHZXUOGN.mjs';
12
+ import { cn } from './chunk-IMKLN273.mjs';
13
+ import * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';
14
+ export { NavigationMenuPrimitive };
15
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
16
+ import { ChevronsUpDown, Check, Plus, ChevronDown, X } from 'lucide-react';
17
+ import Image from 'next/image';
18
+ import { usePathname, useRouter } from 'next/navigation';
19
+ import { useState, useMemo, useCallback, useEffect, useRef, useLayoutEffect, useId } from 'react';
20
+ import { useReducedMotion, motion, useAnimation } from 'motion/react';
21
+
22
+ function NavigationMenu({
23
+ className,
24
+ ...props
25
+ }) {
26
+ return /* @__PURE__ */ jsx(
27
+ NavigationMenuPrimitive.Root,
28
+ {
29
+ "data-slot": "navigation-menu",
30
+ className: cn(
31
+ "relative z-10 flex max-w-max flex-1 items-center justify-center",
32
+ className
33
+ ),
34
+ ...props
35
+ }
36
+ );
37
+ }
38
+ function NavigationMenuList({
39
+ className,
40
+ ...props
41
+ }) {
42
+ return /* @__PURE__ */ jsx(
43
+ NavigationMenuPrimitive.List,
44
+ {
45
+ "data-slot": "navigation-menu-list",
46
+ className: cn(
47
+ "group flex flex-1 list-none items-center justify-center gap-1",
48
+ className
49
+ ),
50
+ ...props
51
+ }
52
+ );
53
+ }
54
+ function NavigationMenuItem({
55
+ className,
56
+ ...props
57
+ }) {
58
+ return /* @__PURE__ */ jsx(
59
+ NavigationMenuPrimitive.Item,
60
+ {
61
+ "data-slot": "navigation-menu-item",
62
+ className: cn("relative", className),
63
+ ...props
64
+ }
65
+ );
66
+ }
67
+ function NavigationMenuTrigger({
68
+ className,
69
+ children,
70
+ ...props
71
+ }) {
72
+ return /* @__PURE__ */ jsx(
73
+ NavigationMenuPrimitive.Trigger,
74
+ {
75
+ "data-slot": "navigation-menu-trigger",
76
+ className: cn(navigationMenuTriggerStyle(), className),
77
+ ...props,
78
+ children
79
+ }
80
+ );
81
+ }
82
+ function NavigationMenuContent({
83
+ className,
84
+ ...props
85
+ }) {
86
+ return /* @__PURE__ */ jsx(
87
+ NavigationMenuPrimitive.Content,
88
+ {
89
+ "data-slot": "navigation-menu-content",
90
+ className: cn(
91
+ "absolute top-full left-0 z-50 w-max min-w-full rounded-md border bg-popover p-2 text-popover-foreground shadow-lg",
92
+ "data-[motion=from-end]:animate-in data-[motion=from-start]:animate-in data-[motion=to-end]:animate-out data-[motion=to-start]:animate-out",
93
+ "data-[motion=from-end]:slide-in-from-right-4 data-[motion=from-start]:slide-in-from-left-4 data-[motion=to-end]:slide-out-to-right-4 data-[motion=to-start]:slide-out-to-left-4",
94
+ className
95
+ ),
96
+ ...props
97
+ }
98
+ );
99
+ }
100
+ function NavigationMenuLink({
101
+ className,
102
+ ...props
103
+ }) {
104
+ return /* @__PURE__ */ jsx(
105
+ NavigationMenuPrimitive.Link,
106
+ {
107
+ "data-slot": "navigation-menu-link",
108
+ className: cn(
109
+ "block select-none rounded-sm px-2 py-1.5 text-sm leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
110
+ className
111
+ ),
112
+ ...props
113
+ }
114
+ );
115
+ }
116
+ function NavigationMenuIndicator({
117
+ className,
118
+ ...props
119
+ }) {
120
+ return /* @__PURE__ */ jsx(
121
+ NavigationMenuPrimitive.Indicator,
122
+ {
123
+ "data-slot": "navigation-menu-indicator",
124
+ className: cn(
125
+ "top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in",
126
+ className
127
+ ),
128
+ ...props,
129
+ children: /* @__PURE__ */ jsx("div", { className: "relative top-[60%] size-2 rotate-45 rounded-tl-sm bg-border shadow-md" })
130
+ }
131
+ );
132
+ }
133
+ function NavigationMenuViewport({
134
+ className,
135
+ ...props
136
+ }) {
137
+ return /* @__PURE__ */ jsx("div", { className: "absolute top-full left-0 flex justify-center", children: /* @__PURE__ */ jsx(
138
+ NavigationMenuPrimitive.Viewport,
139
+ {
140
+ "data-slot": "navigation-menu-viewport",
141
+ className: cn(
142
+ "origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]",
143
+ className
144
+ ),
145
+ ...props
146
+ }
147
+ ) });
148
+ }
149
+ function navigationMenuTriggerStyle() {
150
+ return cn(
151
+ "group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-3 py-2 text-sm font-medium transition-colors",
152
+ "hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50"
153
+ );
154
+ }
155
+ var NavigationMenuViewportPrimitive = NavigationMenuPrimitive.Viewport;
156
+ function AppSwitcher({
157
+ apps,
158
+ brandName = "App",
159
+ brandLogoUrl,
160
+ getActiveAppId,
161
+ ShortcutComponent,
162
+ className
163
+ }) {
164
+ const pathname = usePathname();
165
+ const router = useRouter();
166
+ const [open, setOpen] = useState(false);
167
+ const Shortcut = ShortcutComponent || KeyboardShortcut;
168
+ const activeApp = useMemo(() => {
169
+ if (getActiveAppId) {
170
+ const activeId = getActiveAppId(pathname);
171
+ return apps.find((app) => app.id === activeId) || apps[0] || null;
172
+ }
173
+ const matchedApp = apps.find((app) => pathname.startsWith(app.route));
174
+ return matchedApp || apps[0] || null;
175
+ }, [apps, pathname, getActiveAppId]);
176
+ const handleSelect = useCallback(
177
+ (app) => {
178
+ if (app.id !== activeApp?.id) {
179
+ router.push(app.route);
180
+ }
181
+ setOpen(false);
182
+ },
183
+ [activeApp?.id, router]
184
+ );
185
+ useEffect(() => {
186
+ const handleKeyDown = (event) => {
187
+ if (event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) {
188
+ const num = Number.parseInt(event.key, 10);
189
+ if (num >= 1 && num <= 9 && num <= apps.length) {
190
+ event.preventDefault();
191
+ const app = apps[num - 1];
192
+ if (app) {
193
+ handleSelect(app);
194
+ }
195
+ }
196
+ }
197
+ };
198
+ window.addEventListener("keydown", handleKeyDown);
199
+ return () => window.removeEventListener("keydown", handleKeyDown);
200
+ }, [apps, handleSelect]);
201
+ if (!activeApp) {
202
+ return null;
203
+ }
204
+ return /* @__PURE__ */ jsx(SidebarMenu, { className, children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(DropdownMenu, { open, onOpenChange: setOpen, children: [
205
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
206
+ SidebarMenuButton,
207
+ {
208
+ size: "lg",
209
+ className: "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
210
+ children: [
211
+ /* @__PURE__ */ jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-primary/10", children: brandLogoUrl ? /* @__PURE__ */ jsx(
212
+ Image,
213
+ {
214
+ src: brandLogoUrl,
215
+ alt: brandName,
216
+ width: 32,
217
+ height: 32,
218
+ priority: true,
219
+ loading: "eager",
220
+ fetchPriority: "high",
221
+ sizes: "32px",
222
+ className: "h-8 w-8 rounded-lg object-contain"
223
+ }
224
+ ) : /* @__PURE__ */ jsx("div", { className: "h-8 w-8 rounded-lg bg-primary/10" }) }),
225
+ /* @__PURE__ */ jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
226
+ /* @__PURE__ */ jsx("span", { className: "truncate font-semibold", children: brandName }),
227
+ /* @__PURE__ */ jsx(
228
+ "span",
229
+ {
230
+ className: `truncate text-xs font-medium uppercase tracking-wider ${activeApp.colorClass}`,
231
+ children: activeApp.shortName
232
+ }
233
+ )
234
+ ] }),
235
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: "ml-auto h-4 w-4 opacity-50" })
236
+ ]
237
+ }
238
+ ) }),
239
+ /* @__PURE__ */ jsxs(
240
+ DropdownMenuContent,
241
+ {
242
+ className: "w-[calc(var(--sidebar-width)-1rem)] min-w-[220px] rounded-lg p-1",
243
+ align: "start",
244
+ side: "bottom",
245
+ sideOffset: 4,
246
+ children: [
247
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "text-xs text-muted-foreground font-normal uppercase tracking-wide px-2 py-1.5", children: "Switch App" }),
248
+ apps.map((app, index) => {
249
+ const isActive = app.id === activeApp.id;
250
+ const shortcutNumber = index < 9 ? index + 1 : null;
251
+ return /* @__PURE__ */ jsxs(
252
+ DropdownMenuItem,
253
+ {
254
+ onClick: () => handleSelect(app),
255
+ className: "gap-2 p-2 cursor-pointer rounded-md",
256
+ children: [
257
+ /* @__PURE__ */ jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center", children: brandLogoUrl ? /* @__PURE__ */ jsx(
258
+ Image,
259
+ {
260
+ src: brandLogoUrl,
261
+ alt: brandName,
262
+ width: 32,
263
+ height: 32,
264
+ className: "h-8 w-8 rounded-lg"
265
+ }
266
+ ) : /* @__PURE__ */ jsx("div", { className: "h-8 w-8 rounded-lg bg-primary/10" }) }),
267
+ /* @__PURE__ */ jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
268
+ /* @__PURE__ */ jsx("span", { className: "truncate font-semibold", children: brandName }),
269
+ /* @__PURE__ */ jsx(
270
+ "span",
271
+ {
272
+ className: `truncate text-xs font-medium uppercase tracking-wider ${app.colorClass}`,
273
+ children: app.shortName
274
+ }
275
+ )
276
+ ] }),
277
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
278
+ shortcutNumber && /* @__PURE__ */ jsxs(Shortcut, { className: "text-xs text-muted-foreground", children: [
279
+ "\u2303",
280
+ shortcutNumber
281
+ ] }),
282
+ isActive && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-primary" })
283
+ ] })
284
+ ]
285
+ },
286
+ app.id
287
+ );
288
+ })
289
+ ]
290
+ }
291
+ )
292
+ ] }) }) });
293
+ }
294
+ function ComingSoonButton({
295
+ label,
296
+ icon,
297
+ shortcutKey,
298
+ shortcutsVisible = true,
299
+ tooltip = "Coming Soon",
300
+ className
301
+ }) {
302
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
303
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
304
+ "button",
305
+ {
306
+ type: "button",
307
+ disabled: true,
308
+ className: cn(
309
+ "group inline-flex h-8 cursor-not-allowed items-center justify-center gap-1 rounded-lg border border-border bg-muted/50 px-2 text-xs font-normal text-muted-foreground opacity-60 transition-colors",
310
+ className
311
+ ),
312
+ "aria-label": `${label} (${tooltip})`,
313
+ children: [
314
+ icon && /* @__PURE__ */ jsx("span", { className: "h-3.5 w-3.5 transition-transform duration-200 group-hover:scale-110 [&>svg]:h-full [&>svg]:w-full", children: icon }),
315
+ /* @__PURE__ */ jsx("span", { children: label }),
316
+ shortcutKey && /* @__PURE__ */ jsx(
317
+ KeyboardShortcut,
318
+ {
319
+ visible: shortcutsVisible,
320
+ className: "ml-0.5 hidden uppercase md:inline-flex",
321
+ children: shortcutKey
322
+ }
323
+ )
324
+ ]
325
+ }
326
+ ) }),
327
+ /* @__PURE__ */ jsx(TooltipContent, { side: "bottom", children: tooltip })
328
+ ] });
329
+ }
330
+ function defaultGetInitials(name) {
331
+ return name.split(" ").filter((word) => word.length > 0).map((word) => word[0]).join("").slice(0, 2).toUpperCase();
332
+ }
333
+ function matchesShortcut(event, shortcut) {
334
+ const ctrlMatch = shortcut.ctrl ? event.ctrlKey : !event.ctrlKey;
335
+ const shiftMatch = shortcut.shift ? event.shiftKey : !event.shiftKey;
336
+ const altMatch = shortcut.alt ? event.altKey : !event.altKey;
337
+ const metaMatch = shortcut.meta ? event.metaKey : !event.metaKey;
338
+ const keyMatch = event.key === shortcut.key;
339
+ return ctrlMatch && shiftMatch && altMatch && metaMatch && keyMatch;
340
+ }
341
+ function EntitySwitcher({
342
+ entities,
343
+ activeEntity,
344
+ onSelect,
345
+ onAddNew,
346
+ loading = false,
347
+ userId,
348
+ label = "Items",
349
+ addNewLabel = "Add New",
350
+ emptyTitle = "Add Item",
351
+ emptySubtitle = "Get started",
352
+ getDisplayName = (entity) => entity.name,
353
+ getInitials = (entity) => defaultGetInitials(entity.name),
354
+ enableKeyboardShortcuts = false,
355
+ openShortcut,
356
+ openShortcutDisplay,
357
+ side = "bottom",
358
+ align = "start",
359
+ className,
360
+ ShortcutComponent
361
+ }) {
362
+ const Shortcut = ShortcutComponent || KeyboardShortcut;
363
+ const [open, setOpen] = useState(false);
364
+ const [logoHovered, setLogoHovered] = useState(false);
365
+ const { state: sidebarState } = useSidebar();
366
+ const isCollapsed = sidebarState === "collapsed";
367
+ const handleKeyDown = useCallback(
368
+ (event) => {
369
+ if (!enableKeyboardShortcuts) return;
370
+ if (openShortcut && matchesShortcut(event, openShortcut)) {
371
+ event.preventDefault();
372
+ setOpen((prev) => !prev);
373
+ return;
374
+ }
375
+ if (event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) {
376
+ const num = Number.parseInt(event.key, 10);
377
+ if (num >= 1 && num <= 9 && num <= entities.length) {
378
+ event.preventDefault();
379
+ const entity = entities[num - 1];
380
+ if (entity) {
381
+ onSelect(entity);
382
+ setOpen(false);
383
+ }
384
+ }
385
+ }
386
+ },
387
+ [entities, onSelect, enableKeyboardShortcuts, openShortcut]
388
+ );
389
+ useEffect(() => {
390
+ if (!enableKeyboardShortcuts) return;
391
+ window.addEventListener("keydown", handleKeyDown);
392
+ return () => window.removeEventListener("keydown", handleKeyDown);
393
+ }, [handleKeyDown, enableKeyboardShortcuts]);
394
+ if (loading) {
395
+ return /* @__PURE__ */ jsx(SidebarMenu, { className, children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(SidebarMenuButton, { size: "lg", disabled: true, children: [
396
+ /* @__PURE__ */ jsx("div", { className: "flex h-8 w-8 items-center justify-center", children: /* @__PURE__ */ jsx(Spinner, { size: "sm" }) }),
397
+ /* @__PURE__ */ jsx("div", { className: "grid min-w-0 flex-1 text-left text-sm leading-tight group-data-[collapsible=icon]:hidden", children: /* @__PURE__ */ jsx("span", { className: "truncate text-muted-foreground", children: "Loading..." }) })
398
+ ] }) }) });
399
+ }
400
+ if (!activeEntity) {
401
+ const gradientId = userId || "default";
402
+ return /* @__PURE__ */ jsx(SidebarMenu, { className, children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(SidebarMenuButton, { size: "lg", onClick: onAddNew, disabled: !onAddNew, children: [
403
+ /* @__PURE__ */ jsx(
404
+ "div",
405
+ {
406
+ className: "flex h-8 w-8 items-center justify-center rounded-lg text-white",
407
+ style: getAvatarGradient(gradientId).style,
408
+ children: /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" })
409
+ }
410
+ ),
411
+ /* @__PURE__ */ jsxs("div", { className: "grid min-w-0 flex-1 text-left text-sm leading-tight group-data-[collapsible=icon]:hidden", children: [
412
+ /* @__PURE__ */ jsx("span", { className: "truncate font-semibold", children: emptyTitle }),
413
+ /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-muted-foreground", children: emptySubtitle })
414
+ ] })
415
+ ] }) }) });
416
+ }
417
+ const displayName = getDisplayName(activeEntity);
418
+ const initials = getInitials(activeEntity);
419
+ return /* @__PURE__ */ jsx(SidebarMenu, { className, children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(DropdownMenu, { open, onOpenChange: setOpen, children: [
420
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
421
+ SidebarMenuButton,
422
+ {
423
+ size: "lg",
424
+ className: "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
425
+ style: isCollapsed ? { background: "transparent" } : void 0,
426
+ onMouseEnter: () => isCollapsed && setLogoHovered(true),
427
+ onMouseLeave: () => setLogoHovered(false),
428
+ children: [
429
+ /* @__PURE__ */ jsx("div", { className: "relative flex h-8 w-8 shrink-0 items-center justify-center", children: /* @__PURE__ */ jsxs(
430
+ Avatar,
431
+ {
432
+ className: "h-8 w-8 rounded-lg",
433
+ style: {
434
+ transition: "transform 150ms ease, filter 150ms ease",
435
+ transform: isCollapsed && logoHovered ? "scale(1.1)" : "scale(1)",
436
+ filter: isCollapsed && logoHovered ? "brightness(1.2)" : "none"
437
+ },
438
+ children: [
439
+ activeEntity.logoUrl && /* @__PURE__ */ jsx(
440
+ AvatarImage,
441
+ {
442
+ src: activeEntity.logoUrl,
443
+ alt: displayName,
444
+ className: "object-contain p-1"
445
+ }
446
+ ),
447
+ /* @__PURE__ */ jsx(
448
+ AvatarFallback,
449
+ {
450
+ className: "rounded-lg text-xs font-medium text-white",
451
+ style: getAvatarGradient(activeEntity.id).style,
452
+ children: initials
453
+ }
454
+ )
455
+ ]
456
+ }
457
+ ) }),
458
+ /* @__PURE__ */ jsx("div", { className: "grid flex-1 min-w-0 text-left text-sm leading-tight group-data-[collapsible=icon]:hidden", children: /* @__PURE__ */ jsx("span", { className: "truncate font-semibold", children: displayName }) }),
459
+ openShortcutDisplay && /* @__PURE__ */ jsx(Shortcut, { className: "ml-auto hidden text-xs text-muted-foreground md:inline-flex group-data-[collapsible=icon]:hidden", children: openShortcutDisplay }),
460
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: "ml-1 group-data-[collapsible=icon]:hidden" })
461
+ ]
462
+ }
463
+ ) }),
464
+ /* @__PURE__ */ jsxs(
465
+ DropdownMenuContent,
466
+ {
467
+ className: "w-[calc(var(--sidebar-width)-1rem)] rounded-lg",
468
+ align,
469
+ side,
470
+ sideOffset: 4,
471
+ children: [
472
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "text-xs text-muted-foreground font-light uppercase tracking-wide", children: label }),
473
+ entities.map((entity, index) => {
474
+ const name = getDisplayName(entity);
475
+ const entityInitials = getInitials(entity);
476
+ const shortcutNumber = enableKeyboardShortcuts && index < 9 ? index + 1 : null;
477
+ const isActive = entity.id === activeEntity.id;
478
+ return /* @__PURE__ */ jsxs(
479
+ DropdownMenuItem,
480
+ {
481
+ onClick: () => onSelect(entity),
482
+ className: "gap-2 p-2",
483
+ children: [
484
+ /* @__PURE__ */ jsx("div", { className: "relative h-6 w-6", children: /* @__PURE__ */ jsxs(Avatar, { className: "h-6 w-6 rounded-md", children: [
485
+ entity.logoUrl && /* @__PURE__ */ jsx(
486
+ AvatarImage,
487
+ {
488
+ src: entity.logoUrl,
489
+ alt: name,
490
+ className: "object-contain p-0.5"
491
+ }
492
+ ),
493
+ /* @__PURE__ */ jsx(
494
+ AvatarFallback,
495
+ {
496
+ className: "rounded-md text-xs font-medium text-white",
497
+ style: getAvatarGradient(entity.id).style,
498
+ children: entityInitials
499
+ }
500
+ )
501
+ ] }) }),
502
+ /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: name }),
503
+ shortcutNumber && /* @__PURE__ */ jsxs(Shortcut, { className: "text-xs text-muted-foreground", children: [
504
+ "\u2303",
505
+ shortcutNumber
506
+ ] }),
507
+ isActive && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-primary" })
508
+ ]
509
+ },
510
+ entity.id
511
+ );
512
+ }),
513
+ onAddNew && /* @__PURE__ */ jsxs(Fragment, { children: [
514
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
515
+ /* @__PURE__ */ jsxs(
516
+ DropdownMenuItem,
517
+ {
518
+ className: "gap-2 p-2 group cursor-pointer",
519
+ onClick: onAddNew,
520
+ children: [
521
+ /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 text-muted-foreground group-hover:text-white" }),
522
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: addNewLabel })
523
+ ]
524
+ }
525
+ )
526
+ ] })
527
+ ]
528
+ }
529
+ )
530
+ ] }) }) });
531
+ }
532
+ function Footer({
533
+ logo,
534
+ linkGroups = [],
535
+ socialLinks = [],
536
+ copyright,
537
+ bottomContent,
538
+ className,
539
+ containerClassName,
540
+ variant = "default",
541
+ tagline,
542
+ newsletter
543
+ }) {
544
+ if (variant === "minimal") {
545
+ return /* @__PURE__ */ jsx(
546
+ MinimalFooter,
547
+ {
548
+ logo,
549
+ copyright,
550
+ socialLinks,
551
+ linkGroups,
552
+ className,
553
+ containerClassName
554
+ }
555
+ );
556
+ }
557
+ if (variant === "brand") {
558
+ return /* @__PURE__ */ jsx(
559
+ BrandFooter,
560
+ {
561
+ logo,
562
+ tagline,
563
+ newsletter: newsletter === void 0 ? {} : newsletter,
564
+ linkGroups,
565
+ socialLinks,
566
+ copyright,
567
+ bottomContent,
568
+ className,
569
+ containerClassName
570
+ }
571
+ );
572
+ }
573
+ return /* @__PURE__ */ jsx("footer", { className: cn("bg-muted/50 border-t", className), children: /* @__PURE__ */ jsxs(
574
+ Container,
575
+ {
576
+ "data-slot": "footer-container",
577
+ className: cn("py-12 md:py-16", containerClassName),
578
+ children: [
579
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col md:flex-row justify-between gap-8", children: [
580
+ logo && /* @__PURE__ */ jsxs("div", { className: "shrink-0", children: [
581
+ logo,
582
+ socialLinks.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex gap-4 mt-6", children: socialLinks.map((social) => /* @__PURE__ */ jsx(
583
+ "a",
584
+ {
585
+ href: social.href,
586
+ target: "_blank",
587
+ rel: "noopener noreferrer",
588
+ className: "text-muted-foreground hover:text-foreground transition-colors",
589
+ "aria-label": social.label,
590
+ children: social.icon
591
+ },
592
+ social.label
593
+ )) })
594
+ ] }),
595
+ linkGroups.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-12 md:gap-16", children: linkGroups.map((group) => /* @__PURE__ */ jsxs("div", { children: [
596
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground mb-4", children: group.title }),
597
+ /* @__PURE__ */ jsx("ul", { className: "space-y-3", children: group.links.map((link) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
598
+ "a",
599
+ {
600
+ href: link.href,
601
+ className: "text-sm text-muted-foreground hover:text-foreground transition-colors",
602
+ ...link.external && {
603
+ target: "_blank",
604
+ rel: "noopener noreferrer"
605
+ },
606
+ children: link.label
607
+ }
608
+ ) }, link.label)) })
609
+ ] }, group.title)) })
610
+ ] }),
611
+ (copyright || bottomContent) && /* @__PURE__ */ jsxs(Fragment, { children: [
612
+ /* @__PURE__ */ jsx(Separator, { className: "my-8" }),
613
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col md:flex-row justify-between items-center gap-4", children: [
614
+ copyright && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: copyright }),
615
+ bottomContent
616
+ ] })
617
+ ] })
618
+ ]
619
+ }
620
+ ) });
621
+ }
622
+ function BrandFooter({
623
+ logo,
624
+ tagline,
625
+ newsletter,
626
+ linkGroups = [],
627
+ socialLinks = [],
628
+ copyright,
629
+ bottomContent,
630
+ className,
631
+ containerClassName
632
+ }) {
633
+ const [isDark, setIsDark] = useState(false);
634
+ const newsletterConfig = newsletter === false ? void 0 : newsletter;
635
+ useEffect(() => {
636
+ const html = document.documentElement;
637
+ const check = () => setIsDark(html.classList.contains("dark"));
638
+ check();
639
+ const obs = new MutationObserver(check);
640
+ obs.observe(html, { attributes: true, attributeFilter: ["class"] });
641
+ return () => obs.disconnect();
642
+ }, []);
643
+ const footerBg = isDark ? "linear-gradient(to bottom, rgba(0,0,0,0.5), rgba(0,0,0,0.9))" : "linear-gradient(to bottom, color-mix(in oklch, var(--color-primary, #6366f1) 4%, var(--color-background, #fff)), color-mix(in oklch, var(--color-primary, #6366f1) 8%, var(--color-muted, #f5f5f5)))";
644
+ return /* @__PURE__ */ jsxs(
645
+ "footer",
646
+ {
647
+ className: cn("backdrop-blur-2xl", className),
648
+ style: {
649
+ background: footerBg,
650
+ borderTop: "1px solid var(--color-border, hsl(var(--border)))"
651
+ },
652
+ children: [
653
+ /* @__PURE__ */ jsx(
654
+ "div",
655
+ {
656
+ style: {
657
+ height: "1px",
658
+ background: "linear-gradient(to right, transparent, color-mix(in oklch, var(--color-primary, #6366f1) 30%, transparent), transparent)"
659
+ }
660
+ }
661
+ ),
662
+ /* @__PURE__ */ jsxs(
663
+ Container,
664
+ {
665
+ "data-slot": "footer-container",
666
+ className: cn("py-16 md:py-20", containerClassName),
667
+ children: [
668
+ (logo || tagline || newsletterConfig) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col md:flex-row justify-between items-start gap-8 mb-12", children: [
669
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
670
+ logo,
671
+ tagline && /* @__PURE__ */ jsx("p", { className: "text-base text-muted-foreground max-w-sm", children: tagline })
672
+ ] }),
673
+ newsletterConfig && /* @__PURE__ */ jsx(FooterNewsletterForm, { newsletter: newsletterConfig })
674
+ ] }),
675
+ linkGroups.length > 0 && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-8 lg:gap-12 mb-12", children: linkGroups.map((group) => /* @__PURE__ */ jsxs("div", { children: [
676
+ /* @__PURE__ */ jsx("h3", { className: "text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-4", children: group.title }),
677
+ /* @__PURE__ */ jsx("ul", { className: "space-y-3", children: group.links.map((link) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
678
+ "a",
679
+ {
680
+ href: link.href,
681
+ className: "text-sm text-muted-foreground/80 hover:text-foreground transition-colors",
682
+ ...link.external && {
683
+ target: "_blank",
684
+ rel: "noopener noreferrer"
685
+ },
686
+ children: link.label
687
+ }
688
+ ) }, link.label)) })
689
+ ] }, group.title)) }),
690
+ /* @__PURE__ */ jsx(Separator, { className: "mb-8" }),
691
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col md:flex-row justify-between items-center gap-4", children: [
692
+ copyright && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: copyright }),
693
+ socialLinks.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: socialLinks.map((social) => /* @__PURE__ */ jsx(
694
+ "a",
695
+ {
696
+ href: social.href,
697
+ target: "_blank",
698
+ rel: "noopener noreferrer",
699
+ className: "inline-flex h-10 w-10 items-center justify-center text-muted-foreground transition-colors hover:text-foreground",
700
+ "data-slot": "footer-social-link",
701
+ "aria-label": social.label,
702
+ children: social.icon
703
+ },
704
+ social.label
705
+ )) }),
706
+ bottomContent
707
+ ] })
708
+ ]
709
+ }
710
+ )
711
+ ]
712
+ }
713
+ );
714
+ }
715
+ function FooterNewsletterForm({
716
+ newsletter
717
+ }) {
718
+ if (newsletter.onSubmit && !newsletter.endpoint) {
719
+ return /* @__PURE__ */ jsx(FooterNewsletterCallbackForm, { newsletter });
720
+ }
721
+ return /* @__PURE__ */ jsx(
722
+ NewsletterSignup,
723
+ {
724
+ buttonClassName: cn("shrink-0", newsletter.buttonClassName),
725
+ buttonLabel: newsletter.buttonText ?? "Subscribe",
726
+ className: "w-full max-w-sm",
727
+ endpoint: newsletter.endpoint,
728
+ errorMessage: newsletter.errorMessage,
729
+ inputClassName: newsletter.inputClassName,
730
+ inputLabel: newsletter.inputLabel,
731
+ placeholder: newsletter.placeholder,
732
+ source: newsletter.source,
733
+ submittingLabel: newsletter.submittingLabel,
734
+ successClassName: newsletter.successClassName,
735
+ successDescription: newsletter.successDescription,
736
+ successTitle: newsletter.successTitle
737
+ }
738
+ );
739
+ }
740
+ function FooterNewsletterCallbackForm({
741
+ newsletter
742
+ }) {
743
+ const [email, setEmail] = useState("");
744
+ const handleNewsletterSubmit = (e) => {
745
+ e.preventDefault();
746
+ newsletter.onSubmit?.(email);
747
+ setEmail("");
748
+ };
749
+ return /* @__PURE__ */ jsxs(
750
+ "form",
751
+ {
752
+ onSubmit: handleNewsletterSubmit,
753
+ className: "flex gap-2 w-full max-w-sm",
754
+ children: [
755
+ /* @__PURE__ */ jsx(
756
+ Input,
757
+ {
758
+ "aria-label": newsletter.inputLabel ?? "Email address",
759
+ type: "email",
760
+ placeholder: newsletter.placeholder ?? "Enter your email",
761
+ value: email,
762
+ onChange: (e) => setEmail(e.target.value),
763
+ className: cn("flex-1", newsletter.inputClassName),
764
+ required: true
765
+ }
766
+ ),
767
+ /* @__PURE__ */ jsx(Button, { type: "submit", size: "sm", className: newsletter.buttonClassName, children: newsletter.buttonText ?? "Subscribe" })
768
+ ]
769
+ }
770
+ );
771
+ }
772
+ function MinimalFooter({
773
+ logo,
774
+ copyright,
775
+ socialLinks = [],
776
+ linkGroups = [],
777
+ className,
778
+ containerClassName
779
+ }) {
780
+ const allLinks = linkGroups.flatMap((g) => g.links);
781
+ return /* @__PURE__ */ jsx("footer", { className: cn("bg-background border-t border-border", className), children: /* @__PURE__ */ jsx(
782
+ Container,
783
+ {
784
+ "data-slot": "footer-container",
785
+ className: cn("py-6", containerClassName),
786
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-4 md:flex-row md:items-start md:justify-between", children: [
787
+ (copyright || logo) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3", children: [
788
+ copyright && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: copyright }),
789
+ logo && /* @__PURE__ */ jsx("div", { className: "shrink-0", "data-slot": "footer-logo", children: logo })
790
+ ] }),
791
+ socialLinks.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex gap-3", children: socialLinks.map((social) => /* @__PURE__ */ jsx(
792
+ "a",
793
+ {
794
+ href: social.href,
795
+ target: "_blank",
796
+ rel: "noopener noreferrer",
797
+ className: "text-muted-foreground hover:text-foreground transition-colors",
798
+ "aria-label": social.label,
799
+ children: social.icon
800
+ },
801
+ social.label
802
+ )) }),
803
+ allLinks.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex gap-4", children: allLinks.map((link) => /* @__PURE__ */ jsx(
804
+ "a",
805
+ {
806
+ href: link.href,
807
+ className: "text-sm text-muted-foreground hover:text-foreground transition-colors",
808
+ ...link.external && {
809
+ target: "_blank",
810
+ rel: "noopener noreferrer"
811
+ },
812
+ children: link.label
813
+ },
814
+ link.label
815
+ )) })
816
+ ] })
817
+ }
818
+ ) });
819
+ }
820
+ function DefaultMobileMenuIcon({
821
+ open,
822
+ reducedMotion
823
+ }) {
824
+ const controls = useAnimation();
825
+ const lineVariants = {
826
+ normal: {
827
+ opacity: 1,
828
+ rotate: 0,
829
+ y: 0
830
+ },
831
+ animate: (line) => ({
832
+ opacity: line === 2 ? 0 : 1,
833
+ rotate: line === 1 ? 45 : line === 3 ? -45 : 0,
834
+ y: line === 1 ? 6 : line === 3 ? -6 : 0,
835
+ transition: reducedMotion ? { duration: 0 } : {
836
+ damping: 20,
837
+ stiffness: 260,
838
+ type: "spring"
839
+ }
840
+ })
841
+ };
842
+ useEffect(() => {
843
+ controls.start(
844
+ open ? "animate" : "normal",
845
+ reducedMotion ? { duration: 0 } : void 0
846
+ );
847
+ }, [controls, open, reducedMotion]);
848
+ const handleMouseEnter = () => {
849
+ if (!open) {
850
+ controls.start("animate");
851
+ }
852
+ };
853
+ const handleMouseLeave = () => {
854
+ controls.start(open ? "animate" : "normal");
855
+ };
856
+ return /* @__PURE__ */ jsx(
857
+ "span",
858
+ {
859
+ "aria-hidden": "true",
860
+ "data-animation": "lucide-animated-menu",
861
+ "data-slot": "navbar-mobile-menu-icon",
862
+ "data-state": open ? "open" : "closed",
863
+ className: "relative flex h-9 w-9 items-center justify-center",
864
+ onMouseEnter: handleMouseEnter,
865
+ onMouseLeave: handleMouseLeave,
866
+ children: /* @__PURE__ */ jsx(
867
+ "svg",
868
+ {
869
+ "aria-hidden": "true",
870
+ fill: "none",
871
+ focusable: "false",
872
+ height: "20",
873
+ stroke: "currentColor",
874
+ strokeLinecap: "round",
875
+ strokeLinejoin: "round",
876
+ strokeWidth: "2",
877
+ viewBox: "0 0 24 24",
878
+ width: "20",
879
+ xmlns: "http://www.w3.org/2000/svg",
880
+ children: [1, 2, 3].map((line) => /* @__PURE__ */ jsx(
881
+ motion.line,
882
+ {
883
+ animate: controls,
884
+ custom: line,
885
+ variants: lineVariants,
886
+ x1: "4",
887
+ x2: "20",
888
+ y1: line === 1 ? "6" : line === 2 ? "12" : "18",
889
+ y2: line === 1 ? "6" : line === 2 ? "12" : "18"
890
+ },
891
+ line
892
+ ))
893
+ }
894
+ )
895
+ }
896
+ );
897
+ }
898
+ function Navbar({
899
+ logo,
900
+ preset = "default",
901
+ links = [],
902
+ menuGroups = [],
903
+ menuClassNames,
904
+ rightContent,
905
+ mobileContent,
906
+ sticky = true,
907
+ hideOnScrollDown = false,
908
+ variant = "blur",
909
+ className,
910
+ LinkComponent,
911
+ showMobileMenu = true,
912
+ mobileMenuOpenIcon,
913
+ mobileMenuClosedIcon,
914
+ mobileMenuHeight = "content",
915
+ containerClassName
916
+ }) {
917
+ const headerRef = useRef(null);
918
+ const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
919
+ const [mobileMenuTop, setMobileMenuTop] = useState(0);
920
+ const reducedMotion = useReducedMotion() ?? false;
921
+ const { direction, isAtTop } = useScrollDirection({
922
+ threshold: 10,
923
+ topThreshold: 50
924
+ });
925
+ const usesCustomMobileMenuIcons = mobileMenuOpenIcon !== void 0 || mobileMenuClosedIcon !== void 0;
926
+ const isScreenHeightMobileMenu = mobileMenuHeight === "screen";
927
+ const closeMobileMenu = () => setMobileMenuOpen(false);
928
+ const LinkEl = LinkComponent || "a";
929
+ const variantClasses = {
930
+ transparent: isAtTop ? "bg-transparent border-b border-transparent" : "bg-background/80 backdrop-blur-xl backdrop-saturate-150 border-b border-border dark:border-white/10",
931
+ solid: "bg-background border-b border-border",
932
+ blur: "bg-background/60 backdrop-blur-xl backdrop-saturate-150 border-b border-border dark:border-white/10"
933
+ };
934
+ const presetClasses = {
935
+ default: {
936
+ header: "",
937
+ mobileMenuHeader: "bg-background border-b border-border shadow-lg",
938
+ mobileMenu: "bg-background shadow-lg",
939
+ mobileMenuButton: ""
940
+ },
941
+ keenan: {
942
+ header: "border-white/10 bg-black/65 shadow-[0_18px_48px_rgba(0,0,0,0.45)] backdrop-blur-2xl",
943
+ mobileMenuHeader: "border-white/10 bg-black shadow-[0_18px_48px_rgba(0,0,0,0.45)] backdrop-blur-2xl",
944
+ mobileMenu: "border-white/10 bg-black shadow-[0_22px_56px_rgba(0,0,0,0.5)]",
945
+ mobileMenuButton: "text-white hover:bg-white/5 hover:text-white"
946
+ }
947
+ };
948
+ const shouldHide = sticky && hideOnScrollDown && !mobileMenuOpen && !isAtTop && direction === "down";
949
+ useLayoutEffect(() => {
950
+ if (!mobileMenuOpen || !isScreenHeightMobileMenu) {
951
+ setMobileMenuTop(0);
952
+ return;
953
+ }
954
+ const updateMobileMenuTop = () => {
955
+ const nextTop = Math.max(
956
+ headerRef.current?.getBoundingClientRect().bottom ?? 0,
957
+ 0
958
+ );
959
+ setMobileMenuTop(nextTop);
960
+ };
961
+ updateMobileMenuTop();
962
+ window.addEventListener("resize", updateMobileMenuTop);
963
+ window.addEventListener("scroll", updateMobileMenuTop, { passive: true });
964
+ return () => {
965
+ window.removeEventListener("resize", updateMobileMenuTop);
966
+ window.removeEventListener("scroll", updateMobileMenuTop);
967
+ };
968
+ }, [mobileMenuOpen, isScreenHeightMobileMenu]);
969
+ useEffect(() => {
970
+ if (!mobileMenuOpen || !isScreenHeightMobileMenu) {
971
+ return;
972
+ }
973
+ const previousBodyOverflow = document.body.style.overflow;
974
+ const previousHtmlOverflow = document.documentElement.style.overflow;
975
+ document.body.style.overflow = "hidden";
976
+ document.documentElement.style.overflow = "hidden";
977
+ return () => {
978
+ document.body.style.overflow = previousBodyOverflow;
979
+ document.documentElement.style.overflow = previousHtmlOverflow;
980
+ };
981
+ }, [mobileMenuOpen, isScreenHeightMobileMenu]);
982
+ const positionClass = sticky && hideOnScrollDown ? "fixed top-0 left-0 right-0" : sticky ? "sticky top-0" : "";
983
+ return /* @__PURE__ */ jsxs(
984
+ "header",
985
+ {
986
+ ref: headerRef,
987
+ "data-preset": preset,
988
+ className: cn(
989
+ "z-50 w-full transition-[transform,background-color,border-color,backdrop-filter] duration-300",
990
+ positionClass,
991
+ variantClasses[variant],
992
+ presetClasses[preset].header,
993
+ mobileMenuOpen && presetClasses[preset].mobileMenuHeader,
994
+ className
995
+ ),
996
+ style: {
997
+ transform: shouldHide ? "translateY(-100%)" : "translateY(0)"
998
+ },
999
+ children: [
1000
+ /* @__PURE__ */ jsxs(
1001
+ Container,
1002
+ {
1003
+ "data-slot": "navbar-container",
1004
+ className: cn(
1005
+ "flex h-14 items-center justify-between gap-4",
1006
+ containerClassName
1007
+ ),
1008
+ children: [
1009
+ logo,
1010
+ /* @__PURE__ */ jsxs("div", { className: "hidden md:flex items-center gap-2", children: [
1011
+ /* @__PURE__ */ jsxs("nav", { className: "flex items-center gap-6", children: [
1012
+ menuGroups.length > 0 ? /* @__PURE__ */ jsx(
1013
+ NavigationMenu,
1014
+ {
1015
+ "data-slot": "navbar-menu",
1016
+ className: cn("justify-start", menuClassNames?.root),
1017
+ children: /* @__PURE__ */ jsx(
1018
+ NavigationMenuList,
1019
+ {
1020
+ "data-slot": "navbar-menu-list",
1021
+ className: cn("justify-start gap-1", menuClassNames?.list),
1022
+ children: menuGroups.map((group, groupIndex) => /* @__PURE__ */ jsxs(
1023
+ NavigationMenuItem,
1024
+ {
1025
+ "data-slot": "navbar-menu-item",
1026
+ className: menuClassNames?.menuItem,
1027
+ children: [
1028
+ /* @__PURE__ */ jsxs(
1029
+ NavigationMenuTrigger,
1030
+ {
1031
+ "data-slot": "navbar-menu-trigger",
1032
+ className: cn(
1033
+ "gap-1.5 bg-transparent px-2 text-foreground/70 hover:bg-transparent hover:text-foreground focus:bg-transparent focus:text-foreground",
1034
+ menuClassNames?.trigger
1035
+ ),
1036
+ children: [
1037
+ group.label,
1038
+ /* @__PURE__ */ jsx(
1039
+ ChevronDown,
1040
+ {
1041
+ "aria-hidden": "true",
1042
+ className: cn(
1043
+ "relative top-px size-3.5 transition-transform duration-300 group-data-[state=open]:rotate-180",
1044
+ menuClassNames?.triggerIcon
1045
+ ),
1046
+ "data-slot": "navbar-menu-trigger-icon"
1047
+ }
1048
+ )
1049
+ ]
1050
+ }
1051
+ ),
1052
+ /* @__PURE__ */ jsxs(
1053
+ NavigationMenuContent,
1054
+ {
1055
+ "aria-label": group.ariaLabel ?? `${group.label} navigation`,
1056
+ "data-slot": "navbar-menu-content",
1057
+ className: menuClassNames?.content,
1058
+ children: [
1059
+ group.showHeading === false ? null : /* @__PURE__ */ jsx(
1060
+ "p",
1061
+ {
1062
+ className: cn(
1063
+ "px-2 py-1.5 text-xs font-semibold uppercase tracking-wide text-muted-foreground",
1064
+ menuClassNames?.heading
1065
+ ),
1066
+ children: group.label
1067
+ }
1068
+ ),
1069
+ group.links.map(
1070
+ (link) => link.external ? /* @__PURE__ */ jsx(NavigationMenuLink, { asChild: true, children: /* @__PURE__ */ jsxs(
1071
+ "a",
1072
+ {
1073
+ href: link.href,
1074
+ target: "_blank",
1075
+ rel: "noopener noreferrer",
1076
+ className: cn(
1077
+ "group flex min-w-48 items-start gap-2 whitespace-nowrap",
1078
+ menuClassNames?.item
1079
+ ),
1080
+ children: [
1081
+ link.icon,
1082
+ /* @__PURE__ */ jsxs("span", { className: "flex flex-col gap-1", children: [
1083
+ /* @__PURE__ */ jsx(
1084
+ "span",
1085
+ {
1086
+ "data-slot": "navbar-menu-item-label",
1087
+ className: menuClassNames?.itemLabel,
1088
+ children: link.label
1089
+ }
1090
+ ),
1091
+ link.description ? /* @__PURE__ */ jsx(
1092
+ "span",
1093
+ {
1094
+ "data-slot": "navbar-menu-item-description",
1095
+ className: cn(
1096
+ "max-w-72 whitespace-normal text-xs leading-5 text-muted-foreground",
1097
+ menuClassNames?.itemDescription
1098
+ ),
1099
+ children: link.description
1100
+ }
1101
+ ) : null
1102
+ ] })
1103
+ ]
1104
+ }
1105
+ ) }, link.href) : /* @__PURE__ */ jsx(NavigationMenuLink, { asChild: true, children: /* @__PURE__ */ jsxs(
1106
+ LinkEl,
1107
+ {
1108
+ href: link.href,
1109
+ className: cn(
1110
+ "group flex min-w-48 items-start gap-2 whitespace-nowrap",
1111
+ menuClassNames?.item
1112
+ ),
1113
+ children: [
1114
+ link.icon,
1115
+ /* @__PURE__ */ jsxs("span", { className: "flex flex-col gap-1", children: [
1116
+ /* @__PURE__ */ jsx(
1117
+ "span",
1118
+ {
1119
+ "data-slot": "navbar-menu-item-label",
1120
+ className: menuClassNames?.itemLabel,
1121
+ children: link.label
1122
+ }
1123
+ ),
1124
+ link.description ? /* @__PURE__ */ jsx(
1125
+ "span",
1126
+ {
1127
+ "data-slot": "navbar-menu-item-description",
1128
+ className: cn(
1129
+ "max-w-72 whitespace-normal text-xs leading-5 text-muted-foreground",
1130
+ menuClassNames?.itemDescription
1131
+ ),
1132
+ children: link.description
1133
+ }
1134
+ ) : null
1135
+ ] })
1136
+ ]
1137
+ }
1138
+ ) }, link.href)
1139
+ )
1140
+ ]
1141
+ }
1142
+ )
1143
+ ]
1144
+ },
1145
+ `${group.label}-${groupIndex}`
1146
+ ))
1147
+ }
1148
+ )
1149
+ }
1150
+ ) : null,
1151
+ links.map(
1152
+ (link) => link.external ? /* @__PURE__ */ jsxs(
1153
+ "a",
1154
+ {
1155
+ href: link.href,
1156
+ target: "_blank",
1157
+ rel: "noopener noreferrer",
1158
+ className: "flex items-center gap-1.5 text-sm text-foreground/70 hover:text-foreground transition-colors whitespace-nowrap",
1159
+ children: [
1160
+ link.icon,
1161
+ link.label
1162
+ ]
1163
+ },
1164
+ link.href
1165
+ ) : /* @__PURE__ */ jsxs(
1166
+ LinkEl,
1167
+ {
1168
+ href: link.href,
1169
+ className: "flex items-center gap-1.5 text-sm text-foreground/70 hover:text-foreground transition-colors whitespace-nowrap",
1170
+ children: [
1171
+ link.icon,
1172
+ link.label
1173
+ ]
1174
+ },
1175
+ link.href
1176
+ )
1177
+ )
1178
+ ] }),
1179
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3 ml-4", children: rightContent })
1180
+ ] }),
1181
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 md:hidden", children: [
1182
+ rightContent,
1183
+ showMobileMenu && /* @__PURE__ */ jsx(
1184
+ "button",
1185
+ {
1186
+ type: "button",
1187
+ onClick: () => setMobileMenuOpen(!mobileMenuOpen),
1188
+ "data-slot": "navbar-mobile-menu-button",
1189
+ "data-state": mobileMenuOpen ? "open" : "closed",
1190
+ className: cn(
1191
+ "inline-flex h-9 w-9 items-center justify-center rounded-box text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
1192
+ presetClasses[preset].mobileMenuButton
1193
+ ),
1194
+ "aria-label": mobileMenuOpen ? "Close menu" : "Open menu",
1195
+ "aria-expanded": mobileMenuOpen,
1196
+ children: usesCustomMobileMenuIcons ? mobileMenuOpen ? mobileMenuOpenIcon || /* @__PURE__ */ jsx(X, { className: "h-5 w-5" }) : mobileMenuClosedIcon || /* @__PURE__ */ jsx(
1197
+ DefaultMobileMenuIcon,
1198
+ {
1199
+ open: false,
1200
+ reducedMotion
1201
+ }
1202
+ ) : /* @__PURE__ */ jsx(
1203
+ DefaultMobileMenuIcon,
1204
+ {
1205
+ open: mobileMenuOpen,
1206
+ reducedMotion
1207
+ }
1208
+ )
1209
+ }
1210
+ )
1211
+ ] })
1212
+ ]
1213
+ }
1214
+ ),
1215
+ showMobileMenu && mobileMenuOpen && /* @__PURE__ */ jsx(
1216
+ "div",
1217
+ {
1218
+ "data-slot": "navbar-mobile-menu",
1219
+ "data-height": mobileMenuHeight,
1220
+ "data-preset": preset,
1221
+ className: cn(
1222
+ "md:hidden border-t border-border",
1223
+ presetClasses[preset].mobileMenu,
1224
+ isScreenHeightMobileMenu && "fixed inset-x-0 overflow-y-auto overscroll-contain"
1225
+ ),
1226
+ style: isScreenHeightMobileMenu ? {
1227
+ top: mobileMenuTop,
1228
+ height: `calc(100dvh - ${mobileMenuTop}px)`
1229
+ } : void 0,
1230
+ children: /* @__PURE__ */ jsx(
1231
+ Container,
1232
+ {
1233
+ "data-slot": "navbar-mobile-menu-container",
1234
+ className: cn(
1235
+ "py-4",
1236
+ isScreenHeightMobileMenu && "h-full",
1237
+ containerClassName
1238
+ ),
1239
+ children: /* @__PURE__ */ jsx(
1240
+ "nav",
1241
+ {
1242
+ "data-slot": "navbar-mobile-menu-content",
1243
+ className: cn(
1244
+ "flex flex-col gap-4",
1245
+ isScreenHeightMobileMenu && "min-h-full overflow-y-auto"
1246
+ ),
1247
+ children: mobileContent || /* @__PURE__ */ jsx(Fragment, { children: links.map(
1248
+ (link) => link.external ? /* @__PURE__ */ jsxs(
1249
+ "a",
1250
+ {
1251
+ href: link.href,
1252
+ target: "_blank",
1253
+ rel: "noopener noreferrer",
1254
+ className: "flex items-center gap-1.5 text-sm text-foreground/70 hover:text-foreground transition-colors py-2",
1255
+ onClick: closeMobileMenu,
1256
+ children: [
1257
+ link.icon,
1258
+ link.label
1259
+ ]
1260
+ },
1261
+ link.href
1262
+ ) : /* @__PURE__ */ jsxs(
1263
+ LinkEl,
1264
+ {
1265
+ href: link.href,
1266
+ className: "flex items-center gap-1.5 text-sm text-foreground/70 hover:text-foreground transition-colors py-2",
1267
+ onClick: closeMobileMenu,
1268
+ children: [
1269
+ link.icon,
1270
+ link.label
1271
+ ]
1272
+ },
1273
+ link.href
1274
+ )
1275
+ ) })
1276
+ }
1277
+ )
1278
+ }
1279
+ )
1280
+ }
1281
+ )
1282
+ ]
1283
+ }
1284
+ );
1285
+ }
1286
+ function renderCtaLink(cta, LinkComponent) {
1287
+ const linkProps = cta.external ? { href: cta.href, rel: "noreferrer noopener", target: "_blank" } : { href: cta.href };
1288
+ if (LinkComponent && !cta.external) {
1289
+ return /* @__PURE__ */ jsx(LinkComponent, { href: cta.href, children: cta.label });
1290
+ }
1291
+ return /* @__PURE__ */ jsx("a", { ...linkProps, children: cta.label });
1292
+ }
1293
+ function MarketingHeaderPreset({
1294
+ logo,
1295
+ links = [],
1296
+ primaryCta,
1297
+ secondaryCta,
1298
+ rightContent,
1299
+ mobileContent,
1300
+ className,
1301
+ containerClassName,
1302
+ variant = "blur",
1303
+ preset = "default",
1304
+ sticky = true,
1305
+ hideOnScrollDown = true,
1306
+ showMobileMenu = true,
1307
+ LinkComponent
1308
+ }) {
1309
+ const ctas = [secondaryCta, primaryCta].filter(
1310
+ (cta) => Boolean(cta)
1311
+ );
1312
+ const resolvedRightContent = ctas.length > 0 || rightContent ? /* @__PURE__ */ jsxs("div", { className: "hidden items-center gap-2 md:flex", children: [
1313
+ secondaryCta ? /* @__PURE__ */ jsx(Button, { asChild: true, variant: secondaryCta.variant ?? "outline", size: "sm", children: renderCtaLink(secondaryCta, LinkComponent) }) : null,
1314
+ primaryCta ? /* @__PURE__ */ jsx(Button, { asChild: true, variant: primaryCta.variant ?? "default", size: "sm", children: renderCtaLink(primaryCta, LinkComponent) }) : null,
1315
+ rightContent
1316
+ ] }) : void 0;
1317
+ const resolvedMobileContent = mobileContent || ctas.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 pt-2", children: [
1318
+ mobileContent,
1319
+ secondaryCta ? /* @__PURE__ */ jsx(
1320
+ Button,
1321
+ {
1322
+ asChild: true,
1323
+ variant: secondaryCta.variant ?? "outline",
1324
+ size: "sm",
1325
+ className: "justify-start",
1326
+ children: renderCtaLink(secondaryCta, LinkComponent)
1327
+ }
1328
+ ) : null,
1329
+ primaryCta ? /* @__PURE__ */ jsx(
1330
+ Button,
1331
+ {
1332
+ asChild: true,
1333
+ variant: primaryCta.variant ?? "default",
1334
+ size: "sm",
1335
+ className: "justify-start",
1336
+ children: renderCtaLink(primaryCta, LinkComponent)
1337
+ }
1338
+ ) : null
1339
+ ] }) : void 0;
1340
+ return /* @__PURE__ */ jsx(
1341
+ Navbar,
1342
+ {
1343
+ logo,
1344
+ links,
1345
+ rightContent: resolvedRightContent,
1346
+ mobileContent: resolvedMobileContent,
1347
+ className: cn(className),
1348
+ containerClassName,
1349
+ variant,
1350
+ preset,
1351
+ sticky,
1352
+ hideOnScrollDown,
1353
+ showMobileMenu,
1354
+ LinkComponent
1355
+ }
1356
+ );
1357
+ }
1358
+ function NavbarLogo({
1359
+ href = "/",
1360
+ imageSrc,
1361
+ imageAlt,
1362
+ text,
1363
+ imageWidth = 32,
1364
+ imageHeight = 32,
1365
+ invertInDarkMode = false,
1366
+ className,
1367
+ imageClassName,
1368
+ textClassName,
1369
+ LinkComponent,
1370
+ ImageComponent
1371
+ }) {
1372
+ const LinkEl = LinkComponent || "a";
1373
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
1374
+ ImageComponent ? /* @__PURE__ */ jsx(
1375
+ ImageComponent,
1376
+ {
1377
+ src: imageSrc,
1378
+ alt: imageAlt,
1379
+ width: imageWidth,
1380
+ height: imageHeight,
1381
+ className: cn(
1382
+ "rounded-md",
1383
+ invertInDarkMode && "dark:invert dark:brightness-100",
1384
+ imageClassName
1385
+ )
1386
+ }
1387
+ ) : /* @__PURE__ */ jsx(
1388
+ "img",
1389
+ {
1390
+ src: imageSrc,
1391
+ alt: imageAlt,
1392
+ width: imageWidth,
1393
+ height: imageHeight,
1394
+ className: cn(
1395
+ "rounded-md",
1396
+ invertInDarkMode && "dark:invert dark:brightness-100",
1397
+ imageClassName
1398
+ )
1399
+ }
1400
+ ),
1401
+ text && /* @__PURE__ */ jsx(
1402
+ "span",
1403
+ {
1404
+ className: cn(
1405
+ "text-xl font-black text-foreground/80 whitespace-nowrap uppercase tracking-tight",
1406
+ textClassName
1407
+ ),
1408
+ children: text
1409
+ }
1410
+ )
1411
+ ] });
1412
+ return /* @__PURE__ */ jsx(
1413
+ LinkEl,
1414
+ {
1415
+ href,
1416
+ className: cn(
1417
+ "flex items-center gap-2.5 transition-opacity hover:opacity-80 shrink-0",
1418
+ className
1419
+ ),
1420
+ children: content
1421
+ }
1422
+ );
1423
+ }
1424
+ function NavbarUserMenu({
1425
+ user,
1426
+ profile,
1427
+ loading = false,
1428
+ onSignOut,
1429
+ additionalItems = [],
1430
+ size = "sm",
1431
+ align = "end",
1432
+ LinkComponent
1433
+ }) {
1434
+ const menuItems = useMemo(() => {
1435
+ const items = additionalItems.map((item) => ({
1436
+ label: item.label,
1437
+ icon: item.icon,
1438
+ href: item.href,
1439
+ onClick: item.onClick,
1440
+ destructive: item.destructive,
1441
+ separatorBefore: item.separatorBefore
1442
+ }));
1443
+ items.push({
1444
+ label: "Sign Out",
1445
+ onClick: onSignOut,
1446
+ destructive: true,
1447
+ separatorBefore: items.length > 0
1448
+ });
1449
+ return items;
1450
+ }, [additionalItems, onSignOut]);
1451
+ if (loading) {
1452
+ return /* @__PURE__ */ jsx("div", { className: "inline-flex h-8 w-8 items-center justify-center rounded-md", children: /* @__PURE__ */ jsx(Spinner, { size: "sm" }) });
1453
+ }
1454
+ const metadata = user.metadata || {};
1455
+ const avatarUrl = profile?.avatarUrl || profile?.avatar_url || metadata.picture || metadata.avatar_url;
1456
+ const fullName = metadata.full_name || metadata.name || "";
1457
+ const firstName = profile?.firstName || profile?.first_name || (typeof fullName === "string" ? fullName.split(" ")[0] : "") || "";
1458
+ const lastName = profile?.lastName || profile?.last_name || (typeof fullName === "string" ? fullName.split(" ").slice(1).join(" ") : "") || "";
1459
+ const displayName = `${firstName} ${lastName}`.trim() || user.email || "User";
1460
+ const initials = `${firstName?.[0] || ""}${lastName?.[0] || ""}`.toUpperCase() || "U";
1461
+ return /* @__PURE__ */ jsx(
1462
+ UserAvatarMenu,
1463
+ {
1464
+ user: {
1465
+ id: user.id,
1466
+ email: user.email || void 0,
1467
+ avatarUrl,
1468
+ name: displayName,
1469
+ initials
1470
+ },
1471
+ items: menuItems,
1472
+ size,
1473
+ align,
1474
+ menuWidth: "w-40",
1475
+ LinkComponent,
1476
+ trigger: /* @__PURE__ */ jsxs(
1477
+ "button",
1478
+ {
1479
+ type: "button",
1480
+ className: "inline-flex h-8 w-8 items-center justify-center rounded-full focus:outline-none overflow-hidden *:hover:brightness-110 *:transition-all",
1481
+ children: [
1482
+ /* @__PURE__ */ jsxs(Avatar, { className: "h-7 w-7", children: [
1483
+ avatarUrl && /* @__PURE__ */ jsx(AvatarImage, { src: avatarUrl, alt: displayName }),
1484
+ /* @__PURE__ */ jsx(
1485
+ AvatarFallback,
1486
+ {
1487
+ className: "text-xs font-medium text-white",
1488
+ style: getAvatarGradient(user.id).style,
1489
+ children: initials
1490
+ }
1491
+ )
1492
+ ] }),
1493
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "User menu" })
1494
+ ]
1495
+ }
1496
+ )
1497
+ }
1498
+ );
1499
+ }
1500
+ function toLinkGroup(title, links) {
1501
+ return {
1502
+ title,
1503
+ links: links.map((link) => ({
1504
+ href: link.href,
1505
+ label: link.label,
1506
+ external: link.external
1507
+ }))
1508
+ };
1509
+ }
1510
+ function NonprofitFooterPreset({
1511
+ logo,
1512
+ tagline,
1513
+ supportTitle = "Support",
1514
+ supportLinks = [],
1515
+ legalTitle = "Legal",
1516
+ legalLinks = [],
1517
+ socialLinks = [],
1518
+ newsletter,
1519
+ copyright,
1520
+ bottomContent,
1521
+ className,
1522
+ containerClassName
1523
+ }) {
1524
+ const linkGroups = [];
1525
+ if (supportLinks.length > 0) {
1526
+ linkGroups.push(toLinkGroup(supportTitle, supportLinks));
1527
+ }
1528
+ if (legalLinks.length > 0) {
1529
+ linkGroups.push(toLinkGroup(legalTitle, legalLinks));
1530
+ }
1531
+ return /* @__PURE__ */ jsx(
1532
+ Footer,
1533
+ {
1534
+ variant: "brand",
1535
+ logo,
1536
+ tagline,
1537
+ newsletter,
1538
+ linkGroups,
1539
+ socialLinks,
1540
+ copyright,
1541
+ bottomContent,
1542
+ className,
1543
+ containerClassName
1544
+ }
1545
+ );
1546
+ }
1547
+ var DEFAULT_ARIA_LABEL = "Section switcher";
1548
+ function matchesPath(pathname, href, match = "prefix") {
1549
+ if (match === "exact") {
1550
+ return pathname === href;
1551
+ }
1552
+ if (pathname === href) {
1553
+ return true;
1554
+ }
1555
+ if (href === "/") {
1556
+ return pathname === href;
1557
+ }
1558
+ return pathname.startsWith(`${href}/`);
1559
+ }
1560
+ function getFirstEnabledId(items) {
1561
+ return items.find((item) => !item.disabled)?.id ?? null;
1562
+ }
1563
+ function getLongestRouteMatch(items, pathname) {
1564
+ const matches = items.filter((item) => !item.disabled).filter((item) => matchesPath(pathname, item.href, item.match)).sort((a, b) => b.href.length - a.href.length);
1565
+ return matches[0]?.id ?? null;
1566
+ }
1567
+ function normalizeActiveId(items, id) {
1568
+ if (!id) {
1569
+ return null;
1570
+ }
1571
+ const activeItem = items.find((item) => item.id === id && !item.disabled);
1572
+ return activeItem?.id ?? null;
1573
+ }
1574
+ function getIndicatorTransition(reducedMotion) {
1575
+ if (reducedMotion) {
1576
+ return { duration: 0 };
1577
+ }
1578
+ return {
1579
+ type: "spring",
1580
+ stiffness: 520,
1581
+ damping: 40,
1582
+ mass: 0.6
1583
+ };
1584
+ }
1585
+ function DefaultLinkComponent({
1586
+ href,
1587
+ className,
1588
+ children,
1589
+ onClick,
1590
+ ...props
1591
+ }) {
1592
+ return /* @__PURE__ */ jsx("a", { href, className, onClick, ...props, children });
1593
+ }
1594
+ function SegmentedSwitcher({
1595
+ items,
1596
+ value,
1597
+ defaultValue,
1598
+ onValueChange,
1599
+ variant = "investor",
1600
+ showTrackBorder = true,
1601
+ showTrackBackground = true,
1602
+ ariaLabel = DEFAULT_ARIA_LABEL,
1603
+ className
1604
+ }) {
1605
+ const reducedMotion = useReducedMotion() ?? false;
1606
+ const indicatorLayoutId = `segmented-switcher-indicator-${useId().replaceAll(
1607
+ ":",
1608
+ ""
1609
+ )}`;
1610
+ const [uncontrolledValue, setUncontrolledValue] = useState(
1611
+ () => {
1612
+ return normalizeActiveId(items, defaultValue) ?? getFirstEnabledId(items);
1613
+ }
1614
+ );
1615
+ const isControlled = value !== void 0;
1616
+ const firstEnabledId = useMemo(() => getFirstEnabledId(items), [items]);
1617
+ useEffect(() => {
1618
+ if (isControlled) {
1619
+ return;
1620
+ }
1621
+ const nextValue = normalizeActiveId(items, uncontrolledValue) ?? normalizeActiveId(items, defaultValue) ?? firstEnabledId;
1622
+ if (nextValue !== uncontrolledValue) {
1623
+ setUncontrolledValue(nextValue);
1624
+ }
1625
+ }, [defaultValue, firstEnabledId, isControlled, items, uncontrolledValue]);
1626
+ const activeId = normalizeActiveId(items, isControlled ? value : uncontrolledValue) ?? normalizeActiveId(items, defaultValue) ?? firstEnabledId;
1627
+ const transition = getIndicatorTransition(reducedMotion);
1628
+ function handleSelect(item) {
1629
+ if (item.disabled) {
1630
+ return;
1631
+ }
1632
+ if (!isControlled) {
1633
+ setUncontrolledValue(item.id);
1634
+ }
1635
+ if (item.id !== activeId) {
1636
+ onValueChange?.(item.id);
1637
+ }
1638
+ }
1639
+ if (items.length === 0) {
1640
+ return null;
1641
+ }
1642
+ return /* @__PURE__ */ jsx(
1643
+ "nav",
1644
+ {
1645
+ "aria-label": ariaLabel,
1646
+ "data-slot": "segmented-switcher",
1647
+ "data-variant": variant,
1648
+ "data-track-border": showTrackBorder ? void 0 : "false",
1649
+ "data-track-background": showTrackBackground ? void 0 : "false",
1650
+ "data-reduced-motion": reducedMotion ? "true" : void 0,
1651
+ className: cn(className),
1652
+ children: /* @__PURE__ */ jsx("div", { "data-slot": "segmented-switcher-track", children: items.map((item) => {
1653
+ const isActive = activeId === item.id;
1654
+ const isDisabled = item.disabled === true;
1655
+ if (item.href) {
1656
+ return /* @__PURE__ */ jsxs(
1657
+ "a",
1658
+ {
1659
+ href: item.href,
1660
+ "data-slot": "segmented-switcher-item",
1661
+ "data-active": isActive ? "true" : void 0,
1662
+ "data-disabled": isDisabled ? "true" : void 0,
1663
+ "aria-disabled": isDisabled || void 0,
1664
+ tabIndex: isDisabled ? -1 : void 0,
1665
+ onClick: (event) => {
1666
+ if (isDisabled) {
1667
+ event.preventDefault();
1668
+ return;
1669
+ }
1670
+ handleSelect(item);
1671
+ },
1672
+ children: [
1673
+ isActive && /* @__PURE__ */ jsx(
1674
+ motion.span,
1675
+ {
1676
+ layoutId: indicatorLayoutId,
1677
+ transition,
1678
+ "data-slot": "segmented-switcher-indicator",
1679
+ "aria-hidden": "true"
1680
+ }
1681
+ ),
1682
+ /* @__PURE__ */ jsx("span", { "data-slot": "segmented-switcher-item-label", children: item.label })
1683
+ ]
1684
+ },
1685
+ item.id
1686
+ );
1687
+ }
1688
+ return /* @__PURE__ */ jsxs(
1689
+ "button",
1690
+ {
1691
+ type: "button",
1692
+ "data-slot": "segmented-switcher-item",
1693
+ "data-active": isActive ? "true" : void 0,
1694
+ "data-disabled": isDisabled ? "true" : void 0,
1695
+ disabled: isDisabled,
1696
+ "aria-pressed": isActive,
1697
+ onClick: () => handleSelect(item),
1698
+ children: [
1699
+ isActive && /* @__PURE__ */ jsx(
1700
+ motion.span,
1701
+ {
1702
+ layoutId: indicatorLayoutId,
1703
+ transition,
1704
+ "data-slot": "segmented-switcher-indicator",
1705
+ "aria-hidden": "true"
1706
+ }
1707
+ ),
1708
+ /* @__PURE__ */ jsx("span", { "data-slot": "segmented-switcher-item-label", children: item.label })
1709
+ ]
1710
+ },
1711
+ item.id
1712
+ );
1713
+ }) })
1714
+ }
1715
+ );
1716
+ }
1717
+ function RouteSegmentedSwitcherWithPathname(props) {
1718
+ const pathname = usePathname() ?? "/";
1719
+ return /* @__PURE__ */ jsx(RouteSegmentedSwitcherInner, { ...props, pathname });
1720
+ }
1721
+ function RouteSegmentedSwitcherInner({
1722
+ items,
1723
+ pathname,
1724
+ value,
1725
+ onValueChange,
1726
+ LinkComponent,
1727
+ variant = "investor",
1728
+ showTrackBorder = true,
1729
+ showTrackBackground = true,
1730
+ ariaLabel = DEFAULT_ARIA_LABEL,
1731
+ className
1732
+ }) {
1733
+ const reducedMotion = useReducedMotion() ?? false;
1734
+ const indicatorLayoutId = `segmented-switcher-indicator-${useId().replaceAll(
1735
+ ":",
1736
+ ""
1737
+ )}`;
1738
+ const LinkEl = LinkComponent ?? DefaultLinkComponent;
1739
+ const visibleItems = useMemo(
1740
+ () => items.filter((item) => item.enabled !== false),
1741
+ [items]
1742
+ );
1743
+ const firstEnabledId = useMemo(
1744
+ () => getFirstEnabledId(visibleItems),
1745
+ [visibleItems]
1746
+ );
1747
+ const activeId = normalizeActiveId(visibleItems, value) ?? getLongestRouteMatch(visibleItems, pathname) ?? firstEnabledId;
1748
+ const transition = getIndicatorTransition(reducedMotion);
1749
+ function handleClick(event, item) {
1750
+ if (item.disabled) {
1751
+ event.preventDefault();
1752
+ return;
1753
+ }
1754
+ if (item.id !== activeId) {
1755
+ onValueChange?.(item.id);
1756
+ }
1757
+ }
1758
+ if (visibleItems.length === 0) {
1759
+ return null;
1760
+ }
1761
+ return /* @__PURE__ */ jsx(
1762
+ "nav",
1763
+ {
1764
+ "aria-label": ariaLabel,
1765
+ "data-slot": "segmented-switcher",
1766
+ "data-variant": variant,
1767
+ "data-track-border": showTrackBorder ? void 0 : "false",
1768
+ "data-track-background": showTrackBackground ? void 0 : "false",
1769
+ "data-reduced-motion": reducedMotion ? "true" : void 0,
1770
+ className: cn(className),
1771
+ children: /* @__PURE__ */ jsx("div", { "data-slot": "segmented-switcher-track", children: visibleItems.map((item) => {
1772
+ const isActive = activeId === item.id;
1773
+ const isDisabled = item.disabled === true;
1774
+ return /* @__PURE__ */ jsxs(
1775
+ LinkEl,
1776
+ {
1777
+ href: item.href,
1778
+ "data-slot": "segmented-switcher-item",
1779
+ "data-active": isActive ? "true" : void 0,
1780
+ "data-disabled": isDisabled ? "true" : void 0,
1781
+ "aria-current": isActive ? "page" : void 0,
1782
+ "aria-disabled": isDisabled || void 0,
1783
+ tabIndex: isDisabled ? -1 : void 0,
1784
+ onClick: (event) => handleClick(event, item),
1785
+ children: [
1786
+ isActive && /* @__PURE__ */ jsx(
1787
+ motion.span,
1788
+ {
1789
+ layoutId: indicatorLayoutId,
1790
+ transition,
1791
+ "data-slot": "segmented-switcher-indicator",
1792
+ "aria-hidden": "true"
1793
+ }
1794
+ ),
1795
+ /* @__PURE__ */ jsx("span", { "data-slot": "segmented-switcher-item-label", children: item.label })
1796
+ ]
1797
+ },
1798
+ item.id
1799
+ );
1800
+ }) })
1801
+ }
1802
+ );
1803
+ }
1804
+ function RouteSegmentedSwitcher({
1805
+ pathname,
1806
+ ...props
1807
+ }) {
1808
+ if (pathname !== void 0) {
1809
+ return /* @__PURE__ */ jsx(RouteSegmentedSwitcherInner, { ...props, pathname });
1810
+ }
1811
+ return /* @__PURE__ */ jsx(RouteSegmentedSwitcherWithPathname, { ...props });
1812
+ }
1813
+
1814
+ export { AppSwitcher, ComingSoonButton, EntitySwitcher, Footer, MarketingHeaderPreset, Navbar, NavbarLogo, NavbarUserMenu, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NavigationMenuViewportPrimitive, NonprofitFooterPreset, RouteSegmentedSwitcher, SegmentedSwitcher, navigationMenuTriggerStyle };