@opencosmos/ui 1.3.1

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 (260) hide show
  1. package/.claude/CLAUDE.md +239 -0
  2. package/README.md +161 -0
  3. package/dist/cli.mjs +151 -0
  4. package/dist/dates.d.mts +20 -0
  5. package/dist/dates.d.ts +20 -0
  6. package/dist/dates.js +240 -0
  7. package/dist/dates.js.map +1 -0
  8. package/dist/dates.mjs +203 -0
  9. package/dist/dates.mjs.map +1 -0
  10. package/dist/dnd.d.mts +126 -0
  11. package/dist/dnd.d.ts +126 -0
  12. package/dist/dnd.js +274 -0
  13. package/dist/dnd.js.map +1 -0
  14. package/dist/dnd.mjs +250 -0
  15. package/dist/dnd.mjs.map +1 -0
  16. package/dist/fontThemes-Dh8mtXES.d.mts +868 -0
  17. package/dist/fontThemes-Dh8mtXES.d.ts +868 -0
  18. package/dist/forms.d.mts +38 -0
  19. package/dist/forms.d.ts +38 -0
  20. package/dist/forms.js +198 -0
  21. package/dist/forms.js.map +1 -0
  22. package/dist/forms.mjs +159 -0
  23. package/dist/forms.mjs.map +1 -0
  24. package/dist/hooks-1b8WaQf1.d.mts +225 -0
  25. package/dist/hooks-CKW8vE9H.d.ts +225 -0
  26. package/dist/hooks.d.mts +3 -0
  27. package/dist/hooks.d.ts +3 -0
  28. package/dist/hooks.js +971 -0
  29. package/dist/hooks.js.map +1 -0
  30. package/dist/hooks.mjs +943 -0
  31. package/dist/hooks.mjs.map +1 -0
  32. package/dist/index-DscTIrZ2.d.mts +29 -0
  33. package/dist/index-DscTIrZ2.d.ts +29 -0
  34. package/dist/index.d.mts +3382 -0
  35. package/dist/index.d.ts +3382 -0
  36. package/dist/index.js +15146 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/index.mjs +14802 -0
  39. package/dist/index.mjs.map +1 -0
  40. package/dist/providers-CXPDMsl7.d.mts +30 -0
  41. package/dist/providers-Dn_Msjvz.d.ts +30 -0
  42. package/dist/providers.d.mts +3 -0
  43. package/dist/providers.d.ts +3 -0
  44. package/dist/providers.js +1885 -0
  45. package/dist/providers.js.map +1 -0
  46. package/dist/providers.mjs +1859 -0
  47. package/dist/providers.mjs.map +1 -0
  48. package/dist/tables.d.mts +10 -0
  49. package/dist/tables.d.ts +10 -0
  50. package/dist/tables.js +248 -0
  51. package/dist/tables.js.map +1 -0
  52. package/dist/tables.mjs +218 -0
  53. package/dist/tables.mjs.map +1 -0
  54. package/dist/tokens.d.mts +1065 -0
  55. package/dist/tokens.d.ts +1065 -0
  56. package/dist/tokens.js +2637 -0
  57. package/dist/tokens.js.map +1 -0
  58. package/dist/tokens.mjs +2555 -0
  59. package/dist/tokens.mjs.map +1 -0
  60. package/dist/utils-CIIM7dAC.d.ts +986 -0
  61. package/dist/utils-Cs04sxth.d.mts +986 -0
  62. package/dist/utils.d.mts +4 -0
  63. package/dist/utils.d.ts +4 -0
  64. package/dist/utils.js +874 -0
  65. package/dist/utils.js.map +1 -0
  66. package/dist/utils.mjs +806 -0
  67. package/dist/utils.mjs.map +1 -0
  68. package/dist/validation-Bj1ye-v_.d.mts +114 -0
  69. package/dist/validation-Bj1ye-v_.d.ts +114 -0
  70. package/dist/webgl.d.mts +104 -0
  71. package/dist/webgl.d.ts +104 -0
  72. package/dist/webgl.js +226 -0
  73. package/dist/webgl.js.map +1 -0
  74. package/dist/webgl.mjs +195 -0
  75. package/dist/webgl.mjs.map +1 -0
  76. package/package.json +267 -0
  77. package/src/cli.ts +206 -0
  78. package/src/component-registry.ts +183 -0
  79. package/src/components/actions/Button.test.tsx +61 -0
  80. package/src/components/actions/Button.tsx +70 -0
  81. package/src/components/actions/Link.tsx +78 -0
  82. package/src/components/actions/Magnetic.tsx +68 -0
  83. package/src/components/actions/Toggle.test.tsx +40 -0
  84. package/src/components/actions/Toggle.tsx +47 -0
  85. package/src/components/actions/ToggleGroup.tsx +70 -0
  86. package/src/components/actions/index.ts +5 -0
  87. package/src/components/backgrounds/FaultyTerminal.tsx +426 -0
  88. package/src/components/backgrounds/OrbBackground.tsx +424 -0
  89. package/src/components/backgrounds/WarpBackground.tsx +358 -0
  90. package/src/components/backgrounds/index.ts +3 -0
  91. package/src/components/blocks/Hero.tsx +142 -0
  92. package/src/components/blocks/social/OpenGraphCard.tsx +243 -0
  93. package/src/components/cursor/SplashCursor.tsx +1315 -0
  94. package/src/components/cursor/TargetCursor.tsx +187 -0
  95. package/src/components/cursor/index.ts +2 -0
  96. package/src/components/data-display/AspectImage.tsx +73 -0
  97. package/src/components/data-display/Avatar.test.tsx +35 -0
  98. package/src/components/data-display/Avatar.tsx +55 -0
  99. package/src/components/data-display/Badge.test.tsx +43 -0
  100. package/src/components/data-display/Badge.tsx +84 -0
  101. package/src/components/data-display/Brand.tsx +123 -0
  102. package/src/components/data-display/Calendar.tsx +70 -0
  103. package/src/components/data-display/Card.test.tsx +92 -0
  104. package/src/components/data-display/Card.tsx +115 -0
  105. package/src/components/data-display/Code.tsx +210 -0
  106. package/src/components/data-display/CollapsibleCodeBlock.tsx +238 -0
  107. package/src/components/data-display/DataTable.tsx +119 -0
  108. package/src/components/data-display/DescriptionList.tsx +41 -0
  109. package/src/components/data-display/GitHubIcon.tsx +44 -0
  110. package/src/components/data-display/Heading.test.tsx +36 -0
  111. package/src/components/data-display/Heading.tsx +83 -0
  112. package/src/components/data-display/StatCard.tsx +195 -0
  113. package/src/components/data-display/Table.tsx +133 -0
  114. package/src/components/data-display/Text.test.tsx +48 -0
  115. package/src/components/data-display/Text.tsx +144 -0
  116. package/src/components/data-display/Timeline.tsx +194 -0
  117. package/src/components/data-display/TreeView.tsx +226 -0
  118. package/src/components/data-display/Typewriter.tsx +119 -0
  119. package/src/components/data-display/VariableWeightText.tsx +130 -0
  120. package/src/components/data-display/index.ts +19 -0
  121. package/src/components/feedback/Alert.test.tsx +44 -0
  122. package/src/components/feedback/Alert.tsx +65 -0
  123. package/src/components/feedback/EmptyState.tsx +113 -0
  124. package/src/components/feedback/Progress.test.tsx +60 -0
  125. package/src/components/feedback/Progress.tsx +30 -0
  126. package/src/components/feedback/ProgressBar.tsx +158 -0
  127. package/src/components/feedback/Skeleton.test.tsx +39 -0
  128. package/src/components/feedback/Skeleton.tsx +45 -0
  129. package/src/components/feedback/Sonner.tsx +28 -0
  130. package/src/components/feedback/Spinner.test.tsx +33 -0
  131. package/src/components/feedback/Spinner.tsx +99 -0
  132. package/src/components/feedback/Stepper.tsx +307 -0
  133. package/src/components/feedback/Toast/Toast.tsx +243 -0
  134. package/src/components/feedback/Toast/index.ts +2 -0
  135. package/src/components/feedback/index.ts +9 -0
  136. package/src/components/forms/Checkbox.test.tsx +40 -0
  137. package/src/components/forms/Checkbox.tsx +31 -0
  138. package/src/components/forms/ColorPicker.tsx +118 -0
  139. package/src/components/forms/Combobox.tsx +96 -0
  140. package/src/components/forms/DragDrop.tsx +440 -0
  141. package/src/components/forms/FileUpload.tsx +252 -0
  142. package/src/components/forms/FilterButton.tsx +65 -0
  143. package/src/components/forms/Form.tsx +197 -0
  144. package/src/components/forms/Input.test.tsx +46 -0
  145. package/src/components/forms/Input.tsx +43 -0
  146. package/src/components/forms/InputOTP.tsx +81 -0
  147. package/src/components/forms/Label.test.tsx +20 -0
  148. package/src/components/forms/Label.tsx +25 -0
  149. package/src/components/forms/RadioGroup.tsx +51 -0
  150. package/src/components/forms/SearchBar.tsx +215 -0
  151. package/src/components/forms/Select.test.tsx +118 -0
  152. package/src/components/forms/Select.tsx +274 -0
  153. package/src/components/forms/Slider.tsx +29 -0
  154. package/src/components/forms/Switch.test.tsx +76 -0
  155. package/src/components/forms/Switch.tsx +30 -0
  156. package/src/components/forms/TextField.tsx +152 -0
  157. package/src/components/forms/Textarea.test.tsx +41 -0
  158. package/src/components/forms/Textarea.tsx +29 -0
  159. package/src/components/forms/ThemeSwitcher.tsx +290 -0
  160. package/src/components/forms/ThemeToggle.tsx +151 -0
  161. package/src/components/forms/index.ts +19 -0
  162. package/src/components/layout/Accordion.test.tsx +66 -0
  163. package/src/components/layout/Accordion.tsx +64 -0
  164. package/src/components/layout/AspectRatio.tsx +7 -0
  165. package/src/components/layout/Carousel.tsx +277 -0
  166. package/src/components/layout/Collapsible.test.tsx +40 -0
  167. package/src/components/layout/Collapsible.tsx +31 -0
  168. package/src/components/layout/Container.test.tsx +45 -0
  169. package/src/components/layout/Container.tsx +99 -0
  170. package/src/components/layout/CustomizerPanel.tsx +400 -0
  171. package/src/components/layout/DatePicker.tsx +57 -0
  172. package/src/components/layout/Footer/Footer.tsx +175 -0
  173. package/src/components/layout/Footer/index.ts +2 -0
  174. package/src/components/layout/GlassSurface.tsx +82 -0
  175. package/src/components/layout/Grid.test.tsx +31 -0
  176. package/src/components/layout/Grid.tsx +130 -0
  177. package/src/components/layout/Header/Header.tsx +450 -0
  178. package/src/components/layout/Header/index.ts +2 -0
  179. package/src/components/layout/PageLayout.tsx +180 -0
  180. package/src/components/layout/PageTemplate.tsx +158 -0
  181. package/src/components/layout/Resizable.tsx +48 -0
  182. package/src/components/layout/ScrollArea.tsx +53 -0
  183. package/src/components/layout/Separator.test.tsx +28 -0
  184. package/src/components/layout/Separator.tsx +29 -0
  185. package/src/components/layout/Sidebar.tsx +171 -0
  186. package/src/components/layout/Stack.test.tsx +41 -0
  187. package/src/components/layout/Stack.tsx +89 -0
  188. package/src/components/layout/glass-surface.css +60 -0
  189. package/src/components/layout/index.ts +18 -0
  190. package/src/components/motion/AnimatedBeam.tsx +159 -0
  191. package/src/components/navigation/Breadcrumb.test.tsx +57 -0
  192. package/src/components/navigation/Breadcrumb.tsx +119 -0
  193. package/src/components/navigation/Breadcrumbs.tsx +221 -0
  194. package/src/components/navigation/Command.tsx +159 -0
  195. package/src/components/navigation/Menubar.tsx +115 -0
  196. package/src/components/navigation/NavLink.tsx +55 -0
  197. package/src/components/navigation/NavigationMenu.tsx +125 -0
  198. package/src/components/navigation/Pagination.tsx +121 -0
  199. package/src/components/navigation/SecondaryNav.tsx +100 -0
  200. package/src/components/navigation/Tabs.test.tsx +47 -0
  201. package/src/components/navigation/Tabs.tsx +60 -0
  202. package/src/components/navigation/TertiaryNav.tsx +90 -0
  203. package/src/components/navigation/index.ts +10 -0
  204. package/src/components/overlays/AlertDialog.test.tsx +69 -0
  205. package/src/components/overlays/AlertDialog.tsx +166 -0
  206. package/src/components/overlays/ContextMenu.tsx +243 -0
  207. package/src/components/overlays/Dialog.test.tsx +79 -0
  208. package/src/components/overlays/Dialog.tsx +158 -0
  209. package/src/components/overlays/Drawer.tsx +128 -0
  210. package/src/components/overlays/Dropdown.tsx +253 -0
  211. package/src/components/overlays/DropdownMenu.tsx +242 -0
  212. package/src/components/overlays/HoverCard.tsx +32 -0
  213. package/src/components/overlays/Modal.tsx +250 -0
  214. package/src/components/overlays/NotificationCenter.tsx +364 -0
  215. package/src/components/overlays/Popover.test.tsx +40 -0
  216. package/src/components/overlays/Popover.tsx +46 -0
  217. package/src/components/overlays/Sheet.tsx +163 -0
  218. package/src/components/overlays/Tooltip.test.tsx +33 -0
  219. package/src/components/overlays/Tooltip.tsx +32 -0
  220. package/src/components/overlays/index.ts +12 -0
  221. package/src/dates.ts +2 -0
  222. package/src/dnd.ts +1 -0
  223. package/src/forms.ts +1 -0
  224. package/src/globals.css +187 -0
  225. package/src/hooks/index.ts +6 -0
  226. package/src/hooks/useForm.ts +247 -0
  227. package/src/hooks/useMotionPreference.test.ts +102 -0
  228. package/src/hooks/useMotionPreference.ts +78 -0
  229. package/src/hooks/useTheme.ts +58 -0
  230. package/src/hooks.ts +9 -0
  231. package/src/index.ts +168 -0
  232. package/src/lib/animations.ts +356 -0
  233. package/src/lib/breadcrumbs.ts +94 -0
  234. package/src/lib/colors.ts +493 -0
  235. package/src/lib/store/customizer.ts +482 -0
  236. package/src/lib/store/index.ts +3 -0
  237. package/src/lib/store/theme.ts +55 -0
  238. package/src/lib/syntax-parser/index.ts +50 -0
  239. package/src/lib/syntax-parser/patterns.ts +64 -0
  240. package/src/lib/syntax-parser/tokenizer.ts +117 -0
  241. package/src/lib/syntax-parser/types.ts +27 -0
  242. package/src/lib/utils.ts +6 -0
  243. package/src/lib/validation.ts +204 -0
  244. package/src/lib/webgl/Color.ts +11 -0
  245. package/src/lib/webgl/Mesh.ts +41 -0
  246. package/src/lib/webgl/Program.ts +118 -0
  247. package/src/lib/webgl/Renderer.ts +51 -0
  248. package/src/lib/webgl/Triangle.ts +27 -0
  249. package/src/lib/webgl/Vec3.ts +18 -0
  250. package/src/lib/webgl/index.ts +13 -0
  251. package/src/nativewind-env.d.ts +1 -0
  252. package/src/providers/ThemeProvider.tsx +461 -0
  253. package/src/providers/index.ts +1 -0
  254. package/src/providers.ts +7 -0
  255. package/src/tables.ts +1 -0
  256. package/src/test/setup.ts +39 -0
  257. package/src/theme.css +158 -0
  258. package/src/tokens.ts +7 -0
  259. package/src/utils.ts +12 -0
  260. package/src/webgl.ts +1 -0
@@ -0,0 +1,159 @@
1
+ "use client";
2
+ import * as React from "react"
3
+ import { Command as CommandPrimitive } from "cmdk"
4
+ import { Search } from "lucide-react"
5
+
6
+ import { cn } from "../../lib/utils"
7
+ import { Dialog, DialogContent } from "../overlays/Dialog"
8
+
9
+ const Command = (
10
+ {
11
+ ref,
12
+ className,
13
+ ...props
14
+ }: React.ComponentPropsWithoutRef<typeof CommandPrimitive> & {
15
+ ref?: React.Ref<React.ElementRef<typeof CommandPrimitive>>;
16
+ }
17
+ ) => (<CommandPrimitive
18
+ ref={ref}
19
+ className={cn(
20
+ "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
21
+ className
22
+ )}
23
+ {...props}
24
+ />)
25
+
26
+ const CommandDialog = ({ children, ...props }: React.ComponentProps<typeof Dialog>) => {
27
+ return (
28
+ <Dialog {...props}>
29
+ <DialogContent className="overflow-hidden p-0">
30
+ <Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
31
+ {children}
32
+ </Command>
33
+ </DialogContent>
34
+ </Dialog>
35
+ )
36
+ }
37
+
38
+ const CommandInput = (
39
+ {
40
+ ref,
41
+ className,
42
+ ...props
43
+ }: React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input> & {
44
+ ref?: React.Ref<React.ElementRef<typeof CommandPrimitive.Input>>;
45
+ }
46
+ ) => (<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
47
+ <Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
48
+ <CommandPrimitive.Input
49
+ ref={ref}
50
+ className={cn(
51
+ "flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
52
+ className
53
+ )}
54
+ {...props}
55
+ />
56
+ </div>)
57
+
58
+ const CommandList = (
59
+ {
60
+ ref,
61
+ className,
62
+ ...props
63
+ }: React.ComponentPropsWithoutRef<typeof CommandPrimitive.List> & {
64
+ ref?: React.Ref<React.ElementRef<typeof CommandPrimitive.List>>;
65
+ }
66
+ ) => (<CommandPrimitive.List
67
+ ref={ref}
68
+ className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
69
+ {...props}
70
+ />)
71
+
72
+ const CommandEmpty = (
73
+ {
74
+ ref,
75
+ ...props
76
+ }: React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty> & {
77
+ ref?: React.Ref<React.ElementRef<typeof CommandPrimitive.Empty>>;
78
+ }
79
+ ) => (<CommandPrimitive.Empty
80
+ ref={ref}
81
+ className="py-6 text-center text-sm"
82
+ {...props}
83
+ />)
84
+
85
+ const CommandGroup = (
86
+ {
87
+ ref,
88
+ className,
89
+ ...props
90
+ }: React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group> & {
91
+ ref?: React.Ref<React.ElementRef<typeof CommandPrimitive.Group>>;
92
+ }
93
+ ) => (<CommandPrimitive.Group
94
+ ref={ref}
95
+ className={cn(
96
+ "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
97
+ className
98
+ )}
99
+ {...props}
100
+ />)
101
+
102
+ const CommandSeparator = (
103
+ {
104
+ ref,
105
+ className,
106
+ ...props
107
+ }: React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator> & {
108
+ ref?: React.Ref<React.ElementRef<typeof CommandPrimitive.Separator>>;
109
+ }
110
+ ) => (<CommandPrimitive.Separator
111
+ ref={ref}
112
+ className={cn("-mx-1 h-px bg-border", className)}
113
+ {...props}
114
+ />)
115
+
116
+ const CommandItem = (
117
+ {
118
+ ref,
119
+ className,
120
+ ...props
121
+ }: React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item> & {
122
+ ref?: React.Ref<React.ElementRef<typeof CommandPrimitive.Item>>;
123
+ }
124
+ ) => (<CommandPrimitive.Item
125
+ ref={ref}
126
+ className={cn(
127
+ "relative flex cursor-default select-none items-center rounded-xs px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-primary data-[selected=true]:text-primary-foreground data-[disabled=true]:opacity-50",
128
+ className
129
+ )}
130
+ {...props}
131
+ />)
132
+
133
+ const CommandShortcut = ({
134
+ className,
135
+ ...props
136
+ }: React.HTMLAttributes<HTMLSpanElement>) => {
137
+ return (
138
+ <span
139
+ className={cn(
140
+ "ml-auto text-xs tracking-widest text-muted-foreground",
141
+ className
142
+ )}
143
+ {...props}
144
+ />
145
+ )
146
+ }
147
+ CommandShortcut.displayName = "CommandShortcut"
148
+
149
+ export {
150
+ Command,
151
+ CommandDialog,
152
+ CommandInput,
153
+ CommandList,
154
+ CommandEmpty,
155
+ CommandGroup,
156
+ CommandItem,
157
+ CommandSeparator,
158
+ CommandShortcut,
159
+ }
@@ -0,0 +1,115 @@
1
+ "use client";
2
+ import * as React from "react"
3
+ import * as MenubarPrimitive from "@radix-ui/react-menubar"
4
+ import { Check, ChevronRight, Circle } from "lucide-react"
5
+ import { cn } from "../../lib/utils"
6
+
7
+ const MenubarMenu: typeof MenubarPrimitive.Menu = MenubarPrimitive.Menu
8
+ const MenubarGroup: typeof MenubarPrimitive.Group = MenubarPrimitive.Group
9
+ const MenubarPortal: typeof MenubarPrimitive.Portal = MenubarPrimitive.Portal
10
+ const MenubarSub: typeof MenubarPrimitive.Sub = MenubarPrimitive.Sub
11
+ const MenubarRadioGroup: typeof MenubarPrimitive.RadioGroup = MenubarPrimitive.RadioGroup
12
+
13
+ const Menubar = (
14
+ {
15
+ ref,
16
+ className,
17
+ ...props
18
+ }: React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root> & {
19
+ ref?: React.Ref<React.ElementRef<typeof MenubarPrimitive.Root>>;
20
+ }
21
+ ) => (<MenubarPrimitive.Root
22
+ ref={ref}
23
+ className={cn("flex h-9 items-center space-x-1 rounded-md border bg-background p-1", className)}
24
+ {...props}
25
+ />)
26
+
27
+ const MenubarTrigger = (
28
+ {
29
+ ref,
30
+ className,
31
+ ...props
32
+ }: React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger> & {
33
+ ref?: React.Ref<React.ElementRef<typeof MenubarPrimitive.Trigger>>;
34
+ }
35
+ ) => (<MenubarPrimitive.Trigger
36
+ ref={ref}
37
+ className={cn("flex cursor-default select-none items-center rounded-xs px-3 py-1 text-sm font-medium outline-none focus:bg-accent data-[state=open]:bg-accent", className)}
38
+ {...props}
39
+ />)
40
+
41
+ const MenubarContent = (
42
+ {
43
+ ref,
44
+ className,
45
+ align = "start",
46
+ alignOffset = -4,
47
+ sideOffset = 8,
48
+ style,
49
+ ...props
50
+ }: React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content> & {
51
+ ref?: React.Ref<React.ElementRef<typeof MenubarPrimitive.Content>>;
52
+ }
53
+ ) => (<MenubarPrimitive.Portal>
54
+ <MenubarPrimitive.Content
55
+ ref={ref}
56
+ align={align}
57
+ alignOffset={alignOffset}
58
+ sideOffset={sideOffset}
59
+ className={cn("z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md", className)}
60
+ style={{
61
+ backgroundColor: 'var(--color-popover, #ffffff)',
62
+ color: 'var(--color-popover-foreground, #0a0a0a)',
63
+ border: '1px solid var(--color-border, #d4d4d4)',
64
+ borderRadius: 'var(--radius, 0.5rem)',
65
+ boxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',
66
+ zIndex: 50,
67
+ overflow: 'hidden',
68
+ ...style,
69
+ }}
70
+ {...props}
71
+ />
72
+ </MenubarPrimitive.Portal>)
73
+
74
+ const MenubarItem = (
75
+ {
76
+ ref,
77
+ className,
78
+ ...props
79
+ }: React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {
80
+ ref?: React.Ref<React.ElementRef<typeof MenubarPrimitive.Item>>;
81
+ }
82
+ ) => (<MenubarPrimitive.Item
83
+ ref={ref}
84
+ className={cn("relative flex cursor-default select-none items-center rounded-xs px-2 py-1.5 text-sm outline-none focus:bg-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className)}
85
+ {...props}
86
+ />)
87
+
88
+ const MenubarSeparator = (
89
+ {
90
+ ref,
91
+ className,
92
+ ...props
93
+ }: React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator> & {
94
+ ref?: React.Ref<React.ElementRef<typeof MenubarPrimitive.Separator>>;
95
+ }
96
+ ) => (<MenubarPrimitive.Separator ref={ref} className={cn("-mx-1 my-1 h-px bg-muted", className)} {...props} />)
97
+
98
+ const MenubarShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
99
+ return <span className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} />
100
+ }
101
+ MenubarShortcut.displayName = "MenubarShortcut"
102
+
103
+ export {
104
+ Menubar,
105
+ MenubarMenu,
106
+ MenubarTrigger,
107
+ MenubarContent,
108
+ MenubarItem,
109
+ MenubarSeparator,
110
+ MenubarShortcut,
111
+ MenubarGroup,
112
+ MenubarPortal,
113
+ MenubarSub,
114
+ MenubarRadioGroup,
115
+ }
@@ -0,0 +1,55 @@
1
+ import React from 'react';
2
+
3
+ export interface NavLinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
4
+ active?: boolean;
5
+ children?: React.ReactNode;
6
+ icon?: React.ReactNode;
7
+ variant?: 'pill' | 'minimal';
8
+ }
9
+
10
+ export const NavLink = (
11
+ {
12
+ ref,
13
+ active = false,
14
+ children,
15
+ icon,
16
+ variant = 'pill',
17
+ className = '',
18
+ ...props
19
+ }: NavLinkProps & {
20
+ ref?: React.Ref<HTMLAnchorElement>;
21
+ }
22
+ ) => {
23
+ const variants = {
24
+ pill: `px-3 py-2 rounded-lg
25
+ ${active
26
+ ? 'bg-[var(--color-primary)]/10 text-[var(--color-primary)]'
27
+ : 'text-[var(--color-text-secondary)] hover:bg-[var(--color-hover)] hover:text-[var(--color-text-primary)]'}`,
28
+ minimal: `relative pb-1 rounded-xs
29
+ ${active
30
+ ? 'text-[var(--color-text-primary)] font-medium after:absolute after:bottom-0 after:left-0 after:right-0 after:h-0.5 after:bg-[var(--color-primary)] after:rounded-full'
31
+ : 'text-[var(--color-text-secondary)] hover:text-[var(--color-primary)]'}`
32
+ };
33
+
34
+ return (
35
+ <a
36
+ ref={ref}
37
+ className={`
38
+ group flex items-center gap-2 text-sm font-medium transition-all duration-200
39
+ focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus)]
40
+ cursor-pointer
41
+ ${variants[variant]}
42
+ ${className}
43
+ `}
44
+ aria-current={active ? 'page' : undefined}
45
+ {...props}
46
+ >
47
+ {icon && (
48
+ <span className={`w-4 h-4 transition-colors ${active ? 'text-[var(--color-primary)]' : 'text-[var(--color-text-muted)] group-hover:text-[var(--color-text-primary)]'}`}>
49
+ {icon}
50
+ </span>
51
+ )}
52
+ {children}
53
+ </a>
54
+ );
55
+ };
@@ -0,0 +1,125 @@
1
+ "use client";
2
+ import * as React from "react"
3
+ import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
4
+ import { cva } from "class-variance-authority"
5
+ import { ChevronDown } from "lucide-react"
6
+ import { cn } from "../../lib/utils"
7
+
8
+ const NavigationMenu = (
9
+ {
10
+ ref,
11
+ className,
12
+ children,
13
+ ...props
14
+ }: React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root> & {
15
+ ref?: React.Ref<React.ElementRef<typeof NavigationMenuPrimitive.Root>>;
16
+ }
17
+ ) => (<NavigationMenuPrimitive.Root
18
+ ref={ref}
19
+ className={cn("relative z-10 flex max-w-max flex-1 items-center justify-center", className)}
20
+ {...props}
21
+ >
22
+ {children}
23
+ <NavigationMenuViewport />
24
+ </NavigationMenuPrimitive.Root>)
25
+
26
+ const NavigationMenuList = (
27
+ {
28
+ ref,
29
+ className,
30
+ ...props
31
+ }: React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List> & {
32
+ ref?: React.Ref<React.ElementRef<typeof NavigationMenuPrimitive.List>>;
33
+ }
34
+ ) => (<NavigationMenuPrimitive.List
35
+ ref={ref}
36
+ className={cn("group flex flex-1 list-none items-center justify-center space-x-1", className)}
37
+ {...props}
38
+ />)
39
+
40
+ const NavigationMenuItem = NavigationMenuPrimitive.Item
41
+
42
+ const navigationMenuTriggerStyle = cva(
43
+ "group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50"
44
+ )
45
+
46
+ const NavigationMenuTrigger = (
47
+ {
48
+ ref,
49
+ className,
50
+ children,
51
+ ...props
52
+ }: React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger> & {
53
+ ref?: React.Ref<React.ElementRef<typeof NavigationMenuPrimitive.Trigger>>;
54
+ }
55
+ ) => (<NavigationMenuPrimitive.Trigger
56
+ ref={ref}
57
+ className={cn(navigationMenuTriggerStyle(), "group", className)}
58
+ {...props}
59
+ >
60
+ {children}{" "}
61
+ <ChevronDown
62
+ className="relative top-[1px] ml-1 h-3 w-3 transition duration-300 group-data-[state=open]:rotate-180"
63
+ aria-hidden="true"
64
+ />
65
+ </NavigationMenuPrimitive.Trigger>)
66
+
67
+ const NavigationMenuContent = (
68
+ {
69
+ ref,
70
+ className,
71
+ ...props
72
+ }: React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content> & {
73
+ ref?: React.Ref<React.ElementRef<typeof NavigationMenuPrimitive.Content>>;
74
+ }
75
+ ) => (<NavigationMenuPrimitive.Content
76
+ ref={ref}
77
+ className={cn("left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto", className)}
78
+ {...props}
79
+ />)
80
+
81
+ const NavigationMenuLink = NavigationMenuPrimitive.Link
82
+
83
+ const NavigationMenuViewport = (
84
+ {
85
+ ref,
86
+ className,
87
+ ...props
88
+ }: React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport> & {
89
+ ref?: React.Ref<React.ElementRef<typeof NavigationMenuPrimitive.Viewport>>;
90
+ }
91
+ ) => (<div className={cn("absolute left-0 top-full flex justify-center")}>
92
+ <NavigationMenuPrimitive.Viewport
93
+ className={cn("origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]", className)}
94
+ ref={ref}
95
+ {...props}
96
+ />
97
+ </div>)
98
+
99
+ const NavigationMenuIndicator = (
100
+ {
101
+ ref,
102
+ className,
103
+ ...props
104
+ }: React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator> & {
105
+ ref?: React.Ref<React.ElementRef<typeof NavigationMenuPrimitive.Indicator>>;
106
+ }
107
+ ) => (<NavigationMenuPrimitive.Indicator
108
+ ref={ref}
109
+ className={cn("top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in", className)}
110
+ {...props}
111
+ >
112
+ <div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
113
+ </NavigationMenuPrimitive.Indicator>)
114
+
115
+ export {
116
+ navigationMenuTriggerStyle,
117
+ NavigationMenu,
118
+ NavigationMenuList,
119
+ NavigationMenuItem,
120
+ NavigationMenuContent,
121
+ NavigationMenuTrigger,
122
+ NavigationMenuLink,
123
+ NavigationMenuIndicator,
124
+ NavigationMenuViewport,
125
+ }
@@ -0,0 +1,121 @@
1
+ import * as React from "react"
2
+ import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"
3
+
4
+ import { cn } from "../../lib/utils"
5
+ import { ButtonProps, buttonVariants } from "../actions/Button"
6
+
7
+ const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
8
+ <nav
9
+ role="navigation"
10
+ aria-label="pagination"
11
+ className={cn("mx-auto flex w-full justify-center", className)}
12
+ {...props}
13
+ />
14
+ )
15
+ Pagination.displayName = "Pagination"
16
+
17
+ const PaginationContent = (
18
+ {
19
+ ref,
20
+ className,
21
+ ...props
22
+ }: React.ComponentProps<"ul"> & {
23
+ ref?: React.Ref<HTMLUListElement>;
24
+ }
25
+ ) => (<ul
26
+ ref={ref}
27
+ className={cn("flex flex-row items-center gap-1", className)}
28
+ {...props}
29
+ />)
30
+
31
+ const PaginationItem = (
32
+ {
33
+ ref,
34
+ className,
35
+ ...props
36
+ }: React.ComponentProps<"li"> & {
37
+ ref?: React.Ref<HTMLLIElement>;
38
+ }
39
+ ) => (<li ref={ref} className={cn("", className)} {...props} />)
40
+
41
+ type PaginationLinkProps = {
42
+ isActive?: boolean
43
+ } & Pick<ButtonProps, "size"> &
44
+ React.ComponentProps<"a">
45
+
46
+ const PaginationLink = ({
47
+ className,
48
+ isActive,
49
+ size = "icon",
50
+ ...props
51
+ }: PaginationLinkProps) => (
52
+ <a
53
+ aria-current={isActive ? "page" : undefined}
54
+ className={cn(
55
+ buttonVariants({
56
+ variant: isActive ? "outline" : "ghost",
57
+ size,
58
+ }),
59
+ className
60
+ )}
61
+ {...props}
62
+ />
63
+ )
64
+ PaginationLink.displayName = "PaginationLink"
65
+
66
+ const PaginationPrevious = ({
67
+ className,
68
+ ...props
69
+ }: React.ComponentProps<typeof PaginationLink>) => (
70
+ <PaginationLink
71
+ aria-label="Go to previous page"
72
+ size="default"
73
+ className={cn("gap-1 pl-2.5", className)}
74
+ {...props}
75
+ >
76
+ <ChevronLeft className="h-4 w-4" />
77
+ <span>Previous</span>
78
+ </PaginationLink>
79
+ )
80
+ PaginationPrevious.displayName = "PaginationPrevious"
81
+
82
+ const PaginationNext = ({
83
+ className,
84
+ ...props
85
+ }: React.ComponentProps<typeof PaginationLink>) => (
86
+ <PaginationLink
87
+ aria-label="Go to next page"
88
+ size="default"
89
+ className={cn("gap-1 pr-2.5", className)}
90
+ {...props}
91
+ >
92
+ <span>Next</span>
93
+ <ChevronRight className="h-4 w-4" />
94
+ </PaginationLink>
95
+ )
96
+ PaginationNext.displayName = "PaginationNext"
97
+
98
+ const PaginationEllipsis = ({
99
+ className,
100
+ ...props
101
+ }: React.ComponentProps<"span">) => (
102
+ <span
103
+ aria-hidden
104
+ className={cn("flex h-9 w-9 items-center justify-center", className)}
105
+ {...props}
106
+ >
107
+ <MoreHorizontal className="h-4 w-4" />
108
+ <span className="sr-only">More pages</span>
109
+ </span>
110
+ )
111
+ PaginationEllipsis.displayName = "PaginationEllipsis"
112
+
113
+ export {
114
+ Pagination,
115
+ PaginationContent,
116
+ PaginationLink,
117
+ PaginationItem,
118
+ PaginationPrevious,
119
+ PaginationNext,
120
+ PaginationEllipsis,
121
+ }
@@ -0,0 +1,100 @@
1
+ 'use client';;
2
+ import React from 'react';
3
+ import { Button } from '../actions/Button';
4
+
5
+ export interface SecondaryNavItem {
6
+ id: string;
7
+ label: string;
8
+ icon?: React.ReactNode;
9
+ }
10
+
11
+ export interface SecondaryNavProps {
12
+ /**
13
+ * Array of navigation items
14
+ */
15
+ items: SecondaryNavItem[];
16
+ /**
17
+ * Currently active item ID
18
+ */
19
+ activeId: string;
20
+ /**
21
+ * Callback when an item is selected
22
+ */
23
+ onItemChange: (id: string) => void;
24
+ /**
25
+ * Maximum width for content container (should match page variant)
26
+ * @default 'max-w-7xl'
27
+ */
28
+ maxWidth?: 'max-w-7xl' | 'max-w-[1440px]' | 'max-w-4xl';
29
+ /**
30
+ * Additional className for customization
31
+ */
32
+ className?: string;
33
+ /**
34
+ * Sticky behavior mode
35
+ * - 'stacked': Positions automatically below Header (default)
36
+ * - 'standalone': Sticks to top of viewport (0px)
37
+ * @default 'stacked'
38
+ */
39
+ mode?: 'stacked' | 'standalone';
40
+ /**
41
+ * Top offset for sticky positioning.
42
+ * Overrides 'mode' if provided.
43
+ */
44
+ top?: string;
45
+ }
46
+
47
+ /**
48
+ * Secondary Navigation Component
49
+ * ... (keep existing comment block) ...
50
+ */
51
+ export const SecondaryNav = (
52
+ {
53
+ ref,
54
+ items,
55
+ activeId,
56
+ onItemChange,
57
+ maxWidth = 'max-w-7xl',
58
+ mode = 'stacked',
59
+ top,
60
+ className = ''
61
+ }: SecondaryNavProps & {
62
+ ref?: React.Ref<HTMLElement>;
63
+ }
64
+ ) => {
65
+ // Determine sticky position based on mode, unless manually overridden
66
+ const stickyClass = top || (mode === 'stacked' ? 'top-16 lg:top-20' : 'top-0');
67
+
68
+ return (
69
+ <nav
70
+ ref={ref}
71
+ className={`
72
+ sticky ${stickyClass} z-40
73
+ bg-[var(--color-surface)]/60 backdrop-blur-md
74
+ border-b border-[var(--color-border)]
75
+ -mx-4 sm:-mx-6 lg:-mx-8 px-4 sm:px-6 lg:px-8
76
+ ${className}
77
+ `}
78
+ aria-label="Secondary navigation"
79
+ >
80
+ <div className={`${maxWidth} mx-auto px-4 sm:px-6 lg:px-8`}>
81
+ <div className="flex items-center gap-1 overflow-x-auto py-3 scrollbar-hide">
82
+ {items.map((item) => (
83
+ <Button
84
+ key={item.id}
85
+ onClick={() => onItemChange(item.id)}
86
+ variant={activeId === item.id ? 'default' : 'ghost'}
87
+ size="sm"
88
+ className={`whitespace-nowrap ${activeId !== item.id ? 'text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)]' : ''
89
+ }`}
90
+ aria-current={activeId === item.id ? 'page' : undefined}
91
+ >
92
+ {item.icon && <span className="mr-2 flex items-center">{item.icon}</span>}
93
+ {item.label}
94
+ </Button>
95
+ ))}
96
+ </div>
97
+ </div>
98
+ </nav>
99
+ );
100
+ };