@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,1945 @@
1
+ import { Tabs, TabsList, TabsTrigger, TabsContent } from './chunk-GMBGWOCR.mjs';
2
+ import { SidebarTrigger, Sidebar, SidebarHeader, SidebarContent, SidebarSeparator, SidebarGroup, SidebarGroupContent, SidebarMenu, SidebarMenuItem, SidebarMenuButton, SidebarGroupLabel, SidebarFooter, UserAvatarMenu, Avatar, AvatarImage, AvatarFallback, SidebarRail, useSidebar, SidebarProvider, SidebarInset, KeyboardShortcut } from './chunk-BFWX5GJZ.mjs';
3
+ import { Spinner } from './chunk-HBLKVQIQ.mjs';
4
+ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from './chunk-OFQLWSUR.mjs';
5
+ import { Tooltip, TooltipTrigger, TooltipContent } from './chunk-YKZEKJMZ.mjs';
6
+ import { getAvatarGradient } from './chunk-MHZXUOGN.mjs';
7
+ import { cn } from './chunk-IMKLN273.mjs';
8
+ import { normalizeMicrosoftClarityProjectId, getMicrosoftClarityScriptUrl, normalizeGoogleTagManagerContainerId, getGoogleTagManagerScriptUrl, getGoogleTagManagerNoScriptUrl } from '@caffeinebounce/shared-utils';
9
+ import * as React from 'react';
10
+ import { useEffect, useState, useCallback, useMemo, useRef } from 'react';
11
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
12
+ import { ArrowLeft, Monitor, Sun, Moon, CircleHelp, Info, LogOut, ChevronDown, ChevronUp, User, Home, ChevronRight, Search, X, History, Link2 as Link2$1, Loader2, Check, Clock, AlertCircle } from 'lucide-react';
13
+ import Link2 from 'next/link';
14
+ import { useTheme as useTheme$1 } from 'next-themes';
15
+ import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
16
+ import { Toaster as Toaster$1 } from 'sonner';
17
+
18
+ function ClarityAnalytics({
19
+ projectId,
20
+ enabled = true
21
+ }) {
22
+ useEffect(() => {
23
+ if (!enabled) {
24
+ return;
25
+ }
26
+ const normalizedProjectId = normalizeMicrosoftClarityProjectId(projectId);
27
+ if (!normalizedProjectId) {
28
+ if (projectId?.trim()) {
29
+ console.warn(
30
+ `Invalid Microsoft Clarity project ID: ${projectId}. Expected letters, numbers, underscores, or dashes.`
31
+ );
32
+ }
33
+ return;
34
+ }
35
+ if (window.clarity) {
36
+ return;
37
+ }
38
+ const queuedClarity = (...args) => {
39
+ queuedClarity.q ??= [];
40
+ queuedClarity.q.push(args);
41
+ };
42
+ window.clarity = queuedClarity;
43
+ const script = document.createElement("script");
44
+ script.async = true;
45
+ script.src = getMicrosoftClarityScriptUrl(normalizedProjectId);
46
+ const firstScript = document.getElementsByTagName("script")[0];
47
+ if (firstScript?.parentNode) {
48
+ firstScript.parentNode.insertBefore(script, firstScript);
49
+ } else {
50
+ document.head.appendChild(script);
51
+ }
52
+ }, [enabled, projectId]);
53
+ return null;
54
+ }
55
+ function GoogleAnalytics({ measurementId }) {
56
+ useEffect(() => {
57
+ if (!measurementId) {
58
+ return;
59
+ }
60
+ if (!/^G-[A-Z0-9]+$/.test(measurementId)) {
61
+ console.warn(
62
+ `Invalid Google Analytics measurement ID: ${measurementId}. Expected format: G-XXXXXXXXXX`
63
+ );
64
+ return;
65
+ }
66
+ if (window.gtag) {
67
+ return;
68
+ }
69
+ window.dataLayer = window.dataLayer || [];
70
+ function gtag(...args) {
71
+ window.dataLayer?.push(args);
72
+ }
73
+ window.gtag = gtag;
74
+ const script = document.createElement("script");
75
+ script.async = true;
76
+ script.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`;
77
+ script.onload = () => {
78
+ gtag("js", /* @__PURE__ */ new Date());
79
+ gtag("config", measurementId);
80
+ };
81
+ document.head.appendChild(script);
82
+ }, [measurementId]);
83
+ return null;
84
+ }
85
+ function GoogleTagManager({
86
+ containerId,
87
+ dataLayerName = "dataLayer",
88
+ enabled = true
89
+ }) {
90
+ const normalizedContainerId = normalizeGoogleTagManagerContainerId(containerId);
91
+ useEffect(() => {
92
+ if (!enabled) {
93
+ return;
94
+ }
95
+ if (!normalizedContainerId) {
96
+ if (containerId?.trim()) {
97
+ console.warn(
98
+ `Invalid Google Tag Manager container ID: ${containerId}. Expected format: GTM-XXXXXXX`
99
+ );
100
+ }
101
+ return;
102
+ }
103
+ if (document.querySelector(
104
+ `[data-google-tag-manager="${normalizedContainerId}"]`
105
+ )) {
106
+ return;
107
+ }
108
+ const dataLayers = window;
109
+ dataLayers[dataLayerName] ??= [];
110
+ dataLayers[dataLayerName]?.push({
111
+ "gtm.start": Date.now(),
112
+ event: "gtm.js"
113
+ });
114
+ const script = document.createElement("script");
115
+ script.async = true;
116
+ script.dataset.googleTagManager = normalizedContainerId;
117
+ script.src = getGoogleTagManagerScriptUrl(
118
+ normalizedContainerId,
119
+ dataLayerName
120
+ );
121
+ const firstScript = document.getElementsByTagName("script")[0];
122
+ if (firstScript?.parentNode) {
123
+ firstScript.parentNode.insertBefore(script, firstScript);
124
+ } else {
125
+ document.head.appendChild(script);
126
+ }
127
+ }, [containerId, dataLayerName, enabled, normalizedContainerId]);
128
+ if (!enabled || !normalizedContainerId) {
129
+ return null;
130
+ }
131
+ return /* @__PURE__ */ jsx("noscript", { children: /* @__PURE__ */ jsx(
132
+ "iframe",
133
+ {
134
+ height: "0",
135
+ src: getGoogleTagManagerNoScriptUrl(
136
+ normalizedContainerId,
137
+ dataLayerName
138
+ ),
139
+ style: { display: "none", visibility: "hidden" },
140
+ title: "Google Tag Manager",
141
+ width: "0"
142
+ }
143
+ ) });
144
+ }
145
+ var BackLink = React.forwardRef(
146
+ ({ href, children = "Back", className, ...props }, ref) => {
147
+ return /* @__PURE__ */ jsxs(
148
+ Link2,
149
+ {
150
+ ref,
151
+ href,
152
+ className: cn(
153
+ "inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground transition-colors",
154
+ className
155
+ ),
156
+ ...props,
157
+ children: [
158
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "size-4" }),
159
+ children
160
+ ]
161
+ }
162
+ );
163
+ }
164
+ );
165
+ BackLink.displayName = "BackLink";
166
+ function PageLayoutShell({
167
+ title,
168
+ description,
169
+ actions,
170
+ children,
171
+ className,
172
+ contentClassName,
173
+ footer,
174
+ beforeHeader,
175
+ showHeader = Boolean(title || description || actions),
176
+ contentBaseClassName = "flex-1",
177
+ innerClassName
178
+ }) {
179
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-1 flex-col min-w-0 min-h-full", className), children: [
180
+ /* @__PURE__ */ jsxs("div", { className: cn("flex flex-1 flex-col gap-4 p-4", innerClassName), children: [
181
+ beforeHeader,
182
+ showHeader && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
183
+ /* @__PURE__ */ jsxs("div", { children: [
184
+ title && /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold", children: title }),
185
+ description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: description })
186
+ ] }),
187
+ actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: actions })
188
+ ] }),
189
+ /* @__PURE__ */ jsx("div", { className: cn(contentBaseClassName, contentClassName), children })
190
+ ] }),
191
+ footer
192
+ ] });
193
+ }
194
+ function BasePageLayout({
195
+ title,
196
+ description,
197
+ actions,
198
+ children,
199
+ className,
200
+ contentClassName,
201
+ footer
202
+ }) {
203
+ return /* @__PURE__ */ jsx(
204
+ PageLayoutShell,
205
+ {
206
+ title,
207
+ description,
208
+ actions,
209
+ className,
210
+ contentClassName,
211
+ footer,
212
+ children
213
+ }
214
+ );
215
+ }
216
+ function AdminPageLayout({
217
+ title,
218
+ description,
219
+ actions,
220
+ children,
221
+ className,
222
+ contentClassName,
223
+ footer,
224
+ backLink
225
+ }) {
226
+ const showHeader = !backLink && Boolean(title || description || actions);
227
+ return /* @__PURE__ */ jsx(
228
+ PageLayoutShell,
229
+ {
230
+ title,
231
+ description,
232
+ actions,
233
+ className,
234
+ contentClassName,
235
+ footer,
236
+ showHeader,
237
+ beforeHeader: backLink ? /* @__PURE__ */ jsx(BackLink, { href: backLink.href, children: backLink.label }) : null,
238
+ contentBaseClassName: "flex-1 min-w-0",
239
+ innerClassName: "min-w-0",
240
+ children
241
+ }
242
+ );
243
+ }
244
+ function AppFooter({ children, className }) {
245
+ return /* @__PURE__ */ jsx(
246
+ "div",
247
+ {
248
+ className: cn(
249
+ "sticky bottom-0 z-10 mt-auto border-t bg-background/95 px-4 py-1 backdrop-blur supports-[backdrop-filter]:bg-background/60",
250
+ className
251
+ ),
252
+ children
253
+ }
254
+ );
255
+ }
256
+ function getResolvedTheme(resolvedTheme) {
257
+ return resolvedTheme === "dark" ? "dark" : "light";
258
+ }
259
+ function getDocumentTheme() {
260
+ return document.documentElement.classList.contains("dark") ? "dark" : "light";
261
+ }
262
+ function prefersDarkMode() {
263
+ return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-color-scheme: dark)").matches;
264
+ }
265
+ function getCurrentSelection(includeSystem, theme, resolvedTheme) {
266
+ if (includeSystem && theme === "system") {
267
+ return "system";
268
+ }
269
+ return resolvedTheme;
270
+ }
271
+ function getNextThemeSelection(currentSelection, includeSystem) {
272
+ if (!includeSystem) {
273
+ return currentSelection === "dark" ? "light" : "dark";
274
+ }
275
+ if (currentSelection === "light") {
276
+ return "dark";
277
+ }
278
+ if (currentSelection === "dark") {
279
+ return "system";
280
+ }
281
+ return "light";
282
+ }
283
+ function getThemeToggleLabel(nextTheme) {
284
+ return `Switch theme to ${nextTheme}`;
285
+ }
286
+ function getThemeIcon(nextTheme) {
287
+ if (nextTheme === "light") {
288
+ return Sun;
289
+ }
290
+ if (nextTheme === "dark") {
291
+ return Moon;
292
+ }
293
+ return Monitor;
294
+ }
295
+ function useTheme() {
296
+ const { resolvedTheme } = useTheme$1();
297
+ if (typeof document !== "undefined") {
298
+ return document.documentElement.classList.contains("dark") ? "dark" : "light";
299
+ }
300
+ return resolvedTheme === "dark" ? "dark" : "light";
301
+ }
302
+ function matchesShortcut(event, shortcut) {
303
+ const ctrlMatch = shortcut.ctrl ? event.ctrlKey : !event.ctrlKey;
304
+ const shiftMatch = shortcut.shift ? event.shiftKey : !event.shiftKey;
305
+ const altMatch = shortcut.alt ? event.altKey : !event.altKey;
306
+ const metaMatch = shortcut.meta ? event.metaKey : !event.metaKey;
307
+ const keyMatch = event.key === shortcut.key;
308
+ return ctrlMatch && shiftMatch && altMatch && metaMatch && keyMatch;
309
+ }
310
+ function ThemeToggle({
311
+ includeSystem = false,
312
+ shortcut,
313
+ shortcutDisplay,
314
+ showShortcut = true,
315
+ shortcutsVisible,
316
+ tooltip,
317
+ className
318
+ }) {
319
+ const { resolvedTheme, setTheme, theme } = useTheme$1();
320
+ const [mounted, setMounted] = useState(false);
321
+ const shouldShowShortcut = shortcutsVisible ?? showShortcut;
322
+ const renderedTheme = mounted && typeof document !== "undefined" ? getDocumentTheme() : getResolvedTheme(resolvedTheme);
323
+ const currentSelection = getCurrentSelection(
324
+ includeSystem,
325
+ theme,
326
+ renderedTheme
327
+ );
328
+ const nextTheme = getNextThemeSelection(currentSelection, includeSystem);
329
+ const ariaLabel = getThemeToggleLabel(nextTheme);
330
+ const Icon = getThemeIcon(nextTheme);
331
+ const toggleTheme = useCallback(() => {
332
+ setTheme(nextTheme);
333
+ if (typeof document !== "undefined") {
334
+ const nextIsDark = nextTheme === "dark" || nextTheme === "system" && prefersDarkMode();
335
+ document.documentElement.classList.toggle("dark", nextIsDark);
336
+ try {
337
+ localStorage.setItem("theme", nextTheme);
338
+ } catch {
339
+ }
340
+ }
341
+ }, [nextTheme, setTheme]);
342
+ useEffect(() => {
343
+ setMounted(true);
344
+ }, []);
345
+ useEffect(() => {
346
+ if (!shortcut) return;
347
+ const handleKeyDown = (e) => {
348
+ if (matchesShortcut(e, shortcut)) {
349
+ e.preventDefault();
350
+ toggleTheme();
351
+ }
352
+ };
353
+ window.addEventListener("keydown", handleKeyDown);
354
+ return () => window.removeEventListener("keydown", handleKeyDown);
355
+ }, [shortcut, toggleTheme]);
356
+ if (!mounted) {
357
+ if (includeSystem) {
358
+ return /* @__PURE__ */ jsx(
359
+ "button",
360
+ {
361
+ type: "button",
362
+ className: `inline-flex h-8 w-8 items-center justify-center text-icon transition-colors ${className ?? ""}`,
363
+ "aria-label": "Toggle theme",
364
+ children: /* @__PURE__ */ jsx(Monitor, { className: "h-4 w-4" })
365
+ }
366
+ );
367
+ }
368
+ return /* @__PURE__ */ jsx(
369
+ "button",
370
+ {
371
+ type: "button",
372
+ className: `inline-flex h-8 w-8 items-center justify-center text-icon transition-colors ${className ?? ""}`,
373
+ "aria-label": "Toggle theme",
374
+ children: /* @__PURE__ */ jsxs("div", { className: "relative h-4 w-4", children: [
375
+ /* @__PURE__ */ jsx(Sun, { className: "absolute inset-0 h-4 w-4 opacity-0 dark:opacity-100 transition-opacity duration-150" }),
376
+ /* @__PURE__ */ jsx(Moon, { className: "absolute inset-0 h-4 w-4 opacity-100 dark:opacity-0 transition-opacity duration-150" })
377
+ ] })
378
+ }
379
+ );
380
+ }
381
+ const tooltipContent = tooltip ?? /* @__PURE__ */ jsxs(Fragment, { children: [
382
+ /* @__PURE__ */ jsx("span", { children: ariaLabel }),
383
+ shouldShowShortcut && shortcutDisplay && /* @__PURE__ */ jsx(KeyboardShortcut, { className: "ml-2 text-xs", children: shortcutDisplay })
384
+ ] });
385
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
386
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
387
+ "button",
388
+ {
389
+ type: "button",
390
+ onClick: toggleTheme,
391
+ className: `group inline-flex h-8 w-8 items-center justify-center text-icon hover:text-icon-hover transition-colors ${className ?? ""}`,
392
+ "aria-label": ariaLabel,
393
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 transition-transform duration-150 group-hover:rotate-12" })
394
+ }
395
+ ) }),
396
+ /* @__PURE__ */ jsx(TooltipContent, { side: "bottom", children: tooltipContent })
397
+ ] });
398
+ }
399
+ function AppHeader({
400
+ showSidebarTrigger = true,
401
+ showThemeToggle = true,
402
+ themeToggleShortcut,
403
+ shortcutsVisible,
404
+ helpLink,
405
+ aboutLink,
406
+ actions,
407
+ leadingContent,
408
+ className,
409
+ LinkComponent = "a",
410
+ ShortcutComponent
411
+ }) {
412
+ const Link3 = LinkComponent;
413
+ const helpConfig = helpLink ? typeof helpLink === "string" ? { href: helpLink, label: "Help", icon: CircleHelp, tooltip: "Get help" } : { icon: CircleHelp, tooltip: "Get help", ...helpLink } : null;
414
+ const aboutConfig = aboutLink ? typeof aboutLink === "string" ? { href: aboutLink, label: "About", icon: Info, tooltip: "About" } : { icon: Info, tooltip: "About", ...aboutLink } : null;
415
+ const renderLink = (config) => {
416
+ const Icon = config.icon;
417
+ const content = /* @__PURE__ */ jsxs(
418
+ Link3,
419
+ {
420
+ href: config.href,
421
+ className: "inline-flex h-8 w-8 items-center justify-center text-icon transition-colors hover:text-icon-hover",
422
+ children: [
423
+ Icon && /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 transition-transform duration-300 hover:rotate-12" }),
424
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: config.label })
425
+ ]
426
+ }
427
+ );
428
+ if (config.tooltip || config.shortcutDisplay) {
429
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
430
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: content }),
431
+ /* @__PURE__ */ jsxs(TooltipContent, { side: "bottom", children: [
432
+ /* @__PURE__ */ jsx("span", { children: config.tooltip || config.label }),
433
+ config.shortcutDisplay && ShortcutComponent && /* @__PURE__ */ jsx(ShortcutComponent, { className: "ml-2 text-[10px]", children: config.shortcutDisplay })
434
+ ] })
435
+ ] });
436
+ }
437
+ return content;
438
+ };
439
+ return /* @__PURE__ */ jsxs(
440
+ "header",
441
+ {
442
+ className: cn(
443
+ "sticky top-0 z-10 flex h-14 shrink-0 items-center gap-2 border-b bg-background px-4",
444
+ className
445
+ ),
446
+ children: [
447
+ showSidebarTrigger && /* @__PURE__ */ jsx(SidebarTrigger, { className: "-ml-1" }),
448
+ leadingContent,
449
+ /* @__PURE__ */ jsx("div", { className: "flex-1" }),
450
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
451
+ actions,
452
+ helpConfig && renderLink(helpConfig),
453
+ aboutConfig && renderLink(aboutConfig),
454
+ showThemeToggle && /* @__PURE__ */ jsx(
455
+ ThemeToggle,
456
+ {
457
+ shortcutDisplay: themeToggleShortcut,
458
+ shortcutsVisible
459
+ }
460
+ )
461
+ ] })
462
+ ]
463
+ }
464
+ );
465
+ }
466
+ var Collapsible = CollapsiblePrimitive.Root;
467
+ var CollapsibleTrigger2 = CollapsiblePrimitive.CollapsibleTrigger;
468
+ var CollapsibleContent2 = CollapsiblePrimitive.CollapsibleContent;
469
+ function isNavItem(element) {
470
+ return "label" in element && "href" in element && "icon" in element && !("type" in element);
471
+ }
472
+ function isNavSection(element) {
473
+ return "type" in element && element.type === "section";
474
+ }
475
+ function isNavDivider(element) {
476
+ return "type" in element && element.type === "divider";
477
+ }
478
+ function AppSidebar({
479
+ navItems,
480
+ pathname = "",
481
+ user,
482
+ userMenuItems = [],
483
+ userLoading = false,
484
+ header,
485
+ onSignOut,
486
+ signInHref = "/auth/signin",
487
+ profilePath = "/profile",
488
+ collapsible = "icon",
489
+ LinkComponent = "a",
490
+ ShortcutComponent,
491
+ userMenuShortcut,
492
+ onNavigate,
493
+ enableKeyboardShortcuts = true,
494
+ shortcutsVisible
495
+ }) {
496
+ const Link3 = LinkComponent;
497
+ const [menuOpen, setMenuOpen] = useState(false);
498
+ const [suppressSectionTooltip, setSuppressSectionTooltip] = useState(null);
499
+ const isOnProfilePage = pathname === profilePath || pathname.startsWith(`${profilePath}/`);
500
+ const allMenuItems = useMemo(() => {
501
+ const items = [...userMenuItems];
502
+ if (onSignOut && !items.some((item) => item.label === "Sign Out")) {
503
+ items.push({
504
+ label: "Sign Out",
505
+ icon: LogOut,
506
+ onClick: onSignOut,
507
+ destructive: true,
508
+ separatorBefore: items.length > 0
509
+ });
510
+ }
511
+ return items;
512
+ }, [userMenuItems, onSignOut]);
513
+ const allNavItems = useMemo(() => {
514
+ const items = [];
515
+ for (const element of navItems) {
516
+ if (isNavItem(element)) {
517
+ items.push(element);
518
+ } else if (isNavSection(element)) {
519
+ items.push(...element.items);
520
+ }
521
+ }
522
+ return items;
523
+ }, [navItems]);
524
+ const processedNavGroups = useMemo(() => {
525
+ const groups = [];
526
+ let dividerCount = 0;
527
+ let i = 0;
528
+ while (i < navItems.length) {
529
+ const element = navItems[i];
530
+ if (isNavDivider(element)) {
531
+ groups.push({ type: "divider", key: `divider-${dividerCount++}` });
532
+ i++;
533
+ } else if (isNavSection(element)) {
534
+ groups.push({ type: "section", section: element });
535
+ i++;
536
+ } else if (isNavItem(element)) {
537
+ const plainItems = [element];
538
+ const startHref = element.href;
539
+ i++;
540
+ while (i < navItems.length && isNavItem(navItems[i])) {
541
+ plainItems.push(navItems[i]);
542
+ i++;
543
+ }
544
+ groups.push({
545
+ type: "plain-group",
546
+ items: plainItems,
547
+ key: `plain-group-${startHref}`
548
+ });
549
+ } else {
550
+ i++;
551
+ }
552
+ }
553
+ return groups;
554
+ }, [navItems]);
555
+ useEffect(() => {
556
+ if (!enableKeyboardShortcuts || !onNavigate) return;
557
+ const handleKeyDown = (e) => {
558
+ if (!e.ctrlKey || e.shiftKey || e.altKey || e.metaKey) return;
559
+ const matchingItem = allNavItems.find(
560
+ (item) => item.shortcutKey === e.key && !item.disabled
561
+ );
562
+ if (matchingItem) {
563
+ e.preventDefault();
564
+ onNavigate(matchingItem.href);
565
+ }
566
+ };
567
+ window.addEventListener("keydown", handleKeyDown);
568
+ return () => window.removeEventListener("keydown", handleKeyDown);
569
+ }, [enableKeyboardShortcuts, allNavItems, onNavigate]);
570
+ const activeHref = useMemo(() => {
571
+ if (!pathname || allNavItems.length === 0) return null;
572
+ const matches = allNavItems.filter((item) => {
573
+ if (item.href === "/" || item.href === "/dashboard" || item.href === "/finance") {
574
+ return pathname === item.href;
575
+ }
576
+ return pathname === item.href || pathname.startsWith(`${item.href}/`);
577
+ }).sort((a, b) => b.href.length - a.href.length);
578
+ return matches[0]?.href ?? null;
579
+ }, [pathname, allNavItems]);
580
+ const [sectionOpenState, setSectionOpenState] = useState({});
581
+ useEffect(() => {
582
+ setSectionOpenState((prev) => {
583
+ const nextState = {};
584
+ for (const group of processedNavGroups) {
585
+ if (group.type === "section" && group.section.collapsible) {
586
+ nextState[group.section.label] = prev[group.section.label] ?? group.section.defaultOpen === true;
587
+ }
588
+ }
589
+ const nextKeys = Object.keys(nextState);
590
+ const prevKeys = Object.keys(prev);
591
+ const hasChanged = nextKeys.length !== prevKeys.length || nextKeys.some((key) => prev[key] !== nextState[key]);
592
+ return hasChanged ? nextState : prev;
593
+ });
594
+ }, [processedNavGroups]);
595
+ const getIsActive = (item) => {
596
+ if (item.isActive !== void 0) return item.isActive;
597
+ if (!pathname) return false;
598
+ return activeHref === item.href;
599
+ };
600
+ const getIconAnimationClass = (animation) => {
601
+ switch (animation) {
602
+ case "rotate":
603
+ return "motion-safe:group-hover:rotate-90 motion-safe:transition-transform motion-safe:duration-150";
604
+ case "bounce":
605
+ return "motion-safe:group-hover:scale-110 motion-safe:transition-transform motion-safe:duration-150";
606
+ case "scale":
607
+ return "motion-safe:group-hover:scale-110 motion-safe:transition-transform motion-safe:duration-150";
608
+ case "none":
609
+ return "";
610
+ default:
611
+ return "motion-safe:group-hover:scale-110 motion-safe:transition-transform motion-safe:duration-150";
612
+ }
613
+ };
614
+ const renderNavItem = (item) => {
615
+ const isActive = getIsActive(item);
616
+ const Icon = item.icon;
617
+ const Shortcut = ShortcutComponent || KeyboardShortcut;
618
+ const iconAnimationClass = item.disabled ? "" : getIconAnimationClass(item.iconAnimation);
619
+ if (item.disabled) {
620
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
621
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
622
+ SidebarMenuButton,
623
+ {
624
+ className: "cursor-not-allowed opacity-40",
625
+ isActive: false,
626
+ "aria-disabled": "true",
627
+ tabIndex: 0,
628
+ children: [
629
+ /* @__PURE__ */ jsx(Icon, { className: "shrink-0" }),
630
+ /* @__PURE__ */ jsx("span", { children: item.label })
631
+ ]
632
+ }
633
+ ) }),
634
+ /* @__PURE__ */ jsx(TooltipContent, { side: "right", children: item.disabledTooltip || "Coming soon" })
635
+ ] });
636
+ }
637
+ return /* @__PURE__ */ jsx(
638
+ SidebarMenuButton,
639
+ {
640
+ asChild: true,
641
+ isActive,
642
+ className: "group",
643
+ tooltip: item.label,
644
+ children: /* @__PURE__ */ jsxs(Link3, { href: item.href, children: [
645
+ /* @__PURE__ */ jsx(Icon, { className: `shrink-0 ${iconAnimationClass}` }),
646
+ /* @__PURE__ */ jsx("span", { children: item.label }),
647
+ shortcutsVisible && item.shortcutDisplay && /* @__PURE__ */ jsx(Shortcut, { className: "ml-auto text-[10px] text-muted-foreground", children: item.shortcutDisplay })
648
+ ] })
649
+ }
650
+ );
651
+ };
652
+ return /* @__PURE__ */ jsxs(Sidebar, { collapsible, children: [
653
+ header && /* @__PURE__ */ jsx(SidebarHeader, { children: header }),
654
+ /* @__PURE__ */ jsx(SidebarContent, { children: processedNavGroups.map((group) => {
655
+ if (group.type === "divider") {
656
+ return /* @__PURE__ */ jsx(SidebarSeparator, { className: "my-2" }, group.key);
657
+ }
658
+ if (group.type === "section") {
659
+ const section = group.section;
660
+ if (section.visible === false) return null;
661
+ if (section.collapsible) {
662
+ const SectionIcon = section.icon ?? section.items[0]?.icon;
663
+ const sectionHref = section.items[0]?.href;
664
+ return /* @__PURE__ */ jsx(
665
+ Collapsible,
666
+ {
667
+ open: sectionOpenState[section.label] ?? section.defaultOpen === true,
668
+ onOpenChange: (open) => setSectionOpenState((prev) => ({
669
+ ...prev,
670
+ [section.label]: open
671
+ })),
672
+ className: "group/collapsible",
673
+ children: /* @__PURE__ */ jsxs(SidebarGroup, { children: [
674
+ SectionIcon && sectionHref && /* @__PURE__ */ jsx(SidebarGroupContent, { className: "hidden group-data-[collapsible=icon]:block", children: /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(
675
+ DropdownMenu,
676
+ {
677
+ onOpenChange: (open) => {
678
+ setSuppressSectionTooltip(section.label);
679
+ if (!open && document.activeElement instanceof HTMLElement) {
680
+ document.activeElement.blur();
681
+ }
682
+ },
683
+ children: [
684
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
685
+ SidebarMenuButton,
686
+ {
687
+ "aria-label": section.label,
688
+ tooltip: suppressSectionTooltip === section.label ? void 0 : section.label,
689
+ onMouseLeave: () => {
690
+ setSuppressSectionTooltip(
691
+ (prev) => prev === section.label ? null : prev
692
+ );
693
+ },
694
+ className: "!bg-transparent !text-sidebar-foreground !hover:bg-transparent !hover:text-sidebar-foreground !active:bg-transparent !active:text-sidebar-foreground focus-visible:ring-0",
695
+ children: [
696
+ /* @__PURE__ */ jsx(SectionIcon, { className: "shrink-0" }),
697
+ /* @__PURE__ */ jsx("span", { children: section.label })
698
+ ]
699
+ }
700
+ ) }),
701
+ /* @__PURE__ */ jsx(
702
+ DropdownMenuContent,
703
+ {
704
+ side: "right",
705
+ align: "start",
706
+ className: "w-64",
707
+ children: section.items.map((item) => {
708
+ const ItemIcon = item.icon;
709
+ return /* @__PURE__ */ jsx(DropdownMenuItem, { asChild: true, children: /* @__PURE__ */ jsxs(
710
+ Link3,
711
+ {
712
+ href: item.href,
713
+ className: "flex items-center gap-2",
714
+ children: [
715
+ /* @__PURE__ */ jsx(ItemIcon, { className: "size-4" }),
716
+ /* @__PURE__ */ jsx("span", { children: item.label })
717
+ ]
718
+ }
719
+ ) }, item.href);
720
+ })
721
+ }
722
+ )
723
+ ]
724
+ }
725
+ ) }) }) }),
726
+ /* @__PURE__ */ jsxs("div", { className: "group-data-[collapsible=icon]:hidden", children: [
727
+ /* @__PURE__ */ jsx(
728
+ SidebarGroupLabel,
729
+ {
730
+ asChild: true,
731
+ className: "text-xs font-medium uppercase tracking-wider text-sidebar-foreground",
732
+ children: /* @__PURE__ */ jsxs(CollapsibleTrigger2, { className: "flex w-full items-center justify-between [&[data-state=open]>svg.chevron-icon]:rotate-180", children: [
733
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
734
+ SectionIcon && /* @__PURE__ */ jsx(SectionIcon, { className: "size-3.5 shrink-0" }),
735
+ section.label
736
+ ] }),
737
+ /* @__PURE__ */ jsx(ChevronDown, { className: "chevron-icon ml-auto size-4 transition-transform duration-200" })
738
+ ] })
739
+ }
740
+ ),
741
+ /* @__PURE__ */ jsx(CollapsibleContent2, { children: /* @__PURE__ */ jsx(SidebarGroupContent, { children: /* @__PURE__ */ jsx(SidebarMenu, { children: section.items.map((item) => /* @__PURE__ */ jsx(SidebarMenuItem, { children: renderNavItem(item) }, item.href)) }) }) })
742
+ ] })
743
+ ] })
744
+ },
745
+ `section-${section.label}`
746
+ );
747
+ }
748
+ return /* @__PURE__ */ jsxs(SidebarGroup, { children: [
749
+ /* @__PURE__ */ jsx(SidebarGroupLabel, { className: "text-xs font-medium uppercase tracking-wider text-sidebar-foreground", children: section.label }),
750
+ /* @__PURE__ */ jsx(SidebarGroupContent, { children: /* @__PURE__ */ jsx(SidebarMenu, { children: section.items.map((item) => /* @__PURE__ */ jsx(SidebarMenuItem, { children: renderNavItem(item) }, item.href)) }) })
751
+ ] }, `section-${section.label}`);
752
+ }
753
+ if (group.type === "plain-group") {
754
+ return /* @__PURE__ */ jsx(SidebarGroup, { children: /* @__PURE__ */ jsx(SidebarGroupContent, { children: /* @__PURE__ */ jsx(SidebarMenu, { children: group.items.map((item) => /* @__PURE__ */ jsx(SidebarMenuItem, { children: renderNavItem(item) }, item.href)) }) }) }, group.key);
755
+ }
756
+ return null;
757
+ }) }),
758
+ /* @__PURE__ */ jsx(SidebarFooter, { children: userLoading ? /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-2 py-1.5", children: [
759
+ /* @__PURE__ */ jsx(Spinner, { size: "sm" }),
760
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Loading..." })
761
+ ] }) }) }) : user ? /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsx(
762
+ UserAvatarMenu,
763
+ {
764
+ user: {
765
+ id: user.id,
766
+ email: user.email ?? void 0,
767
+ avatarUrl: user.avatarUrl ?? void 0,
768
+ name: user.name || user.email || "User",
769
+ initials: user.initials || user.name?.[0]?.toUpperCase() || "U"
770
+ },
771
+ items: allMenuItems,
772
+ open: menuOpen,
773
+ onOpenChange: setMenuOpen,
774
+ side: "top",
775
+ align: "start",
776
+ menuWidth: "w-[calc(var(--sidebar-width)-1rem)]",
777
+ LinkComponent,
778
+ ShortcutComponent,
779
+ trigger: /* @__PURE__ */ jsxs(
780
+ SidebarMenuButton,
781
+ {
782
+ size: "lg",
783
+ className: `rounded-xl focus-visible:ring-0 ${menuOpen || isOnProfilePage ? "bg-sidebar-accent text-sidebar-accent-foreground" : ""}`,
784
+ children: [
785
+ /* @__PURE__ */ jsxs(Avatar, { className: "h-8 w-8 rounded-full", children: [
786
+ user.avatarUrl && /* @__PURE__ */ jsx(
787
+ AvatarImage,
788
+ {
789
+ src: user.avatarUrl,
790
+ alt: user.name || ""
791
+ }
792
+ ),
793
+ /* @__PURE__ */ jsx(
794
+ AvatarFallback,
795
+ {
796
+ className: "rounded-full text-xs font-medium text-white",
797
+ style: getAvatarGradient(user.id).style,
798
+ children: user.initials || user.name?.[0]?.toUpperCase() || "U"
799
+ }
800
+ )
801
+ ] }),
802
+ /* @__PURE__ */ jsxs("div", { className: "grid flex-1 min-w-0 text-left text-sm leading-tight", children: [
803
+ /* @__PURE__ */ jsx("span", { className: "truncate font-semibold", children: user.name || "User" }),
804
+ /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-muted-foreground", children: user.email })
805
+ ] }),
806
+ ShortcutComponent && userMenuShortcut && /* @__PURE__ */ jsx(ShortcutComponent, { className: "ml-auto hidden text-xs text-muted-foreground md:inline-flex", children: userMenuShortcut }),
807
+ /* @__PURE__ */ jsx(ChevronUp, { className: "ml-1 size-4" })
808
+ ]
809
+ }
810
+ )
811
+ }
812
+ ) }) }) : /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsx(SidebarMenuButton, { asChild: true, children: /* @__PURE__ */ jsxs(Link3, { href: signInHref, children: [
813
+ /* @__PURE__ */ jsx(User, {}),
814
+ /* @__PURE__ */ jsx("span", { children: "Sign In" })
815
+ ] }) }) }) }) }),
816
+ /* @__PURE__ */ jsx(SidebarRail, {})
817
+ ] });
818
+ }
819
+ function FloatingUserMenu({
820
+ user,
821
+ menuItems = [],
822
+ loading = false,
823
+ onSignOut,
824
+ pathname = "",
825
+ profilePath = "/profile",
826
+ LinkComponent = "a"
827
+ }) {
828
+ const { isMobile } = useSidebar();
829
+ const [open, setOpen] = useState(false);
830
+ const isOnProfilePage = pathname === profilePath || pathname.startsWith(`${profilePath}/`);
831
+ const allMenuItems = useMemo(() => {
832
+ const items = [...menuItems];
833
+ if (onSignOut && !items.some((item) => item.label === "Sign Out")) {
834
+ items.push({
835
+ label: "Sign Out",
836
+ icon: LogOut,
837
+ onClick: onSignOut,
838
+ destructive: true,
839
+ separatorBefore: items.length > 0
840
+ });
841
+ }
842
+ return items;
843
+ }, [menuItems, onSignOut]);
844
+ if (!isMobile) return null;
845
+ if (loading) {
846
+ return /* @__PURE__ */ jsx("div", { className: "fixed bottom-2 left-2 z-50 flex h-8 w-8 items-center justify-center rounded-full bg-background shadow-md border", children: /* @__PURE__ */ jsx(Spinner, { size: "sm" }) });
847
+ }
848
+ if (!user) return null;
849
+ const displayName = user.name || user.email || "User";
850
+ const initials = user.initials || user.name?.[0]?.toUpperCase() || "U";
851
+ return /* @__PURE__ */ jsx("div", { className: "fixed bottom-2 left-2 z-50", children: /* @__PURE__ */ jsx(
852
+ UserAvatarMenu,
853
+ {
854
+ user: {
855
+ id: user.id,
856
+ email: user.email ?? void 0,
857
+ avatarUrl: user.avatarUrl ?? void 0,
858
+ name: displayName,
859
+ initials
860
+ },
861
+ items: allMenuItems,
862
+ open,
863
+ onOpenChange: setOpen,
864
+ side: "top",
865
+ align: "start",
866
+ isActive: isOnProfilePage,
867
+ showUserInfo: true,
868
+ LinkComponent,
869
+ trigger: /* @__PURE__ */ jsxs(
870
+ "button",
871
+ {
872
+ type: "button",
873
+ className: `flex h-8 w-8 items-center justify-center rounded-full shadow-md border bg-background transition-all hover:scale-105 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${open || isOnProfilePage ? "ring-2 ring-primary" : ""}`,
874
+ children: [
875
+ /* @__PURE__ */ jsxs(Avatar, { className: "h-8 w-8 rounded-full", children: [
876
+ user.avatarUrl && /* @__PURE__ */ jsx(AvatarImage, { src: user.avatarUrl, alt: displayName }),
877
+ /* @__PURE__ */ jsx(
878
+ AvatarFallback,
879
+ {
880
+ className: "rounded-full text-xs font-medium text-white",
881
+ style: getAvatarGradient(user.id).style,
882
+ children: initials
883
+ }
884
+ )
885
+ ] }),
886
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "User menu" })
887
+ ]
888
+ }
889
+ )
890
+ }
891
+ ) });
892
+ }
893
+ function AppLayout({
894
+ children,
895
+ // Sidebar props
896
+ navItems = [],
897
+ sidebarHeader,
898
+ sidebar: customSidebar,
899
+ sidebarCollapsible = "icon",
900
+ // User props
901
+ user,
902
+ userLoading = false,
903
+ userMenuItems = [],
904
+ onSignOut,
905
+ signInHref,
906
+ pathname = "",
907
+ // Header props
908
+ showHeader = true,
909
+ showSidebarTrigger = true,
910
+ showThemeToggle = true,
911
+ themeToggleShortcut,
912
+ shortcutsVisible,
913
+ helpLink,
914
+ aboutLink,
915
+ headerActions,
916
+ headerLeading,
917
+ header: customHeader,
918
+ headerClassName,
919
+ // Floating user menu
920
+ showFloatingUserMenu = true,
921
+ // General props
922
+ className,
923
+ defaultOpen,
924
+ open,
925
+ onOpenChange,
926
+ LinkComponent,
927
+ ShortcutComponent,
928
+ userMenuShortcut,
929
+ onNavigate,
930
+ enableNavShortcuts = true
931
+ }) {
932
+ const sidebarElement = customSidebar ?? /* @__PURE__ */ jsx(
933
+ AppSidebar,
934
+ {
935
+ navItems,
936
+ pathname,
937
+ user,
938
+ userMenuItems,
939
+ userLoading,
940
+ header: sidebarHeader,
941
+ onSignOut,
942
+ signInHref,
943
+ collapsible: sidebarCollapsible,
944
+ LinkComponent,
945
+ ShortcutComponent,
946
+ userMenuShortcut,
947
+ onNavigate,
948
+ enableKeyboardShortcuts: enableNavShortcuts,
949
+ shortcutsVisible
950
+ }
951
+ );
952
+ const headerElement = customHeader !== void 0 ? customHeader : showHeader ? /* @__PURE__ */ jsx(
953
+ AppHeader,
954
+ {
955
+ showSidebarTrigger,
956
+ showThemeToggle,
957
+ themeToggleShortcut,
958
+ shortcutsVisible,
959
+ helpLink,
960
+ aboutLink,
961
+ actions: headerActions,
962
+ leadingContent: headerLeading,
963
+ className: headerClassName,
964
+ LinkComponent,
965
+ ShortcutComponent
966
+ }
967
+ ) : null;
968
+ return /* @__PURE__ */ jsxs(
969
+ SidebarProvider,
970
+ {
971
+ defaultOpen,
972
+ open,
973
+ onOpenChange,
974
+ className: cn("h-dvh", className),
975
+ children: [
976
+ sidebarElement,
977
+ /* @__PURE__ */ jsxs(SidebarInset, { children: [
978
+ headerElement,
979
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto overflow-x-hidden min-w-0", children })
980
+ ] }),
981
+ showFloatingUserMenu && /* @__PURE__ */ jsx(
982
+ FloatingUserMenu,
983
+ {
984
+ user,
985
+ menuItems: userMenuItems,
986
+ loading: userLoading,
987
+ onSignOut,
988
+ pathname,
989
+ LinkComponent
990
+ }
991
+ )
992
+ ]
993
+ }
994
+ );
995
+ }
996
+ function DashboardGrid({ children, className }) {
997
+ return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-6", className), children });
998
+ }
999
+ function HelpLayout({
1000
+ children,
1001
+ panel,
1002
+ isOpen,
1003
+ className
1004
+ }) {
1005
+ return (
1006
+ // Inherits height from parent (h-full), handles horizontal layout only
1007
+ // min-h-0 allows shrinking below content size for proper overflow handling
1008
+ /* @__PURE__ */ jsxs("div", { className: cn("flex h-full min-h-0", className), children: [
1009
+ /* @__PURE__ */ jsx(
1010
+ "div",
1011
+ {
1012
+ className: cn(
1013
+ "h-full min-h-0 min-w-0 flex-1 transition-all duration-200 ease-out",
1014
+ isOpen && "sm:mr-100"
1015
+ ),
1016
+ children
1017
+ }
1018
+ ),
1019
+ panel
1020
+ ] })
1021
+ );
1022
+ }
1023
+ function HelpPageLayout({
1024
+ breadcrumbs = [],
1025
+ title,
1026
+ description,
1027
+ children,
1028
+ sidebar,
1029
+ relatedContent,
1030
+ className,
1031
+ contentClassName,
1032
+ homeHref = "/admin/help"
1033
+ }) {
1034
+ return /* @__PURE__ */ jsxs(
1035
+ "div",
1036
+ {
1037
+ className: cn(
1038
+ "flex flex-1 flex-col gap-6 p-4 max-w-7xl w-full",
1039
+ className
1040
+ ),
1041
+ children: [
1042
+ /* @__PURE__ */ jsxs(
1043
+ "nav",
1044
+ {
1045
+ "aria-label": "Breadcrumb",
1046
+ className: "flex items-center text-sm text-muted-foreground",
1047
+ children: [
1048
+ /* @__PURE__ */ jsxs(
1049
+ Link2,
1050
+ {
1051
+ href: homeHref,
1052
+ className: "flex items-center hover:text-foreground transition-colors",
1053
+ "data-prevent-help-intercept": "true",
1054
+ children: [
1055
+ /* @__PURE__ */ jsx(Home, { className: "size-4 mr-2" }),
1056
+ "Help Center"
1057
+ ]
1058
+ }
1059
+ ),
1060
+ breadcrumbs.map((crumb, index) => /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
1061
+ /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 mx-2" }),
1062
+ /* @__PURE__ */ jsx(
1063
+ Link2,
1064
+ {
1065
+ href: crumb.href,
1066
+ className: cn(
1067
+ "hover:text-foreground transition-colors",
1068
+ index === breadcrumbs.length - 1 && "text-foreground font-medium pointer-events-none"
1069
+ ),
1070
+ children: crumb.label
1071
+ }
1072
+ )
1073
+ ] }, crumb.href))
1074
+ ]
1075
+ }
1076
+ ),
1077
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col lg:flex-row gap-8 lg:gap-12", children: [
1078
+ sidebar && /* @__PURE__ */ jsx("aside", { className: "w-full lg:w-64 shrink-0 hidden lg:block", children: /* @__PURE__ */ jsx("div", { className: "sticky top-8", children: sidebar }) }),
1079
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1080
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2 mb-8", children: [
1081
+ /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold tracking-tight", children: title }),
1082
+ description && /* @__PURE__ */ jsx("p", { className: "text-lg text-muted-foreground max-w-3xl", children: description })
1083
+ ] }),
1084
+ /* @__PURE__ */ jsx("div", { className: contentClassName, children }),
1085
+ relatedContent && /* @__PURE__ */ jsx("div", { className: "pt-8 border-t mt-8", children: relatedContent })
1086
+ ] })
1087
+ ] })
1088
+ ]
1089
+ }
1090
+ );
1091
+ }
1092
+ function HelpPanelLayout({
1093
+ isOpen,
1094
+ onClose,
1095
+ onBack,
1096
+ canGoBack,
1097
+ searchQuery,
1098
+ onSearchChange,
1099
+ children,
1100
+ footer,
1101
+ className
1102
+ }) {
1103
+ const searchInputRef = useRef(null);
1104
+ const [isSearchExpanded, setIsSearchExpanded] = useState(false);
1105
+ useEffect(() => {
1106
+ if (isOpen && isSearchExpanded && searchInputRef.current) {
1107
+ setTimeout(() => {
1108
+ searchInputRef.current?.focus();
1109
+ }, 50);
1110
+ }
1111
+ }, [isOpen, isSearchExpanded]);
1112
+ useEffect(() => {
1113
+ if (searchQuery) {
1114
+ setIsSearchExpanded(true);
1115
+ }
1116
+ }, [searchQuery]);
1117
+ if (!isOpen) return null;
1118
+ return /* @__PURE__ */ jsxs(
1119
+ "aside",
1120
+ {
1121
+ className: cn(
1122
+ "fixed right-0 top-0 z-40 h-full w-full sm:w-[400px] bg-background border-l shadow-xl",
1123
+ "flex flex-col",
1124
+ "animate-in slide-in-from-right duration-200",
1125
+ className
1126
+ ),
1127
+ "aria-label": "Help panel",
1128
+ children: [
1129
+ /* @__PURE__ */ jsxs("div", { className: "flex h-14 items-center justify-between gap-3 border-b px-3", children: [
1130
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [
1131
+ canGoBack && /* @__PURE__ */ jsx(
1132
+ "button",
1133
+ {
1134
+ type: "button",
1135
+ className: "text-muted-foreground hover:text-foreground transition-colors",
1136
+ onClick: onBack,
1137
+ "aria-label": "Go back",
1138
+ children: /* @__PURE__ */ jsx(ArrowLeft, { className: "size-4 transition-transform duration-300 hover:-translate-x-0.5" })
1139
+ }
1140
+ ),
1141
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 flex-1 min-w-0", children: /* @__PURE__ */ jsxs(
1142
+ "div",
1143
+ {
1144
+ className: cn(
1145
+ "relative flex items-center rounded-md border border-transparent transition-all duration-300 ease-out",
1146
+ isSearchExpanded ? "flex-1 border-input bg-background" : "w-7 hover:bg-accent/50 cursor-pointer"
1147
+ ),
1148
+ children: [
1149
+ /* @__PURE__ */ jsx(
1150
+ "button",
1151
+ {
1152
+ type: "button",
1153
+ onMouseDown: (e) => {
1154
+ if (isSearchExpanded) {
1155
+ e.preventDefault();
1156
+ }
1157
+ },
1158
+ onClick: () => {
1159
+ if (isSearchExpanded) {
1160
+ onSearchChange("");
1161
+ setIsSearchExpanded(false);
1162
+ } else {
1163
+ setIsSearchExpanded(true);
1164
+ }
1165
+ },
1166
+ className: "flex size-7 items-center justify-center shrink-0 cursor-pointer",
1167
+ "aria-label": isSearchExpanded ? "Close search" : "Search help",
1168
+ children: /* @__PURE__ */ jsx(Search, { className: "size-4 text-muted-foreground" })
1169
+ }
1170
+ ),
1171
+ /* @__PURE__ */ jsx(
1172
+ "input",
1173
+ {
1174
+ ref: searchInputRef,
1175
+ type: "text",
1176
+ placeholder: "Search help...",
1177
+ value: searchQuery,
1178
+ onChange: (e) => onSearchChange(e.target.value),
1179
+ onBlur: () => {
1180
+ if (!searchQuery) {
1181
+ setIsSearchExpanded(false);
1182
+ }
1183
+ },
1184
+ onKeyDown: (e) => {
1185
+ if (e.key === "Escape") {
1186
+ onSearchChange("");
1187
+ setIsSearchExpanded(false);
1188
+ }
1189
+ },
1190
+ className: cn(
1191
+ "h-7 bg-transparent text-sm outline-none placeholder:text-muted-foreground transition-all duration-300",
1192
+ isSearchExpanded ? "w-full pr-7 opacity-100" : "w-0 opacity-0 p-0"
1193
+ )
1194
+ }
1195
+ ),
1196
+ /* @__PURE__ */ jsx(
1197
+ "div",
1198
+ {
1199
+ className: cn(
1200
+ "absolute right-1.5 transition-opacity duration-200",
1201
+ isSearchExpanded && searchQuery ? "opacity-100" : "opacity-0 pointer-events-none"
1202
+ ),
1203
+ children: /* @__PURE__ */ jsx(
1204
+ "button",
1205
+ {
1206
+ type: "button",
1207
+ onClick: (e) => {
1208
+ e.stopPropagation();
1209
+ onSearchChange("");
1210
+ searchInputRef.current?.focus();
1211
+ },
1212
+ className: "flex items-center justify-center size-5 rounded-sm text-muted-foreground hover:text-foreground hover:bg-accent/50 transition-colors",
1213
+ "aria-label": "Clear search",
1214
+ children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
1215
+ }
1216
+ )
1217
+ }
1218
+ )
1219
+ ]
1220
+ }
1221
+ ) })
1222
+ ] }),
1223
+ /* @__PURE__ */ jsx(
1224
+ "button",
1225
+ {
1226
+ type: "button",
1227
+ onClick: onClose,
1228
+ className: "text-muted-foreground hover:text-foreground transition-colors",
1229
+ "aria-label": "Close help",
1230
+ children: /* @__PURE__ */ jsx(X, { className: "size-4 transition-transform duration-300 hover:rotate-90" })
1231
+ }
1232
+ )
1233
+ ] }),
1234
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ jsx("div", { className: "p-4", children }) }),
1235
+ footer && /* @__PURE__ */ jsx("div", { className: "border-t px-3 py-2", children: footer })
1236
+ ]
1237
+ }
1238
+ );
1239
+ }
1240
+ function LegalLayout({
1241
+ title,
1242
+ lastUpdated,
1243
+ archiveUrl,
1244
+ backHref,
1245
+ backLabel = "Back",
1246
+ tableOfContents,
1247
+ children,
1248
+ className
1249
+ }) {
1250
+ const [activeSection, setActiveSection] = useState("");
1251
+ const hasMetadata = Boolean(lastUpdated || archiveUrl);
1252
+ useEffect(() => {
1253
+ if (!tableOfContents || tableOfContents.length === 0) return;
1254
+ const observer = new IntersectionObserver(
1255
+ (entries) => {
1256
+ for (const entry of entries) {
1257
+ if (entry.isIntersecting) {
1258
+ setActiveSection(entry.target.id);
1259
+ }
1260
+ }
1261
+ },
1262
+ {
1263
+ rootMargin: "-80px 0px -70% 0px",
1264
+ threshold: 0
1265
+ }
1266
+ );
1267
+ for (const item of tableOfContents) {
1268
+ const element = document.getElementById(item.id);
1269
+ if (element) {
1270
+ observer.observe(element);
1271
+ }
1272
+ }
1273
+ return () => observer.disconnect();
1274
+ }, [tableOfContents]);
1275
+ const scrollToSection = (event, sectionId) => {
1276
+ const target = document.getElementById(sectionId);
1277
+ if (!target) {
1278
+ return;
1279
+ }
1280
+ event.preventDefault();
1281
+ const prefersReducedMotion = typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
1282
+ const targetHeading = target.querySelector("h2, h3, h4, h5, h6") ?? target;
1283
+ const stickyHeader = document.querySelector(
1284
+ '[data-slot="legal-page-header"]'
1285
+ );
1286
+ const stickyHeaderBottom = stickyHeader?.getBoundingClientRect().bottom ?? 0;
1287
+ const targetTop = targetHeading.getBoundingClientRect().top + window.scrollY - stickyHeaderBottom - 8;
1288
+ window.scrollTo({
1289
+ top: Math.max(targetTop, 0),
1290
+ behavior: prefersReducedMotion ? "auto" : "smooth"
1291
+ });
1292
+ window.history.pushState(null, "", `#${sectionId}`);
1293
+ setActiveSection(sectionId);
1294
+ };
1295
+ return /* @__PURE__ */ jsxs(
1296
+ "div",
1297
+ {
1298
+ className: cn(
1299
+ "mx-auto max-w-7xl px-4 pb-8 sm:px-6 lg:px-8",
1300
+ "print:max-w-none print:px-0",
1301
+ className
1302
+ ),
1303
+ children: [
1304
+ /* @__PURE__ */ jsx(
1305
+ "header",
1306
+ {
1307
+ "data-slot": "legal-page-header",
1308
+ className: cn(
1309
+ "sticky top-[3px] z-20 -mx-4 mb-8 border-b border-border bg-background px-4 py-5 sm:-mx-6 sm:px-6 lg:-mx-8 lg:mb-10 lg:px-8",
1310
+ "print:static print:mb-6 print:border-b print:bg-transparent print:p-0 print:backdrop-blur-none"
1311
+ ),
1312
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
1313
+ backHref && /* @__PURE__ */ jsxs(
1314
+ "a",
1315
+ {
1316
+ href: backHref,
1317
+ className: "inline-flex w-fit items-center gap-2 text-sm font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background print:hidden",
1318
+ children: [
1319
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "h-4 w-4", "aria-hidden": "true" }),
1320
+ backLabel
1321
+ ]
1322
+ }
1323
+ ),
1324
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between", children: [
1325
+ /* @__PURE__ */ jsx("h1", { className: "text-4xl font-bold tracking-tight text-foreground sm:text-5xl print:text-3xl", children: title }),
1326
+ hasMetadata && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-2 text-sm text-muted-foreground sm:justify-end", children: [
1327
+ lastUpdated && /* @__PURE__ */ jsxs("span", { children: [
1328
+ "Last updated: ",
1329
+ lastUpdated
1330
+ ] }),
1331
+ archiveUrl && /* @__PURE__ */ jsxs(
1332
+ "a",
1333
+ {
1334
+ href: archiveUrl,
1335
+ className: "inline-flex items-center gap-1.5 text-primary hover:underline print:hidden",
1336
+ children: [
1337
+ /* @__PURE__ */ jsx(History, { className: "h-3.5 w-3.5" }),
1338
+ /* @__PURE__ */ jsx("span", { children: "View version history" })
1339
+ ]
1340
+ }
1341
+ )
1342
+ ] })
1343
+ ] })
1344
+ ] })
1345
+ },
1346
+ "legal-page-header"
1347
+ ),
1348
+ /* @__PURE__ */ jsxs(
1349
+ "div",
1350
+ {
1351
+ className: "lg:grid lg:grid-cols-12 lg:gap-8",
1352
+ children: [
1353
+ tableOfContents && tableOfContents.length > 0 && /* @__PURE__ */ jsx("aside", { className: "hidden lg:col-span-3 lg:sticky lg:top-[10.5rem] lg:block lg:max-h-[calc(100vh-11.5rem)] lg:self-start lg:overflow-y-auto print:hidden", children: /* @__PURE__ */ jsxs("nav", { className: "space-y-1", "aria-label": "Table of contents", children: [
1354
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground mb-4", children: "On this page" }),
1355
+ /* @__PURE__ */ jsx("ul", { className: "space-y-2", children: tableOfContents.map((item) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
1356
+ "a",
1357
+ {
1358
+ href: `#${item.id}`,
1359
+ onClick: (event) => scrollToSection(event, item.id),
1360
+ className: cn(
1361
+ "block text-sm transition-all duration-200 py-1",
1362
+ "border-l-2 pl-3 -ml-px",
1363
+ activeSection === item.id ? "text-primary border-primary font-medium" : "text-muted-foreground border-transparent hover:text-foreground hover:border-muted-foreground/50"
1364
+ ),
1365
+ children: item.title
1366
+ }
1367
+ ) }, item.id)) })
1368
+ ] }) }),
1369
+ /* @__PURE__ */ jsxs(
1370
+ "main",
1371
+ {
1372
+ className: cn(
1373
+ tableOfContents && tableOfContents.length > 0 ? "lg:col-span-9" : "lg:col-span-12",
1374
+ "print:col-span-12"
1375
+ ),
1376
+ children: [
1377
+ tableOfContents && tableOfContents.length > 0 && /* @__PURE__ */ jsxs(
1378
+ "nav",
1379
+ {
1380
+ className: "mb-8 rounded-lg border border-border bg-muted/30 p-4 lg:hidden print:hidden",
1381
+ "aria-label": "Table of contents",
1382
+ children: [
1383
+ /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-foreground mb-3", children: "On this page" }),
1384
+ /* @__PURE__ */ jsx("ul", { className: "space-y-2", children: tableOfContents.map((item) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
1385
+ "a",
1386
+ {
1387
+ href: `#${item.id}`,
1388
+ onClick: (event) => scrollToSection(event, item.id),
1389
+ className: "block text-sm text-muted-foreground hover:text-foreground transition-colors",
1390
+ children: item.title
1391
+ }
1392
+ ) }, item.id)) })
1393
+ ]
1394
+ }
1395
+ ),
1396
+ /* @__PURE__ */ jsx(
1397
+ "div",
1398
+ {
1399
+ className: cn(
1400
+ "prose prose-slate dark:prose-invert max-w-none",
1401
+ // Headings
1402
+ "prose-headings:scroll-mt-32 prose-headings:font-semibold",
1403
+ "prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-2",
1404
+ "prose-h3:text-xl prose-h3:mt-6 prose-h3:mb-2",
1405
+ // Paragraphs - reduced top margin
1406
+ "prose-p:text-base prose-p:leading-7 prose-p:mb-4 prose-p:mt-0",
1407
+ // Links - explicit styling for visibility (but not on section header links)
1408
+ "[&>section>a]:no-underline [&>section>a:hover]:no-underline",
1409
+ "prose-a:text-primary prose-a:underline prose-a:underline-offset-2",
1410
+ "hover:prose-a:text-primary/80",
1411
+ // Lists - ensure bullets/numbers are visible
1412
+ "prose-ul:my-4 prose-ul:list-disc prose-ul:pl-6 prose-ul:space-y-2",
1413
+ "prose-ol:my-4 prose-ol:list-decimal prose-ol:pl-6 prose-ol:space-y-2",
1414
+ "prose-li:my-0 prose-li:pl-2",
1415
+ // Strong text
1416
+ "prose-strong:font-semibold prose-strong:text-foreground",
1417
+ // Print styles
1418
+ "print:prose-headings:text-black print:prose-p:text-black",
1419
+ "print:prose-h2:text-xl print:prose-h3:text-lg"
1420
+ ),
1421
+ children
1422
+ }
1423
+ )
1424
+ ]
1425
+ }
1426
+ )
1427
+ ]
1428
+ },
1429
+ "legal-page-content"
1430
+ )
1431
+ ]
1432
+ }
1433
+ );
1434
+ }
1435
+ function LegalSection({
1436
+ id,
1437
+ title,
1438
+ children,
1439
+ className
1440
+ }) {
1441
+ return /* @__PURE__ */ jsxs("section", { id, className: cn("mb-8 scroll-mt-20 print:mb-6", className), children: [
1442
+ /* @__PURE__ */ jsxs(
1443
+ "a",
1444
+ {
1445
+ href: `#${id}`,
1446
+ className: "group inline-flex items-center gap-2 no-underline hover:no-underline text-foreground print:no-underline mb-4",
1447
+ children: [
1448
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold border-b border-muted-foreground/30 group-hover:border-foreground pb-1 print:text-xl print:border-0 my-0!", children: title }),
1449
+ /* @__PURE__ */ jsx(Link2$1, { className: "h-5 w-5 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity print:hidden shrink-0" })
1450
+ ]
1451
+ }
1452
+ ),
1453
+ children
1454
+ ] });
1455
+ }
1456
+ function MarketingLayout({
1457
+ navbar,
1458
+ children,
1459
+ footer,
1460
+ mainClassName,
1461
+ className
1462
+ }) {
1463
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex min-h-screen flex-col", className), children: [
1464
+ navbar,
1465
+ /* @__PURE__ */ jsx("main", { className: cn("flex-1", mainClassName), children }),
1466
+ footer
1467
+ ] });
1468
+ }
1469
+ function Toaster({ ...props }) {
1470
+ return /* @__PURE__ */ jsx(Toaster$1, { ...props });
1471
+ }
1472
+ var themeScript = `
1473
+ (function() {
1474
+ try {
1475
+ var theme = localStorage.getItem('theme');
1476
+ var isDark =
1477
+ theme === 'dark' ||
1478
+ ((theme === 'system' || !theme) &&
1479
+ window.matchMedia('(prefers-color-scheme: dark)').matches);
1480
+ document.documentElement.classList.toggle('dark', isDark);
1481
+ } catch (e) {}
1482
+ })();
1483
+ `;
1484
+ function RootLayout({
1485
+ children,
1486
+ font,
1487
+ fontClassName = "",
1488
+ analytics,
1489
+ toast,
1490
+ className
1491
+ }) {
1492
+ const baseClasses = "font-sans min-h-dvh bg-background text-foreground flex flex-col antialiased overflow-x-hidden";
1493
+ const showToaster = toast?.enabled !== false;
1494
+ const toasterPosition = toast?.position ?? "bottom-right";
1495
+ let fontClasses = "";
1496
+ const fontStyles = {};
1497
+ if (font) {
1498
+ if (font.variables) {
1499
+ fontClasses = font.variables;
1500
+ }
1501
+ if (font.body) {
1502
+ fontStyles["--font-body"] = font.body;
1503
+ }
1504
+ if (font.headers) {
1505
+ fontStyles["--font-headers"] = font.headers;
1506
+ }
1507
+ if (font.mono) {
1508
+ fontStyles["--font-mono"] = font.mono;
1509
+ }
1510
+ }
1511
+ if (!font?.variables && fontClassName) {
1512
+ fontClasses = fontClassName;
1513
+ }
1514
+ const combinedClassName = [fontClasses, baseClasses, className].filter(Boolean).join(" ");
1515
+ return /* @__PURE__ */ jsxs(
1516
+ "div",
1517
+ {
1518
+ className: combinedClassName,
1519
+ style: Object.keys(fontStyles).length > 0 ? fontStyles : void 0,
1520
+ suppressHydrationWarning: true,
1521
+ children: [
1522
+ analytics?.clarityProjectId && /* @__PURE__ */ jsx(ClarityAnalytics, { projectId: analytics.clarityProjectId }),
1523
+ analytics?.googleAnalyticsId && /* @__PURE__ */ jsx(GoogleAnalytics, { measurementId: analytics.googleAnalyticsId }),
1524
+ children,
1525
+ showToaster && /* @__PURE__ */ jsx(Toaster, { richColors: true, position: toasterPosition })
1526
+ ]
1527
+ }
1528
+ );
1529
+ }
1530
+ function UserPageLayout({
1531
+ title,
1532
+ description,
1533
+ actions,
1534
+ className,
1535
+ contentClassName,
1536
+ loading = false,
1537
+ loadingSkeleton,
1538
+ children,
1539
+ tabs,
1540
+ defaultTab,
1541
+ onTabChange,
1542
+ footer,
1543
+ backLink
1544
+ }) {
1545
+ const showHeader = !backLink && Boolean(title || description || actions);
1546
+ return /* @__PURE__ */ jsx(
1547
+ PageLayoutShell,
1548
+ {
1549
+ title,
1550
+ description,
1551
+ actions,
1552
+ className,
1553
+ contentClassName,
1554
+ footer,
1555
+ showHeader,
1556
+ beforeHeader: backLink ? /* @__PURE__ */ jsx(BackLink, { href: backLink.href, children: backLink.label }) : null,
1557
+ children: loading && loadingSkeleton ? loadingSkeleton : tabs && tabs.length > 0 ? /* @__PURE__ */ jsxs(
1558
+ Tabs,
1559
+ {
1560
+ defaultValue: defaultTab || tabs[0].value,
1561
+ onValueChange: onTabChange,
1562
+ className: "space-y-4",
1563
+ children: [
1564
+ /* @__PURE__ */ jsx(TabsList, { children: tabs.map((tab) => /* @__PURE__ */ jsxs(TabsTrigger, { value: tab.value, className: "gap-2", children: [
1565
+ tab.icon && /* @__PURE__ */ jsx(tab.icon, { className: "h-4 w-4" }),
1566
+ tab.label
1567
+ ] }, tab.value)) }),
1568
+ tabs.map((tab) => /* @__PURE__ */ jsx(TabsContent, { value: tab.value, className: "mt-2", children: tab.content }, tab.value))
1569
+ ]
1570
+ }
1571
+ ) : children
1572
+ }
1573
+ );
1574
+ }
1575
+ function AutoSaveIndicator({
1576
+ status,
1577
+ className,
1578
+ ...props
1579
+ }) {
1580
+ if (status === "idle") return null;
1581
+ return /* @__PURE__ */ jsxs(
1582
+ "span",
1583
+ {
1584
+ className: cn(
1585
+ "inline-flex items-center gap-1.5 text-xs transition-opacity",
1586
+ className
1587
+ ),
1588
+ "aria-live": "polite",
1589
+ ...props,
1590
+ children: [
1591
+ status === "saving" && /* @__PURE__ */ jsxs(Fragment, { children: [
1592
+ /* @__PURE__ */ jsx(Loader2, { className: "w-3 h-3 animate-spin text-muted-foreground" }),
1593
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Saving..." })
1594
+ ] }),
1595
+ status === "saved" && /* @__PURE__ */ jsxs(Fragment, { children: [
1596
+ /* @__PURE__ */ jsx(Check, { className: "w-3 h-3 text-green-600" }),
1597
+ /* @__PURE__ */ jsx("span", { className: "text-green-600", children: "Saved" })
1598
+ ] }),
1599
+ status === "error" && /* @__PURE__ */ jsxs(Fragment, { children: [
1600
+ /* @__PURE__ */ jsx(X, { className: "w-3 h-3 text-destructive" }),
1601
+ /* @__PURE__ */ jsx("span", { className: "text-destructive", children: "Save failed" })
1602
+ ] })
1603
+ ]
1604
+ }
1605
+ );
1606
+ }
1607
+ function ProgressBar({
1608
+ value,
1609
+ max = 100,
1610
+ showLabel = true,
1611
+ size = "md",
1612
+ className,
1613
+ ...props
1614
+ }) {
1615
+ const percentage = Math.min(Math.max(value / max * 100, 0), 100);
1616
+ const sizeClasses = {
1617
+ sm: "h-1.5",
1618
+ md: "h-2.5",
1619
+ lg: "h-4"
1620
+ };
1621
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), ...props, children: [
1622
+ showLabel && /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-1", children: [
1623
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-muted-foreground", children: "Application Progress" }),
1624
+ /* @__PURE__ */ jsxs("span", { className: "text-sm font-medium text-foreground", children: [
1625
+ Math.round(percentage),
1626
+ "%"
1627
+ ] })
1628
+ ] }),
1629
+ /* @__PURE__ */ jsx(
1630
+ "div",
1631
+ {
1632
+ className: cn(
1633
+ "w-full bg-muted rounded-full overflow-hidden",
1634
+ sizeClasses[size]
1635
+ ),
1636
+ role: "progressbar",
1637
+ "aria-valuenow": value,
1638
+ "aria-valuemin": 0,
1639
+ "aria-valuemax": max,
1640
+ "aria-label": `Application ${Math.round(percentage)}% complete`,
1641
+ children: /* @__PURE__ */ jsx(
1642
+ "div",
1643
+ {
1644
+ className: cn(
1645
+ "h-full bg-primary rounded-full transition-all duration-300 ease-out"
1646
+ ),
1647
+ style: { width: `${percentage}%` }
1648
+ }
1649
+ )
1650
+ }
1651
+ )
1652
+ ] });
1653
+ }
1654
+ var stepperSizes = {
1655
+ default: {
1656
+ circle: "w-8 h-8",
1657
+ connector: "mx-4",
1658
+ gap: "gap-2",
1659
+ icon: "w-4 h-4",
1660
+ label: "text-sm",
1661
+ mobileLabel: "text-[11px]",
1662
+ number: "text-sm"
1663
+ },
1664
+ compact: {
1665
+ circle: "w-7 h-7",
1666
+ connector: "mx-2",
1667
+ gap: "gap-1.5",
1668
+ icon: "w-3.5 h-3.5",
1669
+ label: "text-xs",
1670
+ mobileLabel: "text-[11px]",
1671
+ number: "text-xs"
1672
+ }
1673
+ };
1674
+ function Stepper({
1675
+ steps,
1676
+ currentStep,
1677
+ completedSteps,
1678
+ onStepClick,
1679
+ mobileVariant = "summary",
1680
+ size = "default",
1681
+ className,
1682
+ ...props
1683
+ }) {
1684
+ const currentIndex = steps.findIndex((s) => s.id === currentStep);
1685
+ const styles = stepperSizes[size];
1686
+ return /* @__PURE__ */ jsxs(
1687
+ "nav",
1688
+ {
1689
+ "aria-label": "Application progress",
1690
+ className: cn("w-full", className),
1691
+ ...props,
1692
+ children: [
1693
+ /* @__PURE__ */ jsx("ol", { className: "hidden md:flex items-center w-full", children: steps.map((step, index) => {
1694
+ const isCompleted = completedSteps.includes(step.id);
1695
+ const isCurrent = step.id === currentStep;
1696
+ const isClickable = isCompleted || isCurrent;
1697
+ return /* @__PURE__ */ jsxs(
1698
+ "li",
1699
+ {
1700
+ className: cn(
1701
+ "flex items-center",
1702
+ index < steps.length - 1 && "flex-1"
1703
+ ),
1704
+ children: [
1705
+ /* @__PURE__ */ jsxs(
1706
+ "button",
1707
+ {
1708
+ type: "button",
1709
+ onClick: () => isClickable && onStepClick?.(step.id),
1710
+ disabled: !isClickable,
1711
+ className: cn(
1712
+ "flex items-center group",
1713
+ styles.gap,
1714
+ isClickable && "cursor-pointer",
1715
+ !isClickable && "cursor-not-allowed opacity-50"
1716
+ ),
1717
+ "aria-current": isCurrent ? "step" : void 0,
1718
+ children: [
1719
+ /* @__PURE__ */ jsx(
1720
+ "span",
1721
+ {
1722
+ className: cn(
1723
+ "flex items-center justify-center rounded-full border-2 shrink-0 transition-colors",
1724
+ styles.circle,
1725
+ isCompleted && "bg-primary border-primary text-primary-foreground",
1726
+ isCurrent && !isCompleted && "border-primary text-primary bg-background",
1727
+ !isCompleted && !isCurrent && "border-muted-foreground/30 text-muted-foreground"
1728
+ ),
1729
+ children: isCompleted ? /* @__PURE__ */ jsx(Check, { className: styles.icon }) : /* @__PURE__ */ jsx("span", { className: cn(styles.number, "font-medium"), children: index + 1 })
1730
+ }
1731
+ ),
1732
+ /* @__PURE__ */ jsx(
1733
+ "span",
1734
+ {
1735
+ className: cn(
1736
+ "font-medium hidden lg:block",
1737
+ styles.label,
1738
+ isCurrent && "text-primary",
1739
+ !isCurrent && "text-muted-foreground",
1740
+ isClickable && "group-hover:text-foreground"
1741
+ ),
1742
+ children: step.label
1743
+ }
1744
+ )
1745
+ ]
1746
+ }
1747
+ ),
1748
+ index < steps.length - 1 && /* @__PURE__ */ jsx(
1749
+ "div",
1750
+ {
1751
+ className: cn(
1752
+ "flex-1 h-0.5",
1753
+ styles.connector,
1754
+ isCompleted ? "bg-primary" : "bg-muted"
1755
+ )
1756
+ }
1757
+ )
1758
+ ]
1759
+ },
1760
+ step.id
1761
+ );
1762
+ }) }),
1763
+ mobileVariant === "steps" ? /* @__PURE__ */ jsx(
1764
+ "ol",
1765
+ {
1766
+ "data-slot": "stepper-mobile-steps",
1767
+ className: "md:hidden flex items-start w-full",
1768
+ children: steps.map((step, index) => {
1769
+ const isCompleted = completedSteps.includes(step.id);
1770
+ const isCurrent = step.id === currentStep;
1771
+ const isClickable = isCompleted || isCurrent;
1772
+ return /* @__PURE__ */ jsxs(
1773
+ "li",
1774
+ {
1775
+ className: cn(
1776
+ "flex items-start min-w-0",
1777
+ index < steps.length - 1 && "flex-1"
1778
+ ),
1779
+ children: [
1780
+ /* @__PURE__ */ jsxs(
1781
+ "button",
1782
+ {
1783
+ type: "button",
1784
+ onClick: () => isClickable && onStepClick?.(step.id),
1785
+ disabled: !isClickable,
1786
+ className: cn(
1787
+ "group flex min-w-0 flex-col items-center gap-1 text-center",
1788
+ isClickable && "cursor-pointer",
1789
+ !isClickable && "cursor-not-allowed opacity-50"
1790
+ ),
1791
+ "aria-current": isCurrent ? "step" : void 0,
1792
+ children: [
1793
+ /* @__PURE__ */ jsx(
1794
+ "span",
1795
+ {
1796
+ className: cn(
1797
+ "flex items-center justify-center rounded-full border-2 shrink-0 transition-colors",
1798
+ styles.circle,
1799
+ isCompleted && "bg-primary border-primary text-primary-foreground",
1800
+ isCurrent && !isCompleted && "border-primary text-primary bg-background",
1801
+ !isCompleted && !isCurrent && "border-muted-foreground/30 text-muted-foreground"
1802
+ ),
1803
+ children: isCompleted ? /* @__PURE__ */ jsx(Check, { className: styles.icon }) : /* @__PURE__ */ jsx("span", { className: cn(styles.number, "font-medium"), children: index + 1 })
1804
+ }
1805
+ ),
1806
+ /* @__PURE__ */ jsx(
1807
+ "span",
1808
+ {
1809
+ className: cn(
1810
+ "max-w-16 truncate font-medium leading-tight",
1811
+ styles.mobileLabel,
1812
+ isCurrent && "text-primary",
1813
+ !isCurrent && "text-muted-foreground",
1814
+ isClickable && "group-hover:text-foreground"
1815
+ ),
1816
+ children: step.label
1817
+ }
1818
+ )
1819
+ ]
1820
+ }
1821
+ ),
1822
+ index < steps.length - 1 && /* @__PURE__ */ jsx(
1823
+ "div",
1824
+ {
1825
+ className: cn(
1826
+ "mt-3.5 h-0.5 min-w-3 flex-1 mx-1",
1827
+ isCompleted ? "bg-primary" : "bg-muted"
1828
+ )
1829
+ }
1830
+ )
1831
+ ]
1832
+ },
1833
+ step.id
1834
+ );
1835
+ })
1836
+ }
1837
+ ) : /* @__PURE__ */ jsxs("div", { className: "md:hidden flex items-center justify-between", children: [
1838
+ /* @__PURE__ */ jsxs("span", { className: "text-sm font-medium text-muted-foreground", children: [
1839
+ "Step ",
1840
+ currentIndex + 1,
1841
+ " of ",
1842
+ steps.length
1843
+ ] }),
1844
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: steps[currentIndex]?.label })
1845
+ ] })
1846
+ ]
1847
+ }
1848
+ );
1849
+ }
1850
+ function TimeEstimate({ minutes, className, ...props }) {
1851
+ const displayText = minutes < 1 ? "Less than a minute" : minutes === 1 ? "~1 minute" : `~${Math.round(minutes)} minutes`;
1852
+ return /* @__PURE__ */ jsxs(
1853
+ "div",
1854
+ {
1855
+ className: cn(
1856
+ "flex items-center gap-1.5 text-sm text-muted-foreground",
1857
+ className
1858
+ ),
1859
+ ...props,
1860
+ children: [
1861
+ /* @__PURE__ */ jsx(Clock, { className: "w-4 h-4" }),
1862
+ /* @__PURE__ */ jsxs("span", { children: [
1863
+ "Estimated time remaining: ",
1864
+ displayText
1865
+ ] })
1866
+ ]
1867
+ }
1868
+ );
1869
+ }
1870
+ function WizardLayout({
1871
+ children,
1872
+ steps,
1873
+ currentStep,
1874
+ completedSteps,
1875
+ onStepClick,
1876
+ progress,
1877
+ timeRemaining,
1878
+ saveStatus = "idle",
1879
+ deadline,
1880
+ isSubmitted = false,
1881
+ submittedTitle = "Your application has been submitted",
1882
+ submittedSubtitle = "You will receive an email confirmation shortly.",
1883
+ loading = false,
1884
+ loadingMessage = "Loading...",
1885
+ error,
1886
+ className
1887
+ }) {
1888
+ const [daysRemaining, setDaysRemaining] = useState(null);
1889
+ useEffect(() => {
1890
+ if (deadline?.daysRemaining !== void 0) {
1891
+ setDaysRemaining(deadline.daysRemaining);
1892
+ }
1893
+ }, [deadline?.daysRemaining]);
1894
+ if (loading) {
1895
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[400px]", children: /* @__PURE__ */ jsx("div", { className: "animate-pulse text-muted-foreground", children: loadingMessage }) });
1896
+ }
1897
+ if (error) {
1898
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center min-h-[400px] gap-4", children: [
1899
+ /* @__PURE__ */ jsx(AlertCircle, { className: "w-12 h-12 text-destructive" }),
1900
+ /* @__PURE__ */ jsx("p", { className: "text-destructive", children: error })
1901
+ ] });
1902
+ }
1903
+ return /* @__PURE__ */ jsxs("div", { className: cn("max-w-4xl mx-auto px-4 py-8", className), children: [
1904
+ deadline && /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
1905
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold mb-1", children: deadline.label }),
1906
+ daysRemaining !== null && daysRemaining <= 7 && !isSubmitted && /* @__PURE__ */ jsx(
1907
+ "div",
1908
+ {
1909
+ className: cn(
1910
+ "text-sm",
1911
+ daysRemaining <= 1 ? "text-destructive font-medium" : "text-amber-600"
1912
+ ),
1913
+ children: daysRemaining <= 0 ? "Applications close today!" : daysRemaining === 1 ? "1 day remaining to submit" : `${daysRemaining} days remaining to submit`
1914
+ }
1915
+ )
1916
+ ] }),
1917
+ !isSubmitted && /* @__PURE__ */ jsxs("div", { className: "mb-8 space-y-4", children: [
1918
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1919
+ /* @__PURE__ */ jsx(ProgressBar, { value: progress, size: "md" }),
1920
+ /* @__PURE__ */ jsx(AutoSaveIndicator, { status: saveStatus, className: "ml-4" })
1921
+ ] }),
1922
+ timeRemaining !== void 0 && /* @__PURE__ */ jsx(TimeEstimate, { minutes: timeRemaining })
1923
+ ] }),
1924
+ /* @__PURE__ */ jsx(
1925
+ Stepper,
1926
+ {
1927
+ steps,
1928
+ currentStep,
1929
+ completedSteps: isSubmitted ? steps.map((s) => s.id) : completedSteps,
1930
+ onStepClick: isSubmitted ? void 0 : onStepClick,
1931
+ className: "mb-8"
1932
+ }
1933
+ ),
1934
+ isSubmitted && /* @__PURE__ */ jsxs("div", { className: "mb-6 p-4 bg-green-50 dark:bg-green-950 border border-green-200 dark:border-green-800 rounded-lg", children: [
1935
+ /* @__PURE__ */ jsxs("p", { className: "text-green-800 dark:text-green-200 font-medium", children: [
1936
+ "\u2713 ",
1937
+ submittedTitle
1938
+ ] }),
1939
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-green-600 dark:text-green-400 mt-1", children: submittedSubtitle })
1940
+ ] }),
1941
+ /* @__PURE__ */ jsx("div", { className: "bg-card border rounded-lg p-6", children })
1942
+ ] });
1943
+ }
1944
+
1945
+ export { AdminPageLayout, AppFooter, AppHeader, AppLayout, AppSidebar, AutoSaveIndicator, BackLink, BasePageLayout, ClarityAnalytics, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, DashboardGrid, FloatingUserMenu, GoogleAnalytics, GoogleTagManager, HelpLayout, HelpPageLayout, HelpPanelLayout, LegalLayout, LegalSection, MarketingLayout, ProgressBar, RootLayout, Stepper, ThemeToggle, TimeEstimate, Toaster, UserPageLayout, WizardLayout, isNavDivider, isNavItem, isNavSection, themeScript, useTheme };