@catalystsoftware/ui 1.0.2 → 1.0.5

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 (157) hide show
  1. package/data/tailwind.config.js +261 -3821
  2. package/dist/components/catalyst-ui/buttons/burger.tsx +207 -0
  3. package/dist/components/catalyst-ui/core/data-display/timeline.tsx +210 -0
  4. package/dist/components/catalyst-ui/core/feedback/alert.tsx +491 -0
  5. package/dist/components/catalyst-ui/core/feedback/spinner-1.tsx +65 -0
  6. package/dist/components/catalyst-ui/core/feedback/toast.tsx +1857 -0
  7. package/dist/components/catalyst-ui/core/navigation/menu.tsx +164 -0
  8. package/dist/components/catalyst-ui/forms/toggle-class.tsx +176 -0
  9. package/dist/components/catalyst-ui/hooks/use-copy-to-clipboard.tsx +419 -0
  10. package/dist/components/catalyst-ui/hooks/use-counter.tsx +13 -0
  11. package/dist/components/catalyst-ui/hooks/use-event-listener.tsx +23 -0
  12. package/dist/components/catalyst-ui/hooks/use-export-markdown.tsx +47 -0
  13. package/dist/components/catalyst-ui/hooks/use-focus.tsx +17 -0
  14. package/dist/components/catalyst-ui/hooks/use-interval.tsx +23 -0
  15. package/dist/components/catalyst-ui/hooks/use-is-client.tsx +16 -0
  16. package/dist/components/catalyst-ui/hooks/use-media-query.tsx +19 -0
  17. package/dist/components/catalyst-ui/hooks/use-mobile.tsx +19 -0
  18. package/dist/components/catalyst-ui/hooks/use-resize-observer.tsx +81 -0
  19. package/dist/components/catalyst-ui/hooks/use-timeout.tsx +21 -0
  20. package/dist/components/catalyst-ui/hooks/use-timer.tsx +209 -0
  21. package/dist/components/catalyst-ui/hooks/use-toggle.tsx +12 -0
  22. package/dist/components/catalyst-ui/media/image.tsx +13 -0
  23. package/dist/components/catalyst-ui/overlays/dual-sidebar.tsx +4142 -0
  24. package/dist/components/catalyst-ui/overlays/sidebar-original.tsx +726 -0
  25. package/dist/components/catalyst-ui/primitives/accordion.tsx +250 -0
  26. package/dist/components/catalyst-ui/primitives/alert-dialog.tsx +126 -0
  27. package/dist/components/catalyst-ui/primitives/aspect-ratio.tsx +9 -0
  28. package/dist/components/catalyst-ui/primitives/avatar.tsx +296 -0
  29. package/dist/components/catalyst-ui/primitives/badge.tsx +57 -0
  30. package/dist/components/catalyst-ui/primitives/breadcrumb.tsx +101 -0
  31. package/dist/components/catalyst-ui/primitives/button.tsx +265 -0
  32. package/dist/components/catalyst-ui/primitives/calendar-v4.tsx +208 -0
  33. package/dist/components/catalyst-ui/primitives/calendar.tsx +295 -0
  34. package/dist/components/catalyst-ui/primitives/card.tsx +618 -0
  35. package/dist/components/catalyst-ui/primitives/carousel.tsx +238 -0
  36. package/dist/components/catalyst-ui/primitives/chart.tsx +347 -0
  37. package/dist/components/catalyst-ui/primitives/checkbox.tsx +225 -0
  38. package/dist/components/catalyst-ui/primitives/collapsible.tsx +212 -0
  39. package/dist/components/catalyst-ui/primitives/command.tsx +393 -0
  40. package/dist/components/catalyst-ui/primitives/context-menu.tsx +236 -0
  41. package/dist/components/catalyst-ui/primitives/dialog.tsx +471 -0
  42. package/dist/components/catalyst-ui/primitives/drawer.tsx +761 -0
  43. package/dist/components/catalyst-ui/primitives/dropdown-menu.tsx +290 -0
  44. package/dist/components/catalyst-ui/primitives/empty.tsx +104 -0
  45. package/dist/components/catalyst-ui/primitives/field.tsx +244 -0
  46. package/dist/components/catalyst-ui/primitives/hover-card.tsx +124 -0
  47. package/dist/components/catalyst-ui/primitives/input-otp.tsx +76 -0
  48. package/dist/components/catalyst-ui/primitives/input.tsx +64 -0
  49. package/dist/components/catalyst-ui/primitives/item.tsx +196 -0
  50. package/dist/components/catalyst-ui/primitives/kbd.tsx +75 -0
  51. package/dist/components/catalyst-ui/primitives/label.tsx +24 -0
  52. package/dist/components/catalyst-ui/primitives/navigation-menu.tsx +150 -0
  53. package/dist/components/catalyst-ui/primitives/pagination.tsx +198 -0
  54. package/dist/components/catalyst-ui/primitives/popover.tsx +232 -0
  55. package/dist/components/catalyst-ui/primitives/progress.tsx +34 -0
  56. package/dist/components/catalyst-ui/primitives/radio-group.tsx +43 -0
  57. package/dist/components/catalyst-ui/primitives/resizable.tsx +56 -0
  58. package/dist/components/catalyst-ui/primitives/select.tsx +155 -0
  59. package/dist/components/catalyst-ui/primitives/separator.tsx +74 -0
  60. package/dist/components/catalyst-ui/primitives/sheet.tsx +126 -0
  61. package/dist/components/catalyst-ui/primitives/skeleton.tsx +15 -0
  62. package/dist/components/catalyst-ui/primitives/slider.tsx +27 -0
  63. package/dist/components/catalyst-ui/primitives/switch.tsx +187 -0
  64. package/dist/components/catalyst-ui/primitives/tabs.tsx +335 -0
  65. package/dist/components/catalyst-ui/primitives/textarea.tsx +24 -0
  66. package/dist/components/catalyst-ui/primitives/toggle-group.tsx +55 -0
  67. package/dist/components/catalyst-ui/primitives/toggle.tsx +42 -0
  68. package/dist/components/catalyst-ui/primitives/tooltip.tsx +116 -0
  69. package/dist/components/catalyst-ui/utils/basic-auth.tsx +40 -0
  70. package/dist/components/catalyst-ui/utils/context-storage.tsx +19 -0
  71. package/dist/components/catalyst-ui/utils/cors-middleware.tsx +71 -0
  72. package/dist/components/catalyst-ui/utils/deferred-content.tsx +595 -0
  73. package/dist/components/catalyst-ui/utils/honeypot-middleware.tsx +38 -0
  74. package/dist/components/catalyst-ui/utils/incId.tsx +75 -0
  75. package/dist/components/catalyst-ui/utils/jwk-auth.tsx +36 -0
  76. package/dist/components/catalyst-ui/utils/request-id.tsx +14 -0
  77. package/dist/components/catalyst-ui/utils/secure-headers.tsx +37 -0
  78. package/dist/components/catalyst-ui/utils/server-timing.tsx +23 -0
  79. package/dist/components/catalyst-ui/utils/utils.ts +43 -0
  80. package/dist/components/catalyst-ui/utils/with-cookie.tsx +43 -0
  81. package/dist/components/catalyst-ui/x/accordian-x.tsx +428 -0
  82. package/dist/components/catalyst-ui/x/alert-x.tsx +413 -0
  83. package/dist/components/catalyst-ui/x/animated-text-x.tsx +2242 -0
  84. package/dist/components/catalyst-ui/x/avatar-x.tsx +515 -0
  85. package/dist/components/catalyst-ui/x/badge-x.tsx +670 -0
  86. package/dist/components/catalyst-ui/x/button-X.tsx +2857 -0
  87. package/dist/components/catalyst-ui/x/button-group-x.tsx +847 -0
  88. package/dist/components/catalyst-ui/x/calendar-x.tsx +1910 -0
  89. package/dist/components/catalyst-ui/x/card-x.tsx +2597 -0
  90. package/dist/components/catalyst-ui/x/checkbox-x.tsx +656 -0
  91. package/dist/components/catalyst-ui/x/collapsible-x.tsx +1360 -0
  92. package/dist/components/catalyst-ui/x/combobox-x.tsx +911 -0
  93. package/dist/components/catalyst-ui/x/data-table-x.tsx +1753 -0
  94. package/dist/components/catalyst-ui/x/date-picker-x.tsx +648 -0
  95. package/dist/components/catalyst-ui/x/dialog-x.tsx +659 -0
  96. package/dist/components/catalyst-ui/x/dropdown-menu-x.tsx +612 -0
  97. package/dist/components/catalyst-ui/x/hover-card-x.tsx +375 -0
  98. package/dist/components/catalyst-ui/x/icon-x.tsx +840 -0
  99. package/dist/components/catalyst-ui/x/input-mask-x.tsx +981 -0
  100. package/dist/components/catalyst-ui/x/input-otp-x.tsx +659 -0
  101. package/dist/components/catalyst-ui/x/loader-x.tsx +1757 -0
  102. package/dist/components/catalyst-ui/x/pagination-x.tsx +622 -0
  103. package/dist/components/catalyst-ui/x/popover-x.tsx +744 -0
  104. package/dist/components/catalyst-ui/x/radio-group-x.tsx +499 -0
  105. package/dist/components/catalyst-ui/x/select-x.tsx +1127 -0
  106. package/dist/components/catalyst-ui/x/sheet-x.tsx +668 -0
  107. package/dist/components/catalyst-ui/x/switch-x.tsx +681 -0
  108. package/dist/components/catalyst-ui/x/table-x.tsx +574 -0
  109. package/dist/components/catalyst-ui/x/tabs-x.tsx +839 -0
  110. package/dist/components/catalyst-ui/x/textarea-x.tsx +1263 -0
  111. package/dist/components/catalyst-ui/x/tooltip-x.tsx +396 -0
  112. package/dist/components/catalyst-ui/x/tracker-x.tsx +560 -0
  113. package/dist/data/bg-data.tsx +901 -0
  114. package/dist/data/buttons-data.tsx +2327 -0
  115. package/dist/data/charts-data.tsx +102 -0
  116. package/dist/data/chat-data.tsx +83 -0
  117. package/dist/data/code-data.tsx +1040 -0
  118. package/dist/data/comboboxes-data.tsx +1843 -0
  119. package/dist/data/command-data.tsx +1381 -0
  120. package/dist/data/core-data.tsx +15953 -0
  121. package/dist/data/crm-data.tsx +47 -0
  122. package/dist/data/data.tsx +159 -0
  123. package/dist/data/date-and-time-data.tsx +554 -0
  124. package/dist/data/dependencies.tsx +7 -0
  125. package/dist/data/ecommerce-data.tsx +1387 -0
  126. package/dist/data/forms-data.tsx +7890 -0
  127. package/dist/data/hooks-data.tsx +5487 -0
  128. package/dist/data/index.ts +34 -0
  129. package/dist/data/inputs-data.tsx +557 -0
  130. package/dist/data/interactive-data.tsx +5394 -0
  131. package/dist/data/lofi-data.tsx +18295 -0
  132. package/dist/data/marketing-data.tsx +2546 -0
  133. package/dist/data/media-data.tsx +1510 -0
  134. package/dist/data/motion-data.tsx +5801 -0
  135. package/dist/data/overlay-data.tsx +4136 -0
  136. package/dist/data/pdf-data.tsx +124 -0
  137. package/dist/data/pos-data.tsx +213 -0
  138. package/dist/data/postcss.config.js +6 -0
  139. package/dist/data/primitive-data.tsx +5170 -0
  140. package/dist/data/prompt-data.tsx +1226 -0
  141. package/dist/data/requiredLibs.ts +4 -0
  142. package/dist/data/sandbox-data.tsx +1 -0
  143. package/dist/data/sidebars-data.tsx +5421 -0
  144. package/dist/data/stacks-data.tsx +32 -0
  145. package/dist/data/table-data.tsx +706 -0
  146. package/dist/data/tailwind.config.js +270 -0
  147. package/dist/data/tailwind.config.ngin.js +3830 -0
  148. package/dist/data/tailwind.css +431 -0
  149. package/dist/data/tools-data.tsx +6910 -0
  150. package/dist/data/typography-data.tsx +2050 -0
  151. package/dist/data/utils-data.tsx +6500 -0
  152. package/dist/data/x-data.tsx +1171 -0
  153. package/dist/data.tsx +159 -0
  154. package/package.json +1 -1
  155. package/dist/index.d.ts +0 -3
  156. package/dist/index.d.ts.map +0 -1
  157. package/dist/index.js.map +0 -362
@@ -0,0 +1,4142 @@
1
+ import React, { createContext, useCallback, useContext, useEffect, useState, forwardRef } from "react";
2
+ import { type VariantProps, cva } from "class-variance-authority";
3
+ import { useIsMobile } from "~/modules/hooks/use-mobile";
4
+ import { cn, Loader } from "~/components/catalyst-ui";
5
+ import { Button, Drawer, TooltipProvider, Tooltip, TooltipContent, TooltipTrigger, Input, Skeleton, Separator, Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Dialog, DialogContent, DialogDescription, DialogTitle, DialogTrigger, LoaderX, } from "~/components/catalyst-ui";
6
+ import { useNavigation, NavLink, useLocation } from "@remix-run/react";
7
+ import { Drawer as DrawerPrimitive } from "vaul";
8
+ import { Slot } from "@radix-ui/react-slot";
9
+ import * as AvatarPrimitive from '@radix-ui/react-avatar'
10
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
11
+ import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
12
+ import { Bell, Bot, Globe, Home, Keyboard, Link, Lock, Menu, MessageCircle, Paintbrush, Settings, Video, } from "lucide-react";
13
+ import { Circle, Check, ChevronRight } from "@catalystsoftware/icons";
14
+ import { Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarProvider, } from "~/components/catalyst-ui";
15
+ import { motion } from "motion/react";
16
+
17
+ /**
18
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ DualSidebar System ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
19
+ * ★ ━━━━ ☆ ━━━━ ━━━━ ☆ ━━━━ ★
20
+ * type SidebarVariant = 'sidebar' | 'inset' | 'floating' | 'frosted' | 'card' | 'glass' | 'compact-card' | 'bordered' | 'minimal' | 'elevated'
21
+ * type SidebarSide = 'left' | 'right'
22
+ * type SidebarCollapsible = 'offcanvas' | 'icon' | 'none'
23
+ * type DSTheme = 'neutral' | 'red' | 'orange' | 'green' | 'blue' | 'violet' | 'default'
24
+ *
25
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Basic Setup ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
26
+ * ```jsx
27
+ * // App.tsx or root component
28
+ * <DSProvider>
29
+ * <DSLeft variant="sidebar">
30
+ * <DSHeader>Left Sidebar</DSHeader>
31
+ * <DSContent>
32
+ * <DSMenu>
33
+ * <DSMenuLink to="/dashboard" icon={<Home />}>Dashboard</DSMenuLink>
34
+ * <DSMenuLink to="/profile" icon={<User />}>Profile</DSMenuLink>
35
+ * </DSMenu>
36
+ * </DSContent>
37
+ * </DSLeft>
38
+ *
39
+ * <DSRight variant="floating">
40
+ * <DSHeader>Right Sidebar</DSHeader>
41
+ * <DSContent>Right content</DSContent>
42
+ * </DSRight>
43
+ *
44
+ * <DSInset>
45
+ * <main>Main content here</main>
46
+ * </DSInset>
47
+ * </DSProvider>
48
+ * ```
49
+ *
50
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ With Icon Sidebars ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
51
+ * ```jsx
52
+ * <DSProvider>
53
+ * <DSLeftIcon iconWidth="48px">
54
+ * <DSContent>
55
+ * <DSMenu>
56
+ * <DSMenuButton tooltip="Dashboard"><Home /></DSMenuButton>
57
+ * <DSMenuButton tooltip="Profile"><User /></DSMenuButton>
58
+ * </DSMenu>
59
+ * </DSContent>
60
+ * </DSLeftIcon>
61
+ *
62
+ * <DSLeft variant="sidebar">
63
+ * <DSHeader>Full Sidebar</DSHeader>
64
+ * <DSContent>Expanded content</DSContent>
65
+ * </DSLeft>
66
+ *
67
+ * <DSInset>
68
+ * Main content area
69
+ * </DSInset>
70
+ * </DSProvider>
71
+ * ```
72
+ *
73
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Variant Examples ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
74
+ * ```jsx
75
+ * // Inset variant
76
+ * <DSLeft variant="inset">
77
+ * <DSHeader>Inset Sidebar</DSHeader>
78
+ * <DSContent>Rounded sidebar with padding</DSContent>
79
+ * </DSLeft>
80
+ *
81
+ * // Floating variant
82
+ * <DSRight variant="floating">
83
+ * <DSHeader>Floating Sidebar</DSHeader>
84
+ * <DSContent>Rounded with shadow</DSContent>
85
+ * </DSRight>
86
+ *
87
+ * // Frosted glass variant
88
+ * <DSLeft variant="frosted">
89
+ * <DSHeader>Glass Sidebar</DSHeader>
90
+ * <DSContent>Backdrop blur effect</DSContent>
91
+ * </DSLeft>
92
+ *
93
+ * // Card variant
94
+ * <DSRight variant="card">
95
+ * <DSHeader>Card Sidebar</DSHeader>
96
+ * <DSContent>Card-like appearance</DSContent>
97
+ * </DSRight>
98
+ * ```
99
+ *
100
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Menu Components ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
101
+ * ```jsx
102
+ * <DSMenu>
103
+ * // Regular menu button
104
+ * <DSMenuButton variant="default" icon={<Home />}>
105
+ * Dashboard
106
+ * </DSMenuButton>
107
+ *
108
+ * // Active menu button
109
+ * <DSMenuButton isActive variant="solid" icon={<Settings />}>
110
+ * Settings
111
+ * </DSMenuButton>
112
+ *
113
+ * // With badge
114
+ * <DSMenuButton icon={<Bell />}>
115
+ * Notifications
116
+ * <DSMenuBadge variant="primary">5</DSMenuBadge>
117
+ * </DSMenuButton>
118
+ *
119
+ * // Navigation link with loading state
120
+ * <DSMenuLink to="/dashboard" icon={<Home />}>
121
+ * Dashboard
122
+ * </DSMenuLink>
123
+ *
124
+ * // External link
125
+ * <DSMenuAnchor to="https://example.com" icon={<ExternalLink />}>
126
+ * External
127
+ * </DSMenuAnchor>
128
+ *
129
+ * // With submenu
130
+ * <DSMenuItem>
131
+ * <DSMenuButton icon={<Folder />}>Documents</DSMenuButton>
132
+ * <DSMenuSub>
133
+ * <DSMenuSubButton>Resume.pdf</DSMenuSubButton>
134
+ * <DSMenuSubButton>Projects.zip</DSMenuSubButton>
135
+ * </DSMenuSub>
136
+ * </DSMenuItem>
137
+ * </DSMenu>
138
+ * ```
139
+ *
140
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Group Components ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
141
+ * ```jsx
142
+ * <DSGroup variant="card">
143
+ * <DSGroupLabel variant="prominent">Account</DSGroupLabel>
144
+ * <DSGroupContent>
145
+ * <DSMenuLink to="/profile" icon={<User />}>Profile</DSMenuLink>
146
+ * <DSMenuLink to="/settings" icon={<Settings />}>Settings</DSMenuLink>
147
+ * </DSGroupContent>
148
+ * </DSGroup>
149
+ *
150
+ * <DSGroup variant="separated">
151
+ * <DSGroupLabel>Navigation</DSGroupLabel>
152
+ * <DSGroupContent>
153
+ * <DSMenuLink to="/dashboard" icon={<Home />}>Dashboard</DSMenuLink>
154
+ * <DSMenuLink to="/analytics" icon={<Chart />}>Analytics</DSMenuLink>
155
+ * </DSGroupContent>
156
+ * </DSGroup>
157
+ * ```
158
+ *
159
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Theme System ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
160
+ * ```jsx
161
+ * // Using the theme selector
162
+ * <DSThemeSelector size={28}>
163
+ * <Paintbrush className="size-4" />
164
+ * </DSThemeSelector>
165
+ *
166
+ * // Programmatic theme control
167
+ * const { theme, setTheme } = useDSTheme()
168
+ *
169
+ * // Changing theme
170
+ * <button onClick={() => setTheme('blue')}>
171
+ * Switch to Blue Theme
172
+ * </button>
173
+ * ```
174
+ *
175
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Drawer Components ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
176
+ * ```jsx
177
+ * // Top drawer
178
+ * <DSD drawerHeight="300px" variant="card">
179
+ * <DSTrigger>Open Drawer</DSTrigger>
180
+ * <DSDContent>
181
+ * <DSDHeader>
182
+ * <DSDTitle>Notifications</DSDTitle>
183
+ * <DSDDescription>You have 5 new notifications</DSDDescription>
184
+ * </DSDHeader>
185
+ * <div className="p-4">Drawer content</div>
186
+ * <DSDFooter>
187
+ * <Button>Close</Button>
188
+ * </DSDFooter>
189
+ * </DSDContent>
190
+ * </DSD>
191
+ *
192
+ * // Side drawer variants
193
+ * <DSD direction="right" variant="glass">
194
+ * <DSTrigger>Open Side Drawer</DSTrigger>
195
+ * <DSDContent>
196
+ * <DSDHeader>Side Panel</DSDHeader>
197
+ * <div className="p-4">Side content</div>
198
+ * </DSDContent>
199
+ * </DSD>
200
+ * ```
201
+ *
202
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Dropdown Menu ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
203
+ * ```jsx
204
+ * <DSDM>
205
+ * <DSDMTrigger asChild>
206
+ * <Button variant="ghost">Open Menu</Button>
207
+ * </DSDMTrigger>
208
+ * <DSDMContent>
209
+ * <DSDMGroup>
210
+ * <DSDMItem>
211
+ * <User className="mr-2" /> Profile
212
+ * </DSDMItem>
213
+ * <DSDMItem>
214
+ * <Settings className="mr-2" /> Settings
215
+ * </DSDMItem>
216
+ * </DSDMGroup>
217
+ * <DSDMSeparator />
218
+ * <DSDMItem variant="destructive">
219
+ * <LogOut className="mr-2" /> Logout
220
+ * </DSDMItem>
221
+ * </DSDMContent>
222
+ * </DSDM>
223
+ * ```
224
+ *
225
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Collapsible Sections ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
226
+ * ```jsx
227
+ * <DSC>
228
+ * <DSCTrigger asChild>
229
+ * <DSMenuButton icon={<ChevronRight />}>Settings</DSMenuButton>
230
+ * </DSCTrigger>
231
+ * <DSCContent>
232
+ * <DSMenuSub>
233
+ * <DSMenuSubButton>Appearance</DSMenuSubButton>
234
+ * <DSMenuSubButton>Notifications</DSMenuSubButton>
235
+ * <DSMenuSubButton>Privacy</DSMenuSubButton>
236
+ * </DSMenuSub>
237
+ * </DSCContent>
238
+ * </DSC>
239
+ * ```
240
+ *
241
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Props Reference ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
242
+ * - DSProvider Props:
243
+ * - `defaultOpenLeft`: boolean - Default left sidebar open state
244
+ * - `defaultOpenRight`: boolean - Default right sidebar open state
245
+ * - `defaultWidth`: string - Default sidebar width (default: "275px")
246
+ *
247
+ * - DSLeft/DSRight Props:
248
+ * - `variant`: SidebarVariant - Visual style of sidebar
249
+ * - `collapsible`: SidebarCollapsible - Collapse behavior
250
+ * - `loadingUI`: boolean - Show loading skeleton (default: true)
251
+ *
252
+ * - DSLeftIcon/DSRightIcon Props:
253
+ * - `iconWidth`: string - Width of icon sidebar (default: "48px")
254
+ * - `variant`: SidebarVariant - Visual style
255
+ *
256
+ * - DSInset Props:
257
+ * - `variant`: 'default' | 'inset' | 'card' | 'bordered' - Main content area style
258
+ *
259
+ * - DSMenuButton Props:
260
+ * - `variant`: 'default' | 'ghost' | 'outline' | 'soft' | 'solid' | 'minimal' | 'bordered' | 'pill'
261
+ * - `size`: 'default' | 'sm' | 'lg' | 'icon'
262
+ * - `isActive`: boolean - Active state styling
263
+ * - `tooltip`: string | TooltipContentProps - Tooltip content
264
+ * - `icon`: ReactNode - Icon element
265
+ *
266
+ * - DSMenuLink/DSMenuAnchor Props:
267
+ * - `to`: string - Navigation path or URL
268
+ * - `variant`: Menu button variant
269
+ * - `size`: Menu button size
270
+ * - `icon`: ReactNode - Icon element
271
+ * - `tooltip`: string - Tooltip text
272
+ * - `newTab`: boolean - Open in new tab (DSMenuAnchor only)
273
+ *
274
+ * - DSGroup Props:
275
+ * - `variant`: 'default' | 'separated' | 'card' | 'bordered' | 'subtle'
276
+ *
277
+ * - DSGroupLabel Props:
278
+ * - `variant`: 'default' | 'prominent' | 'subtle' | 'separated'
279
+ * - `asChild`: boolean - Merge with child element
280
+ *
281
+ * - DSD (Drawer) Props:
282
+ * - `drawerHeight`: string - Height when open
283
+ * - `variant`: 'default' | 'card' | 'glass' | 'elevated' | 'bordered' | 'macos'
284
+ * - `direction`: 'top' | 'bottom' | 'right' | 'left'
285
+ * - `size`: 'default' | 'sm' | 'md' | 'lg' | 'full'
286
+ *
287
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Hooks & Context ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
288
+ * ```typescript
289
+ * // Use sidebar state and controls
290
+ * const {
291
+ * leftState, // 'expanded' | 'collapsed'
292
+ * rightState, // 'expanded' | 'collapsed'
293
+ * toggleLeft, // () => void
294
+ * toggleRight, // () => void
295
+ * openLeft, // boolean
296
+ * openRight, // boolean
297
+ * setOpenLeft, // (open: boolean) => void
298
+ * setOpenRight, // (open: boolean) => void
299
+ * isMobile, // boolean
300
+ * sidebarWidth, // number
301
+ * leftVariant, // SidebarVariant
302
+ * rightVariant, // SidebarVariant
303
+ * setLeftVariant, // (variant: SidebarVariant) => void
304
+ * setRightVariant, // (variant: SidebarVariant) => void
305
+ * } = useDS()
306
+ *
307
+ * // Use theme controls
308
+ * const {
309
+ * theme, // DSTheme
310
+ * setTheme, // (theme: DSTheme) => void
311
+ * themeVars, // Record<string, string>
312
+ * } = useDSTheme()
313
+ * ```
314
+ *
315
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Keyboard Shortcuts ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
316
+ * - **Cmd/Ctrl + B**: Toggle left sidebar
317
+ * - **Cmd/Ctrl + G**: Toggle right sidebar
318
+ * - **Mobile**: Swipe gestures supported
319
+ * - **Accessibility**: Full keyboard navigation and ARIA labels
320
+ *
321
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Responsive Behavior ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
322
+ * - **Desktop**: Sidebars can be expanded/collapsed with icon mode
323
+ * - **Tablet**: Adaptive layouts with optimized spacing
324
+ * - **Mobile**: Sidebars become offcanvas drawers with swipe support
325
+ * - **Auto-adjust**: Content area automatically resizes based on sidebar states
326
+ *
327
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Theming System ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
328
+ * ```typescript
329
+ * // Available themes
330
+ * const themes = [
331
+ * 'neutral', // Default neutral colors
332
+ * 'red', // Red accent theme
333
+ * 'orange', // Orange accent theme
334
+ * 'green', // Green accent theme
335
+ * 'blue', // Blue accent theme (default)
336
+ * 'violet', // Purple accent theme
337
+ * 'default' // System default
338
+ * ]
339
+ *
340
+ * // Theme persistence
341
+ * // - Automatically saved to localStorage
342
+ * // - Survives page refreshes
343
+ * // - CSS custom properties updated in real-time
344
+ * ```
345
+ *
346
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Loading States ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
347
+ * ```jsx
348
+ * // Show loading skeleton during navigation
349
+ * <DSLeft loadingUI={true}>
350
+ * <DSContent>
351
+ * <DSMenuSkeleton showIcon />
352
+ * <DSMenuSkeleton showIcon />
353
+ * <DSMenuSkeleton />
354
+ * </DSContent>
355
+ * </DSLeft>
356
+ *
357
+ * // Or use the standalone loader
358
+ * <DSLoading variant="card" size="md" />
359
+ * ```
360
+ *
361
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Example: Complete Layout ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
362
+ * ```jsx
363
+ * <DSProvider defaultOpenLeft={true} defaultWidth="280px">
364
+ * <DSLeftIcon>
365
+ * <DSContent>
366
+ * <DSMenu>
367
+ * <DSMenuButton tooltip="Dashboard"><Home /></DSMenuButton>
368
+ * <DSMenuButton tooltip="Messages"><MessageCircle /></DSMenuButton>
369
+ * <DSMenuButton tooltip="Settings"><Settings /></DSMenuButton>
370
+ * </DSMenu>
371
+ * </DSContent>
372
+ * </DSLeftIcon>
373
+ *
374
+ * <DSLeft variant="frosted" collapsible="offcanvas">
375
+ * <DSHeader>
376
+ * <div className="flex items-center gap-3">
377
+ * <Avatar>
378
+ * <AvatarImage src="/avatar.jpg" />
379
+ * <AvatarFallback>JD</AvatarFallback>
380
+ * </Avatar>
381
+ * <div>
382
+ * <h3 className="font-semibold">John Doe</h3>
383
+ * <p className="text-sm text-muted-foreground">Admin</p>
384
+ * </div>
385
+ * </div>
386
+ * </DSHeader>
387
+ *
388
+ * <DSContent>
389
+ * <DSGroup variant="card">
390
+ * <DSGroupLabel>Navigation</DSGroupLabel>
391
+ * <DSMenu>
392
+ * <DSMenuLink to="/dashboard" icon={<Home />}>Dashboard</DSMenuLink>
393
+ * <DSMenuLink to="/analytics" icon={<ChartBar />}>Analytics</DSMenuLink>
394
+ * <DSMenuLink to="/users" icon={<Users />}>Users</DSMenuLink>
395
+ * </DSMenu>
396
+ * </DSGroup>
397
+ *
398
+ * <DSGroup variant="separated">
399
+ * <DSGroupLabel>Settings</DSGroupLabel>
400
+ * <DSMenu>
401
+ * <DSMenuLink to="/settings" icon={<Settings />}>General</DSMenuLink>
402
+ * <DSMenuLink to="/notifications" icon={<Bell />}>
403
+ * Notifications
404
+ * <DSMenuBadge variant="primary">3</DSMenuBadge>
405
+ * </DSMenuLink>
406
+ * </DSMenu>
407
+ * </DSGroup>
408
+ * </DSContent>
409
+ *
410
+ * <DSFooter>
411
+ * <div className="flex items-center justify-between">
412
+ * <DSThemeSelector size={24}>
413
+ * <Paintbrush className="size-3" />
414
+ * </DSThemeSelector>
415
+ * <Button variant="ghost" size="icon">
416
+ * <LogOut className="size-4" />
417
+ * </Button>
418
+ * </div>
419
+ * </DSFooter>
420
+ * </DSLeft>
421
+ *
422
+ * <DSRight variant="floating">
423
+ * <DSHeader>
424
+ * <h3 className="font-semibold">Quick Actions</h3>
425
+ * </DSHeader>
426
+ * <DSContent>
427
+ * <div className="p-4">Right panel content</div>
428
+ * </DSContent>
429
+ * </DSRight>
430
+ *
431
+ * <DSInset variant="inset">
432
+ * <div className="p-6">
433
+ * <h1 className="text-3xl font-bold">Dashboard</h1>
434
+ * <p className="mt-2 text-muted-foreground">Welcome to your workspace</p>
435
+ * </div>
436
+ * </DSInset>
437
+ *
438
+ * <DSD drawerHeight="400px" variant="macos">
439
+ * <DSDContent>
440
+ * <DSDHeader>
441
+ * <DSDTitle>Notifications</DSDTitle>
442
+ * </DSDHeader>
443
+ * <div className="p-4">Notification list</div>
444
+ * </DSDContent>
445
+ * </DSD>
446
+ * </DSProvider>
447
+ * ```
448
+ *
449
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Advanced Features ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
450
+ * 1. **Dual Sidebar Support**: Independent left and right sidebars
451
+ * 2. **Icon Mode**: Persistent icon-only sidebars
452
+ * 3. **Multiple Variants**: 10+ visual styles for sidebars
453
+ * 4. **Theme System**: 7 built-in color themes with persistence
454
+ * 5. **Responsive Design**: Mobile-optimized offcanvas drawers
455
+ * 6. **Loading States**: Built-in skeleton loaders
456
+ * 7. **Keyboard Navigation**: Full accessibility support
457
+ * 8. **Drawer System**: Slide-in panels from any direction
458
+ * 9. **Dropdown Menus**: Rich context menus
459
+ * 10. **Collapsible Sections**: Expandable/collapsible content areas
460
+ *
461
+ * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Performance Notes ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
462
+ * - **Lazy Loading**: Components load only when needed
463
+ * - **CSS Variables**: Efficient theming with CSS custom properties
464
+ * - **Memoization**: Heavy use of React.memo and useMemo
465
+ * - **Bundle Splitting**: Code-split for better performance
466
+ * - **Optimized Renders**: Minimal re-renders with context optimization
467
+ *
468
+ */
469
+
470
+
471
+ const DS_COOKIE_NAME = "ds_state";
472
+ const DS_COOKIE_NAME_RIGHT = "ds_state_right";
473
+ const DS_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
474
+ const DS_WIDTH = "275px";
475
+ const DS_WIDTH_MOBILE = "288px";
476
+ const DS_WIDTH_ICON = "48px";
477
+ const DS_KEYBOARD_SHORTCUT_LEFT = "b";
478
+ const DS_KEYBOARD_SHORTCUT_RIGHT = "g";
479
+
480
+ const THEME_VERSION = "v3";
481
+ const THEME_OPTIONS = ["neutral", "red", "orange", "green", "blue", "violet", "default"] as const;
482
+ const LOCAL_DS_STORAGE_KEY = "ds-theme-v3";
483
+
484
+ type DSTheme = (typeof THEME_OPTIONS)[number];
485
+
486
+ type SidebarVariant = "sidebar" | "inset" | "floating" | "frosted" | "floating-card" | "glass" | "compact-card" | "minimal" | "bordered" | "elevated";
487
+ type SidebarSide = 'left' | 'right'
488
+ type SidebarCollapsible = 'offcanvas' | 'icon' | 'none'
489
+ const dsVariants = cva('', {
490
+ variants: {
491
+ variant: {
492
+ sidebar: 'fixed inset-y-0 z-20 bg-sidebar flex flex-col transition-transform duration-300 h-full',
493
+ inset: 'fixed inset-y-0 z-20 bg-sidebar rounded-[15px] p-[15px] flex flex-col transition-transform duration-300 shadow-2xl h-full',
494
+ floating: 'fixed inset-y-0 z-20 bg-sidebar rounded-[15px] flex flex-col transition-transform duration-300 shadow-2xl h-full',
495
+ frosted: 'fixed inset-y-0 z-20 backdrop-blur-2xl bg-background/80 border border-white/10 shadow-xl flex flex-col transition-transform duration-300 h-full',
496
+ card: 'fixed z-20 bg-sidebar rounded-xl shadow-2xl flex flex-col transition-all duration-300 my-[5vh] max-h-[90vh] overflow-auto h-full',
497
+ glass: 'fixed inset-y-0 z-20 backdrop-blur-xl bg-white/10 border border-white/20 shadow-lg flex flex-col transition-transform duration-300 h-full',
498
+ 'compact-card': 'fixed z-20 bg-sidebar rounded-lg shadow-lg flex flex-col transition-all duration-300 my-2 max-h-[95vh] overflow-auto',
499
+ bordered: 'fixed inset-y-0 z-20 bg-sidebar border-2 border-primary/20 rounded-lg shadow-sm flex flex-col transition-transform duration-300 h-full',
500
+ minimal: 'fixed inset-y-0 z-20 bg-sidebar flex flex-col transition-transform duration-300 h-full',
501
+ elevated: 'fixed inset-y-0 z-20 bg-sidebar shadow-2xl rounded-2xl border border-border/50 flex flex-col transition-transform duration-300 h-full',
502
+ },
503
+ },
504
+ defaultVariants: {
505
+ variant: 'sidebar',
506
+ },
507
+ })
508
+ const iconDSVariants = cva('fixed inset-y-0 z-20 hidden h-svh flex-col md:flex', {
509
+ variants: {
510
+ variant: {
511
+ sidebar: 'bg-background',
512
+ inset: 'bg-sidebar',
513
+ floating: 'bg-sidebar m-2 rounded-lg max-h-[calc(100vh-16px)]',
514
+ frosted: 'backdrop-blur-xl bg-background/70',
515
+ card: 'bg-sidebar rounded-lg my-[5vh] max-h-[90vh]',
516
+ glass: 'backdrop-blur-lg bg-white/5',
517
+ 'compact-card': 'bg-sidebar rounded-md my-2 max-h-[95vh]',
518
+ bordered: 'bg-sidebar border-2 border-primary/10',
519
+ minimal: 'bg-background',
520
+ elevated: 'bg-sidebar shadow-xl rounded-lg border border-border/30',
521
+ },
522
+ side: {
523
+ left: 'left-0 border-r border-border',
524
+ right: 'right-0 border-l border-border',
525
+ },
526
+ },
527
+ defaultVariants: {
528
+ variant: 'sidebar',
529
+ side: 'left',
530
+ },
531
+ });
532
+ const DSMenuButtonVariants = cva(
533
+ "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none transition-all duration-200 disabled:pointer-events-none disabled:opacity-50 group-has-[[data-dual-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", // ring-sidebar-ring
534
+ {
535
+ variants: {
536
+ variant: {
537
+ default: [
538
+ "data-[active=true]:text-sidebar-accent-foreground",
539
+ "text-sidebar-muted-foreground hover:text-sidebar-foreground border-l-2 border-transparent duration-300 hover:border-primary" // hover:text-primary
540
+ ],
541
+ ghost: "hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground data-[active=true]:bg-sidebar-accent/70",
542
+ outline: "bg-transparent border border-sidebar-border hover:bg-sidebar-accent hover:border-sidebar-accent data-[active=true]:bg-sidebar-accent data-[active=true]:border-sidebar-accent data-[active=true]:text-foreground",
543
+ soft: "hover:bg-sidebar-accent/30 hover:text-sidebar-accent-foreground data-[active=true]:bg-sidebar-accent/50",
544
+ solid: "bg-sidebar-accent/10 hover:bg-sidebar-accent data-[active=true]:bg-primary data-[active=true]:text-primary-foreground",
545
+ minimal: "hover:text-primary data-[active=true]:text-primary data-[active=true]:font-semibold",
546
+ bordered: "border-l-2 border-transparent hover:border-sidebar-accent hover:bg-sidebar-accent/20 data-[active=true]:border-primary data-[active=true]:bg-sidebar-accent",
547
+ pill: "rounded-full hover:bg-sidebar-accent data-[active=true]:bg-primary data-[active=true]:text-primary-foreground",
548
+ },
549
+ size: {
550
+ default: "h-9 text-sm px-3",
551
+ sm: "h-7 text-xs px-2",
552
+ lg: "h-11 text-base px-4 group-data-[collapsible=icon]:!p-0",
553
+ icon: "h-9 w-9 p-0 justify-center",
554
+ },
555
+ isActive: {
556
+ true: "font-medium text-sidebar-foreground border-primary",
557
+ false: "",
558
+ },
559
+ },
560
+ defaultVariants: {
561
+ variant: "default",
562
+ size: "default",
563
+ isActive: false,
564
+ },
565
+ }
566
+ );
567
+ const groupVariants = cva("relative flex w-full min-w-0 flex-col p-2", {
568
+ variants: {
569
+ variant: {
570
+ default: "",
571
+ separated: "border-t border-sidebar-border pt-4 mt-2",
572
+ card: "bg-sidebar-accent/5 rounded-lg p-3 m-1",
573
+ bordered: "border border-sidebar-border rounded-md p-3 m-1",
574
+ subtle: "bg-sidebar-accent/3 p-3",
575
+ },
576
+ },
577
+ defaultVariants: {
578
+ variant: "default",
579
+ },
580
+ });
581
+ const groupLabelVariants = cva(
582
+ "flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-none ring-sidebar-ring transition-[margin,opa] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
583
+ {
584
+ variants: {
585
+ variant: {
586
+ default: "",
587
+ prominent: "font-semibold text-sidebar-foreground uppercase tracking-wider",
588
+ subtle: "text-xs text-muted-foreground",
589
+ separated: "border-b border-sidebar-border pb-2 mb-2",
590
+ },
591
+ },
592
+ defaultVariants: {
593
+ variant: "default",
594
+ },
595
+ }
596
+ );
597
+ const menuItemVariants = cva("group/menu-item relative", {
598
+ variants: {
599
+ variant: {
600
+ default: "",
601
+ spaced: "my-0.5",
602
+ compact: "my-0",
603
+ comfortable: "my-1",
604
+ },
605
+ },
606
+ defaultVariants: {
607
+ variant: "default",
608
+ },
609
+ });
610
+ const drawerVariants = cva(["group/drawer-content fixed z-50 flex flex-col",],
611
+ {
612
+ variants: {
613
+ variant: {
614
+ default: "",
615
+ card: [
616
+ "bg-card rounded-t-xl shadow-xl",
617
+ "data-[vaul-drawer-direction=bottom]:mb-5",
618
+ "data-[vaul-drawer-direction=top]:mt-5",
619
+ "data-[vaul-drawer-direction=left]:ml-5",
620
+ "data-[vaul-drawer-direction=right]:mr-5",
621
+ ],
622
+ glass: [
623
+ "backdrop-blur-xl bg-background/80 border-t border-white/10 max-w-sm ",
624
+ "data-[vaul-drawer-direction=bottom]:mb-5",
625
+ "data-[vaul-drawer-direction=top]:mt-5",
626
+ "data-[vaul-drawer-direction=left]:ml-5",
627
+ "data-[vaul-drawer-direction=right]:mr-5",
628
+ ],
629
+ elevated: [
630
+ "bg-background shadow-2xl max-w-sm ",
631
+ "data-[vaul-drawer-direction=bottom]:mb-5",
632
+ "data-[vaul-drawer-direction=top]:mt-5",
633
+ "data-[vaul-drawer-direction=left]:ml-5",
634
+ "data-[vaul-drawer-direction=right]:mr-5",
635
+ ],
636
+ bordered: [
637
+ "bg-background border-t-2 border-primary/20 max-w-sm ",
638
+ "data-[vaul-drawer-direction=bottom]:mb-5",
639
+ "data-[vaul-drawer-direction=top]:mt-5",
640
+ "data-[vaul-drawer-direction=left]:ml-5",
641
+ "data-[vaul-drawer-direction=right]:mr-5",
642
+ ],
643
+ macos: [
644
+ "backdrop-blur-xl bg-card/70 shadow-2xl border border-border/50 w-full max-w-sm rounded-3xl mx-auto ",
645
+ "data-[vaul-drawer-direction=bottom]:mb-5",
646
+ "data-[vaul-drawer-direction=top]:mt-5",
647
+ "data-[vaul-drawer-direction=left]:ml-5",
648
+ "data-[vaul-drawer-direction=right]:mr-5",
649
+ ],
650
+ },
651
+ direction: {
652
+ top: "border-b rounded-b-lg max-h-[80vh] mb-24 top-0 inset-x-0 left-1/2 -translate-x-1/2",
653
+ bottom: "border-t rounded-t-lg max-h-[80vh] mt-24 bottom-0 inset-x-0 left-1/2 -translate-x-1/2",
654
+ right: "sm:max-w-sm border-l w-3/4 right-0 inset-y-0 top-1/2 -translate-y-1/2",
655
+ left: "inset-y-0 left-0 w-3/4 border-r sm:max-w-sm top-1/2 -translate-y-1/2",
656
+ },
657
+ size: {
658
+ default: "h-auto",
659
+ sm: "h-[50vh]",
660
+ md: "h-[70vh]",
661
+ lg: "h-[90vh]",
662
+ full: "h-screen",
663
+ },
664
+ },
665
+ defaultVariants: {
666
+ variant: "default",
667
+ size: "default",
668
+ },
669
+ }
670
+ );
671
+ const loadingVariants = cva(
672
+ "flex flex-col items-center justify-center text-center p-8 min-h-[400px] h-screen bg-gradient-to-b from-background to-muted/20",
673
+ {
674
+ variants: {
675
+ variant: {
676
+ default: "",
677
+ minimal: "bg-transparent from-transparent to-transparent",
678
+ card: "bg-card rounded-lg shadow-lg max-h-[600px]",
679
+ centered: "h-auto min-h-[300px]",
680
+ },
681
+ size: {
682
+ default: "w-[256px]",
683
+ sm: "w-[200px]",
684
+ md: "w-[280px]",
685
+ lg: "w-[320px]",
686
+ full: "w-full",
687
+ },
688
+ },
689
+ defaultVariants: {
690
+ variant: "default",
691
+ size: "default",
692
+ },
693
+ }
694
+ );
695
+ const insetVariants = cva(
696
+ "relative flex flex-1 flex-col mx-auto bg-background min-w-0 flex-grow transition-[margin] duration-300",
697
+ {
698
+ variants: {
699
+ variant: {
700
+ default: "bg-background w-full h-full",
701
+ inset: ``, // bg-background rounded-[8px] p-[8px] m-[8px] mt-[16px]! overflow-hidden h-[calc(100vh-16px)] w-full max-w-[calc(100vw-${DS_WIDTH}-32px)]
702
+ card: "bg-card rounded-xl shadow-lg m-4 h-[calc(100vh-32px)]",
703
+ bordered: "bg-background border-2 border-border rounded-lg m-2 h-[calc(100vh-16px)]",
704
+ },
705
+ },
706
+ defaultVariants: {
707
+ variant: "default",
708
+ },
709
+ }
710
+ );
711
+ const menuBadgeVariants = cva(
712
+ "pointer-events-none absolute right-1 flex h-5 min-w-5 select-none items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground",
713
+ "peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground",
714
+ "peer-data-[size=sm]/menu-button:top-1",
715
+ "peer-data-[size=default]/menu-button:top-1.5",
716
+ "peer-data-[size=lg]/menu-button:top-2.5",
717
+ "group-data-[collapsible=icon]:hidden",
718
+ {
719
+ variants: {
720
+ variant: {
721
+ default: "bg-sidebar-accent text-sidebar-accent-foreground",
722
+ primary: "bg-primary text-primary-foreground",
723
+ secondary: "bg-secondary text-secondary-foreground",
724
+ success: "bg-green-500/10 text-green-600 dark:text-green-400",
725
+ warning: "bg-yellow-500/10 text-yellow-600 dark:text-yellow-400",
726
+ danger: "bg-red-500/10 text-red-600 dark:text-red-400",
727
+ outline: "border border-sidebar-border bg-transparent",
728
+ ghost: "bg-sidebar-accent/30 text-sidebar-accent-foreground",
729
+ dot: "min-w-2 w-2 h-2 rounded-full p-0 bg-primary",
730
+ },
731
+ },
732
+ defaultVariants: {
733
+ variant: "default",
734
+ },
735
+ }
736
+ );
737
+ const menuSubButtonVariants = cva(
738
+ "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-none ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
739
+ "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
740
+ "group-data-[collapsible=icon]:hidden",
741
+ {
742
+ variants: {
743
+ variant: {
744
+ default: "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
745
+ ghost: "hover:bg-sidebar-accent/30 data-[active=true]:bg-sidebar-accent/50",
746
+ minimal: "hover:text-primary data-[active=true]:text-primary data-[active=true]:font-medium",
747
+ indent: "pl-6 hover:bg-sidebar-accent/30 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium",
748
+ },
749
+ size: {
750
+ default: "h-8 text-sm",
751
+ sm: "h-7 text-xs",
752
+ lg: "h-9 text-sm",
753
+ },
754
+ },
755
+ defaultVariants: {
756
+ variant: "default",
757
+ size: "default",
758
+ },
759
+ }
760
+ );
761
+ const separatorVariants = cva("mx-2 w-auto bg-sidebar-border", {
762
+ variants: {
763
+ variant: {
764
+ default: "h-px",
765
+ thick: "h-0.5",
766
+ dashed: "h-px border-t border-dashed border-sidebar-border bg-transparent",
767
+ gradient: "h-px bg-gradient-to-r from-transparent via-sidebar-border to-transparent",
768
+ },
769
+ spacing: {
770
+ default: "my-2",
771
+ sm: "my-1",
772
+ lg: "my-4",
773
+ none: "my-0",
774
+ },
775
+ },
776
+ defaultVariants: {
777
+ variant: "default",
778
+ spacing: "default",
779
+ },
780
+ });
781
+ const headerVariants = cva("flex flex-col gap-2 p-2 group-data-[variant=floating]:bg-sidebar group-data-[variant=floating]:text-sidebar-foreground group-data-[variant=sidebar]:bg-sidebar group-data-[variant=sidebar]:text-sidebar-foreground", {
782
+ variants: {
783
+ variant: {
784
+ default: "",
785
+ bordered: "border-b border-sidebar-border",
786
+ elevated: "shadow-sm",
787
+ compact: "p-1 gap-1",
788
+ },
789
+ },
790
+ defaultVariants: {
791
+ variant: "default",
792
+ },
793
+ });
794
+ const footerVariants = cva("flex flex-col gap-2 p-2 group-data-[variant=floating]:bg-sidebar group-data-[variant=floating]:text-sidebar-foreground group-data-[variant=sidebar]:bg-sidebar group-data-[variant=sidebar]:text-sidebar-foreground", {
795
+ variants: {
796
+ variant: {
797
+ default: "",
798
+ bordered: "border-t border-sidebar-border",
799
+ elevated: "shadow-sm",
800
+ compact: "p-1 gap-1",
801
+ },
802
+ },
803
+ defaultVariants: {
804
+ variant: "default",
805
+ },
806
+ });
807
+ const headerStyles = {
808
+ container: "flex flex-col gap-3 p-4 pb-2",
809
+ topBar: "flex justify-between max-md:hidden",
810
+ logo: "inline-flex items-center gap-2.5 font-medium",
811
+ logoIcon: "size-6.5 dark:invert",
812
+ logoText: "ms-2.5 text-lg font-semibold",
813
+ collapseButton: "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors duration-100 disabled:pointer-events-none disabled:opacity-50 focus-visible:outline-none hover:bg-fd-accent hover:text-fd-accent-foreground p-1.5 [&_svg]:size-4.5 mt-px mb-auto text-fd-muted-foreground",
814
+ };
815
+ // Search/Menu Button
816
+ const searchButtonStyles = {
817
+ base: "flex items-center gap-2 rounded-lg p-2 border bg-fd-secondary/50 text-start text-fd-secondary-foreground transition-colors hover:bg-fd-accent data-[state=open]:bg-fd-accent data-[state=open]:text-fd-accent-foreground lg:hidden",
818
+ icon: "size-9 md:size-5",
819
+ title: "text-sm font-medium",
820
+ subtitle: "text-[13px] text-fd-muted-foreground empty:hidden md:hidden",
821
+ chevron: "ms-auto size-4 text-fd-muted-foreground",
822
+ };
823
+ const navItemStyles = {
824
+ // Section Headers
825
+ sectionHeader: "inline-flex items-center gap-2 mb-1.5 px-2 empty:mb-0 [&_svg]:size-4 [&_svg]:shrink-0",
826
+
827
+ // Regular Links
828
+ link: "relative flex flex-row items-center gap-2 rounded-xl p-2 text-start text-fd-muted-foreground [overflow-wrap:anywhere] [&_svg]:size-4 [&_svg]:shrink-0 transition-colors hover:bg-fd-accent/50 hover:text-fd-accent-foreground/80 hover:transition-none",
829
+
830
+ // Active Link
831
+ activeLink: "relative flex flex-row items-center gap-2 rounded-xl p-2 text-start [overflow-wrap:anywhere] [&_svg]:size-4 [&_svg]:shrink-0 bg-fd-primary/10 text-fd-primary",
832
+
833
+ // Collapsible Button
834
+ collapsibleButton: "relative flex flex-row items-center gap-2 rounded-xl p-2 text-start text-fd-muted-foreground [overflow-wrap:anywhere] [&_svg]:size-4 [&_svg]:shrink-0 transition-colors hover:bg-fd-accent/50 hover:text-fd-accent-foreground/80 hover:transition-none w-full",
835
+
836
+ // Nested Items (with indent)
837
+ nestedLink: "relative flex flex-row items-center gap-2 rounded-xl p-2 text-start text-fd-muted-foreground [overflow-wrap:anywhere] [&_svg]:size-4 [&_svg]:shrink-0 transition-colors hover:bg-fd-accent/50 hover:text-fd-accent-foreground/80 hover:transition-none",
838
+
839
+ // Vertical line for nested items
840
+ verticalLine: "absolute w-px inset-y-1 bg-fd-border start-2.5",
841
+ activeVerticalLine: "absolute w-px inset-y-3 z-2 start-2.5 md:inset-y-2",
842
+ activeVerticalLineColor: "absolute w-px inset-y-3 z-2 start-2.5 md:inset-y-2 bg-fd-primary",
843
+ };
844
+ const footerStyles = {
845
+ container: "border-t px-4 py-3 flex flex-row items-center justify-end data-[empty=true]:hidden",
846
+ socialLink: "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors duration-100 disabled:pointer-events-none disabled:opacity-50 focus-visible:outline-none hover:bg-fd-accent hover:text-fd-accent-foreground p-1.5 [&_svg]:size-4.5 text-fd-muted-foreground",
847
+ };
848
+ type DSContextProps = {
849
+ leftState: "expanded" | "collapsed";
850
+ rightState: "expanded" | "collapsed";
851
+ openLeft: boolean;
852
+ openRight: boolean;
853
+ setOpenLeft: (open: boolean) => void;
854
+ setOpenRight: (open: boolean) => void;
855
+ openMobile: boolean;
856
+ openMobileRight: boolean;
857
+ setOpenMobile: (open: boolean) => void;
858
+ setOpenMobileRight: (open: boolean) => void;
859
+ isMobile: boolean;
860
+ sidebarWidth: number;
861
+ toggleLeft: () => void;
862
+ toggleRight: () => void;
863
+
864
+ leftVariant: SidebarVariant;
865
+ rightVariant: SidebarVariant;
866
+ setLeftVariant: (variant: SidebarVariant) => void;
867
+ setRightVariant: (variant: SidebarVariant) => void;
868
+
869
+ isIconLeftActive: boolean;
870
+ setIsIconLeftActive: (open: boolean) => void;
871
+ iconLeftWidth: number;
872
+ setIconLeftWidth: (width: number) => void;
873
+
874
+ isIconRightActive: boolean;
875
+ setIsIconRightActive: (open: boolean) => void;
876
+ iconRightWidth: number;
877
+ setIconRightWidth: (width: number) => void;
878
+
879
+ topHeight: string;
880
+ setTopHeight: (height: string) => void;
881
+
882
+ bottomHeight: string;
883
+ setBottomHeight: (height: string) => void;
884
+ };
885
+
886
+ interface DSThemeContextProps {
887
+ theme: DSTheme;
888
+ setTheme: (theme: DSTheme) => void;
889
+ themeVars: Record<string, string>;
890
+ }
891
+
892
+ const DSContext = createContext<DSContextProps | null>(null);
893
+ const DSThemeContext = createContext<DSThemeContextProps | undefined>(undefined);
894
+
895
+ function useDS() {
896
+ const context = useContext(DSContext);
897
+ if (!context) throw new Error("useDS must be used within DSProvider");
898
+ return context;
899
+ }
900
+
901
+ function useDSTheme() {
902
+ const ctx = useContext(DSThemeContext);
903
+ if (!ctx) throw new Error("useDSTheme must be used within DSProvider");
904
+ return ctx;
905
+ }
906
+
907
+ const DSThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
908
+ const storageKey = LOCAL_DS_STORAGE_KEY;
909
+ const Context = DSThemeContext;
910
+
911
+ const [theme, setTheme] = React.useState<DSTheme>(() => {
912
+ if (typeof window !== "undefined") {
913
+ const storedTheme = localStorage.getItem(storageKey);
914
+ if (storedTheme && THEME_OPTIONS.includes(storedTheme as DSTheme)) {
915
+ return storedTheme as DSTheme;
916
+ }
917
+ }
918
+ return "default";
919
+ });
920
+
921
+ const themeVars = React.useMemo(() => {
922
+ if (theme === "default") return {};
923
+ return (colorThemes as any)[theme]?.[THEME_VERSION]?.dark || {};
924
+ }, [theme]);
925
+
926
+ React.useEffect(() => {
927
+ if (typeof window !== "undefined") {
928
+ localStorage.setItem(storageKey, theme);
929
+ }
930
+ }, [theme, storageKey]);
931
+
932
+ React.useEffect(() => {
933
+ if (typeof document === "undefined") return;
934
+ const root = document.documentElement;
935
+ const prefix = "--dual";
936
+
937
+ if (Object.keys(themeVars).length > 0) {
938
+ Object.entries(themeVars).forEach(([key, value]) => {
939
+ const newKey = key.replace("--sidebar", prefix);
940
+ root.style.setProperty(newKey, String(value));
941
+ });
942
+ }
943
+
944
+ return () => {
945
+ Object.keys(themeVars).forEach((key) => {
946
+ const newKey = key.replace("--sidebar", prefix);
947
+ root.style.removeProperty(newKey);
948
+ });
949
+ };
950
+ }, [themeVars]);
951
+
952
+ return <Context.Provider value={{ theme, setTheme, themeVars }}>{children}</Context.Provider>;
953
+ };
954
+
955
+ function DSThemeSelector({ size = 28, className, children }: { size?: number; className?: string; children: React.ReactNode; }) {
956
+ const { theme, setTheme } = useDSTheme();
957
+ const [open, setOpen] = React.useState(false);
958
+ const [flyingTheme, setFlyingTheme] = React.useState<DSTheme | null>(null);
959
+ const [showOverlay, setShowOverlay] = React.useState(false);
960
+ const [flyingButtonPos, setFlyingButtonPos] = React.useState<{ left: number; top: number } | null>(null);
961
+ const [mainButtonOriginalPos, setMainButtonOriginalPos] = React.useState<{ left: number; top: number } | null>(null);
962
+ const mainButtonRef = React.useRef<HTMLButtonElement>(null);
963
+
964
+ const radius = size * 1.6;
965
+ const themeList = THEME_OPTIONS;
966
+ const mainButtonCenterOffset = size * 1.5;
967
+ const mainButtonSize = size;
968
+
969
+ function getThemeColor(t: string) {
970
+ const themeObj = colorThemes[t as DSTheme]?.[THEME_VERSION]?.dark;
971
+ const primaryColor = themeObj?.["--primary"];
972
+ if (primaryColor) {
973
+ if (primaryColor.startsWith("oklch")) {
974
+ return primaryColor;
975
+ } else {
976
+ return `hsl(${primaryColor})`;
977
+ }
978
+ }
979
+ return "#888";
980
+ }
981
+
982
+ const handleMainButtonClick = () => {
983
+ if (flyingTheme) return;
984
+ if (!open && mainButtonRef.current) {
985
+ const rect = mainButtonRef.current.getBoundingClientRect();
986
+ setMainButtonOriginalPos({
987
+ left: rect.left + rect.width / 2,
988
+ top: rect.top + rect.height / 2,
989
+ });
990
+ }
991
+ setOpen((v) => !v);
992
+ setShowOverlay(!open);
993
+ };
994
+
995
+ const handleThemeSelect = (t: DSTheme, event: React.MouseEvent<HTMLButtonElement>) => {
996
+ const button = event.currentTarget;
997
+ const rect = button.getBoundingClientRect();
998
+
999
+ setFlyingButtonPos({
1000
+ left: rect.left + rect.width / 2,
1001
+ top: rect.top + rect.height / 2,
1002
+ });
1003
+
1004
+ setFlyingTheme(t);
1005
+ setShowOverlay(true);
1006
+ setOpen(false);
1007
+
1008
+ setTimeout(() => {
1009
+ setTheme(t);
1010
+ }, 300);
1011
+
1012
+ setTimeout(() => {
1013
+ setShowOverlay(false);
1014
+ setFlyingTheme(null);
1015
+ setFlyingButtonPos(null);
1016
+ setMainButtonOriginalPos(null);
1017
+ }, 600);
1018
+ };
1019
+
1020
+ let mainButtonStyle: React.CSSProperties = {
1021
+ zIndex: 70,
1022
+ };
1023
+
1024
+ if (open || mainButtonOriginalPos) {
1025
+ const targetLeft = open ? window.innerWidth / 2 : mainButtonOriginalPos?.left || window.innerWidth / 2;
1026
+ const targetTop = open ? window.innerHeight / 2 : mainButtonOriginalPos?.top || window.innerHeight / 2;
1027
+
1028
+ mainButtonStyle = {
1029
+ ...mainButtonStyle,
1030
+ position: "fixed",
1031
+ left: `${targetLeft}px`,
1032
+ top: `${targetTop}px`,
1033
+ transform: "translate(-50%, -50%)",
1034
+ };
1035
+ } else {
1036
+ mainButtonStyle = {
1037
+ ...mainButtonStyle,
1038
+ position: "absolute",
1039
+ left: mainButtonCenterOffset - mainButtonSize / 2,
1040
+ top: mainButtonCenterOffset - mainButtonSize / 2,
1041
+ };
1042
+ }
1043
+
1044
+ return (
1045
+ <>
1046
+ {showOverlay && <div
1047
+ className="fixed inset-0 bg-black/60 transition-opacity duration-500 theme-overlay"
1048
+ // style={{ zIndex: Z_INDEX.OVERLAY, position: 'fixed', }}
1049
+ />}
1050
+
1051
+ <div
1052
+ className={cn("flex items-center justify-center transition-all duration-1000 theme-container", className)}
1053
+ style={{
1054
+ width: size * 3,
1055
+ height: size * 3,
1056
+ // zIndex: Z_INDEX.CONTAINER,
1057
+ position: open ? 'static' : 'relative',
1058
+ isolation: 'isolate',
1059
+ }}
1060
+ >
1061
+ <button
1062
+ ref={mainButtonRef}
1063
+ onClick={handleMainButtonClick}
1064
+ className={cn(
1065
+ "flex items-center justify-center rounded-full bg-background shadow-lg transition-all duration-500 theme-main-button",
1066
+ `h-[${mainButtonSize}px] w-[${mainButtonSize}px]`,
1067
+ open ? "bg-sidebar-accent text-sidebar-accent-foreground" : "",
1068
+ open || mainButtonOriginalPos ? "!fixed" : ""
1069
+ )}
1070
+ style={{
1071
+ ...mainButtonStyle,
1072
+ // zIndex: Z_INDEX.MAIN_BUTTON,
1073
+ }}
1074
+ >
1075
+ {children}
1076
+ </button>
1077
+
1078
+ {themeList.map((t, i) => {
1079
+ const angle = (360 / themeList.length) * i - 90;
1080
+ const rad = (angle * Math.PI) / 180;
1081
+ const radialX = Math.cos(rad) * radius;
1082
+ const radialY = Math.sin(rad) * radius;
1083
+
1084
+ let currentX = 0;
1085
+ let currentY = 0;
1086
+ let currentScale = 0;
1087
+ let currentOpacity = 0;
1088
+ let currentZIndex = 10;
1089
+ let currentDelay = open ? `${i * 90}ms` : "0ms";
1090
+ let isFixed = false;
1091
+ let fixedLeft = 0;
1092
+ let fixedTop = 0;
1093
+
1094
+ if (flyingTheme === t) {
1095
+ isFixed = true;
1096
+ currentScale = 1.2;
1097
+ currentOpacity = 1;
1098
+ currentZIndex = 10000;
1099
+ currentDelay = "0ms";
1100
+ fixedLeft = window.innerWidth / 2;
1101
+ fixedTop = window.innerHeight / 2;
1102
+ } else if (open) {
1103
+ isFixed = true;
1104
+ fixedLeft = window.innerWidth / 2 + radialX;
1105
+ fixedTop = window.innerHeight / 2 + radialY;
1106
+ currentScale = 1;
1107
+ currentOpacity = 1;
1108
+ currentZIndex = 10;
1109
+ } else if (!open && flyingTheme === null) {
1110
+ currentX = 0;
1111
+ currentY = 0;
1112
+ currentScale = 0;
1113
+ currentOpacity = 0;
1114
+ currentZIndex = 10;
1115
+ }
1116
+
1117
+ const buttonSize = size * 1;
1118
+ const buttonOffset = buttonSize / 2;
1119
+
1120
+ return (
1121
+ <button
1122
+ key={t}
1123
+ style={{
1124
+ width: buttonSize,
1125
+ height: buttonSize,
1126
+ ...(isFixed
1127
+ ? {
1128
+ left: `${fixedLeft}px`,
1129
+ top: `${fixedTop}px`,
1130
+ transform: `translate(-50%, -50%) scale(${currentScale})`,
1131
+ }
1132
+ : {
1133
+ left: mainButtonCenterOffset + currentX - buttonOffset,
1134
+ top: mainButtonCenterOffset + currentY - buttonOffset,
1135
+ transform: `scale(${currentScale})`,
1136
+ }),
1137
+ // zIndex: flyingTheme === t ? Z_INDEX.FLYING_THEME : Z_INDEX.MAIN_BUTTON,
1138
+ opacity: currentOpacity,
1139
+ transitionDelay: currentDelay,
1140
+ transitionTimingFunction: flyingTheme === t ? "cubic-bezier(0.8, -0.5, 0.2, 1.5)" : "ease-out"
1141
+ }}
1142
+ className={cn(
1143
+ `rounded-full border bg-background shadow transition-all duration-500 flex items-center justify-center`,
1144
+ theme === t ? "ring-2 ring-primary border-primary" : "border-muted hover:ring-2 hover:ring-primary",
1145
+ flyingTheme === t ? "ring-4 ring-primary !fixed" : open ? "!fixed" : "absolute",
1146
+ flyingTheme === t ? "theme-flying-theme" : "theme-buttons",
1147
+ )}
1148
+ aria-label={`Switch to ${t} theme`}
1149
+ onClick={(e) => handleThemeSelect(t as DSTheme, e)}
1150
+ disabled={!!flyingTheme}
1151
+ >
1152
+ <Circle style={{ color: getThemeColor(t), fill: getThemeColor(t) }} size={size * 0.3} />
1153
+ </button>
1154
+ );
1155
+ })}
1156
+ </div>
1157
+ </>
1158
+ );
1159
+ }
1160
+
1161
+ const DSProvider = forwardRef<
1162
+ HTMLDivElement,
1163
+ React.ComponentProps<"div"> & {
1164
+ defaultOpenLeft?: boolean;
1165
+ defaultOpenRight?: boolean;
1166
+ defaultWidth?: string;
1167
+ }
1168
+ >(({ defaultOpenLeft = false, defaultOpenRight = false, defaultWidth = DS_WIDTH, className, style, children, ...props }, ref) => {
1169
+ const isMobile = useIsMobile();
1170
+ const [openMobile, setOpenMobile] = useState(false);
1171
+ const [openMobileRight, setOpenMobileRight] = useState(false);
1172
+
1173
+ const [openLeft, setOpenLeft] = useState(defaultOpenLeft);
1174
+ const [openRight, setOpenRight] = useState(defaultOpenRight);
1175
+
1176
+ const [leftVariant, setLeftVariant] = useState("sidebar");
1177
+ const [rightVariant, setRightVariant] = useState("sidebar");
1178
+
1179
+ const [isIconLeftActive, setIsIconLeftActive] = useState(false);
1180
+ const [iconLeftWidth, setIconLeftWidth] = useState("0px");
1181
+
1182
+ const [isIconRightActive, setIsIconRightActive] = useState(false);
1183
+ const [iconRightWidth, setIconRightWidth] = useState("0px");
1184
+
1185
+ const [topHeight, setTopHeight] = useState("0px");
1186
+ const [bottomHeight, setBottomHeight] = useState("0px");
1187
+
1188
+ const [dsdVariant, setDsdVariant] = useState("default");
1189
+ const [dsdDirection, setDsdDirection] = useState("bottom");
1190
+ const [dsdSize, setDsdSize] = useState("md");
1191
+
1192
+ const sidebarWidth = defaultWidth;
1193
+ const cookieName = DS_COOKIE_NAME;
1194
+ const cookieNameRight = DS_COOKIE_NAME_RIGHT;
1195
+
1196
+ const openL = openLeft;
1197
+ const openR = openRight;
1198
+
1199
+ const toggleLeft = useCallback(() => {
1200
+ isMobile ? setOpenMobile((p) => !p) : setOpenLeft((p) => !p);
1201
+ document.cookie = `${cookieName}=${openL}; path=/; max-age=${DS_COOKIE_MAX_AGE}`;
1202
+ }, [isMobile]);
1203
+
1204
+ const toggleRight = useCallback(() => {
1205
+ isMobile ? setOpenMobileRight((p) => !p) : setOpenRight((p) => !p);
1206
+ document.cookie = `${cookieNameRight}=${openR}; path=/; max-age=${DS_COOKIE_MAX_AGE}`;
1207
+ }, [isMobile]);
1208
+
1209
+ useEffect(() => {
1210
+ const shortcutLeft = DS_KEYBOARD_SHORTCUT_LEFT;
1211
+ const handleKeyDown = (event: KeyboardEvent) => {
1212
+ if (event.key === shortcutLeft && (event.metaKey || event.ctrlKey)) {
1213
+ event.preventDefault();
1214
+ // toggleLeft(prev => !prev);
1215
+ toggleLeft();
1216
+ }
1217
+ };
1218
+ window.addEventListener("keydown", handleKeyDown);
1219
+ return () => window.removeEventListener("keydown", handleKeyDown);
1220
+ }, [toggleLeft]);
1221
+
1222
+ useEffect(() => {
1223
+ const shortcutRight = DS_KEYBOARD_SHORTCUT_RIGHT;
1224
+ const handleKeyDown = (event: KeyboardEvent) => {
1225
+ if (event.key === shortcutRight && (event.metaKey || event.ctrlKey)) {
1226
+ event.preventDefault();
1227
+ // toggleRight(prev => !prev);
1228
+ toggleRight();
1229
+ }
1230
+ };
1231
+ window.addEventListener("keydown", handleKeyDown);
1232
+ return () => window.removeEventListener("keydown", handleKeyDown);
1233
+ }, [toggleRight]);
1234
+
1235
+ const leftState = openL ? "expanded" : "collapsed";
1236
+ const rightState = openR ? "expanded" : "collapsed";
1237
+
1238
+ const contextValue = React.useMemo<DSContextProps>(
1239
+ () => ({
1240
+ leftState,
1241
+ rightState,
1242
+
1243
+ openLeft,
1244
+ setOpenLeft,
1245
+
1246
+ openRight,
1247
+ setOpenRight,
1248
+
1249
+ toggleLeft,
1250
+ toggleRight,
1251
+
1252
+ isMobile,
1253
+
1254
+ openMobile,
1255
+ setOpenMobile,
1256
+ openMobileRight,
1257
+ setOpenMobileRight,
1258
+
1259
+ sidebarWidth,
1260
+
1261
+ leftVariant,
1262
+ setLeftVariant,
1263
+ rightVariant,
1264
+ setRightVariant,
1265
+
1266
+ isIconLeftActive,
1267
+ setIsIconLeftActive,
1268
+ iconLeftWidth,
1269
+ setIconLeftWidth,
1270
+
1271
+ isIconRightActive,
1272
+ setIsIconRightActive,
1273
+ iconRightWidth,
1274
+ setIconRightWidth,
1275
+
1276
+ topHeight,
1277
+ setTopHeight,
1278
+ bottomHeight,
1279
+ setBottomHeight,
1280
+
1281
+ dsdVariant,
1282
+ setDsdVariant,
1283
+ dsdDirection,
1284
+ setDsdDirection,
1285
+ dsdSize,
1286
+ setDsdSize
1287
+ }),
1288
+ [isMobile, openLeft, leftVariant, openRight, rightVariant, isIconLeftActive, iconLeftWidth, isIconRightActive, iconRightWidth, topHeight, bottomHeight, sidebarWidth]
1289
+ );
1290
+
1291
+ const Context = DSContext;
1292
+
1293
+ return (
1294
+ <DSThemeProvider>
1295
+ <Context.Provider value={contextValue}>
1296
+ <TooltipProvider delayDuration={0}>
1297
+ <div
1298
+ style={
1299
+ {
1300
+ "--dual-sidebar-width": sidebarWidth,
1301
+ "--dual-sidebar-width-icon": DS_WIDTH_ICON,
1302
+ ...style,
1303
+ } as React.CSSProperties
1304
+ }
1305
+ className={cn(
1306
+ "group/dual-sidebar-wrapper flex min-h-svh w-full",
1307
+ leftVariant === 'inset' || rightVariant === 'inset' ? "bg-sidebar" : null,
1308
+ "w-[100vw] h-[100vh] overflow-hidden",
1309
+ //"bg-[#111827] ",
1310
+ className
1311
+ )}
1312
+ ref={ref}
1313
+ {...props}
1314
+ >
1315
+ {children}
1316
+ </div>
1317
+ </TooltipProvider>
1318
+ </Context.Provider>
1319
+ </DSThemeProvider>
1320
+ );
1321
+ });
1322
+ DSProvider.displayName = "DSProvider";
1323
+
1324
+ const DSInset = forwardRef<HTMLDivElement, React.ComponentProps<"main">>(({ children, variant = "default", className, ...props }, ref) => {
1325
+ const { openLeft, openRight, sidebarWidth, leftVariant, rightVariant, isIconLeftActive, iconLeftWidth, isIconRightActive, iconRightWidth, topHeight, bottomHeight } = useDS();
1326
+ let paddingTop = topHeight;
1327
+ let paddingBottom = bottomHeight;
1328
+ let marginLeft = "0px";
1329
+ let marginRight = "0px";
1330
+ let leftWidth = sidebarWidth;
1331
+ let rightWidth = sidebarWidth;
1332
+ const closedGap = "0px";
1333
+ const paddingLeft = '8px'
1334
+ const paddingRight = '8px'
1335
+
1336
+ if (isIconLeftActive) {
1337
+ leftWidth = `calc(${iconLeftWidth} + ${sidebarWidth})`;
1338
+ }
1339
+ if (isIconRightActive) {
1340
+ rightWidth = `calc(${iconRightWidth} + ${sidebarWidth})`;
1341
+ }
1342
+
1343
+ if (isIconLeftActive) {
1344
+ marginLeft = iconLeftWidth;
1345
+ } else {
1346
+ marginLeft = closedGap;
1347
+ }
1348
+
1349
+ if (isIconRightActive) {
1350
+ marginRight = iconRightWidth;
1351
+ } else {
1352
+ marginRight = closedGap;
1353
+ }
1354
+
1355
+ if (openLeft && (leftVariant === "sidebar" || leftVariant === "inset")) {
1356
+ marginLeft = leftWidth;
1357
+ }
1358
+
1359
+ if (openRight && (rightVariant === "sidebar" || rightVariant === "inset")) {
1360
+ marginRight = `calc(${rightWidth} + 17px)`;
1361
+ }
1362
+
1363
+ let maxWidth = "none"; // Default value
1364
+ if (isIconLeftActive) marginLeft = `calc(${marginLeft} + 12px)`;
1365
+ if (isIconLeftActive && isIconRightActive && (leftVariant === "inset" || rightVariant === "inset")) {
1366
+ maxWidth = `calc(100vw - ${iconLeftWidth} - ${iconRightWidth} - 28px)`;
1367
+ }
1368
+
1369
+ const insetClass = "bg-background rounded-[15px] mt-[7px] overflow-hidden h-[calc(100vh-20px)] w-[calc(100vw-130px)] relative flex flex-1 flex-col overflow-hidden";
1370
+ const defaultVisualClasses = "bg-background w-full h-full";
1371
+ const floatingClass = "";
1372
+ const sidebarClass = "";
1373
+ return (
1374
+ <main
1375
+ ref={ref}
1376
+ className={cn(
1377
+ insetVariants({ variant }),
1378
+ className
1379
+ )}
1380
+ style={{
1381
+ marginLeft,
1382
+ marginRight,
1383
+ paddingTop,
1384
+ paddingBottom,
1385
+ maxWidth,
1386
+ paddingLeft,
1387
+ paddingRight,
1388
+ }}
1389
+ {...props}
1390
+ >
1391
+ {children}
1392
+ </main>
1393
+ );
1394
+ });
1395
+ DSInset.displayName = "DSInset";
1396
+
1397
+ const DSLeft1 = forwardRef<
1398
+ HTMLDivElement,
1399
+ React.ComponentProps<"div"> & {
1400
+ variant?: SidebarVariant;
1401
+ collapsible?: SidebarCollapsible;
1402
+ loadingUI?: boolean;
1403
+ }
1404
+ >(({ variant = "sidebar", collapsible = "offcanvas", className, children, loadingUI = true, ...props }, ref) => {
1405
+ const { isMobile, leftState, openMobile, setOpenMobile, openLeft, sidebarWidth, setLeftVariant, isIconLeftActive, setIsIconLeftActive, iconLeftWidth, setIconLeftWidth } = useDS();
1406
+
1407
+ const navigation = useNavigation();
1408
+ const [hasInitialLoaded, setHasInitialLoaded] = useState(false);
1409
+
1410
+ useEffect(() => {
1411
+ setLeftVariant(variant);
1412
+ }, [variant, setLeftVariant]);
1413
+
1414
+ useEffect(() => {
1415
+ if (navigation.state === "idle" && !hasInitialLoaded) {
1416
+ setHasInitialLoaded(true);
1417
+ }
1418
+ }, [navigation.state, hasInitialLoaded]);
1419
+
1420
+ const showLoading = loadingUI && navigation.state === "loading" && !hasInitialLoaded;
1421
+
1422
+ if (collapsible === "none") {
1423
+ return (
1424
+ <div className={cn("flex h-full w-[--dual-sidebar-width] flex-col bg-sidebar text-sidebar-foreground", className)} ref={ref} {...props}>
1425
+ {showLoading ? <DSLoading /> : children}
1426
+ </div>
1427
+ );
1428
+ }
1429
+ if (isMobile) {
1430
+ return (
1431
+ <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>
1432
+ <SheetContent data-dual-sidebar="sidebar" data-mobile="true" className="w-[--dual-sidebar-width] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden" style={{ "--dual-sidebar-width": DS_WIDTH_MOBILE } as React.CSSProperties} side="left">
1433
+ <SheetHeader className="sr-only">
1434
+ <SheetTitle>Sidebar</SheetTitle>
1435
+ <SheetDescription>Displays the mobile sidebar.</SheetDescription>
1436
+ </SheetHeader>
1437
+ <div className="flex h-full w-full flex-col">{showLoading ? <DSLoading /> : children}</div>
1438
+ </SheetContent>
1439
+ </Sheet>
1440
+ );
1441
+ }
1442
+
1443
+ // const baseClasses = `fixed inset-y-0 left-1 z-20 w-72 bg-sidebar rounded-[15px] flex flex-col transitio
1444
+ // n-transform duration-300 shadow-2xl`;
1445
+ const closedOffset = "8px";
1446
+ const iconOffset = isIconLeftActive ? iconLeftWidth : "0px";
1447
+ const transformClass = openLeft ? "translate-x-0" : "translate-x-[calc(-100%-4px)]";
1448
+ return (
1449
+ <div
1450
+ className={cn(
1451
+ dsVariants({ variant, side: "left" }),
1452
+ transformClass,
1453
+ !isIconLeftActive && "left-0",
1454
+ className
1455
+ )}
1456
+ style={{
1457
+ width: sidebarWidth,
1458
+ "--dual-sidebar-width-icon": DS_WIDTH_ICON,
1459
+ left: isIconLeftActive ? iconOffset : undefined,
1460
+ transform: openLeft ? "translateX(0)" : `translateX(calc(-100% - ${closedOffset}))`,
1461
+ }}
1462
+ {...props}
1463
+ >
1464
+ {showLoading ? <DSLoading /> : children}
1465
+ </div>
1466
+ );
1467
+ });
1468
+ const DSLeft = forwardRef<
1469
+ HTMLDivElement,
1470
+ React.ComponentProps<"div"> & {
1471
+ variant?: SidebarVariant;
1472
+ collapsible?: SidebarCollapsible;
1473
+ loadingUI?: boolean;
1474
+ }
1475
+ >(({ variant = "sidebar", collapsible = "offcanvas", className, children, loadingUI = true, ...props }, ref) => {
1476
+ const { isMobile, leftState, openMobile, setOpenMobile, openLeft, sidebarWidth, setLeftVariant, isIconLeftActive, setIsIconLeftActive, iconLeftWidth, setIconLeftWidth } = useDS();
1477
+
1478
+ const navigation = useNavigation();
1479
+ const [hasInitialLoaded, setHasInitialLoaded] = useState(false);
1480
+
1481
+ useEffect(() => {
1482
+ setLeftVariant(variant);
1483
+ }, [variant, setLeftVariant]);
1484
+
1485
+ useEffect(() => {
1486
+ if (navigation.state === "idle" && !hasInitialLoaded) {
1487
+ setHasInitialLoaded(true);
1488
+ }
1489
+ }, [navigation.state, hasInitialLoaded]);
1490
+
1491
+ const showLoading = loadingUI && navigation.state === "loading" && !hasInitialLoaded;
1492
+
1493
+ if (collapsible === "none") {
1494
+ return (
1495
+ <div className={cn("flex h-full w-[--dual-sidebar-width] flex-col bg-sidebar text-sidebar-foreground", className)} ref={ref} {...props}>
1496
+ {showLoading ? <DSLoading /> : children}
1497
+ </div>
1498
+ );
1499
+ }
1500
+ if (isMobile) {
1501
+ return (
1502
+ <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>
1503
+ <SheetContent data-dual-sidebar="sidebar" data-mobile="true" className="w-[--dual-sidebar-width] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden" style={{ "--dual-sidebar-width": DS_WIDTH_MOBILE } as React.CSSProperties} side="left">
1504
+ <SheetHeader className="sr-only">
1505
+ <SheetTitle>Sidebar</SheetTitle>
1506
+ <SheetDescription>Displays the mobile sidebar.</SheetDescription>
1507
+ </SheetHeader>
1508
+ <div className="flex h-full w-full flex-col">{showLoading ? <DSLoading /> : children}</div>
1509
+ </SheetContent>
1510
+ </Sheet>
1511
+ );
1512
+ }
1513
+
1514
+ const closedOffset = "8px";
1515
+ const iconOffset = isIconLeftActive ? iconLeftWidth : "0px";
1516
+ const transformClass = openLeft ? "translate-x-0" : "translate-x-[calc(-100%-4px)]";
1517
+ const isInsetOrFloating = variant === "floating" || variant === "inset";
1518
+
1519
+ return (
1520
+ <div
1521
+ className={cn(
1522
+ dsVariants({ variant, side: "left" }),
1523
+ transformClass,
1524
+ !isIconLeftActive && "left-0",
1525
+ isInsetOrFloating && "p-2",
1526
+ className
1527
+ )}
1528
+ {...props}
1529
+ >
1530
+ <div
1531
+ data-slot="sidebar-gap"
1532
+ className={cn()}
1533
+ style={{
1534
+ width: isInsetOrFloating && !openLeft
1535
+ ? `calc(${DS_WIDTH_ICON} + 1rem)`
1536
+ : sidebarWidth,
1537
+ "--dual-sidebar-width-icon": DS_WIDTH_ICON,
1538
+ left: isIconLeftActive ? iconOffset : undefined,
1539
+ transform: openLeft
1540
+ ? "translateX(0)"
1541
+ : `translateX(calc(-${sidebarWidth} - ${closedOffset}))`,
1542
+ }}
1543
+ />
1544
+ <div className={cn(
1545
+ "flex h-full w-full flex-col bg-sidebar",
1546
+ isInsetOrFloating && "rounded-lg border border-sidebar-border shadow-sm"
1547
+ )}>
1548
+ {showLoading ? <DSLoading /> : children}
1549
+ </div>
1550
+ </div>
1551
+ );
1552
+ });
1553
+ DSLeft.displayName = "DSLeft";
1554
+
1555
+ const DSLeftIcon = forwardRef<
1556
+ HTMLDivElement,
1557
+ React.ComponentProps<"div"> & {
1558
+ // We assume the desired width is DS_WIDTH_ICON or similar constant
1559
+ iconWidth?: string;
1560
+ variant?: SidebarVariant;
1561
+
1562
+ }
1563
+ >(({ iconWidth = DS_WIDTH_ICON, variant = "sidebar", className, children, ...props }, ref) => {
1564
+ // 1. Communicate its existence and width to the context (NEW STATE)
1565
+ const { setIsIconLeftActive, setIconLeftWidth, leftVariant } = useDS(); // Assumes new context setters
1566
+
1567
+ // Set context state on mount/unmount
1568
+ useEffect(() => {
1569
+ setIsIconLeftActive(true);
1570
+ setIconLeftWidth(iconWidth);
1571
+ return () => {
1572
+ setIsIconLeftActive(false);
1573
+ setIconLeftWidth("0px");
1574
+ };
1575
+ }, [iconWidth, setIsIconLeftActive, setIconLeftWidth]);
1576
+
1577
+ return (
1578
+ <div
1579
+ ref={ref}
1580
+ /** className={cn(
1581
+ leftVariant === "inset" ? "bg-sidebar" : "bg-background",
1582
+ "fixed inset-y-0 left-0 z-20 hidden h-svh flex-col md:flex",
1583
+ // Transition/width applied via style
1584
+ className
1585
+ )} */
1586
+ className={cn(
1587
+ iconDSVariants({ variant: leftVariant, side: "left" }),
1588
+ className
1589
+ )}
1590
+ style={
1591
+ {
1592
+ // Set the width for this specific component
1593
+ "--dual-sidebar-icon-width-fixed": iconWidth,
1594
+ width: iconWidth, // Apply width directly
1595
+ } as React.CSSProperties
1596
+ }
1597
+ data-side="left-icon"
1598
+ {...props}
1599
+ >
1600
+ <div
1601
+ className="flex h-full w-full flex-col bg-sidebar border-r border-border" // Add a right border
1602
+ >
1603
+ {children}
1604
+ </div>
1605
+ </div>
1606
+ );
1607
+ });
1608
+ DSLeftIcon.displayName = "DSLeftIcon";
1609
+
1610
+ const DSRight1 = forwardRef<
1611
+ HTMLDivElement,
1612
+ React.ComponentProps<"div"> & {
1613
+ variant?: SidebarVariant;
1614
+ collapsible?: SidebarCollapsible;
1615
+ loadingUI?: boolean;
1616
+ }
1617
+ >(({ variant = "sidebar", collapsible = "offcanvas", className, children, loadingUI = true, ...props }, ref) => {
1618
+ const { isMobile, rightState, openMobileRight, setOpenMobileRight, openRight, sidebarWidth, setRightVariant, isIconRightActive, setIsIconRightActive, iconRightWidth, setIconRightWidth } = useDS();
1619
+ const navigation = useNavigation();
1620
+ const [hasInitialLoaded, setHasInitialLoaded] = useState(false);
1621
+
1622
+ useEffect(() => {
1623
+ setRightVariant(variant);
1624
+ }, [variant, setRightVariant]);
1625
+
1626
+ React.useEffect(() => {
1627
+ if (navigation.state === "idle" && !hasInitialLoaded) {
1628
+ setHasInitialLoaded(true);
1629
+ }
1630
+ }, [navigation.state, hasInitialLoaded]);
1631
+
1632
+ // Show loading only during initial load if loadingUI is enabled
1633
+ const showLoading = loadingUI && navigation.state === "loading" && !hasInitialLoaded;
1634
+
1635
+ if (collapsible === "none") {
1636
+ return (
1637
+ <div className={cn("flex h-full w-[--dual-sidebar-width] flex-col bg-sidebar text-sidebar-foreground", className)} ref={ref} {...props}>
1638
+ {showLoading ? <DSLoading /> : children}
1639
+ </div>
1640
+ );
1641
+ }
1642
+
1643
+ if (isMobile) {
1644
+ return (
1645
+ <Sheet open={openMobileRight} onOpenChange={setOpenMobileRight} {...props}>
1646
+ <SheetContent
1647
+ data-dual-sidebar="sidebar"
1648
+ data-mobile="true"
1649
+ className="w-[--dual-sidebar-width] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
1650
+ style={{ "--dual-sidebar-width": DS_WIDTH_MOBILE } as React.CSSProperties}
1651
+ side="right"
1652
+ >
1653
+ <SheetHeader className="sr-only">
1654
+ <SheetTitle>Sidebar</SheetTitle>
1655
+ <SheetDescription>Displays the mobile sidebar.</SheetDescription>
1656
+ </SheetHeader>
1657
+ <div className="flex h-full w-full flex-col">{showLoading ? <DSLoading /> : children}</div>
1658
+ </SheetContent>
1659
+ </Sheet>
1660
+ );
1661
+ }
1662
+ const closedOffset = "8px";
1663
+ const iconOffset = isIconRightActive ? iconRightWidth : "0px";
1664
+ const baseClasses = `fixed inset-y-0 right-1 z-20 w-72 bg-sidebar rounded-[15px] flex flex-col transition-transform duration-300 shadow-2xl`;
1665
+ const transformClass = openRight ? "translate-x-0" : "translte-x-[calc(100%+4px)]"; // Hide completely + offset for parent margin/bordera
1666
+
1667
+ return (
1668
+ <div
1669
+ //className={cn(baseClasses, transformClass, !isIconRightActive && "right-0", className)}
1670
+ className={cn(
1671
+ dsVariants({ variant, side: "right" }),
1672
+ transformClass,
1673
+ !isIconRightActive && "right-0",
1674
+ className
1675
+ )}
1676
+ style={{
1677
+ width: sidebarWidth,
1678
+ "--dual-sidebar-width-icon": DS_WIDTH_ICON,
1679
+ right: isIconRightActive ? iconOffset : undefined,
1680
+ transform: openRight ? "translateX(0)" : `translateX(calc(100% + ${closedOffset}))`,
1681
+ }}
1682
+ {...props}
1683
+ >
1684
+ {showLoading ? <DSLoading /> : children}
1685
+ </div>
1686
+ );
1687
+ });
1688
+ const DSRight = forwardRef<
1689
+ HTMLDivElement,
1690
+ React.ComponentProps<"div"> & {
1691
+ variant?: SidebarVariant;
1692
+ collapsible?: SidebarCollapsible;
1693
+ loadingUI?: boolean;
1694
+ }
1695
+ >(({ variant = "sidebar", collapsible = "offcanvas", className, children, loadingUI = true, ...props }, ref) => {
1696
+ const { isMobile, rightState, openMobileRight, setOpenMobileRight, openRight, sidebarWidth, setRightVariant, isIconRightActive, setIsIconRightActive, iconRightWidth, setIconRightWidth } = useDS();
1697
+ const navigation = useNavigation();
1698
+ const [hasInitialLoaded, setHasInitialLoaded] = useState(false);
1699
+
1700
+ useEffect(() => {
1701
+ setRightVariant(variant);
1702
+ }, [variant, setRightVariant]);
1703
+
1704
+ React.useEffect(() => {
1705
+ if (navigation.state === "idle" && !hasInitialLoaded) {
1706
+ setHasInitialLoaded(true);
1707
+ }
1708
+ }, [navigation.state, hasInitialLoaded]);
1709
+
1710
+ const showLoading = loadingUI && navigation.state === "loading" && !hasInitialLoaded;
1711
+
1712
+ if (collapsible === "none") {
1713
+ return (
1714
+ <div className={cn("flex h-full w-[--dual-sidebar-width] flex-col bg-sidebar text-sidebar-foreground", className)} ref={ref} {...props}>
1715
+ {showLoading ? <DSLoading /> : children}
1716
+ </div>
1717
+ );
1718
+ }
1719
+
1720
+ if (isMobile) {
1721
+ return (
1722
+ <Sheet open={openMobileRight} onOpenChange={setOpenMobileRight} {...props}>
1723
+ <SheetContent
1724
+ data-dual-sidebar="sidebar"
1725
+ data-mobile="true"
1726
+ className="w-[--dual-sidebar-width] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
1727
+ style={{ "--dual-sidebar-width": DS_WIDTH_MOBILE } as React.CSSProperties}
1728
+ side="right"
1729
+ >
1730
+ <SheetHeader className="sr-only">
1731
+ <SheetTitle>Sidebar</SheetTitle>
1732
+ <SheetDescription>Displays the mobile sidebar.</SheetDescription>
1733
+ </SheetHeader>
1734
+ <div className="flex h-full w-full flex-col">{showLoading ? <DSLoading /> : children}</div>
1735
+ </SheetContent>
1736
+ </Sheet>
1737
+ );
1738
+ }
1739
+
1740
+ const closedOffset = "8px";
1741
+ const iconOffset = isIconRightActive ? iconRightWidth : "0px";
1742
+ const transformClass = openRight ? "translate-x-0" : "translate-x-[calc(100%+4px)]";
1743
+ const isInsetOrFloating = variant === "floating" || variant === "inset";
1744
+
1745
+ return (
1746
+ <div
1747
+ className={cn(
1748
+ dsVariants({ variant, side: "right" }),
1749
+ transformClass,
1750
+ !isIconRightActive && "right-0",
1751
+ isInsetOrFloating && "p-2",
1752
+ className
1753
+ )}
1754
+ style={{
1755
+ width: isInsetOrFloating && !openRight
1756
+ ? `calc(${DS_WIDTH_ICON} + 1rem)` // 1rem = spacing(4) = 16px
1757
+ : sidebarWidth,
1758
+ "--dual-sidebar-width-icon": DS_WIDTH_ICON,
1759
+ right: isIconRightActive ? iconOffset : undefined,
1760
+ transform: openRight ? "translateX(0)" : `translateX(calc(100% + ${closedOffset}))`,
1761
+ }}
1762
+ {...props}
1763
+ >
1764
+ <div className={cn(
1765
+ "flex h-full w-full flex-col bg-sidebar",
1766
+ isInsetOrFloating && "rounded-lg border border-sidebar-border shadow-sm"
1767
+ )}>
1768
+ {showLoading ? <DSLoading /> : children}
1769
+ </div>
1770
+ </div>
1771
+ );
1772
+ });
1773
+ DSRight.displayName = "DSRight";
1774
+
1775
+ const DSRightIcon = forwardRef<
1776
+ HTMLDivElement,
1777
+ React.ComponentProps<"div"> & {
1778
+ // We assume the desired width is DS_WIDTH_ICON or similar constant
1779
+ iconWidth?: string;
1780
+ variant?: SidebarVariant;
1781
+ }
1782
+ >(({ iconWidth = DS_WIDTH_ICON, variant = "sidebar", className, children, ...props }, ref) => {
1783
+ // 1. Communicate its existence and width to the context (NEW STATE)
1784
+ const { setIsIconRightActive, setIconRightWidth, rightVariant } = useDS(); // Assumes new context setters
1785
+
1786
+ // Set context state on mount/unmount
1787
+ useEffect(() => {
1788
+ setIsIconRightActive(true);
1789
+ setIconRightWidth(iconWidth);
1790
+ return () => {
1791
+ setIsIconRightActive(false);
1792
+ setIconRightWidth("0px");
1793
+ };
1794
+ }, [iconWidth, setIsIconRightActive, setIconRightWidth]);
1795
+
1796
+ return (
1797
+ <div
1798
+ ref={ref}
1799
+ /**className={cn(
1800
+ // rightVariant === 'inset' ? 'bg-sidebar' : 'bg-background',
1801
+ "fixed inset-y-0 right-0 z-20 hidden h-svh flex-col md:flex",
1802
+ // Transition/width applied via style
1803
+ className
1804
+ )} */
1805
+ className={cn(
1806
+ iconDSVariants({ variant: rightVariant, side: "right" }),
1807
+ className
1808
+ )}
1809
+ style={
1810
+ {
1811
+ // Set the width for this specific component
1812
+ "--dual-sidebar-icon-width-fixed": iconWidth,
1813
+ width: iconWidth, // Apply width directly
1814
+ } as React.CSSProperties
1815
+ }
1816
+ data-side="right-icon"
1817
+ {...props}
1818
+ >
1819
+ <div
1820
+ className="flex h-full w-full flex-col bg-sidebar border-l border-border" // Add a right border
1821
+ >
1822
+ {children}
1823
+ </div>
1824
+ </div>
1825
+ );
1826
+ });
1827
+ DSRightIcon.displayName = "DSRightIcon";
1828
+
1829
+
1830
+
1831
+ function DSBurger({ opened, size = "md", color = "currentColor", onClick }: any) {
1832
+ const [internalOpened, setInternalOpened] = React.useState(false);
1833
+ const isOpened = opened !== undefined ? opened : internalOpened;
1834
+
1835
+ const sizeClasses = {
1836
+ sm: "w-4 h-4",
1837
+ md: "w-6 h-6",
1838
+ lg: "w-8 h-8",
1839
+ xl: "w-10 h-10",
1840
+ };
1841
+
1842
+ const lineHeight = {
1843
+ sm: "2px",
1844
+ md: "2px",
1845
+ lg: "3px",
1846
+ xl: "3px",
1847
+ };
1848
+
1849
+ const handleClick = () => {
1850
+ if (opened === undefined) {
1851
+ setInternalOpened(!internalOpened);
1852
+ }
1853
+ onClick?.();
1854
+ };
1855
+
1856
+ return (
1857
+ <button
1858
+ className={cn("relative cursor-pointer bg-transparent border-none p-0", sizeClasses[size])}
1859
+ style={{ color }}
1860
+ onClick={handleClick}
1861
+ aria-label={isOpened ? "Close menu" : "Open menu"}
1862
+ >
1863
+ <motion.span
1864
+ className="absolute left-0 block rounded-full bg-current"
1865
+ style={{
1866
+ width: "100%",
1867
+ height: lineHeight[size],
1868
+ top: "50%",
1869
+ left: 0,
1870
+ }}
1871
+ animate={{
1872
+ rotate: isOpened ? 45 : 0,
1873
+ y: isOpened ? "-50%" : "calc(-50% - 6px)",
1874
+ }}
1875
+ transition={{ duration: 0.3 }}
1876
+ />
1877
+ <motion.span
1878
+ className="absolute left-0 top-1/2 block rounded-full bg-current"
1879
+ style={{
1880
+ width: "100%",
1881
+ height: lineHeight[size],
1882
+ y: "-50%",
1883
+ }}
1884
+ animate={{
1885
+ opacity: isOpened ? 0 : 1,
1886
+ }}
1887
+ transition={{ duration: 0.3 }}
1888
+ />
1889
+ <motion.span
1890
+ className="absolute left-0 block rounded-full bg-current"
1891
+ style={{
1892
+ width: "100%",
1893
+ height: lineHeight[size],
1894
+ top: "50%",
1895
+ left: 0,
1896
+ }}
1897
+ animate={{
1898
+ rotate: isOpened ? -45 : 0,
1899
+ y: isOpened ? "-50%" : "calc(-50% + 6px)",
1900
+ }}
1901
+ transition={{ duration: 0.3 }}
1902
+ />
1903
+ </button>
1904
+ );
1905
+ }
1906
+
1907
+ const DSTrigger = forwardRef<React.ElementRef<typeof Button>, React.ComponentProps<typeof Button> & { side?: "left" | "right" }>(({ side = "left", className, onClick, ...props }, ref) => {
1908
+ const { toggleLeft, toggleRight, openLeft, openRight } = useDS();
1909
+ const open = side === "left" ? openLeft : openRight;
1910
+ const handleClick = () => {
1911
+ if (side === "left") {
1912
+ toggleLeft();
1913
+ } else {
1914
+ toggleRight();
1915
+ }
1916
+ };
1917
+ return (
1918
+ <Button
1919
+ ref={ref}
1920
+ data-dual-sidebar="trigger"
1921
+ variant="ghost"
1922
+ size="icon"
1923
+ className={cn("h-7 w-7", className)}
1924
+ onClick={(event) => {
1925
+ onClick?.(event);
1926
+ handleClick();
1927
+ }}
1928
+ {...props}
1929
+ >
1930
+ <DSBurger opened={open} />
1931
+ <span className="sr-only">Toggle Sidebar</span>
1932
+ </Button>
1933
+ );
1934
+ });
1935
+ DSTrigger.displayName = "DSTrigger";
1936
+
1937
+ const DSLeftRail = forwardRef<HTMLButtonElement, React.ComponentProps<"button"> & { side?: SidebarSide }>(({ side = "left", className, ...props }, ref) => {
1938
+ const { toggleLeft } = useDS();
1939
+
1940
+ return (
1941
+ <button
1942
+ ref={ref}
1943
+ data-dual-sidebar="rail"
1944
+ aria-label="Toggle Sidebar"
1945
+ tabIndex={-1}
1946
+ // onClick={toggleLeft}
1947
+ onMouseEnter={toggleLeft}
1948
+ title="Toggle Sidebar"
1949
+ className={cn(
1950
+ "absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border -right-4 ",
1951
+ "cursor-w-resize",
1952
+ "group-data-[state=collapsed]:cursor-e-resize",
1953
+ "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar",
1954
+ "group-data-[collapsible=offcanvas]:-right-2",
1955
+ className
1956
+ )}
1957
+ {...props}
1958
+ />
1959
+ );
1960
+ });
1961
+ DSLeftRail.displayName = "DSLeftRail";
1962
+
1963
+ const DSRightRail = forwardRef<HTMLButtonElement, React.ComponentProps<"button"> & { side?: "left" | "right" }>(({ side = "right", className, ...props }, ref) => {
1964
+ const { toggleRight } = useDS();
1965
+
1966
+ return (
1967
+ <button
1968
+ ref={ref}
1969
+ data-dual-sidebar="rail"
1970
+ aria-label="Toggle Sidebar"
1971
+ tabIndex={-1}
1972
+ onMouseEnter={toggleRight}
1973
+ title="Toggle Sidebar"
1974
+ className={cn(
1975
+ "absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border left-0 sm:flex",
1976
+ "cursor-e-resize",
1977
+ "group-data-[state=collapsed]:cursor-w-resize",
1978
+ "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar",
1979
+ "group-data-[data-collapsible=offcanvas]:-left-2",
1980
+ className
1981
+ )}
1982
+ {...props}
1983
+ />
1984
+ );
1985
+ });
1986
+ DSRightRail.displayName = "DSRightRail";
1987
+
1988
+ const DSHeader = forwardRef<HTMLDivElement, React.ComponentProps<"div">>(({ className, ...props }, ref) => {
1989
+ const { variant } = useDS();
1990
+ return (
1991
+ <div ref={ref} data-dual-sidebar="header" className={cn(headerVariants({ variant }), className)} {...props} />
1992
+ );
1993
+ });
1994
+ DSHeader.displayName = "DSHeader";
1995
+
1996
+ const DSFooter = forwardRef<HTMLDivElement, React.ComponentProps<"div">>(({ className, ...props }, ref) => {
1997
+ const { variant } = useDS();
1998
+ return (
1999
+ <div ref={ref} data-dual-sidebar="footer" className={cn(footerVariants({ variant }), className)} {...props} />
2000
+ );
2001
+ });
2002
+ DSFooter.displayName = "DSFooter";
2003
+
2004
+ const DSSeparator = forwardRef<React.ElementRef<typeof Separator>, React.ComponentProps<typeof Separator>>(({ className, ...props }, ref) => {
2005
+ const { variant } = useDS();
2006
+ return <Separator ref={ref} data-dual-sidebar="separator" className={cn(separatorVariants({ variant, spacing }), className)} {...props} />;
2007
+ });
2008
+ DSSeparator.displayName = "DSSeparator";
2009
+
2010
+ const DSContent = forwardRef<HTMLDivElement, React.ComponentProps<"div">>(({ className, ...props }, ref) => {
2011
+ return (
2012
+ <div
2013
+ ref={ref}
2014
+ data-dual-sidebar="content"
2015
+ className={cn(
2016
+ "flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto overflow-x-hidden group-data-[collapsible=icon]:overflow-hidden",
2017
+ "group-data-[variant=floating]:bg-sidebar group-data-[variant=floating]:text-sidebar-foreground",
2018
+ "group-data-[variant=sidebar]:bg-sidebar group-data-[variant=sidebar]:text-sidebar-foreground",
2019
+ className
2020
+ )}
2021
+ {...props}
2022
+ />
2023
+ );
2024
+ });
2025
+ DSContent.displayName = "DSContent";
2026
+
2027
+ const DSInput = forwardRef<React.ElementRef<typeof Input>, React.ComponentProps<typeof Input>>(({ className, ...props }, ref) => {
2028
+ return <Input ref={ref} data-dual-sidebar="input" className={cn("h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring", className)} {...props} />;
2029
+ });
2030
+ DSInput.displayName = "DSInput";
2031
+
2032
+ const DSGroup = forwardRef<HTMLDivElement, React.ComponentProps<"div">>(({ className, ...props }, ref) => {
2033
+ const { variant } = useDS();
2034
+ return <div ref={ref} data-dual-sidebar="group" className={cn(groupVariants({ variant }), className)} {...props} />;
2035
+ });
2036
+ DSGroup.displayName = "DSGroup";
2037
+
2038
+ const DSGroupLabel = forwardRef<HTMLDivElement, React.ComponentProps<"div"> & { asChild?: boolean }>(({ className, asChild = false, ...props }, ref) => {
2039
+ const { variant } = useDS();
2040
+ const Comp = asChild ? Slot : "div";
2041
+ return (
2042
+ <Comp ref={ref} data-dual-sidebar="group-label" className={cn(groupLabelVariants({ variant }), "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0", className)} {...props} />
2043
+ );
2044
+ });
2045
+ DSGroupLabel.displayName = "DSGroupLabel";
2046
+
2047
+ const DSGroupAction = forwardRef<HTMLButtonElement, React.ComponentProps<"button"> & { asChild?: boolean }>(({ className, asChild = false, ...props }, ref) => {
2048
+ const Comp = asChild ? Slot : "button";
2049
+
2050
+ return (
2051
+ <Comp
2052
+ ref={ref}
2053
+ data-dual-sidebar="group-action"
2054
+ className={cn(
2055
+ "absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
2056
+ "after:absolute after:-inset-2 after:md:hidden",
2057
+ "group-data-[collapsible=icon]:hidden",
2058
+ className
2059
+ )}
2060
+ {...props}
2061
+ />
2062
+ );
2063
+ });
2064
+ DSGroupAction.displayName = "DSGroupAction";
2065
+
2066
+ const DSGroupContent = forwardRef<HTMLDivElement, React.ComponentProps<"div">>(({ className, ...props }, ref) => <div ref={ref} data-dual-sidebar="group-content" className={cn("w-full text-sm", className)} {...props} />);
2067
+ DSGroupContent.displayName = "DSGroupContent";
2068
+
2069
+ const DSMenu = forwardRef<HTMLUListElement, React.ComponentProps<"ul">>(({ className, ...props }, ref) => <ul ref={ref} data-dual-sidebar="menu" className={cn("flex w-full min-w-0 flex-col gap-1", className)} {...props} />);
2070
+ DSMenu.displayName = "DSMenu";
2071
+
2072
+ const DSMenuItem = React.forwardRef<
2073
+ HTMLLIElement,
2074
+ React.ComponentProps<"li">
2075
+ >(({ className, ...props }, ref) => {
2076
+ const { variant } = useDS();
2077
+ return (
2078
+ <li
2079
+ ref={ref}
2080
+ data-dual-sidebar="menu-item"
2081
+ className={cn(menuItemVariants({ variant }), className)}
2082
+ {...props}
2083
+ />
2084
+ );
2085
+ });
2086
+
2087
+ DSMenuItem.displayName = "DSMenuItem";
2088
+
2089
+ const DSMenuButton = forwardRef<
2090
+ HTMLButtonElement,
2091
+ React.ComponentProps<"button"> & {
2092
+ asChild?: boolean;
2093
+ isActive?: boolean;
2094
+ tooltip?: string | React.ComponentProps<typeof TooltipContent>;
2095
+ side: "left" | "right";
2096
+ } & VariantProps<typeof DSMenuButtonVariants>
2097
+ >(({ asChild = false, isActive = false, variant = "default", size = "default", tooltip, className, side, ...props }, ref) => {
2098
+ const Comp = asChild ? Slot : "button";
2099
+ const { isMobile, leftState, rightState } = useDS();
2100
+
2101
+ const button = <Comp ref={ref} data-dual-sidebar="menu-button" data-size={size} data-active={isActive} className={cn(DSMenuButtonVariants({ variant, size }), className)} {...props} />;
2102
+
2103
+ if (!tooltip) {
2104
+ return button;
2105
+ }
2106
+
2107
+ if (typeof tooltip === "string") {
2108
+ tooltip = {
2109
+ children: tooltip,
2110
+ };
2111
+ }
2112
+
2113
+ return (
2114
+ <DSMenuItem>
2115
+ <Tooltip>
2116
+ <TooltipTrigger asChild>{button}</TooltipTrigger>
2117
+ <TooltipContent side={side === "left" ? "right" : "left"} align="center" hidden={(leftState || rightState) !== "collapsed" || isMobile} {...tooltip} />
2118
+ </Tooltip>
2119
+ </DSMenuItem>
2120
+ );
2121
+ });
2122
+ DSMenuButton.displayName = "DSMenuButton";
2123
+
2124
+ const DSMenuAction = forwardRef<
2125
+ HTMLButtonElement,
2126
+ React.ComponentProps<"button"> & {
2127
+ asChild?: boolean;
2128
+ showOnHover?: boolean;
2129
+ }
2130
+ >(({ className, asChild = false, showOnHover = false, ...props }, ref) => {
2131
+ const Comp = asChild ? Slot : "button";
2132
+
2133
+ return (
2134
+ <Comp
2135
+ ref={ref}
2136
+ data-dual-sidebar="menu-action"
2137
+ className={cn(
2138
+ "absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0",
2139
+ "after:absolute after:-inset-2 after:md:hidden",
2140
+ "peer-data-[size=sm]/menu-button:top-1",
2141
+ "peer-data-[size=default]/menu-button:top-1.5",
2142
+ "peer-data-[size=lg]/menu-button:top-2.5",
2143
+ "group-data-[collapsible=icon]:hidden",
2144
+ showOnHover && "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0",
2145
+ className
2146
+ )}
2147
+ {...props}
2148
+ />
2149
+ );
2150
+ });
2151
+ DSMenuAction.displayName = "DSMenuAction";
2152
+
2153
+ const DSMenuBadge = forwardRef<HTMLDivElement, React.ComponentProps<"div">>(({ className, ...props }, ref) => (<div ref={ref} data-dual-sidebar="menu-badge" className={cn(menuBadgeVariants({ variant }), className)} {...props} />));
2154
+ DSMenuBadge.displayName = "DSMenuBadge";
2155
+
2156
+ const DSMenuSkeleton = forwardRef<
2157
+ HTMLDivElement,
2158
+ React.ComponentProps<"div"> & {
2159
+ showIcon?: boolean;
2160
+ }
2161
+ >(({ className, showIcon = false, ...props }, ref) => {
2162
+ const width = React.useMemo(() => {
2163
+ return `${Math.floor(Math.random() * 40) + 50}%`;
2164
+ }, []);
2165
+
2166
+ return (
2167
+ <div ref={ref} data-dual-sidebar="menu-skeleton" className={cn("flex h-8 items-center gap-2 rounded-md px-2", className)} {...props}>
2168
+ {showIcon && <Skeleton className="size-4 rounded-md" data-dual-sidebar="menu-skeleton-icon" />}
2169
+ <Skeleton
2170
+ className="h-4 max-w-[--skeleton-width] flex-1"
2171
+ data-dual-sidebar="menu-skeleton-text"
2172
+ style={
2173
+ {
2174
+ "--skeleton-width": width,
2175
+ } as React.CSSProperties
2176
+ }
2177
+ />
2178
+ </div>
2179
+ );
2180
+ });
2181
+ DSMenuSkeleton.displayName = "DSMenuSkeleton";
2182
+
2183
+ interface DSMenuAnchorProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
2184
+ icon?: React.ReactNode;
2185
+ tooltip?: string;
2186
+ to: string;
2187
+ newTab?: boolean;
2188
+ variant?: "default" | "ghost" | "outline" | "soft" | "solid" | "minimal" | "bordered" | "pill";
2189
+ size?: "default" | "sm" | "lg" | "icon";
2190
+ }
2191
+
2192
+ interface DSMenuAnchorProps extends React.ComponentProps<"a"> {
2193
+ icon?: React.ReactNode;
2194
+ tooltip?: string | React.ComponentProps<typeof TooltipContent>;
2195
+ variant?: "default" | "ghost" | "outline" | "soft" | "solid" | "minimal" | "bordered" | "pill";
2196
+ size?: "default" | "sm" | "lg" | "icon";
2197
+ newTab?: boolean;
2198
+ }
2199
+
2200
+ const DSMenuAnchor = forwardRef<HTMLAnchorElement, DSMenuAnchorProps>(({
2201
+ className,
2202
+ icon,
2203
+ tooltip,
2204
+ children,
2205
+ to,
2206
+ newTab = true,
2207
+ variant = "default",
2208
+ size = "default",
2209
+ onClick,
2210
+ ...props
2211
+ }, ref) => {
2212
+ const navigation = useNavigation();
2213
+ const location = useLocation();
2214
+ const { isMobile, leftState, rightState } = useDS();
2215
+
2216
+ const isActive = location.pathname === to;
2217
+ const isNavigatingToThisLink = navigation.state === "loading" && navigation.location?.href === to;
2218
+
2219
+ const anchorProps = newTab
2220
+ ? {
2221
+ target: "_blank",
2222
+ rel: "noopener noreferrer",
2223
+ }
2224
+ : {};
2225
+
2226
+ const anchorContent = (
2227
+ <>
2228
+ {icon &&
2229
+ React.isValidElement(icon) &&
2230
+ React.cloneElement(icon, {
2231
+ className: cn("size-4 shrink-0", icon.props.className),
2232
+ })}
2233
+ <span className="flex-1 truncate">{children}</span>
2234
+
2235
+ {isNavigatingToThisLink && (
2236
+ <div className="ml-auto flex items-center">
2237
+ <div className="animate-spin rounded-full h-5 w-5 border-t-3 border-primary border-solid"></div>
2238
+ </div>
2239
+ )}
2240
+ </>
2241
+ );
2242
+
2243
+ const anchor = (
2244
+ <a
2245
+ ref={ref}
2246
+ href={to}
2247
+ {...anchorProps}
2248
+ onClick={onClick}
2249
+ className={cn(
2250
+ DSMenuButtonVariants({ variant, size, isActive }),
2251
+ isActive && "text-primary bg-muted font-medium",
2252
+ className
2253
+ )}
2254
+ {...props}
2255
+ >
2256
+ {anchorContent}
2257
+ </a>
2258
+ );
2259
+
2260
+ // If tooltip exists, wrap with Tooltip
2261
+ if (tooltip) {
2262
+ const tooltipProps = typeof tooltip === 'string' ? { children: tooltip } : tooltip;
2263
+
2264
+ return (
2265
+ <DSMenuItem>
2266
+ <Tooltip>
2267
+ <TooltipTrigger asChild>
2268
+ {anchor}
2269
+ </TooltipTrigger>
2270
+ <TooltipContent
2271
+ side="right"
2272
+ align="center"
2273
+ hidden={(leftState || rightState) !== "collapsed" || isMobile}
2274
+ {...tooltipProps}
2275
+ />
2276
+ </Tooltip>
2277
+ </DSMenuItem>
2278
+ );
2279
+ }
2280
+
2281
+ // No tooltip
2282
+ return (
2283
+ <DSMenuItem>
2284
+ {anchor}
2285
+ </DSMenuItem>
2286
+ );
2287
+ });
2288
+
2289
+ DSMenuAnchor.displayName = "DSMenuAnchor";
2290
+
2291
+ interface DSMenuLinkProps extends React.ComponentProps<typeof NavLink> {
2292
+ icon?: React.ReactNode;
2293
+ tooltip?: string;
2294
+ variant?: "default" | "ghost" | "outline" | "soft" | "solid" | "minimal" | "bordered" | "pill";
2295
+ size?: "default" | "sm" | "lg" | "icon";
2296
+ }
2297
+
2298
+ const DSMenuLink = forwardRef<HTMLAnchorElement, DSMenuLinkProps>(({ className, icon, tooltip, children, to, variant = "default", size = "default", ...props }, ref) => {
2299
+ const navigation = useNavigation();
2300
+ const location = useLocation();
2301
+ const { isMobile, leftState, rightState } = useDS();
2302
+
2303
+ const isNavigatingToThisLink = navigation.state === 'loading' && navigation.location?.pathname === to;
2304
+ const isActive = location.pathname === to;
2305
+
2306
+ const linkContent = (
2307
+ <>
2308
+ {icon &&
2309
+ React.isValidElement(icon) &&
2310
+ React.cloneElement(icon, {
2311
+ className: cn("size-4 shrink-0", icon.props.className),
2312
+ })}
2313
+ <span className="flex-1 truncate">{children}</span>
2314
+
2315
+ {isNavigatingToThisLink && (
2316
+ <div className="ml-auto flex items-center">
2317
+ <div className="animate-spin rounded-full h-5 w-5 border-t-3 border-primary border-solid"></div>
2318
+ </div>
2319
+ )}
2320
+ </>
2321
+ );
2322
+
2323
+ const link = (
2324
+ <NavLink
2325
+ ref={ref}
2326
+ to={to}
2327
+ className={cn(
2328
+ DSMenuButtonVariants({ variant, size, isActive }),
2329
+ isActive && "text-primary bg-muted font-medium",
2330
+ className
2331
+ )}
2332
+ {...props}
2333
+ >
2334
+ {linkContent}
2335
+ </NavLink>
2336
+ );
2337
+
2338
+ // If tooltip exists, wrap with Tooltip
2339
+ if (tooltip) {
2340
+ const tooltipProps = typeof tooltip === 'string' ? { children: tooltip } : tooltip;
2341
+
2342
+ return (
2343
+ <DSMenuItem>
2344
+ <Tooltip>
2345
+ <TooltipTrigger asChild>
2346
+ {link}
2347
+ </TooltipTrigger>
2348
+ <TooltipContent
2349
+ side="right"
2350
+ align="center"
2351
+ hidden={(leftState || rightState) !== "collapsed" || isMobile}
2352
+ {...tooltipProps}
2353
+ />
2354
+ </Tooltip>
2355
+ </DSMenuItem>
2356
+ );
2357
+ }
2358
+
2359
+ // No tooltip
2360
+ return (
2361
+ <DSMenuItem>
2362
+ {link}
2363
+ </DSMenuItem>
2364
+ );
2365
+ });
2366
+ DSMenuLink.displayName = "DSMenuLink";
2367
+
2368
+ const DSMenuSub = forwardRef<HTMLUListElement, React.ComponentProps<"ul">>(({ className, ...props }, ref) => (<ul ref={ref} data-dual-sidebar="menu-sub" className={cn("mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-border px-2.5 py-0.5", "group-data-[collapsible=icon]:hidden", className)} {...props} />));
2369
+ DSMenuSub.displayName = "DSMenuSub";
2370
+
2371
+ const DSMenuSubItem = forwardRef<HTMLLIElement, React.ComponentProps<"li">>(({ ...props }, ref) => <li ref={ref} {...props} />);
2372
+ DSMenuSubItem.displayName = "DSMenuSubItem";
2373
+
2374
+ const DSMenuSubButton = forwardRef<
2375
+ HTMLAnchorElement,
2376
+ React.ComponentProps<"a"> & {
2377
+ asChild?: boolean;
2378
+ size?: "sm" | "md";
2379
+ isActive?: boolean;
2380
+ }
2381
+ >(({ asChild = false, size = "md", isActive, className, ...props }, ref) => {
2382
+ const Comp = asChild ? Slot : "a";
2383
+ const { variant } = useDS();
2384
+ return (
2385
+ <Comp ref={ref} data-dual-sidebar="menu-sub-button" data-size={size} data-active={isActive} className={cn(menuSubButtonVariants({ variant, size }), className)} {...props} />
2386
+ );
2387
+ });
2388
+ DSMenuSubButton.displayName = "DSMenuSubButton";
2389
+
2390
+ const DSD = forwardRef<
2391
+ HTMLDivElement,
2392
+ React.ComponentProps<typeof Drawer> & {
2393
+ drawerHeight: string;
2394
+ variant?: "default" | "card" | "glass" | "elevated" | "bordered";
2395
+ }
2396
+ >(({ drawerHeight = "80vh", variant = 'default', direction = 'bottom', size = 'md', children, ...props }, ref) => {
2397
+ const { setTopHeight, dsdVariant, setDsdVariant, dsdDirection, setDsdDirection, dsdSize,
2398
+ setDsdSize } = useDS();
2399
+
2400
+ const [isOpen, setIsOpen] = React.useState(false);
2401
+
2402
+ React.useEffect(() => {
2403
+ setDsdVariant(variant)
2404
+ setDsdDirection(direction)
2405
+ setDsdSize(size)
2406
+ setTopHeight(isOpen ? drawerHeight : "0px");
2407
+ return () => setTopHeight("0px");
2408
+ }, [isOpen, drawerHeight, setTopHeight]);
2409
+
2410
+ return (
2411
+ <Drawer ref={ref} placement="top" onOpenChange={setIsOpen} {...props}>
2412
+ {children}
2413
+ </Drawer>
2414
+ );
2415
+ });
2416
+ DSD.displayName = "DSD";
2417
+ function DSDTrigger({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {
2418
+ return <DrawerPrimitive.Trigger data-slot="drawer-trigger" {...props} />;
2419
+ }
2420
+ function DSDPortal({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Portal>) {
2421
+ return <DrawerPrimitive.Portal data-slot="drawer-portal" {...props} />;
2422
+ }
2423
+ function DSDClose({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Close>) {
2424
+ return <DrawerPrimitive.Close data-slot="drawer-close" {...props} />;
2425
+ }
2426
+ function DSDOverlay({ className, ...props }: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {
2427
+ return (
2428
+ <DrawerPrimitive.Overlay data-slot="drawer-overlay" className={cn("data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50", className)} {...props} />
2429
+ );
2430
+ }
2431
+ function DSDContent({ className, children, ...props }: React.ComponentProps<typeof DrawerPrimitive.Content>) {
2432
+ const { setTopHeight, dsdVariant, setDsdVariant, dsdDirection, setDsdDirection, dsdSize, setDsdSize } = useDS();
2433
+ const variant = dsdVariant
2434
+ const direction = dsdDirection
2435
+ const size = dsdSize
2436
+ return (
2437
+ <DSDPortal data-slot="drawer-portal">
2438
+ <DSDOverlay />
2439
+ <DrawerPrimitive.Content data-slot="drawer-content" className={cn(drawerVariants({ direction, size, variant }), className)} {...props} >
2440
+ <div className="bg-muted mx-auto mt-4 hidden h-2 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block" />
2441
+ {children}
2442
+ </DrawerPrimitive.Content>
2443
+ </DSDPortal>
2444
+ );
2445
+ }
2446
+ function DSDHeader({ className, ...props }: React.ComponentProps<"div">) {
2447
+ return (
2448
+ <div
2449
+ data-slot="drawer-header"
2450
+ className={cn("flex flex-col gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-1.5 md:text-left", className)}
2451
+ {...props}
2452
+ />
2453
+ );
2454
+ }
2455
+ function DSDFooter({ className, ...props }: React.ComponentProps<"div">) {
2456
+ return <div data-slot="drawer-footer" className={cn("mt-auto flex flex-col gap-2 p-4", className)} {...props} />;
2457
+ }
2458
+ function DSDTitle({ className, ...props }: React.ComponentProps<typeof DrawerPrimitive.Title>) {
2459
+ return <DrawerPrimitive.Title data-slot="drawer-title" className={cn("text-foreground font-semibold", className)} {...props} />;
2460
+ }
2461
+ function DSDDescription({ className, ...props }: React.ComponentProps<typeof DrawerPrimitive.Description>) {
2462
+ return <DrawerPrimitive.Description data-slot="drawer-description" className={cn("text-muted-foreground text-sm", className)} {...props} />;
2463
+ }
2464
+ function DSLoading({
2465
+ variant = "default",
2466
+ size = "default"
2467
+ }: {
2468
+ variant?: "default" | "minimal" | "card" | "centered";
2469
+ size?: "default" | "sm" | "md" | "lg" | "full";
2470
+ }) {
2471
+ const isMobile = useIsMobile();
2472
+ const width = isMobile ? DS_WIDTH_MOBILE : DS_WIDTH;
2473
+ return (
2474
+ <div className={cn(loadingVariants({ variant, size }), width)}>
2475
+ {/**<div className={cn("flex flex-col items-center justify-center text-center p-8 w-[256px] min-h-[400px] h-screen bg-gradient-to-b from-background to-muted/20", width)}> */}
2476
+ <div className="space-y-3">
2477
+ <h3 className="text-lg font-semibold text-foreground animate-pulse">Loading Sidebar</h3>
2478
+ <p className="text-sm text-muted-foreground/80 animate-pulse delay-150">Please wait while the content loads...</p>
2479
+ </div>
2480
+ <div className="mb-6">
2481
+ <LoaderX variant='3' />
2482
+ </div>
2483
+ {/** <div className="w-full mt-8 space-y-3">
2484
+ <div className="h-3 bg-muted rounded-full animate-pulse"></div>
2485
+ <div className="h-3 bg-muted rounded-full animate-pulse delay-75 w-3/4"></div>
2486
+ <div className="h-3 bg-muted rounded-full animate-pulse delay-150 w-1/2"></div>
2487
+ </div>
2488
+
2489
+ <div className="flex space-x-1 mt-6">
2490
+ <div className="w-2 h-2 bg-primary/60 rounded-full animate-bounce"></div>
2491
+ <div className="w-2 h-2 bg-primary/60 rounded-full animate-bounce delay-100"></div>
2492
+ <div className="w-2 h-2 bg-primary/60 rounded-full animate-bounce delay-200"></div>
2493
+ </div> */}
2494
+ </div>
2495
+ );
2496
+ }
2497
+ const colorThemes = {
2498
+ neutral: {
2499
+ v4: {
2500
+ root: {
2501
+ "--radius": "0.65rem",
2502
+ "--background": "oklch(1 0 0)",
2503
+ "--foreground": "oklch(0.145 0 0)",
2504
+ "--card": "oklch(1 0 0)",
2505
+ "--card-foreground": "oklch(0.145 0 0)",
2506
+ "--popover": "oklch(1 0 0)",
2507
+ "--popover-foreground": "oklch(0.145 0 0)",
2508
+ "--primary": "oklch(0.205 0 0)",
2509
+ "--primary-foreground": "oklch(0.985 0 0)",
2510
+ "--secondary": "oklch(0.97 0 0)",
2511
+ "--secondary-foreground": "oklch(0.205 0 0)",
2512
+ "--muted": "oklch(0.97 0 0)",
2513
+ "--muted-foreground": "oklch(0.556 0 0)",
2514
+ "--accent": "oklch(0.97 0 0)",
2515
+ "--accent-foreground": "oklch(0.205 0 0)",
2516
+ "--destructive": "oklch(0.577 0.245 27.325)",
2517
+ "--border": "oklch(0.922 0 0)",
2518
+ "--input": "oklch(0.922 0 0)",
2519
+ "--ring": "oklch(0.708 0 0)",
2520
+ "--chart-1": "oklch(0.646 0.222 41.116)",
2521
+ "--chart-2": "oklch(0.6 0.118 184.704)",
2522
+ "--chart-3": "oklch(0.398 0.07 227.392)",
2523
+ "--chart-4": "oklch(0.828 0.189 84.429)",
2524
+ "--chart-5": "oklch(0.769 0.188 70.08)",
2525
+ "--sidebar": "oklch(0.985 0 0)",
2526
+ "--sidebar-foreground": "oklch(0.145 0 0)",
2527
+ "--sidebar-primary": "oklch(0.205 0 0)",
2528
+ "--sidebar-primary-foreground": "oklch(0.985 0 0)",
2529
+ "--sidebar-accent": "oklch(0.97 0 0)",
2530
+ "--sidebar-accent-foreground": "oklch(0.205 0 0)",
2531
+ "--sidebar-border": "oklch(0.922 0 0)",
2532
+ "--sidebar-ring": "oklch(0.708 0 0)",
2533
+ },
2534
+ dark: {
2535
+ "--background": "oklch(0.145 0 0)",
2536
+ "--foreground": "oklch(0.985 0 0)",
2537
+ "--card": "oklch(0.205 0 0)",
2538
+ "--card-foreground": "oklch(0.985 0 0)",
2539
+ "--popover": "oklch(0.205 0 0)",
2540
+ "--popover-foreground": "oklch(0.985 0 0)",
2541
+ "--primary": "oklch(0.922 0 0)",
2542
+ "--primary-foreground": "oklch(0.205 0 0)",
2543
+ "--secondary": "oklch(0.269 0 0)",
2544
+ "--secondary-foreground": "oklch(0.985 0 0)",
2545
+ "--muted": "oklch(0.269 0 0)",
2546
+ "--muted-foreground": "oklch(0.708 0 0)",
2547
+ "--accent": "oklch(0.269 0 0)",
2548
+ "--accent-foreground": "oklch(0.985 0 0)",
2549
+ "--destructive": "oklch(0.704 0.191 22.216)",
2550
+ "--border": "oklch(1 0 0 / 10%)",
2551
+ "--input": "oklch(1 0 0 / 15%)",
2552
+ "--ring": "oklch(0.556 0 0)",
2553
+ "--chart-1": "oklch(0.488 0.243 264.376)",
2554
+ "--chart-2": "oklch(0.696 0.17 162.48)",
2555
+ "--chart-3": "oklch(0.769 0.188 70.08)",
2556
+ "--chart-4": "oklch(0.627 0.265 303.9)",
2557
+ "--chart-5": "oklch(0.645 0.246 16.439)",
2558
+ "--sidebar": "oklch(0.205 0 0)",
2559
+ "--sidebar-foreground": "oklch(0.985 0 0)",
2560
+ "--sidebar-primary": "oklch(0.488 0.243 264.376)",
2561
+ "--sidebar-primary-foreground": "oklch(0.985 0 0)",
2562
+ "--sidebar-accent": "oklch(0.269 0 0)",
2563
+ "--sidebar-accent-foreground": "oklch(0.985 0 0)",
2564
+ "--sidebar-border": "oklch(1 0 0 / 10%)",
2565
+ "--sidebar-ring": "oklch(0.556 0 0)",
2566
+ },
2567
+ },
2568
+ v3: {
2569
+ root: {
2570
+ "--background": "0 0% 100%",
2571
+ "--foreground": "0 0% 3.9%",
2572
+ "--card": "0 0% 100%",
2573
+ "--card-foreground": "0 0% 3.9%",
2574
+ "--popover": "0 0% 100%",
2575
+ "--popover-foreground": "0 0% 3.9%",
2576
+ "--primary": "0 0% 9%",
2577
+ "--primary-foreground": "0 0% 98%",
2578
+ "--secondary": "0 0% 96.1%",
2579
+ "--secondary-foreground": "0 0% 9%",
2580
+ "--muted": "0 0% 96.1%",
2581
+ "--muted-foreground": "0 0% 45.1%",
2582
+ "--accent": "0 0% 96.1%",
2583
+ "--accent-foreground": "0 0% 9%",
2584
+ "--destructive": "0 84.2% 60.2%",
2585
+ "--destructive-foreground": "0 0% 98%",
2586
+ "--border": "0 0% 89.8%",
2587
+ "--input": "0 0% 89.8%",
2588
+ "--ring": "0 0% 3.9%",
2589
+ "--radius": "0.5rem",
2590
+ "--chart-1": "12 76% 61%",
2591
+ "--chart-2": "173 58% 39%",
2592
+ "--chart-3": "197 37% 24%",
2593
+ "--chart-4": "43 74% 66%",
2594
+ "--chart-5": "27 87% 67%",
2595
+ "--sidebar": "221 39% 11%",
2596
+ "--sidebar-foreground": "0 0% 98%",
2597
+ "--sidebar-primary": "217.2 91.2% 59.8%",
2598
+ "--special": "227 21% 8%",
2599
+ "--special-muted-background": "240 10% 4%",
2600
+ "--special-border": "240 4% 16%",
2601
+ "--special-foreground": "240 5% 84%",
2602
+ "--special-muted-foreground": "240 4% 46%",
2603
+ },
2604
+ dark: {
2605
+ "--background": "0 0% 3.9%",
2606
+ "--foreground": "0 0% 98%",
2607
+ "--card": "0 0% 3.9%",
2608
+ "--card-foreground": "0 0% 98%",
2609
+ "--popover": "0 0% 3.9%",
2610
+ "--popover-foreground": "0 0% 98%",
2611
+ "--primary": "0 0% 98%",
2612
+ "--primary-foreground": "0 0% 9%",
2613
+ "--secondary": "0 0% 14.9%",
2614
+ "--secondary-foreground": "0 0% 98%",
2615
+ "--muted": "0 0% 14.9%",
2616
+ "--muted-foreground": "0 0% 63.9%",
2617
+ "--accent": "0 0% 14.9%",
2618
+ "--accent-foreground": "0 0% 98%",
2619
+ "--destructive": "0 62.8% 30.6%",
2620
+ "--destructive-foreground": "0 0% 98%",
2621
+ "--border": "0 0% 14.9%",
2622
+ "--input": "0 0% 14.9%",
2623
+ "--ring": "0 0% 83.1%",
2624
+ "--chart-1": "220 70% 50%",
2625
+ "--chart-2": "160 60% 45%",
2626
+ "--chart-3": "30 80% 55%",
2627
+ "--chart-4": "280 65% 60%",
2628
+ "--chart-5": "340 75% 55%",
2629
+ "--sidebar": "221 39% 11%",
2630
+ "--sidebar-foreground": "0 0% 98%",
2631
+ "--sidebar-primary": "217.2 91.2% 59.8%",
2632
+ "--special": "227 21% 8%",
2633
+ "--special-muted-background": "240 10% 4%",
2634
+ "--special-border": "240 4% 16%",
2635
+ "--special-foreground": "240 5% 84%",
2636
+ "--special-muted-foreground": "240 4% 46%",
2637
+ },
2638
+ },
2639
+ },
2640
+ red: {
2641
+ v4: {
2642
+ root: {
2643
+ "--radius": "0.65rem",
2644
+ "--background": "oklch(1 0 0)",
2645
+ "--foreground": "oklch(0.141 0.005 285.823)",
2646
+ "--card": "oklch(1 0 0)",
2647
+ "--card-foreground": "oklch(0.141 0.005 285.823)",
2648
+ "--popover": "oklch(1 0 0)",
2649
+ "--popover-foreground": "oklch(0.141 0.005 285.823)",
2650
+ "--primary": "oklch(0.637 0.237 25.331)",
2651
+ "--primary-foreground": "oklch(0.971 0.013 17.38)",
2652
+ "--secondary": "oklch(0.967 0.001 286.375)",
2653
+ "--secondary-foreground": "oklch(0.21 0.006 285.885)",
2654
+ "--muted": "oklch(0.967 0.001 286.375)",
2655
+ "--muted-foreground": "oklch(0.552 0.016 285.938)",
2656
+ "--accent": "oklch(0.967 0.001 286.375)",
2657
+ "--accent-foreground": "oklch(0.21 0.006 285.885)",
2658
+ "--destructive": "oklch(0.577 0.245 27.325)",
2659
+ "--border": "oklch(0.92 0.004 286.32)",
2660
+ "--input": "oklch(0.92 0.004 286.32)",
2661
+ "--ring": "oklch(0.637 0.237 25.331)",
2662
+ "--chart-1": "oklch(0.646 0.222 41.116)",
2663
+ "--chart-2": "oklch(0.6 0.118 184.704)",
2664
+ "--chart-3": "oklch(0.398 0.07 227.392)",
2665
+ "--chart-4": "oklch(0.828 0.189 84.429)",
2666
+ "--chart-5": "oklch(0.769 0.188 70.08)",
2667
+ "--sidebar": "oklch(0.985 0 0)",
2668
+ "--sidebar-foreground": "oklch(0.141 0.005 285.823)",
2669
+ "--sidebar-primary": "oklch(0.637 0.237 25.331)",
2670
+ "--sidebar-primary-foreground": "oklch(0.971 0.013 17.38)",
2671
+ "--sidebar-accent": "oklch(0.967 0.001 286.375)",
2672
+ "--sidebar-accent-foreground": "oklch(0.21 0.006 285.885)",
2673
+ "--sidebar-border": "oklch(0.92 0.004 286.32)",
2674
+ "--sidebar-ring": "oklch(0.637 0.237 25.331)",
2675
+ },
2676
+ dark: {
2677
+ "--background": "oklch(0.141 0.005 285.823)",
2678
+ "--foreground": "oklch(0.985 0 0)",
2679
+ "--card": "oklch(0.21 0.006 285.885)",
2680
+ "--card-foreground": "oklch(0.985 0 0)",
2681
+ "--popover": "oklch(0.21 0.006 285.885)",
2682
+ "--popover-foreground": "oklch(0.985 0 0)",
2683
+ "--primary": "oklch(0.637 0.237 25.331)",
2684
+ "--primary-foreground": "oklch(0.971 0.013 17.38)",
2685
+ "--secondary": "oklch(0.274 0.006 286.033)",
2686
+ "--secondary-foreground": "oklch(0.985 0 0)",
2687
+ "--muted": "oklch(0.274 0.006 286.033)",
2688
+ "--muted-foreground": "oklch(0.705 0.015 286.067)",
2689
+ "--accent": "oklch(0.274 0.006 286.033)",
2690
+ "--accent-foreground": "oklch(0.985 0 0)",
2691
+ "--destructive": "oklch(0.704 0.191 22.216)",
2692
+ "--border": "oklch(1 0 0 / 10%)",
2693
+ "--input": "oklch(1 0 0 / 15%)",
2694
+ "--ring": "oklch(0.637 0.237 25.331)",
2695
+ "--chart-1": "oklch(0.488 0.243 264.376)",
2696
+ "--chart-2": "oklch(0.696 0.17 162.48)",
2697
+ "--chart-3": "oklch(0.769 0.188 70.08)",
2698
+ "--chart-4": "oklch(0.627 0.265 303.9)",
2699
+ "--chart-5": "oklch(0.645 0.246 16.439)",
2700
+ "--sidebar": "oklch(0.21 0.006 285.885)",
2701
+ "--sidebar-foreground": "oklch(0.985 0 0)",
2702
+ "--sidebar-primary": "oklch(0.637 0.237 25.331)",
2703
+ "--sidebar-primary-foreground": "oklch(0.971 0.013 17.38)",
2704
+ "--sidebar-accent": "oklch(0.274 0.006 286.033)",
2705
+ "--sidebar-accent-foreground": "oklch(0.985 0 0)",
2706
+ "--sidebar-border": "oklch(1 0 0 / 10%)",
2707
+ "--sidebar-ring": "oklch(0.637 0.237 25.331)",
2708
+ },
2709
+ },
2710
+ v3: {
2711
+ root: {
2712
+ "--background": "0 0% 100%",
2713
+ "--foreground": "0 0% 3.9%",
2714
+ "--card": "0 0% 100%",
2715
+ "--card-foreground": "0 0% 3.9%",
2716
+ "--popover": "0 0% 100%",
2717
+ "--popover-foreground": "0 0% 3.9%",
2718
+ "--primary": "0 72.2% 50.6%",
2719
+ "--primary-foreground": "0 85.7% 97.3%",
2720
+ "--secondary": "0 0% 96.1%",
2721
+ "--secondary-foreground": "0 0% 9%",
2722
+ "--muted": "0 0% 96.1%",
2723
+ "--muted-foreground": "0 0% 45.1%",
2724
+ "--accent": "0 0% 96.1%",
2725
+ "--accent-foreground": "0 0% 9%",
2726
+ "--destructive": "0 84.2% 60.2%",
2727
+ "--destructive-foreground": "0 0% 98%",
2728
+ "--border": "0 0% 89.8%",
2729
+ "--input": "0 0% 89.8%",
2730
+ "--ring": "0 72.2% 50.6%",
2731
+ "--radius": "0.5rem",
2732
+ "--chart-1": "12 76% 61%",
2733
+ "--chart-2": "173 58% 39%",
2734
+ "--chart-3": "197 37% 24%",
2735
+ "--chart-4": "43 74% 66%",
2736
+ "--chart-5": "27 87% 67%",
2737
+ "--sidebar": "221 39% 11%",
2738
+ "--sidebar-foreground": "0 0% 98%",
2739
+ "--sidebar-primary": "217.2 91.2% 59.8%",
2740
+ "--special": "227 21% 8%",
2741
+ "--special-muted-background": "240 10% 4%",
2742
+ "--special-border": "240 4% 16%",
2743
+ "--special-foreground": "240 5% 84%",
2744
+ "--special-muted-foreground": "240 4% 46%",
2745
+ },
2746
+ dark: {
2747
+ "--background": "0 0% 3.9%",
2748
+ "--foreground": "0 0% 98%",
2749
+ "--card": "0 0% 3.9%",
2750
+ "--card-foreground": "0 0% 98%",
2751
+ "--popover": "0 0% 3.9%",
2752
+ "--popover-foreground": "0 0% 98%",
2753
+ "--primary": "0 72.2% 50.6%",
2754
+ "--primary-foreground": "0 85.7% 97.3%",
2755
+ "--secondary": "0 0% 14.9%",
2756
+ "--secondary-foreground": "0 0% 98%",
2757
+ "--muted": "0 0% 14.9%",
2758
+ "--muted-foreground": "0 0% 63.9%",
2759
+ "--accent": "0 0% 14.9%",
2760
+ "--accent-foreground": "0 0% 98%",
2761
+ "--destructive": "0 62.8% 30.6%",
2762
+ "--destructive-foreground": "0 0% 98%",
2763
+ "--border": "0 0% 14.9%",
2764
+ "--input": "0 0% 14.9%",
2765
+ "--ring": "0 72.2% 50.6%",
2766
+ "--chart-1": "220 70% 50%",
2767
+ "--chart-2": "160 60% 45%",
2768
+ "--chart-3": "30 80% 55%",
2769
+ "--chart-4": "280 65% 60%",
2770
+ "--chart-5": "340 75% 55%",
2771
+ "--sidebar": "221 39% 11%",
2772
+ "--sidebar-foreground": "0 0% 98%",
2773
+ "--sidebar-primary": "217.2 91.2% 59.8%",
2774
+ "--special": "227 21% 8%",
2775
+ "--special-muted-background": "240 10% 4%",
2776
+ "--special-border": "240 4% 16%",
2777
+ "--special-foreground": "240 5% 84%",
2778
+ "--special-muted-foreground": "240 4% 46%",
2779
+ },
2780
+ },
2781
+ },
2782
+ rose: {
2783
+ v4: {
2784
+ root: {
2785
+ "--radius": "0.65rem",
2786
+ "--background": "oklch(1 0 0)",
2787
+ "--foreground": "oklch(0.141 0.005 285.823)",
2788
+ "--card": "oklch(1 0 0)",
2789
+ "--card-foreground": "oklch(0.141 0.005 285.823)",
2790
+ "--popover": "oklch(1 0 0)",
2791
+ "--popover-foreground": "oklch(0.141 0.005 285.823)",
2792
+ "--primary": "oklch(0.645 0.246 16.439)",
2793
+ "--primary-foreground": "oklch(0.969 0.015 12.422)",
2794
+ "--secondary": "oklch(0.967 0.001 286.375)",
2795
+ "--secondary-foreground": "oklch(0.21 0.006 285.885)",
2796
+ "--muted": "oklch(0.967 0.001 286.375)",
2797
+ "--muted-foreground": "oklch(0.552 0.016 285.938)",
2798
+ "--accent": "oklch(0.967 0.001 286.375)",
2799
+ "--accent-foreground": "oklch(0.21 0.006 285.885)",
2800
+ "--destructive": "oklch(0.577 0.245 27.325)",
2801
+ "--border": "oklch(0.92 0.004 286.32)",
2802
+ "--input": "oklch(0.92 0.004 286.32)",
2803
+ "--ring": "oklch(0.645 0.246 16.439)",
2804
+ "--chart-1": "oklch(0.646 0.222 41.116)",
2805
+ "--chart-2": "oklch(0.6 0.118 184.704)",
2806
+ "--chart-3": "oklch(0.398 0.07 227.392)",
2807
+ "--chart-4": "oklch(0.828 0.189 84.429)",
2808
+ "--chart-5": "oklch(0.769 0.188 70.08)",
2809
+ "--sidebar": "oklch(0.985 0 0)",
2810
+ "--sidebar-foreground": "oklch(0.141 0.005 285.823)",
2811
+ "--sidebar-primary": "oklch(0.645 0.246 16.439)",
2812
+ "--sidebar-primary-foreground": "oklch(0.969 0.015 12.422)",
2813
+ "--sidebar-accent": "oklch(0.967 0.001 286.375)",
2814
+ "--sidebar-accent-foreground": "oklch(0.21 0.006 285.885)",
2815
+ "--sidebar-border": "oklch(0.92 0.004 286.32)",
2816
+ "--sidebar-ring": "oklch(0.645 0.246 16.439)",
2817
+ },
2818
+ dark: {
2819
+ "--background": "oklch(0.141 0.005 285.823)",
2820
+ "--foreground": "oklch(0.985 0 0)",
2821
+ "--card": "oklch(0.21 0.006 285.885)",
2822
+ "--card-foreground": "oklch(0.985 0 0)",
2823
+ "--popover": "oklch(0.21 0.006 285.885)",
2824
+ "--popover-foreground": "oklch(0.985 0 0)",
2825
+ "--primary": "oklch(0.645 0.246 16.439)",
2826
+ "--primary-foreground": "oklch(0.969 0.015 12.422)",
2827
+ "--secondary": "oklch(0.274 0.006 286.033)",
2828
+ "--secondary-foreground": "oklch(0.985 0 0)",
2829
+ "--muted": "oklch(0.274 0.006 286.033)",
2830
+ "--muted-foreground": "oklch(0.705 0.015 286.067)",
2831
+ "--accent": "oklch(0.274 0.006 286.033)",
2832
+ "--accent-foreground": "oklch(0.985 0 0)",
2833
+ "--destructive": "oklch(0.704 0.191 22.216)",
2834
+ "--border": "oklch(1 0 0 / 10%)",
2835
+ "--input": "oklch(1 0 0 / 15%)",
2836
+ "--ring": "oklch(0.645 0.246 16.439)",
2837
+ "--chart-1": "oklch(0.488 0.243 264.376)",
2838
+ "--chart-2": "oklch(0.696 0.17 162.48)",
2839
+ "--chart-3": "oklch(0.769 0.188 70.08)",
2840
+ "--chart-4": "oklch(0.627 0.265 303.9)",
2841
+ "--chart-5": "oklch(0.645 0.246 16.439)",
2842
+ "--sidebar": "oklch(0.21 0.006 285.885)",
2843
+ "--sidebar-foreground": "oklch(0.985 0 0)",
2844
+ "--sidebar-primary": "oklch(0.645 0.246 16.439)",
2845
+ "--sidebar-primary-foreground": "oklch(0.969 0.015 12.422)",
2846
+ "--sidebar-accent": "oklch(0.274 0.006 286.033)",
2847
+ "--sidebar-accent-foreground": "oklch(0.985 0 0)",
2848
+ "--sidebar-border": "oklch(1 0 0 / 10%)",
2849
+ "--sidebar-ring": "oklch(0.645 0.246 16.439)",
2850
+ },
2851
+ },
2852
+ v3: {
2853
+ root: {
2854
+ "--background": "0 0% 100%",
2855
+ "--foreground": "240 10% 3.9%",
2856
+ "--card": "0 0% 100%",
2857
+ "--card-foreground": "240 10% 3.9%",
2858
+ "--popover": "0 0% 100%",
2859
+ "--popover-foreground": "240 10% 3.9%",
2860
+ "--primary": "346.8 77.2% 49.8%",
2861
+ "--primary-foreground": "355.7 100% 97.3%",
2862
+ "--secondary": "240 4.8% 95.9%",
2863
+ "--secondary-foreground": "240 5.9% 10%",
2864
+ "--muted": "240 4.8% 95.9%",
2865
+ "--muted-foreground": "240 3.8% 46.1%",
2866
+ "--accent": "240 4.8% 95.9%",
2867
+ "--accent-foreground": "240 5.9% 10%",
2868
+ "--destructive": "0 84.2% 60.2%",
2869
+ "--destructive-foreground": "0 0% 98%",
2870
+ "--border": "240 5.9% 90%",
2871
+ "--input": "240 5.9% 90%",
2872
+ "--ring": "346.8 77.2% 49.8%",
2873
+ "--radius": "0.5rem",
2874
+ "--chart-1": "12 76% 61%",
2875
+ "--chart-2": "173 58% 39%",
2876
+ "--chart-3": "197 37% 24%",
2877
+ "--chart-4": "43 74% 66%",
2878
+ "--chart-5": "27 87% 67%",
2879
+ "--sidebar": "221 39% 11%",
2880
+ "--sidebar-foreground": "0 0% 98%",
2881
+ "--sidebar-primary": "217.2 91.2% 59.8%",
2882
+ "--special": "227 21% 8%",
2883
+ "--special-muted-background": "240 10% 4%",
2884
+ "--special-border": "240 4% 16%",
2885
+ "--special-foreground": "240 5% 84%",
2886
+ "--special-muted-foreground": "240 4% 46%",
2887
+ },
2888
+ dark: {
2889
+ "--background": "20 14.3% 4.1%",
2890
+ "--foreground": "0 0% 95%",
2891
+ "--card": "24 9.8% 10%",
2892
+ "--card-foreground": "0 0% 95%",
2893
+ "--popover": "0 0% 9%",
2894
+ "--popover-foreground": "0 0% 95%",
2895
+ "--primary": "346.8 77.2% 49.8%",
2896
+ "--primary-foreground": "355.7 100% 97.3%",
2897
+ "--secondary": "240 3.7% 15.9%",
2898
+ "--secondary-foreground": "0 0% 98%",
2899
+ "--muted": "0 0% 15%",
2900
+ "--muted-foreground": "240 5% 64.9%",
2901
+ "--accent": "12 6.5% 15.1%",
2902
+ "--accent-foreground": "0 0% 98%",
2903
+ "--destructive": "0 62.8% 30.6%",
2904
+ "--destructive-foreground": "0 85.7% 97.3%",
2905
+ "--border": "240 3.7% 15.9%",
2906
+ "--input": "240 3.7% 15.9%",
2907
+ "--ring": "346.8 77.2% 49.8%",
2908
+ "--chart-1": "220 70% 50%",
2909
+ "--chart-2": "160 60% 45%",
2910
+ "--chart-3": "30 80% 55%",
2911
+ "--chart-4": "280 65% 60%",
2912
+ "--chart-5": "340 75% 55%",
2913
+ "--sidebar": "221 39% 11%",
2914
+ "--sidebar-foreground": "0 0% 98%",
2915
+ "--sidebar-primary": "217.2 91.2% 59.8%",
2916
+ "--special": "227 21% 8%",
2917
+ "--special-muted-background": "240 10% 4%",
2918
+ "--special-border": "240 4% 16%",
2919
+ "--special-foreground": "240 5% 84%",
2920
+ "--special-muted-foreground": "240 4% 46%",
2921
+ },
2922
+ },
2923
+ },
2924
+ orange: {
2925
+ v4: {
2926
+ root: {
2927
+ "--radius": "0.65rem",
2928
+ "--background": "oklch(1 0 0)",
2929
+ "--foreground": "oklch(0.141 0.005 285.823)",
2930
+ "--card": "oklch(1 0 0)",
2931
+ "--card-foreground": "oklch(0.141 0.005 285.823)",
2932
+ "--popover": "oklch(1 0 0)",
2933
+ "--popover-foreground": "oklch(0.141 0.005 285.823)",
2934
+ "--primary": "oklch(0.705 0.213 47.604)",
2935
+ "--primary-foreground": "oklch(0.98 0.016 73.684)",
2936
+ "--secondary": "oklch(0.967 0.001 286.375)",
2937
+ "--secondary-foreground": "oklch(0.21 0.006 285.885)",
2938
+ "--muted": "oklch(0.967 0.001 286.375)",
2939
+ "--muted-foreground": "oklch(0.552 0.016 285.938)",
2940
+ "--accent": "oklch(0.967 0.001 286.375)",
2941
+ "--accent-foreground": "oklch(0.21 0.006 285.885)",
2942
+ "--destructive": "oklch(0.577 0.245 27.325)",
2943
+ "--border": "oklch(0.92 0.004 286.32)",
2944
+ "--input": "oklch(0.92 0.004 286.32)",
2945
+ "--ring": "oklch(0.705 0.213 47.604)",
2946
+ "--chart-1": "oklch(0.646 0.222 41.116)",
2947
+ "--chart-2": "oklch(0.6 0.118 184.704)",
2948
+ "--chart-3": "oklch(0.398 0.07 227.392)",
2949
+ "--chart-4": "oklch(0.828 0.189 84.429)",
2950
+ "--chart-5": "oklch(0.769 0.188 70.08)",
2951
+ "--sidebar": "oklch(0.985 0 0)",
2952
+ "--sidebar-foreground": "oklch(0.141 0.005 285.823)",
2953
+ "--sidebar-primary": "oklch(0.705 0.213 47.604)",
2954
+ "--sidebar-primary-foreground": "oklch(0.98 0.016 73.684)",
2955
+ "--sidebar-accent": "oklch(0.967 0.001 286.375)",
2956
+ "--sidebar-accent-foreground": "oklch(0.21 0.006 285.885)",
2957
+ "--sidebar-border": "oklch(0.92 0.004 286.32)",
2958
+ "--sidebar-ring": "oklch(0.705 0.213 47.604)",
2959
+ },
2960
+ dark: {
2961
+ "--background": "oklch(0.141 0.005 285.823)",
2962
+ "--foreground": "oklch(0.985 0 0)",
2963
+ "--card": "oklch(0.21 0.006 285.885)",
2964
+ "--card-foreground": "oklch(0.985 0 0)",
2965
+ "--popover": "oklch(0.21 0.006 285.885)",
2966
+ "--popover-foreground": "oklch(0.985 0 0)",
2967
+ "--primary": "oklch(0.646 0.222 41.116)",
2968
+ "--primary-foreground": "oklch(0.98 0.016 73.684)",
2969
+ "--secondary": "oklch(0.274 0.006 286.033)",
2970
+ "--secondary-foreground": "oklch(0.985 0 0)",
2971
+ "--muted": "oklch(0.274 0.006 286.033)",
2972
+ "--muted-foreground": "oklch(0.705 0.015 286.067)",
2973
+ "--accent": "oklch(0.274 0.006 286.033)",
2974
+ "--accent-foreground": "oklch(0.985 0 0)",
2975
+ "--destructive": "oklch(0.704 0.191 22.216)",
2976
+ "--border": "oklch(1 0 0 / 10%)",
2977
+ "--input": "oklch(1 0 0 / 15%)",
2978
+ "--ring": "oklch(0.646 0.222 41.116)",
2979
+ "--chart-1": "oklch(0.488 0.243 264.376)",
2980
+ "--chart-2": "oklch(0.696 0.17 162.48)",
2981
+ "--chart-3": "oklch(0.769 0.188 70.08)",
2982
+ "--chart-4": "oklch(0.627 0.265 303.9)",
2983
+ "--chart-5": "oklch(0.645 0.246 16.439)",
2984
+ "--sidebar": "oklch(0.21 0.006 285.885)",
2985
+ "--sidebar-foreground": "oklch(0.985 0 0)",
2986
+ "--sidebar-primary": "oklch(0.646 0.222 41.116)",
2987
+ "--sidebar-primary-foreground": "oklch(0.98 0.016 73.684)",
2988
+ "--sidebar-accent": "oklch(0.274 0.006 286.033)",
2989
+ "--sidebar-accent-foreground": "oklch(0.985 0 0)",
2990
+ "--sidebar-border": "oklch(1 0 0 / 10%)",
2991
+ "--sidebar-ring": "oklch(0.646 0.222 41.116)",
2992
+ },
2993
+ },
2994
+ v3: {
2995
+ root: {
2996
+ "--background": "0 0% 100%",
2997
+ "--foreground": "20 14.3% 4.1%",
2998
+ "--card": "0 0% 100%",
2999
+ "--card-foreground": "20 14.3% 4.1%",
3000
+ "--popover": "0 0% 100%",
3001
+ "--popover-foreground": "20 14.3% 4.1%",
3002
+ "--primary": "24.6 95% 53.1%",
3003
+ "--primary-foreground": "60 9.1% 97.8%",
3004
+ "--secondary": "60 4.8% 95.9%",
3005
+ "--secondary-foreground": "24 9.8% 10%",
3006
+ "--muted": "60 4.8% 95.9%",
3007
+ "--muted-foreground": "25 5.3% 44.7%",
3008
+ "--accent": "60 4.8% 95.9%",
3009
+ "--accent-foreground": "24 9.8% 10%",
3010
+ "--destructive": "0 84.2% 60.2%",
3011
+ "--destructive-foreground": "60 9.1% 97.8%",
3012
+ "--border": "20 5.9% 90%",
3013
+ "--input": "20 5.9% 90%",
3014
+ "--ring": "24.6 95% 53.1%",
3015
+ "--radius": "0.5rem",
3016
+ "--chart-1": "12 76% 61%",
3017
+ "--chart-2": "173 58% 39%",
3018
+ "--chart-3": "197 37% 24%",
3019
+ "--chart-4": "43 74% 66%",
3020
+ "--chart-5": "27 87% 67%",
3021
+ "--sidebar": "221 39% 11%",
3022
+ "--sidebar-foreground": "0 0% 98%",
3023
+ "--sidebar-primary": "217.2 91.2% 59.8%",
3024
+ "--special": "227 21% 8%",
3025
+ "--special-muted-background": "240 10% 4%",
3026
+ "--special-border": "240 4% 16%",
3027
+ "--special-foreground": "240 5% 84%",
3028
+ "--special-muted-foreground": "240 4% 46%",
3029
+ },
3030
+ dark: {
3031
+ "--background": "20 14.3% 4.1%",
3032
+ "--foreground": "60 9.1% 97.8%",
3033
+ "--card": "20 14.3% 4.1%",
3034
+ "--card-foreground": "60 9.1% 97.8%",
3035
+ "--popover": "20 14.3% 4.1%",
3036
+ "--popover-foreground": "60 9.1% 97.8%",
3037
+ "--primary": "20.5 90.2% 48.2%",
3038
+ "--primary-foreground": "60 9.1% 97.8%",
3039
+ "--secondary": "12 6.5% 15.1%",
3040
+ "--secondary-foreground": "60 9.1% 97.8%",
3041
+ "--muted": "12 6.5% 15.1%",
3042
+ "--muted-foreground": "24 5.4% 63.9%",
3043
+ "--accent": "12 6.5% 15.1%",
3044
+ "--accent-foreground": "60 9.1% 97.8%",
3045
+ "--destructive": "0 72.2% 50.6%",
3046
+ "--destructive-foreground": "60 9.1% 97.8%",
3047
+ "--border": "12 6.5% 15.1%",
3048
+ "--input": "12 6.5% 15.1%",
3049
+ "--ring": "20.5 90.2% 48.2%",
3050
+ "--chart-1": "220 70% 50%",
3051
+ "--chart-2": "160 60% 45%",
3052
+ "--chart-3": "30 80% 55%",
3053
+ "--chart-4": "280 65% 60%",
3054
+ "--chart-5": "340 75% 55%",
3055
+ "--sidebar": "221 39% 11%",
3056
+ "--sidebar-foreground": "0 0% 98%",
3057
+ "--sidebar-primary": "217.2 91.2% 59.8%",
3058
+ "--special": "227 21% 8%",
3059
+ "--special-muted-background": "240 10% 4%",
3060
+ "--special-border": "240 4% 16%",
3061
+ "--special-foreground": "240 5% 84%",
3062
+ "--special-muted-foreground": "240 4% 46%",
3063
+ },
3064
+ },
3065
+ },
3066
+ green: {
3067
+ v4: {
3068
+ root: {
3069
+ "--radius": "0.65rem",
3070
+ "--background": "oklch(1 0 0)",
3071
+ "--foreground": "oklch(0.141 0.005 285.823)",
3072
+ "--card": "oklch(1 0 0)",
3073
+ "--card-foreground": "oklch(0.141 0.005 285.823)",
3074
+ "--popover": "oklch(1 0 0)",
3075
+ "--popover-foreground": "oklch(0.141 0.005 285.823)",
3076
+ "--primary": "oklch(0.723 0.219 149.579)",
3077
+ "--primary-foreground": "oklch(0.982 0.018 155.826)",
3078
+ "--secondary": "oklch(0.967 0.001 286.375)",
3079
+ "--secondary-foreground": "oklch(0.21 0.006 285.885)",
3080
+ "--muted": "oklch(0.967 0.001 286.375)",
3081
+ "--muted-foreground": "oklch(0.552 0.016 285.938)",
3082
+ "--accent": "oklch(0.967 0.001 286.375)",
3083
+ "--accent-foreground": "oklch(0.21 0.006 285.885)",
3084
+ "--destructive": "oklch(0.577 0.245 27.325)",
3085
+ "--border": "oklch(0.92 0.004 286.32)",
3086
+ "--input": "oklch(0.92 0.004 286.32)",
3087
+ "--ring": "oklch(0.723 0.219 149.579)",
3088
+ "--chart-1": "oklch(0.646 0.222 41.116)",
3089
+ "--chart-2": "oklch(0.6 0.118 184.704)",
3090
+ "--chart-3": "oklch(0.398 0.07 227.392)",
3091
+ "--chart-4": "oklch(0.828 0.189 84.429)",
3092
+ "--chart-5": "oklch(0.769 0.188 70.08)",
3093
+ "--sidebar": "oklch(0.985 0 0)",
3094
+ "--sidebar-foreground": "oklch(0.141 0.005 285.823)",
3095
+ "--sidebar-primary": "oklch(0.723 0.219 149.579)",
3096
+ "--sidebar-primary-foreground": "oklch(0.982 0.018 155.826)",
3097
+ "--sidebar-accent": "oklch(0.967 0.001 286.375)",
3098
+ "--sidebar-accent-foreground": "oklch(0.21 0.006 285.885)",
3099
+ "--sidebar-border": "oklch(0.92 0.004 286.32)",
3100
+ "--sidebar-ring": "oklch(0.723 0.219 149.579)",
3101
+ },
3102
+ dark: {
3103
+ "--background": "oklch(0.141 0.005 285.823)",
3104
+ "--foreground": "oklch(0.985 0 0)",
3105
+ "--card": "oklch(0.21 0.006 285.885)",
3106
+ "--card-foreground": "oklch(0.985 0 0)",
3107
+ "--popover": "oklch(0.21 0.006 285.885)",
3108
+ "--popover-foreground": "oklch(0.985 0 0)",
3109
+ "--primary": "oklch(0.696 0.17 162.48)",
3110
+ "--primary-foreground": "oklch(0.393 0.095 152.535)",
3111
+ "--secondary": "oklch(0.274 0.006 286.033)",
3112
+ "--secondary-foreground": "oklch(0.985 0 0)",
3113
+ "--muted": "oklch(0.274 0.006 286.033)",
3114
+ "--muted-foreground": "oklch(0.705 0.015 286.067)",
3115
+ "--accent": "oklch(0.274 0.006 286.033)",
3116
+ "--accent-foreground": "oklch(0.985 0 0)",
3117
+ "--destructive": "oklch(0.704 0.191 22.216)",
3118
+ "--border": "oklch(1 0 0 / 10%)",
3119
+ "--input": "oklch(1 0 0 / 15%)",
3120
+ "--ring": "oklch(0.527 0.154 150.069)",
3121
+ "--chart-1": "oklch(0.488 0.243 264.376)",
3122
+ "--chart-2": "oklch(0.696 0.17 162.48)",
3123
+ "--chart-3": "oklch(0.769 0.188 70.08)",
3124
+ "--chart-4": "oklch(0.627 0.265 303.9)",
3125
+ "--chart-5": "oklch(0.645 0.246 16.439)",
3126
+ "--sidebar": "oklch(0.21 0.006 285.885)",
3127
+ "--sidebar-foreground": "oklch(0.985 0 0)",
3128
+ "--sidebar-primary": "oklch(0.696 0.17 162.48)",
3129
+ "--sidebar-primary-foreground": "oklch(0.393 0.095 152.535)",
3130
+ "--sidebar-accent": "oklch(0.274 0.006 286.033)",
3131
+ "--sidebar-accent-foreground": "oklch(0.985 0 0)",
3132
+ "--sidebar-border": "oklch(1 0 0 / 10%)",
3133
+ "--sidebar-ring": "oklch(0.527 0.154 150.069)",
3134
+ },
3135
+ },
3136
+ v3: {
3137
+ root: {
3138
+ "--background": "0 0% 100%",
3139
+ "--foreground": "240 10% 3.9%",
3140
+ "--card": "0 0% 100%",
3141
+ "--card-foreground": "240 10% 3.9%",
3142
+ "--popover": "0 0% 100%",
3143
+ "--popover-foreground": "240 10% 3.9%",
3144
+ "--primary": "142.1 76.2% 36.3%",
3145
+ "--primary-foreground": "355.7 100% 97.3%",
3146
+ "--secondary": "240 4.8% 95.9%",
3147
+ "--secondary-foreground": "240 5.9% 10%",
3148
+ "--muted": "240 4.8% 95.9%",
3149
+ "--muted-foreground": "240 3.8% 46.1%",
3150
+ "--accent": "240 4.8% 95.9%",
3151
+ "--accent-foreground": "240 5.9% 10%",
3152
+ "--destructive": "0 84.2% 60.2%",
3153
+ "--destructive-foreground": "0 0% 98%",
3154
+ "--border": "240 5.9% 90%",
3155
+ "--input": "240 5.9% 90%",
3156
+ "--ring": "142.1 76.2% 36.3%",
3157
+ "--radius": "0.5rem",
3158
+ "--chart-1": "12 76% 61%",
3159
+ "--chart-2": "173 58% 39%",
3160
+ "--chart-3": "197 37% 24%",
3161
+ "--chart-4": "43 74% 66%",
3162
+ "--chart-5": "27 87% 67%",
3163
+ "--sidebar": "221 39% 11%",
3164
+ "--sidebar-foreground": "0 0% 98%",
3165
+ "--sidebar-primary": "217.2 91.2% 59.8%",
3166
+ "--special": "227 21% 8%",
3167
+ "--special-muted-background": "240 10% 4%",
3168
+ "--special-border": "240 4% 16%",
3169
+ "--special-foreground": "240 5% 84%",
3170
+ "--special-muted-foreground": "240 4% 46%",
3171
+ },
3172
+ dark: {
3173
+ "--background": "20 14.3% 4.1%",
3174
+ "--foreground": "0 0% 95%",
3175
+ "--card": "24 9.8% 10%",
3176
+ "--card-foreground": "0 0% 95%",
3177
+ "--popover": "0 0% 9%",
3178
+ "--popover-foreground": "0 0% 95%",
3179
+ "--primary": "142.1 70.6% 45.3%",
3180
+ "--primary-foreground": "144.9 80.4% 10%",
3181
+ "--secondary": "240 3.7% 15.9%",
3182
+ "--secondary-foreground": "0 0% 98%",
3183
+ "--muted": "0 0% 15%",
3184
+ "--muted-foreground": "240 5% 64.9%",
3185
+ "--accent": "12 6.5% 15.1%",
3186
+ "--accent-foreground": "0 0% 98%",
3187
+ "--destructive": "0 62.8% 30.6%",
3188
+ "--destructive-foreground": "0 85.7% 97.3%",
3189
+ "--border": "240 3.7% 15.9%",
3190
+ "--input": "240 3.7% 15.9%",
3191
+ "--ring": "142.4 71.8% 29.2%",
3192
+ "--chart-1": "220 70% 50%",
3193
+ "--chart-2": "160 60% 45%",
3194
+ "--chart-3": "30 80% 55%",
3195
+ "--chart-4": "280 65% 60%",
3196
+ "--chart-5": "340 75% 55%",
3197
+ "--sidebar": "221 39% 11%",
3198
+ "--sidebar-foreground": "0 0% 98%",
3199
+ "--sidebar-primary": "217.2 91.2% 59.8%",
3200
+ "--special": "227 21% 8%",
3201
+ "--special-muted-background": "240 10% 4%",
3202
+ "--special-border": "240 4% 16%",
3203
+ "--special-foreground": "240 5% 84%",
3204
+ "--special-muted-foreground": "240 4% 46%",
3205
+ },
3206
+ },
3207
+ },
3208
+ blue: {
3209
+ v4: {
3210
+ root: {
3211
+ "--radius": "0.65rem",
3212
+ "--background": "oklch(1 0 0)",
3213
+ "--foreground": "oklch(0.141 0.005 285.823)",
3214
+ "--card": "oklch(1 0 0)",
3215
+ "--card-foreground": "oklch(0.141 0.005 285.823)",
3216
+ "--popover": "oklch(1 0 0)",
3217
+ "--popover-foreground": "oklch(0.141 0.005 285.823)",
3218
+ "--primary": "oklch(0.623 0.214 259.815)",
3219
+ "--primary-foreground": "oklch(0.97 0.014 254.604)",
3220
+ "--secondary": "oklch(0.967 0.001 286.375)",
3221
+ "--secondary-foreground": "oklch(0.21 0.006 285.885)",
3222
+ "--muted": "oklch(0.967 0.001 286.375)",
3223
+ "--muted-foreground": "oklch(0.552 0.016 285.938)",
3224
+ "--accent": "oklch(0.967 0.001 286.375)",
3225
+ "--accent-foreground": "oklch(0.21 0.006 285.885)",
3226
+ "--destructive": "oklch(0.577 0.245 27.325)",
3227
+ "--border": "oklch(0.92 0.004 286.32)",
3228
+ "--input": "oklch(0.92 0.004 286.32)",
3229
+ "--ring": "oklch(0.623 0.214 259.815)",
3230
+ "--chart-1": "oklch(0.646 0.222 41.116)",
3231
+ "--chart-2": "oklch(0.6 0.118 184.704)",
3232
+ "--chart-3": "oklch(0.398 0.07 227.392)",
3233
+ "--chart-4": "oklch(0.828 0.189 84.429)",
3234
+ "--chart-5": "oklch(0.769 0.188 70.08)",
3235
+ "--sidebar": "oklch(0.985 0 0)",
3236
+ "--sidebar-foreground": "oklch(0.141 0.005 285.823)",
3237
+ "--sidebar-primary": "oklch(0.623 0.214 259.815)",
3238
+ "--sidebar-primary-foreground": "oklch(0.97 0.014 254.604)",
3239
+ "--sidebar-accent": "oklch(0.967 0.001 286.375)",
3240
+ "--sidebar-accent-foreground": "oklch(0.21 0.006 285.885)",
3241
+ "--sidebar-border": "oklch(0.92 0.004 286.32)",
3242
+ "--sidebar-ring": "oklch(0.623 0.214 259.815)",
3243
+ },
3244
+ dark: {
3245
+ "--background": "oklch(0.141 0.005 285.823)",
3246
+ "--foreground": "oklch(0.985 0 0)",
3247
+ "--card": "oklch(0.21 0.006 285.885)",
3248
+ "--card-foreground": "oklch(0.985 0 0)",
3249
+ "--popover": "oklch(0.21 0.006 285.885)",
3250
+ "--popover-foreground": "oklch(0.985 0 0)",
3251
+ "--primary": "oklch(0.546 0.245 262.881)",
3252
+ "--primary-foreground": "oklch(0.379 0.146 265.522)",
3253
+ "--secondary": "oklch(0.274 0.006 286.033)",
3254
+ "--secondary-foreground": "oklch(0.985 0 0)",
3255
+ "--muted": "oklch(0.274 0.006 286.033)",
3256
+ "--muted-foreground": "oklch(0.705 0.015 286.067)",
3257
+ "--accent": "oklch(0.274 0.006 286.033)",
3258
+ "--accent-foreground": "oklch(0.985 0 0)",
3259
+ "--destructive": "oklch(0.704 0.191 22.216)",
3260
+ "--border": "oklch(1 0 0 / 10%)",
3261
+ "--input": "oklch(1 0 0 / 15%)",
3262
+ "--ring": "oklch(0.488 0.243 264.376)",
3263
+ "--chart-1": "oklch(0.488 0.243 264.376)",
3264
+ "--chart-2": "oklch(0.696 0.17 162.48)",
3265
+ "--chart-3": "oklch(0.769 0.188 70.08)",
3266
+ "--chart-4": "oklch(0.627 0.265 303.9)",
3267
+ "--chart-5": "oklch(0.645 0.246 16.439)",
3268
+ "--sidebar": "oklch(0.21 0.006 285.885)",
3269
+ "--sidebar-foreground": "oklch(0.985 0 0)",
3270
+ "--sidebar-primary": "oklch(0.546 0.245 262.881)",
3271
+ "--sidebar-primary-foreground": "oklch(0.379 0.146 265.522)",
3272
+ "--sidebar-accent": "oklch(0.274 0.006 286.033)",
3273
+ "--sidebar-accent-foreground": "oklch(0.985 0 0)",
3274
+ "--sidebar-border": "oklch(1 0 0 / 10%)",
3275
+ "--sidebar-ring": "oklch(0.488 0.243 264.376)",
3276
+ },
3277
+ },
3278
+ v3: {
3279
+ root: {
3280
+ "--background": "0 0% 100%",
3281
+ "--foreground": "222.2 84% 4.9%",
3282
+ "--card": "0 0% 100%",
3283
+ "--card-foreground": "222.2 84% 4.9%",
3284
+ "--popover": "0 0% 100%",
3285
+ "--popover-foreground": "222.2 84% 4.9%",
3286
+ "--primary": "221.2 83.2% 53.3%",
3287
+ "--primary-foreground": "210 40% 98%",
3288
+ "--secondary": "210 40% 96.1%",
3289
+ "--secondary-foreground": "222.2 47.4% 11.2%",
3290
+ "--muted": "210 40% 96.1%",
3291
+ "--muted-foreground": "215.4 16.3% 46.9%",
3292
+ "--accent": "210 40% 96.1%",
3293
+ "--accent-foreground": "222.2 47.4% 11.2%",
3294
+ "--destructive": "0 84.2% 60.2%",
3295
+ "--destructive-foreground": "210 40% 98%",
3296
+ "--border": "214.3 31.8% 91.4%",
3297
+ "--input": "214.3 31.8% 91.4%",
3298
+ "--ring": "221.2 83.2% 53.3%",
3299
+ "--radius": "0.5rem",
3300
+ "--chart-1": "12 76% 61%",
3301
+ "--chart-2": "173 58% 39%",
3302
+ "--chart-3": "197 37% 24%",
3303
+ "--chart-4": "43 74% 66%",
3304
+ "--chart-5": "27 87% 67%",
3305
+ "--sidebar": "221 39% 11%",
3306
+ "--sidebar-foreground": "0 0% 98%",
3307
+ "--sidebar-primary": "221.2 83.2% 53.3%",
3308
+ "--special": "221 39% 11%",
3309
+ "--special-muted-background": "210 40% 96.1%",
3310
+ "--special-border": "214.3 31.8% 91.4%",
3311
+ "--special-foreground": "0 0% 98%",
3312
+ "--special-muted-foreground": "215.4 16.3% 46.9%",
3313
+
3314
+ },
3315
+ dark: {
3316
+ "--background": "222.2 84% 4.9%",
3317
+ "--foreground": "210 40% 98%",
3318
+ "--card": "222.2 84% 4.9%",
3319
+ "--card-foreground": "210 40% 98%",
3320
+ "--popover": "222.2 84% 4.9%",
3321
+ "--popover-foreground": "210 40% 98%",
3322
+ "--primary": "217.2 91.2% 59.8%",
3323
+ "--primary-foreground": "222.2 47.4% 11.2%",
3324
+ "--secondary": "217.2 32.6% 17.5%",
3325
+ "--secondary-foreground": "210 40% 98%",
3326
+ "--muted": "217.2 32.6% 17.5%",
3327
+ "--muted-foreground": "215 20.2% 65.1%",
3328
+ "--accent": "217.2 32.6% 17.5%",
3329
+ "--accent-foreground": "210 40% 98%",
3330
+ "--destructive": "0 62.8% 30.6%",
3331
+ "--destructive-foreground": "210 40% 98%",
3332
+ "--border": "217.2 32.6% 17.5%",
3333
+ "--input": "217.2 32.6% 17.5%",
3334
+ "--ring": "224.3 76.3% 48%",
3335
+ "--chart-1": "220 70% 50%",
3336
+ "--chart-2": "160 60% 45%",
3337
+ "--chart-3": "30 80% 55%",
3338
+ "--chart-4": "280 65% 60%",
3339
+ "--chart-5": "340 75% 55%",
3340
+ "--sidebar": "221 39% 11%",
3341
+ "--sidebar-foreground": "0 0% 98%",
3342
+ "--sidebar-primary": "221.2 83.2% 53.3%",
3343
+ "--special": "221 39% 11%",
3344
+ "--special-muted-background": "210 40% 96.1%",
3345
+ "--special-border": "214.3 31.8% 91.4%",
3346
+ "--special-foreground": "0 0% 98%",
3347
+ "--special-muted-foreground": "215.4 16.3% 46.9%",
3348
+ },
3349
+ },
3350
+ },
3351
+ yellow: {
3352
+ v4: {
3353
+ root: {
3354
+ "--radius": "0.65rem",
3355
+ "--background": "oklch(1 0 0)",
3356
+ "--foreground": "oklch(0.141 0.005 285.823)",
3357
+ "--card": "oklch(1 0 0)",
3358
+ "--card-foreground": "oklch(0.141 0.005 285.823)",
3359
+ "--popover": "oklch(1 0 0)",
3360
+ "--popover-foreground": "oklch(0.141 0.005 285.823)",
3361
+ "--primary": "oklch(0.795 0.184 86.047)",
3362
+ "--primary-foreground": "oklch(0.421 0.095 57.708)",
3363
+ "--secondary": "oklch(0.967 0.001 286.375)",
3364
+ "--secondary-foreground": "oklch(0.21 0.006 285.885)",
3365
+ "--muted": "oklch(0.967 0.001 286.375)",
3366
+ "--muted-foreground": "oklch(0.552 0.016 285.938)",
3367
+ "--accent": "oklch(0.967 0.001 286.375)",
3368
+ "--accent-foreground": "oklch(0.21 0.006 285.885)",
3369
+ "--destructive": "oklch(0.577 0.245 27.325)",
3370
+ "--border": "oklch(0.92 0.004 286.32)",
3371
+ "--input": "oklch(0.92 0.004 286.32)",
3372
+ "--ring": "oklch(0.795 0.184 86.047)",
3373
+ "--chart-1": "oklch(0.646 0.222 41.116)",
3374
+ "--chart-2": "oklch(0.6 0.118 184.704)",
3375
+ "--chart-3": "oklch(0.398 0.07 227.392)",
3376
+ "--chart-4": "oklch(0.828 0.189 84.429)",
3377
+ "--chart-5": "oklch(0.769 0.188 70.08)",
3378
+ "--sidebar": "oklch(0.985 0 0)",
3379
+ "--sidebar-foreground": "oklch(0.141 0.005 285.823)",
3380
+ "--sidebar-primary": "oklch(0.795 0.184 86.047)",
3381
+ "--sidebar-primary-foreground": "oklch(0.421 0.095 57.708)",
3382
+ "--sidebar-accent": "oklch(0.967 0.001 286.375)",
3383
+ "--sidebar-accent-foreground": "oklch(0.21 0.006 285.885)",
3384
+ "--sidebar-border": "oklch(0.92 0.004 286.32)",
3385
+ "--sidebar-ring": "oklch(0.795 0.184 86.047)",
3386
+ },
3387
+ dark: {
3388
+ "--background": "oklch(0.141 0.005 285.823)",
3389
+ "--foreground": "oklch(0.985 0 0)",
3390
+ "--card": "oklch(0.21 0.006 285.885)",
3391
+ "--card-foreground": "oklch(0.985 0 0)",
3392
+ "--popover": "oklch(0.21 0.006 285.885)",
3393
+ "--popover-foreground": "oklch(0.985 0 0)",
3394
+ "--primary": "oklch(0.795 0.184 86.047)",
3395
+ "--primary-foreground": "oklch(0.421 0.095 57.708)",
3396
+ "--secondary": "oklch(0.274 0.006 286.033)",
3397
+ "--secondary-foreground": "oklch(0.985 0 0)",
3398
+ "--muted": "oklch(0.274 0.006 286.033)",
3399
+ "--muted-foreground": "oklch(0.705 0.015 286.067)",
3400
+ "--accent": "oklch(0.274 0.006 286.033)",
3401
+ "--accent-foreground": "oklch(0.985 0 0)",
3402
+ "--destructive": "oklch(0.704 0.191 22.216)",
3403
+ "--border": "oklch(1 0 0 / 10%)",
3404
+ "--input": "oklch(1 0 0 / 15%)",
3405
+ "--ring": "oklch(0.554 0.135 66.442)",
3406
+ "--chart-1": "oklch(0.488 0.243 264.376)",
3407
+ "--chart-2": "oklch(0.696 0.17 162.48)",
3408
+ "--chart-3": "oklch(0.769 0.188 70.08)",
3409
+ "--chart-4": "oklch(0.627 0.265 303.9)",
3410
+ "--chart-5": "oklch(0.645 0.246 16.439)",
3411
+ "--sidebar": "oklch(0.21 0.006 285.885)",
3412
+ "--sidebar-foreground": "oklch(0.985 0 0)",
3413
+ "--sidebar-primary": "oklch(0.795 0.184 86.047)",
3414
+ "--sidebar-primary-foreground": "oklch(0.421 0.095 57.708)",
3415
+ "--sidebar-accent": "oklch(0.274 0.006 286.033)",
3416
+ "--sidebar-accent-foreground": "oklch(0.985 0 0)",
3417
+ "--sidebar-border": "oklch(1 0 0 / 10%)",
3418
+ "--sidebar-ring": "oklch(0.554 0.135 66.442)",
3419
+ },
3420
+ },
3421
+ v3: {
3422
+ root: {
3423
+ "--background": "0 0% 100%",
3424
+ "--foreground": "20 14.3% 4.1%",
3425
+ "--card": "0 0% 100%",
3426
+ "--card-foreground": "20 14.3% 4.1%",
3427
+ "--popover": "0 0% 100%",
3428
+ "--popover-foreground": "20 14.3% 4.1%",
3429
+ "--primary": "47.9 95.8% 53.1%",
3430
+ "--primary-foreground": "26 83.3% 14.1%",
3431
+ "--secondary": "60 4.8% 95.9%",
3432
+ "--secondary-foreground": "24 9.8% 10%",
3433
+ "--muted": "60 4.8% 95.9%",
3434
+ "--muted-foreground": "25 5.3% 44.7%",
3435
+ "--accent": "60 4.8% 95.9%",
3436
+ "--accent-foreground": "24 9.8% 10%",
3437
+ "--destructive": "0 84.2% 60.2%",
3438
+ "--destructive-foreground": "60 9.1% 97.8%",
3439
+ "--border": "20 5.9% 90%",
3440
+ "--input": "20 5.9% 90%",
3441
+ "--ring": "20 14.3% 4.1%",
3442
+ "--radius": "0.5rem",
3443
+ "--chart-1": "12 76% 61%",
3444
+ "--chart-2": "173 58% 39%",
3445
+ "--chart-3": "197 37% 24%",
3446
+ "--chart-4": "43 74% 66%",
3447
+ "--chart-5": "27 87% 67%",
3448
+ "--sidebar": "221 39% 11%",
3449
+ "--sidebar-foreground": "0 0% 98%",
3450
+ "--sidebar-primary": "217.2 91.2% 59.8%",
3451
+ "--special": "227 21% 8%",
3452
+ "--special-muted-background": "240 10% 4%",
3453
+ "--special-border": "240 4% 16%",
3454
+ "--special-foreground": "240 5% 84%",
3455
+ "--special-muted-foreground": "240 4% 46%",
3456
+ },
3457
+ dark: {
3458
+ "--background": "20 14.3% 4.1%",
3459
+ "--foreground": "60 9.1% 97.8%",
3460
+ "--card": "20 14.3% 4.1%",
3461
+ "--card-foreground": "60 9.1% 97.8%",
3462
+ "--popover": "20 14.3% 4.1%",
3463
+ "--popover-foreground": "60 9.1% 97.8%",
3464
+ "--primary": "47.9 95.8% 53.1%",
3465
+ "--primary-foreground": "26 83.3% 14.1%",
3466
+ "--secondary": "12 6.5% 15.1%",
3467
+ "--secondary-foreground": "60 9.1% 97.8%",
3468
+ "--muted": "12 6.5% 15.1%",
3469
+ "--muted-foreground": "24 5.4% 63.9%",
3470
+ "--accent": "12 6.5% 15.1%",
3471
+ "--accent-foreground": "60 9.1% 97.8%",
3472
+ "--destructive": "0 62.8% 30.6%",
3473
+ "--destructive-foreground": "60 9.1% 97.8%",
3474
+ "--border": "12 6.5% 15.1%",
3475
+ "--input": "12 6.5% 15.1%",
3476
+ "--ring": "35.5 91.7% 32.9%",
3477
+ "--chart-1": "220 70% 50%",
3478
+ "--chart-2": "160 60% 45%",
3479
+ "--chart-3": "30 80% 55%",
3480
+ "--chart-4": "280 65% 60%",
3481
+ "--chart-5": "340 75% 55%",
3482
+ "--sidebar": "221 39% 11%",
3483
+ "--sidebar-foreground": "0 0% 98%",
3484
+ "--sidebar-primary": "217.2 91.2% 59.8%",
3485
+ "--special": "227 21% 8%",
3486
+ "--special-muted-background": "240 10% 4%",
3487
+ "--special-border": "240 4% 16%",
3488
+ "--special-foreground": "240 5% 84%",
3489
+ "--special-muted-foreground": "240 4% 46%",
3490
+ },
3491
+ },
3492
+ },
3493
+ violet: {
3494
+ v4: {
3495
+ root: {
3496
+ "--radius": "0.65rem",
3497
+ "--background": "oklch(1 0 0)",
3498
+ "--foreground": "oklch(0.141 0.005 285.823)",
3499
+ "--card": "oklch(1 0 0)",
3500
+ "--card-foreground": "oklch(0.141 0.005 285.823)",
3501
+ "--popover": "oklch(1 0 0)",
3502
+ "--popover-foreground": "oklch(0.141 0.005 285.823)",
3503
+ "--primary": "oklch(0.637 0.237 25.331)",
3504
+ "--primary-foreground": "oklch(0.971 0.013 17.38)",
3505
+ "--secondary": "oklch(0.967 0.001 286.375)",
3506
+ "--secondary-foreground": "oklch(0.21 0.006 285.885)",
3507
+ "--muted": "oklch(0.967 0.001 286.375)",
3508
+ "--muted-foreground": "oklch(0.552 0.016 285.938)",
3509
+ "--accent": "oklch(0.967 0.001 286.375)",
3510
+ "--accent-foreground": "oklch(0.21 0.006 285.885)",
3511
+ "--destructive": "oklch(0.577 0.245 27.325)",
3512
+ "--border": "oklch(0.92 0.004 286.32)",
3513
+ "--input": "oklch(0.92 0.004 286.32)",
3514
+ "--ring": "oklch(0.637 0.237 25.331)",
3515
+ "--chart-1": "oklch(0.646 0.222 41.116)",
3516
+ "--chart-2": "oklch(0.6 0.118 184.704)",
3517
+ "--chart-3": "oklch(0.398 0.07 227.392)",
3518
+ "--chart-4": "oklch(0.828 0.189 84.429)",
3519
+ "--chart-5": "oklch(0.769 0.188 70.08)",
3520
+ "--sidebar": "oklch(0.985 0 0)",
3521
+ "--sidebar-foreground": "oklch(0.141 0.005 285.823)",
3522
+ "--sidebar-primary": "oklch(0.637 0.237 25.331)",
3523
+ "--sidebar-primary-foreground": "oklch(0.971 0.013 17.38)",
3524
+ "--sidebar-accent": "oklch(0.967 0.001 286.375)",
3525
+ "--sidebar-accent-foreground": "oklch(0.21 0.006 285.885)",
3526
+ "--sidebar-border": "oklch(0.92 0.004 286.32)",
3527
+ "--sidebar-ring": "oklch(0.637 0.237 25.331)",
3528
+ },
3529
+ dark: {
3530
+ "--background": "oklch(0.141 0.005 285.823)",
3531
+ "--foreground": "oklch(0.985 0 0)",
3532
+ "--card": "oklch(0.21 0.006 285.885)",
3533
+ "--card-foreground": "oklch(0.985 0 0)",
3534
+ "--popover": "oklch(0.21 0.006 285.885)",
3535
+ "--popover-foreground": "oklch(0.985 0 0)",
3536
+ "--primary": "oklch(0.637 0.237 25.331)",
3537
+ "--primary-foreground": "oklch(0.971 0.013 17.38)",
3538
+ "--secondary": "oklch(0.274 0.006 286.033)",
3539
+ "--secondary-foreground": "oklch(0.985 0 0)",
3540
+ "--muted": "oklch(0.274 0.006 286.033)",
3541
+ "--muted-foreground": "oklch(0.705 0.015 286.067)",
3542
+ "--accent": "oklch(0.274 0.006 286.033)",
3543
+ "--accent-foreground": "oklch(0.985 0 0)",
3544
+ "--destructive": "oklch(0.704 0.191 22.216)",
3545
+ "--border": "oklch(1 0 0 / 10%)",
3546
+ "--input": "oklch(1 0 0 / 15%)",
3547
+ "--ring": "oklch(0.637 0.237 25.331)",
3548
+ "--chart-1": "oklch(0.488 0.243 264.376)",
3549
+ "--chart-2": "oklch(0.696 0.17 162.48)",
3550
+ "--chart-3": "oklch(0.769 0.188 70.08)",
3551
+ "--chart-4": "oklch(0.627 0.265 303.9)",
3552
+ "--chart-5": "oklch(0.645 0.246 16.439)",
3553
+ "--sidebar": "oklch(0.21 0.006 285.885)",
3554
+ "--sidebar-foreground": "oklch(0.985 0 0)",
3555
+ "--sidebar-primary": "oklch(0.637 0.237 25.331)",
3556
+ "--sidebar-primary-foreground": "oklch(0.971 0.013 17.38)",
3557
+ "--sidebar-accent": "oklch(0.274 0.006 286.033)",
3558
+ "--sidebar-accent-foreground": "oklch(0.985 0 0)",
3559
+ "--sidebar-border": "oklch(1 0 0 / 10%)",
3560
+ "--sidebar-ring": "oklch(0.637 0.237 25.331)",
3561
+ },
3562
+ },
3563
+ v3: {
3564
+ root: {
3565
+ "--background": "0 0% 100%",
3566
+ "--foreground": "224 71.4% 4.1%",
3567
+ "--card": "0 0% 100%",
3568
+ "--card-foreground": "224 71.4% 4.1%",
3569
+ "--popover": "0 0% 100%",
3570
+ "--popover-foreground": "224 71.4% 4.1%",
3571
+ "--primary": "262.1 83.3% 57.8%",
3572
+ "--primary-foreground": "210 20% 98%",
3573
+ "--secondary": "220 14.3% 95.9%",
3574
+ "--secondary-foreground": "220.9 39.3% 11%",
3575
+ "--muted": "220 14.3% 95.9%",
3576
+ "--muted-foreground": "220 8.9% 46.1%",
3577
+ "--accent": "220 14.3% 95.9%",
3578
+ "--accent-foreground": "220.9 39.3% 11%",
3579
+ "--destructive": "0 84.2% 60.2%",
3580
+ "--destructive-foreground": "210 20% 98%",
3581
+ "--border": "220 13% 91%",
3582
+ "--input": "220 13% 91%",
3583
+ "--ring": "262.1 83.3% 57.8%",
3584
+ "--radius": "0.5rem",
3585
+ "--chart-1": "12 76% 61%",
3586
+ "--chart-2": "173 58% 39%",
3587
+ "--chart-3": "197 37% 24%",
3588
+ "--chart-4": "43 74% 66%",
3589
+ "--chart-5": "27 87% 67%",
3590
+ "--sidebar": "221 39% 11%",
3591
+ "--sidebar-foreground": "0 0% 98%",
3592
+ "--sidebar-primary": "217.2 91.2% 59.8%",
3593
+ "--special": "227 21% 8%",
3594
+ "--special-muted-background": "240 10% 4%",
3595
+ "--special-border": "240 4% 16%",
3596
+ "--special-foreground": "240 5% 84%",
3597
+ "--special-muted-foreground": "240 4% 46%",
3598
+ },
3599
+ dark: {
3600
+ "--background": "224 71.4% 4.1%",
3601
+ "--foreground": "210 20% 98%",
3602
+ "--card": "224 71.4% 4.1%",
3603
+ "--card-foreground": "210 20% 98%",
3604
+ "--popover": "224 71.4% 4.1%",
3605
+ "--popover-foreground": "210 20% 98%",
3606
+ "--primary": "263.4 70% 50.4%",
3607
+ "--primary-foreground": "210 20% 98%",
3608
+ "--secondary": "215 27.9% 16.9%",
3609
+ "--secondary-foreground": "210 20% 98%",
3610
+ "--muted": "215 27.9% 16.9%",
3611
+ "--muted-foreground": "217.9 10.6% 64.9%",
3612
+ "--accent": "215 27.9% 16.9%",
3613
+ "--accent-foreground": "210 20% 98%",
3614
+ "--destructive": "0 62.8% 30.6%",
3615
+ "--destructive-foreground": "210 20% 98%",
3616
+ "--border": "215 27.9% 16.9%",
3617
+ "--input": "215 27.9% 16.9%",
3618
+ "--ring": "263.4 70% 50.4%",
3619
+ "--chart-1": "220 70% 50%",
3620
+ "--chart-2": "160 60% 45%",
3621
+ "--chart-3": "30 80% 55%",
3622
+ "--chart-4": "280 65% 60%",
3623
+ "--chart-5": "340 75% 55%",
3624
+ "--sidebar": "221 39% 11%",
3625
+ "--sidebar-foreground": "0 0% 98%",
3626
+ "--sidebar-primary": "217.2 91.2% 59.8%",
3627
+ "--special": "227 21% 8%",
3628
+ "--special-muted-background": "240 10% 4%",
3629
+ "--special-border": "240 4% 16%",
3630
+ "--special-foreground": "240 5% 84%",
3631
+ "--special-muted-foreground": "240 4% 46%",
3632
+ },
3633
+ },
3634
+ },
3635
+ };
3636
+ const DSA = forwardRef<
3637
+ React.ElementRef<typeof AvatarPrimitive.Root>,
3638
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
3639
+ >(({ className, ...props }, ref) => (
3640
+ <AvatarPrimitive.Root
3641
+ ref={ref}
3642
+ className={cn(
3643
+ 'relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full',
3644
+ className
3645
+ )}
3646
+ {...props}
3647
+ />
3648
+ ))
3649
+ DSA.displayName = AvatarPrimitive.Root.displayName
3650
+
3651
+ const DSAImage = forwardRef<
3652
+ React.ElementRef<typeof AvatarPrimitive.Image>,
3653
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
3654
+ >(({ className, ...props }, ref) => (
3655
+ <AvatarPrimitive.Image
3656
+ ref={ref}
3657
+ className={cn('aspect-square h-full w-full', className)}
3658
+ {...props}
3659
+ />
3660
+ ))
3661
+ DSAImage.displayName = AvatarPrimitive.Image.displayName
3662
+
3663
+ const DSAFallback = forwardRef<
3664
+ React.ElementRef<typeof AvatarPrimitive.Fallback>,
3665
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
3666
+ >(({ className, ...props }, ref) => (
3667
+ <AvatarPrimitive.Fallback
3668
+ ref={ref}
3669
+ className={cn(
3670
+ 'flex h-full w-full items-center justify-center rounded-full bg-muted',
3671
+ className
3672
+ )}
3673
+ {...props}
3674
+ />
3675
+ ))
3676
+ DSAFallback.displayName = AvatarPrimitive.Fallback.displayName
3677
+
3678
+ function DSDM({
3679
+ ...props
3680
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
3681
+ return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />
3682
+ }
3683
+
3684
+ function DSDMPortal({
3685
+ ...props
3686
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
3687
+ return (
3688
+ <DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
3689
+ )
3690
+ }
3691
+
3692
+ function DSDMTrigger({
3693
+ ...props
3694
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
3695
+ return (
3696
+ <DropdownMenuPrimitive.Trigger
3697
+ data-slot="dropdown-menu-trigger"
3698
+ {...props}
3699
+ />
3700
+ )
3701
+ }
3702
+
3703
+ function DSDMContent({
3704
+ className,
3705
+ sideOffset = 4,
3706
+ ...props
3707
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
3708
+ return (
3709
+ <DropdownMenuPrimitive.Portal>
3710
+ <DropdownMenuPrimitive.Content
3711
+ data-slot="dropdown-menu-content"
3712
+ sideOffset={sideOffset}
3713
+ className={cn(
3714
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
3715
+ className
3716
+ )}
3717
+ {...props}
3718
+ />
3719
+ </DropdownMenuPrimitive.Portal>
3720
+ )
3721
+ }
3722
+
3723
+ function DSDMGroup({
3724
+ ...props
3725
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
3726
+ return (
3727
+ <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
3728
+ )
3729
+ }
3730
+
3731
+ function DSDMItem({
3732
+ className,
3733
+ inset,
3734
+ variant = "default",
3735
+ ...props
3736
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
3737
+ inset?: boolean
3738
+ variant?: "default" | "destructive"
3739
+ }) {
3740
+
3741
+ return (
3742
+ <DropdownMenuPrimitive.Item
3743
+ data-slot="dropdown-menu-item"
3744
+ data-inset={inset}
3745
+ data-variant={variant}
3746
+ className={cn(
3747
+ "focus:bg-accent focus:text-accent-foreground cursor-pointer data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
3748
+ className
3749
+ )}
3750
+ {...props}
3751
+ />
3752
+ )
3753
+ }
3754
+
3755
+ function DSDMAnchor({
3756
+ className,
3757
+ children,
3758
+ to,
3759
+ variant = "default",
3760
+ newTab = true,
3761
+ ...props
3762
+ }: {
3763
+ className?: string
3764
+ children: React.ReactNode
3765
+ to: string
3766
+ newTab?: boolean
3767
+ }) {
3768
+ const anchorProps = newTab ? {
3769
+ target: "_blank",
3770
+ rel: "noopener noreferrer"
3771
+ } : {};
3772
+ return (
3773
+ <a
3774
+ href={to}
3775
+ {...anchorProps}
3776
+ className={cn(className)}
3777
+ {...props}
3778
+ >
3779
+ <DSDMItem variant={variant}>
3780
+ <span className="flex-1 truncate">{children}</span>
3781
+ </DSDMItem>
3782
+ </a>
3783
+ );
3784
+ }
3785
+
3786
+ function DSDMCheckboxItem({
3787
+ className,
3788
+ children,
3789
+ checked,
3790
+ ...props
3791
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
3792
+ return (
3793
+ <DropdownMenuPrimitive.CheckboxItem
3794
+ data-slot="dropdown-menu-checkbox-item"
3795
+ className={cn(
3796
+ "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
3797
+ className
3798
+ )}
3799
+ checked={checked}
3800
+ {...props}
3801
+ >
3802
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
3803
+ <DropdownMenuPrimitive.ItemIndicator>
3804
+ <Check className="size-4" />
3805
+ </DropdownMenuPrimitive.ItemIndicator>
3806
+ </span>
3807
+ {children}
3808
+ </DropdownMenuPrimitive.CheckboxItem>
3809
+ )
3810
+ }
3811
+
3812
+ function DSDMRadioGroup({
3813
+ ...props
3814
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
3815
+ return (
3816
+ <DropdownMenuPrimitive.RadioGroup
3817
+ data-slot="dropdown-menu-radio-group"
3818
+ {...props}
3819
+ />
3820
+ )
3821
+ }
3822
+
3823
+ function DSDMRadioItem({
3824
+ className,
3825
+ children,
3826
+ ...props
3827
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
3828
+ return (
3829
+ <DropdownMenuPrimitive.RadioItem
3830
+ data-slot="dropdown-menu-radio-item"
3831
+ className={cn(
3832
+ "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
3833
+ className
3834
+ )}
3835
+ {...props}
3836
+ >
3837
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
3838
+ <DropdownMenuPrimitive.ItemIndicator>
3839
+ <Circle className="size-2 fill-current" />
3840
+ </DropdownMenuPrimitive.ItemIndicator>
3841
+ </span>
3842
+ {children}
3843
+ </DropdownMenuPrimitive.RadioItem>
3844
+ )
3845
+ }
3846
+
3847
+ function DSDMLabel({
3848
+ className,
3849
+ inset,
3850
+ ...props
3851
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
3852
+ inset?: boolean
3853
+ }) {
3854
+ return (
3855
+ <DropdownMenuPrimitive.Label
3856
+ data-slot="dropdown-menu-label"
3857
+ data-inset={inset}
3858
+ className={cn(
3859
+ "px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
3860
+ className
3861
+ )}
3862
+ {...props}
3863
+ />
3864
+ )
3865
+ }
3866
+
3867
+ function DSDMSeparator({
3868
+ className,
3869
+ ...props
3870
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
3871
+ return (
3872
+ <DropdownMenuPrimitive.Separator
3873
+ data-slot="dropdown-menu-separator"
3874
+ className={cn("bg-border -mx-1 my-1 h-px", className)}
3875
+ {...props}
3876
+ />
3877
+ )
3878
+ }
3879
+
3880
+ function DSDMShortcut({
3881
+ className,
3882
+ ...props
3883
+ }: React.ComponentProps<"span">) {
3884
+ return (
3885
+ <span
3886
+ data-slot="dropdown-menu-shortcut"
3887
+ className={cn(
3888
+ "text-muted-foreground ml-auto text-xs tracking-widest",
3889
+ className
3890
+ )}
3891
+ {...props}
3892
+ />
3893
+ )
3894
+ }
3895
+
3896
+ function DSDMSub({
3897
+ ...props
3898
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
3899
+ return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />
3900
+ }
3901
+
3902
+ function DSDMSubTrigger({
3903
+ className,
3904
+ inset,
3905
+ children,
3906
+ ...props
3907
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
3908
+ inset?: boolean
3909
+ }) {
3910
+ return (
3911
+ <DropdownMenuPrimitive.SubTrigger
3912
+ data-slot="dropdown-menu-sub-trigger"
3913
+ data-inset={inset}
3914
+ className={cn(
3915
+ "focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8",
3916
+ className
3917
+ )}
3918
+ {...props}
3919
+ >
3920
+ {children}
3921
+ <ChevronRight className="ml-auto size-4" />
3922
+ </DropdownMenuPrimitive.SubTrigger>
3923
+ )
3924
+ }
3925
+
3926
+ function DSDMSubContent({
3927
+ className,
3928
+ ...props
3929
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
3930
+ return (
3931
+ <DropdownMenuPrimitive.SubContent
3932
+ data-slot="dropdown-menu-sub-content"
3933
+ className={cn(
3934
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
3935
+ className
3936
+ )}
3937
+ {...props}
3938
+ />
3939
+ )
3940
+ }
3941
+ const DSC = CollapsiblePrimitive.Root;
3942
+ const DSCTrigger = CollapsiblePrimitive.CollapsibleTrigger;
3943
+
3944
+ interface CollapsibleContentProps
3945
+ extends React.ComponentPropsWithoutRef<typeof CollapsiblePrimitive.CollapsibleContent> { }
3946
+
3947
+ const DSCContent = forwardRef<
3948
+ React.ElementRef<typeof CollapsiblePrimitive.CollapsibleContent>,
3949
+ CollapsibleContentProps
3950
+ >(({ className, ...props }, ref) => {
3951
+ return (
3952
+ <CollapsiblePrimitive.CollapsibleContent
3953
+ ref={ref}
3954
+ className={cn(
3955
+ "text-border",
3956
+ className
3957
+ )}
3958
+ {...props}
3959
+ />
3960
+ );
3961
+ });
3962
+ DSCContent.displayName = "DSCContent";
3963
+ const data = {
3964
+ nav: [
3965
+ { name: "Notifications", icon: Bell },
3966
+ { name: "Navigation", icon: Menu },
3967
+ { name: "Home", icon: Home },
3968
+ { name: "Appearance", icon: Paintbrush },
3969
+ { name: "Messages & media", icon: MessageCircle },
3970
+ { name: "Language & region", icon: Globe },
3971
+ { name: "Accessibility", icon: Keyboard },
3972
+ { name: "Mark as read", icon: Check },
3973
+ { name: "Audio & video", icon: Video },
3974
+ { name: "Connected accounts", icon: Link },
3975
+ { name: "Privacy & visibility", icon: Lock },
3976
+ { name: "Advanced", icon: Settings },
3977
+ ],
3978
+ }
3979
+ export function DialogSidebar() {
3980
+ const [open, setOpen] = useState(false)
3981
+
3982
+ return (
3983
+ <Dialog open={open} onOpenChange={setOpen}>
3984
+ <DialogTrigger asChild>
3985
+ <DSMenuButton className="px-2.5 md:px-2"><Bot /></DSMenuButton>
3986
+ </DialogTrigger>
3987
+ <DialogContent className="overflow-hidden p-0 md:max-h-[500px] md:max-w-[700px] lg:max-w-[800px]">
3988
+ <DialogTitle className="sr-only">Settings</DialogTitle>
3989
+ <DialogDescription className="sr-only">
3990
+ Customize your settings here.
3991
+ </DialogDescription>
3992
+ <SidebarProvider className="items-start">
3993
+ <Sidebar collapsible="none" className="hidden md:flex">
3994
+ <SidebarContent>
3995
+ <SidebarGroup>
3996
+ <SidebarGroupContent>
3997
+ <SidebarMenu>
3998
+ {data.nav.map((item) => (
3999
+ <SidebarMenuItem key={item.name}>
4000
+ <SidebarMenuButton
4001
+ asChild
4002
+ isActive={item.name === "Messages & media"}
4003
+ >
4004
+ <a href="#">
4005
+ <item.icon />
4006
+ <span>{item.name}</span>
4007
+ </a>
4008
+ </SidebarMenuButton>
4009
+ </SidebarMenuItem>
4010
+ ))}
4011
+ </SidebarMenu>
4012
+ </SidebarGroupContent>
4013
+ </SidebarGroup>
4014
+ </SidebarContent>
4015
+ </Sidebar>
4016
+ <main className="flex h-[480px] flex-1 flex-col overflow-hidden">
4017
+ <header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12">
4018
+ <div className="flex items-center gap-2 px-4">
4019
+ <Breadcrumb>
4020
+ <BreadcrumbList>
4021
+ <BreadcrumbItem className="hidden md:block">
4022
+ <BreadcrumbLink href="#">Settings</BreadcrumbLink>
4023
+ </BreadcrumbItem>
4024
+ <BreadcrumbSeparator className="hidden md:block" />
4025
+ <BreadcrumbItem>
4026
+ <BreadcrumbPage>Messages & media</BreadcrumbPage>
4027
+ </BreadcrumbItem>
4028
+ </BreadcrumbList>
4029
+ </Breadcrumb>
4030
+ </div>
4031
+ </header>
4032
+ <div className="flex flex-1 flex-col gap-4 overflow-y-auto p-4 pt-0">
4033
+ {Array.from({ length: 10 }).map((_, i) => (
4034
+ <div
4035
+ key={i}
4036
+ className="bg-muted/50 aspect-video max-w-3xl rounded-xl"
4037
+ />
4038
+ ))}
4039
+ </div>
4040
+ </main>
4041
+ </SidebarProvider>
4042
+ </DialogContent>
4043
+ </Dialog>
4044
+ )
4045
+ }
4046
+
4047
+ export {
4048
+ // DS stands for DualSidebar
4049
+ // use sidebar
4050
+ useDS,
4051
+ // sidebar rails
4052
+ DSLeftRail,
4053
+ DSRightRail,
4054
+ // sidebar layouts
4055
+ DSHeader,
4056
+ DSContent,
4057
+ DSFooter,
4058
+ // sidebar avatar
4059
+ DSA,
4060
+ DSAImage,
4061
+ DSAFallback,
4062
+ // sidebar menu items
4063
+ DSGroup,
4064
+ DSGroupAction,
4065
+ DSGroupContent,
4066
+ DSGroupLabel,
4067
+ DSInput,
4068
+ DSMenu,
4069
+ DSMenuAction,
4070
+ DSMenuBadge,
4071
+ DSMenuButton,
4072
+ DSMenuItem,
4073
+ DSMenuSkeleton,
4074
+ DSMenuSub,
4075
+ DSMenuSubButton,
4076
+ DSMenuSubItem,
4077
+ DSSeparator,
4078
+ // optimistic ui nav links and loading ui
4079
+ DSMenuAnchor,
4080
+ DSMenuLink,
4081
+ DSLoading,
4082
+ // theme selector
4083
+ useDSTheme,
4084
+ DSThemeSelector,
4085
+ type DSTheme,
4086
+ DSThemeProvider,
4087
+ // sidebar provider
4088
+ DSProvider,
4089
+ // sidebar inset
4090
+ DSInset,
4091
+ // left trigger
4092
+ DSTrigger,
4093
+ // left sidebar
4094
+ DSLeft,
4095
+ DSLeftIcon,
4096
+ // right sidebar
4097
+ DSRight,
4098
+ DSRightIcon,
4099
+ // DSD stands for DualSidebarDrawer
4100
+ DSD,
4101
+ DSDTrigger,
4102
+ DSDPortal,
4103
+ DSDClose,
4104
+ DSDOverlay,
4105
+ DSDContent,
4106
+ DSDHeader,
4107
+ DSDFooter,
4108
+ DSDTitle,
4109
+ DSDDescription,
4110
+ // DSDM
4111
+ DSDM,
4112
+ DSDMPortal,
4113
+ DSDMTrigger,
4114
+ DSDMContent,
4115
+ DSDMGroup,
4116
+ DSDMLabel,
4117
+ DSDMItem,
4118
+ DSDMCheckboxItem,
4119
+ DSDMRadioGroup,
4120
+ DSDMRadioItem,
4121
+ DSDMSeparator,
4122
+ DSDMShortcut,
4123
+ DSDMSub,
4124
+ DSDMSubTrigger,
4125
+ DSDMSubContent,
4126
+ DSDMAnchor,
4127
+ // Collapsible
4128
+ DSC,
4129
+ DSCTrigger,
4130
+ DSCContent,
4131
+ DS_COOKIE_NAME,
4132
+ DS_COOKIE_NAME_RIGHT,
4133
+ DS_COOKIE_MAX_AGE,
4134
+ DS_WIDTH,
4135
+ DS_WIDTH_MOBILE,
4136
+ DS_WIDTH_ICON,
4137
+ DS_KEYBOARD_SHORTCUT_LEFT,
4138
+ DS_KEYBOARD_SHORTCUT_RIGHT,
4139
+ THEME_VERSION,
4140
+ THEME_OPTIONS,
4141
+ LOCAL_DS_STORAGE_KEY,
4142
+ };