@olympusoss/canvas 2.20.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/README.md +69 -35
  2. package/package.json +45 -177
  3. package/src/cn.ts +3 -0
  4. package/src/index.ts +12 -603
  5. package/src/theme.ts +62 -0
  6. package/src/tokens.ts +11 -0
  7. package/styles/base.css +17 -0
  8. package/styles/canvas.css +77 -52
  9. package/styles/components/alert.css +66 -0
  10. package/styles/components/app-shell.css +46 -0
  11. package/styles/components/avatar.css +22 -0
  12. package/styles/components/badge.css +83 -0
  13. package/styles/components/breadcrumb.css +35 -0
  14. package/styles/components/button-group.css +23 -0
  15. package/styles/components/button.css +107 -0
  16. package/styles/components/calendar.css +73 -0
  17. package/styles/components/card.css +58 -0
  18. package/styles/components/checkbox.css +55 -0
  19. package/styles/components/code-block.css +18 -0
  20. package/styles/components/combobox.css +75 -0
  21. package/styles/components/command.css +94 -0
  22. package/styles/components/data-table.css +142 -0
  23. package/styles/components/dialog.css +72 -0
  24. package/styles/components/dropdown.css +54 -0
  25. package/styles/components/empty-state.css +17 -0
  26. package/styles/components/field.css +27 -0
  27. package/styles/components/filter-panel.css +58 -0
  28. package/styles/components/form.css +27 -0
  29. package/styles/components/icon.css +8 -0
  30. package/styles/components/input-group.css +45 -0
  31. package/styles/components/input.css +56 -0
  32. package/styles/components/kbd.css +15 -0
  33. package/styles/components/page-header.css +52 -0
  34. package/styles/components/pagination.css +48 -0
  35. package/styles/components/popover.css +14 -0
  36. package/styles/components/radio.css +28 -0
  37. package/styles/components/row-menu.css +69 -0
  38. package/styles/components/section-card.css +49 -0
  39. package/styles/components/select.css +57 -0
  40. package/styles/components/separator.css +32 -0
  41. package/styles/components/sheet.css +70 -0
  42. package/styles/components/sidebar.css +146 -0
  43. package/styles/components/skeleton.css +32 -0
  44. package/styles/components/spinner.css +26 -0
  45. package/styles/components/stat-card.css +71 -0
  46. package/styles/components/stepper.css +63 -0
  47. package/styles/components/switch.css +45 -0
  48. package/styles/components/tabs.css +40 -0
  49. package/styles/components/textarea.css +31 -0
  50. package/styles/components/toast.css +95 -0
  51. package/styles/components/tooltip.css +53 -0
  52. package/styles/components/topbar.css +24 -0
  53. package/styles/components/typography.css +105 -0
  54. package/styles/patterns/backdrops.css +35 -0
  55. package/styles/patterns/density.css +66 -0
  56. package/styles/patterns/focus.css +22 -0
  57. package/styles/patterns/glass.css +85 -0
  58. package/styles/patterns/high-contrast.css +70 -0
  59. package/styles/patterns/reduced-motion.css +12 -0
  60. package/styles/patterns/scrollbar.css +10 -0
  61. package/styles/reset.css +89 -0
  62. package/styles/tokens/colors.css +106 -0
  63. package/styles/tokens/motion.css +33 -0
  64. package/styles/tokens/radius.css +10 -0
  65. package/styles/tokens/shadows.css +35 -0
  66. package/styles/tokens/spacing.css +19 -0
  67. package/styles/tokens/typography.css +6 -0
  68. package/styles/tokens/z-index.css +12 -0
  69. package/styles/utilities/display.css +66 -0
  70. package/styles/utilities/flexbox.css +240 -0
  71. package/styles/utilities/gap.css +288 -0
  72. package/styles/utilities/grid.css +138 -0
  73. package/styles/utilities/position.css +78 -0
  74. package/styles/utilities/sizing.css +138 -0
  75. package/tsconfig.json +20 -21
  76. package/src/components/atoms/README.md +0 -11
  77. package/src/components/atoms/aspect-ratio.tsx +0 -32
  78. package/src/components/atoms/avatar.tsx +0 -98
  79. package/src/components/atoms/badge.tsx +0 -44
  80. package/src/components/atoms/brand-mark.tsx +0 -74
  81. package/src/components/atoms/button.tsx +0 -105
  82. package/src/components/atoms/checkbox.tsx +0 -63
  83. package/src/components/atoms/flex-box.tsx +0 -105
  84. package/src/components/atoms/icon.tsx +0 -34
  85. package/src/components/atoms/input.tsx +0 -92
  86. package/src/components/atoms/label.tsx +0 -41
  87. package/src/components/atoms/logo.tsx +0 -89
  88. package/src/components/atoms/progress.tsx +0 -55
  89. package/src/components/atoms/radio-group.tsx +0 -122
  90. package/src/components/atoms/scroll-area.tsx +0 -106
  91. package/src/components/atoms/section.tsx +0 -48
  92. package/src/components/atoms/separator.tsx +0 -45
  93. package/src/components/atoms/skeleton.tsx +0 -17
  94. package/src/components/atoms/slider.tsx +0 -93
  95. package/src/components/atoms/spinner.tsx +0 -47
  96. package/src/components/atoms/switch.tsx +0 -60
  97. package/src/components/atoms/textarea.tsx +0 -78
  98. package/src/components/atoms/toggle.tsx +0 -80
  99. package/src/components/charts/activity-heatmap.tsx +0 -186
  100. package/src/components/charts/axes.tsx +0 -21
  101. package/src/components/charts/chart-container.tsx +0 -254
  102. package/src/components/charts/chart-legend.tsx +0 -67
  103. package/src/components/charts/chart-tooltip.tsx +0 -161
  104. package/src/components/charts/chart-types.tsx +0 -49
  105. package/src/components/charts/containers.tsx +0 -11
  106. package/src/components/charts/data.tsx +0 -16
  107. package/src/components/charts/details.tsx +0 -25
  108. package/src/components/charts/dot-pulse.tsx +0 -61
  109. package/src/components/charts/gauge.tsx +0 -106
  110. package/src/components/charts/grids.tsx +0 -8
  111. package/src/components/charts/index.ts +0 -62
  112. package/src/components/charts/labeled-bar-list.tsx +0 -85
  113. package/src/components/charts/metric-breakdown.tsx +0 -316
  114. package/src/components/charts/references.tsx +0 -8
  115. package/src/components/charts/service-health-list.tsx +0 -85
  116. package/src/components/charts/sparkline-area.tsx +0 -80
  117. package/src/components/charts/sparkline.tsx +0 -52
  118. package/src/components/charts/stacked-bar.tsx +0 -104
  119. package/src/components/charts/text.tsx +0 -10
  120. package/src/components/charts/world-heat-map-inner.tsx +0 -317
  121. package/src/components/charts/world-heat-map.tsx +0 -184
  122. package/src/components/molecules/README.md +0 -12
  123. package/src/components/molecules/action-bar.tsx +0 -73
  124. package/src/components/molecules/activity-item.tsx +0 -74
  125. package/src/components/molecules/alert.tsx +0 -86
  126. package/src/components/molecules/animated-background.tsx +0 -92
  127. package/src/components/molecules/auth-shell.tsx +0 -95
  128. package/src/components/molecules/brand-lockup.tsx +0 -48
  129. package/src/components/molecules/breadcrumb.tsx +0 -157
  130. package/src/components/molecules/button-group.tsx +0 -104
  131. package/src/components/molecules/calendar.tsx +0 -217
  132. package/src/components/molecules/card.tsx +0 -102
  133. package/src/components/molecules/client-brand.tsx +0 -95
  134. package/src/components/molecules/code-block.tsx +0 -86
  135. package/src/components/molecules/countdown-button.tsx +0 -92
  136. package/src/components/molecules/empty-state.tsx +0 -56
  137. package/src/components/molecules/error-state.tsx +0 -42
  138. package/src/components/molecules/field-display.tsx +0 -35
  139. package/src/components/molecules/input-otp.tsx +0 -74
  140. package/src/components/molecules/launcher-card.tsx +0 -152
  141. package/src/components/molecules/loading-state.tsx +0 -36
  142. package/src/components/molecules/notification-item.tsx +0 -67
  143. package/src/components/molecules/notification-list.tsx +0 -45
  144. package/src/components/molecules/number-badge.tsx +0 -53
  145. package/src/components/molecules/or-separator.tsx +0 -38
  146. package/src/components/molecules/page-header.tsx +0 -88
  147. package/src/components/molecules/page-tabs.tsx +0 -94
  148. package/src/components/molecules/pagination.tsx +0 -150
  149. package/src/components/molecules/password-input.tsx +0 -83
  150. package/src/components/molecules/password-strength-meter.tsx +0 -104
  151. package/src/components/molecules/phone-input.tsx +0 -200
  152. package/src/components/molecules/search-bar.tsx +0 -64
  153. package/src/components/molecules/secret-field.tsx +0 -158
  154. package/src/components/molecules/section-card.tsx +0 -91
  155. package/src/components/molecules/social-buttons.tsx +0 -165
  156. package/src/components/molecules/stat-card.tsx +0 -100
  157. package/src/components/molecules/status-badge.tsx +0 -42
  158. package/src/components/molecules/stepper.tsx +0 -96
  159. package/src/components/molecules/table.tsx +0 -157
  160. package/src/components/molecules/terminal.tsx +0 -74
  161. package/src/components/molecules/toggle-group.tsx +0 -145
  162. package/src/components/molecules/tooltip.tsx +0 -155
  163. package/src/components/molecules/user-avatar-chip.tsx +0 -71
  164. package/src/components/organisms/README.md +0 -14
  165. package/src/components/organisms/accordion.tsx +0 -154
  166. package/src/components/organisms/alert-dialog.tsx +0 -277
  167. package/src/components/organisms/carousel.tsx +0 -244
  168. package/src/components/organisms/collapsible.tsx +0 -69
  169. package/src/components/organisms/command.tsx +0 -144
  170. package/src/components/organisms/context-menu.tsx +0 -339
  171. package/src/components/organisms/dashboard-grid.tsx +0 -369
  172. package/src/components/organisms/data-table.tsx +0 -330
  173. package/src/components/organisms/dialog.tsx +0 -312
  174. package/src/components/organisms/drawer.tsx +0 -123
  175. package/src/components/organisms/dropdown-menu.tsx +0 -440
  176. package/src/components/organisms/editors/code-editor.tsx +0 -144
  177. package/src/components/organisms/editors/index.ts +0 -4
  178. package/src/components/organisms/editors/markdown-editor.tsx +0 -153
  179. package/src/components/organisms/editors/markdown-renderer.ts +0 -27
  180. package/src/components/organisms/editors/prose-canvas-classes.ts +0 -45
  181. package/src/components/organisms/editors/rich-text-editor.tsx +0 -126
  182. package/src/components/organisms/editors/toolbar/md-toolbar.tsx +0 -129
  183. package/src/components/organisms/editors/toolbar/rte-toolbar.tsx +0 -211
  184. package/src/components/organisms/editors/toolbar/toolbar-shell.tsx +0 -45
  185. package/src/components/organisms/editors/use-codemirror-theme.ts +0 -61
  186. package/src/components/organisms/error-boundary.tsx +0 -61
  187. package/src/components/organisms/form.tsx +0 -174
  188. package/src/components/organisms/hover-card.tsx +0 -115
  189. package/src/components/organisms/menubar.tsx +0 -498
  190. package/src/components/organisms/navbar.tsx +0 -104
  191. package/src/components/organisms/navigation-menu.tsx +0 -235
  192. package/src/components/organisms/popover.tsx +0 -149
  193. package/src/components/organisms/resizable.tsx +0 -58
  194. package/src/components/organisms/schema-form.tsx +0 -232
  195. package/src/components/organisms/select.tsx +0 -309
  196. package/src/components/organisms/sheet.tsx +0 -265
  197. package/src/components/organisms/sidebar.tsx +0 -1040
  198. package/src/components/organisms/sonner.tsx +0 -96
  199. package/src/components/organisms/tabs.tsx +0 -133
  200. package/src/components/organisms/theme-provider.tsx +0 -101
  201. package/src/hooks/use-mobile.tsx +0 -19
  202. package/src/lib/portal-container.tsx +0 -35
  203. package/src/lib/utils.ts +0 -6
  204. package/src/native.ts +0 -23
  205. package/src/tokens/colors.ts +0 -91
  206. package/src/tokens/index.ts +0 -3
  207. package/src/tokens/spacing.ts +0 -55
  208. package/src/tokens/typography.ts +0 -27
  209. package/styles/dashboard-grid.css +0 -47
  210. package/styles/fonts/Roboto-VariableFont_wdth_wght.ttf +0 -0
  211. package/styles/glass.css +0 -171
  212. package/styles/leaflet.css +0 -13
  213. package/styles/tokens.css +0 -317
  214. package/tailwind.config.ts +0 -70
@@ -1,498 +0,0 @@
1
- "use client";
2
-
3
- import * as MenubarPrimitive from "@radix-ui/react-menubar";
4
- import { Check, ChevronRight, Circle } from "lucide-react";
5
- import * as React from "react";
6
-
7
- import { usePortalContainer } from "../../lib/portal-container";
8
- import { cn } from "../../lib/utils";
9
-
10
- export interface MenubarProps extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root> {
11
- /** Controlled active menu value (the `value` of the open `<MenubarMenu>`). */
12
- value?: string;
13
- /** Initial active menu value for uncontrolled usage. */
14
- defaultValue?: string;
15
- /** Fires when the open menu changes. */
16
- onValueChange?: (value: string) => void;
17
- /**
18
- * Reading direction. Affects keyboard arrow navigation.
19
- * @default "ltr"
20
- */
21
- dir?: "ltr" | "rtl";
22
- /**
23
- * Loop arrow-key navigation across the top-level menus.
24
- * @default false
25
- */
26
- loop?: boolean;
27
- /** A list of `<MenubarMenu>`s. */
28
- children?: React.ReactNode;
29
- className?: string;
30
- }
31
-
32
- const Menubar = React.forwardRef<React.ElementRef<typeof MenubarPrimitive.Root>, MenubarProps>(
33
- ({ className, ...props }, ref) => (
34
- <MenubarPrimitive.Root
35
- ref={ref}
36
- data-slot="menubar"
37
- className={cn(
38
- "flex h-9 items-center space-x-1 rounded-md border border-border bg-background p-1 shadow-sm",
39
- className,
40
- )}
41
- {...props}
42
- />
43
- ),
44
- );
45
- Menubar.displayName = MenubarPrimitive.Root.displayName;
46
-
47
- export interface MenubarMenuProps extends React.ComponentProps<typeof MenubarPrimitive.Menu> {
48
- /** Required for controlled menus — unique id of this menu. */
49
- value?: string;
50
- /** Trigger + Content (sub-menus and items). */
51
- children?: React.ReactNode;
52
- }
53
-
54
- function MenubarMenu({ ...props }: MenubarMenuProps) {
55
- return <MenubarPrimitive.Menu {...props} />;
56
- }
57
-
58
- export interface MenubarGroupProps
59
- extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Group> {
60
- /** Items grouped together for screen-reader semantics. */
61
- children?: React.ReactNode;
62
- }
63
-
64
- function MenubarGroup({ ...props }: MenubarGroupProps) {
65
- return <MenubarPrimitive.Group {...props} />;
66
- }
67
-
68
- export interface MenubarPortalProps
69
- extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Portal> {
70
- /** DOM element to portal into. Defaults to `document.body`. */
71
- container?: HTMLElement | null;
72
- /**
73
- * Force the portal to mount even when the menu is closed.
74
- * @default false
75
- */
76
- forceMount?: true;
77
- children?: React.ReactNode;
78
- }
79
-
80
- function MenubarPortal({ ...props }: MenubarPortalProps) {
81
- return <MenubarPrimitive.Portal {...props} />;
82
- }
83
-
84
- export interface MenubarRadioGroupProps
85
- extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioGroup> {
86
- /** Currently selected value (the `value` of the active RadioItem). */
87
- value?: string;
88
- /** Fires when the user picks a different RadioItem. */
89
- onValueChange?: (value: string) => void;
90
- /** A list of `<MenubarRadioItem>`s. */
91
- children?: React.ReactNode;
92
- }
93
-
94
- function MenubarRadioGroup({ ...props }: MenubarRadioGroupProps) {
95
- return <MenubarPrimitive.RadioGroup {...props} />;
96
- }
97
-
98
- export interface MenubarSubProps extends React.ComponentProps<typeof MenubarPrimitive.Sub> {
99
- /** Controlled open state of the sub-menu. */
100
- open?: boolean;
101
- /**
102
- * Initial open state for uncontrolled usage.
103
- * @default false
104
- */
105
- defaultOpen?: boolean;
106
- /** Fires whenever the sub-menu opens or closes. */
107
- onOpenChange?: (open: boolean) => void;
108
- /** SubTrigger + SubContent. */
109
- children?: React.ReactNode;
110
- }
111
-
112
- function MenubarSub({ ...props }: MenubarSubProps) {
113
- return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />;
114
- }
115
-
116
- export interface MenubarTriggerProps
117
- extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger> {
118
- /**
119
- * Disable this top-level trigger.
120
- * @default false
121
- */
122
- disabled?: boolean;
123
- /**
124
- * Render as a Radix Slot.
125
- * @default false
126
- */
127
- asChild?: boolean;
128
- /** Trigger label (typically a top-level menu name). */
129
- children?: React.ReactNode;
130
- className?: string;
131
- }
132
-
133
- const MenubarTrigger = React.forwardRef<
134
- React.ElementRef<typeof MenubarPrimitive.Trigger>,
135
- MenubarTriggerProps
136
- >(({ className, ...props }, ref) => (
137
- <MenubarPrimitive.Trigger
138
- ref={ref}
139
- className={cn(
140
- "flex cursor-default select-none items-center rounded-sm px-3 py-1 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
141
- className,
142
- )}
143
- {...props}
144
- />
145
- ));
146
- MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;
147
-
148
- export interface MenubarSubTriggerProps
149
- extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> {
150
- /**
151
- * Add left padding so this row aligns with sibling checkbox/radio
152
- * items that have leading indicators.
153
- * @default false
154
- */
155
- inset?: boolean;
156
- /**
157
- * Disable the sub-trigger.
158
- * @default false
159
- */
160
- disabled?: boolean;
161
- /**
162
- * Render as a Radix Slot.
163
- * @default false
164
- */
165
- asChild?: boolean;
166
- /** Sub-trigger label. */
167
- children?: React.ReactNode;
168
- className?: string;
169
- }
170
-
171
- const MenubarSubTrigger = React.forwardRef<
172
- React.ElementRef<typeof MenubarPrimitive.SubTrigger>,
173
- MenubarSubTriggerProps
174
- >(({ className, inset, children, ...props }, ref) => (
175
- <MenubarPrimitive.SubTrigger
176
- ref={ref}
177
- className={cn(
178
- "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
179
- inset && "pl-8",
180
- className,
181
- )}
182
- {...props}
183
- >
184
- {children}
185
- <ChevronRight className="ml-auto h-4 w-4" />
186
- </MenubarPrimitive.SubTrigger>
187
- ));
188
- MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;
189
-
190
- export interface MenubarSubContentProps
191
- extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent> {
192
- /** Distance from the parent menu (px). */
193
- sideOffset?: number;
194
- /** Distance from the alignment edge (px). */
195
- alignOffset?: number;
196
- /**
197
- * Avoid colliding with viewport edges.
198
- * @default true
199
- */
200
- avoidCollisions?: boolean;
201
- /** Force the sub-content to mount even when closed. */
202
- forceMount?: true;
203
- /**
204
- * Loop arrow-key navigation through items.
205
- * @default false
206
- */
207
- loop?: boolean;
208
- asChild?: boolean;
209
- /** Items + groups + separators. */
210
- children?: React.ReactNode;
211
- className?: string;
212
- }
213
-
214
- const MenubarSubContent = React.forwardRef<
215
- React.ElementRef<typeof MenubarPrimitive.SubContent>,
216
- MenubarSubContentProps
217
- >(({ className, ...props }, ref) => (
218
- <MenubarPrimitive.SubContent
219
- ref={ref}
220
- data-slot="menubar-sub-content"
221
- className={cn(
222
- "z-50 min-w-[8rem] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg 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 origin-[var(--radix-menubar-content-transform-origin)]",
223
- className,
224
- )}
225
- {...props}
226
- />
227
- ));
228
- MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;
229
-
230
- export interface MenubarContentProps
231
- extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content> {
232
- /**
233
- * Distance from the trigger (px).
234
- * @default 8
235
- */
236
- sideOffset?: number;
237
- /**
238
- * Distance from the alignment edge (px).
239
- * @default -4
240
- */
241
- alignOffset?: number;
242
- /**
243
- * Preferred side of the trigger to render on.
244
- * @default "bottom"
245
- */
246
- side?: "top" | "right" | "bottom" | "left";
247
- /**
248
- * Alignment along the chosen side.
249
- * @default "start"
250
- */
251
- align?: "start" | "center" | "end";
252
- /**
253
- * Avoid colliding with the viewport edges.
254
- * @default true
255
- */
256
- avoidCollisions?: boolean;
257
- /** Padding kept from collision boundaries. */
258
- collisionPadding?: number | { top?: number; right?: number; bottom?: number; left?: number };
259
- /** Loop arrow-key navigation through items. */
260
- loop?: boolean;
261
- /** Force the content to mount even when closed. */
262
- forceMount?: true;
263
- asChild?: boolean;
264
- /** Fires when the Escape key is pressed. */
265
- onEscapeKeyDown?: (event: KeyboardEvent) => void;
266
- /** Fires on pointer event outside the menu. */
267
- onPointerDownOutside?: (event: CustomEvent<{ originalEvent: PointerEvent }>) => void;
268
- /** Fires on any interaction outside (focus + pointer). */
269
- onInteractOutside?: (event: Event) => void;
270
- /** Items + groups + separators + sub-menus. */
271
- children?: React.ReactNode;
272
- className?: string;
273
- }
274
-
275
- const MenubarContent = React.forwardRef<
276
- React.ElementRef<typeof MenubarPrimitive.Content>,
277
- MenubarContentProps
278
- >(({ className, align = "start", alignOffset = -4, sideOffset = 8, ...props }, ref) => {
279
- const container = usePortalContainer();
280
- return (
281
- <MenubarPrimitive.Portal container={container ?? undefined}>
282
- <MenubarPrimitive.Content
283
- ref={ref}
284
- data-slot="menubar-content"
285
- align={align}
286
- alignOffset={alignOffset}
287
- sideOffset={sideOffset}
288
- className={cn(
289
- "z-50 min-w-[12rem] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in 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 origin-[var(--radix-menubar-content-transform-origin)]",
290
- className,
291
- )}
292
- {...props}
293
- />
294
- </MenubarPrimitive.Portal>
295
- );
296
- });
297
- MenubarContent.displayName = MenubarPrimitive.Content.displayName;
298
-
299
- export interface MenubarItemProps
300
- extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> {
301
- /**
302
- * Add left padding so this row aligns with sibling checkbox/radio
303
- * items that have leading indicators.
304
- * @default false
305
- */
306
- inset?: boolean;
307
- /**
308
- * Disable the item.
309
- * @default false
310
- */
311
- disabled?: boolean;
312
- /** Fires when the item is activated (click, Enter, Space). */
313
- onSelect?: (event: Event) => void;
314
- /**
315
- * Render as a Radix Slot — wrap a router `<Link>` to use the item as
316
- * navigation.
317
- * @default false
318
- */
319
- asChild?: boolean;
320
- /** Item label or any nested elements. */
321
- children?: React.ReactNode;
322
- className?: string;
323
- }
324
-
325
- const MenubarItem = React.forwardRef<
326
- React.ElementRef<typeof MenubarPrimitive.Item>,
327
- MenubarItemProps
328
- >(({ className, inset, ...props }, ref) => (
329
- <MenubarPrimitive.Item
330
- ref={ref}
331
- className={cn(
332
- "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
333
- inset && "pl-8",
334
- className,
335
- )}
336
- {...props}
337
- />
338
- ));
339
- MenubarItem.displayName = MenubarPrimitive.Item.displayName;
340
-
341
- export interface MenubarCheckboxItemProps
342
- extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem> {
343
- /** Controlled checked state. */
344
- checked?: boolean | "indeterminate";
345
- /** Fires when the user toggles the item. */
346
- onCheckedChange?: (checked: boolean) => void;
347
- /**
348
- * Disable the item.
349
- * @default false
350
- */
351
- disabled?: boolean;
352
- /** Fires when the item is activated. */
353
- onSelect?: (event: Event) => void;
354
- asChild?: boolean;
355
- /** Item label. */
356
- children?: React.ReactNode;
357
- className?: string;
358
- }
359
-
360
- const MenubarCheckboxItem = React.forwardRef<
361
- React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,
362
- MenubarCheckboxItemProps
363
- >(({ className, children, checked, ...props }, ref) => (
364
- <MenubarPrimitive.CheckboxItem
365
- ref={ref}
366
- className={cn(
367
- "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
368
- className,
369
- )}
370
- checked={checked}
371
- {...props}
372
- >
373
- <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
374
- <MenubarPrimitive.ItemIndicator>
375
- <Check className="h-4 w-4" />
376
- </MenubarPrimitive.ItemIndicator>
377
- </span>
378
- {children}
379
- </MenubarPrimitive.CheckboxItem>
380
- ));
381
- MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;
382
-
383
- export interface MenubarRadioItemProps
384
- extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem> {
385
- /** Required — value reported when this item is selected. Match parent `<RadioGroup>`'s value. */
386
- value: string;
387
- /**
388
- * Disable the item.
389
- * @default false
390
- */
391
- disabled?: boolean;
392
- /** Fires when the item is activated. */
393
- onSelect?: (event: Event) => void;
394
- asChild?: boolean;
395
- children?: React.ReactNode;
396
- className?: string;
397
- }
398
-
399
- const MenubarRadioItem = React.forwardRef<
400
- React.ElementRef<typeof MenubarPrimitive.RadioItem>,
401
- MenubarRadioItemProps
402
- >(({ className, children, ...props }, ref) => (
403
- <MenubarPrimitive.RadioItem
404
- ref={ref}
405
- className={cn(
406
- "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
407
- className,
408
- )}
409
- {...props}
410
- >
411
- <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
412
- <MenubarPrimitive.ItemIndicator>
413
- <Circle className="h-4 w-4 fill-current" />
414
- </MenubarPrimitive.ItemIndicator>
415
- </span>
416
- {children}
417
- </MenubarPrimitive.RadioItem>
418
- ));
419
- MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;
420
-
421
- export interface MenubarLabelProps
422
- extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> {
423
- /**
424
- * Add left padding so this row aligns with sibling checkbox/radio
425
- * items.
426
- * @default false
427
- */
428
- inset?: boolean;
429
- asChild?: boolean;
430
- /** Section heading text. */
431
- children?: React.ReactNode;
432
- className?: string;
433
- }
434
-
435
- const MenubarLabel = React.forwardRef<
436
- React.ElementRef<typeof MenubarPrimitive.Label>,
437
- MenubarLabelProps
438
- >(({ className, inset, ...props }, ref) => (
439
- <MenubarPrimitive.Label
440
- ref={ref}
441
- className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)}
442
- {...props}
443
- />
444
- ));
445
- MenubarLabel.displayName = MenubarPrimitive.Label.displayName;
446
-
447
- export interface MenubarSeparatorProps
448
- extends React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator> {
449
- asChild?: boolean;
450
- className?: string;
451
- }
452
-
453
- const MenubarSeparator = React.forwardRef<
454
- React.ElementRef<typeof MenubarPrimitive.Separator>,
455
- MenubarSeparatorProps
456
- >(({ className, ...props }, ref) => (
457
- <MenubarPrimitive.Separator
458
- ref={ref}
459
- className={cn("-mx-1 my-1 h-px bg-muted", className)}
460
- {...props}
461
- />
462
- ));
463
- MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;
464
-
465
- export interface MenubarShortcutProps extends React.HTMLAttributes<HTMLSpanElement> {
466
- /** Keyboard shortcut text (e.g. "⌘K", "⌃Z"). */
467
- children?: React.ReactNode;
468
- className?: string;
469
- }
470
-
471
- const MenubarShortcut = ({ className, ...props }: MenubarShortcutProps) => {
472
- return (
473
- <span
474
- className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)}
475
- {...props}
476
- />
477
- );
478
- };
479
- MenubarShortcut.displayName = "MenubarShortcut";
480
-
481
- export {
482
- Menubar,
483
- MenubarCheckboxItem,
484
- MenubarContent,
485
- MenubarGroup,
486
- MenubarItem,
487
- MenubarLabel,
488
- MenubarMenu,
489
- MenubarPortal,
490
- MenubarRadioGroup,
491
- MenubarRadioItem,
492
- MenubarSeparator,
493
- MenubarShortcut,
494
- MenubarSub,
495
- MenubarSubContent,
496
- MenubarSubTrigger,
497
- MenubarTrigger,
498
- };
@@ -1,104 +0,0 @@
1
- "use client";
2
-
3
- import { Menu, X } from "lucide-react";
4
- import * as React from "react";
5
-
6
- import { cn } from "../../lib/utils";
7
- import { Button } from "../atoms/button";
8
-
9
- export interface NavLink {
10
- label: string;
11
- href: string;
12
- external?: boolean;
13
- }
14
-
15
- export interface NavBarProps extends React.HTMLAttributes<HTMLElement> {
16
- logo?: React.ReactNode;
17
- links?: NavLink[];
18
- actions?: React.ReactNode;
19
- /**
20
- * When `true` (default) the bar uses `position: sticky` + `top: 0` so it
21
- * stays anchored to the top of its scroll container while page content
22
- * scrolls underneath. The translucent background + `backdrop-blur` creates
23
- * a frosted-glass effect through which the scrolling content reads.
24
- * Set `false` to render inline (e.g. for examples or non-sticky layouts).
25
- */
26
- sticky?: boolean;
27
- /** Custom link component (e.g. Next.js Link) for client-side navigation */
28
- linkComponent?: React.ElementType;
29
- }
30
-
31
- const NavBar = React.forwardRef<HTMLElement, NavBarProps>(
32
- ({ logo, links = [], actions, sticky = true, linkComponent, className, ...props }, ref) => {
33
- const [mobileOpen, setMobileOpen] = React.useState(false);
34
- const LinkEl = linkComponent || "a";
35
-
36
- return (
37
- <nav
38
- ref={ref}
39
- className={cn(
40
- "z-50 border-b border-border bg-background/80 backdrop-blur",
41
- sticky && "sticky top-0",
42
- className,
43
- )}
44
- {...props}
45
- >
46
- <div className="mx-auto flex h-14 max-w-6xl items-center justify-between px-4 sm:px-6">
47
- {/* Logo */}
48
- {logo && <div className="shrink-0">{logo}</div>}
49
-
50
- {/* Desktop links */}
51
- <div className="hidden items-center gap-6 md:flex">
52
- {links.map((link) => (
53
- <LinkEl
54
- key={link.href}
55
- href={link.href}
56
- className="text-sm font-medium text-muted-foreground no-underline transition-colors hover:text-brand"
57
- {...(link.external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
58
- >
59
- {link.label}
60
- </LinkEl>
61
- ))}
62
- {actions}
63
- </div>
64
-
65
- {/* Mobile hamburger */}
66
- {(links.length > 0 || actions) && (
67
- <Button
68
- variant="ghost"
69
- size="icon"
70
- className="md:hidden"
71
- onClick={() => setMobileOpen((v) => !v)}
72
- aria-label={mobileOpen ? "Close menu" : "Open menu"}
73
- >
74
- {mobileOpen ? <X className="h-5 w-5" /> : <Menu className="h-5 w-5" />}
75
- </Button>
76
- )}
77
- </div>
78
-
79
- {/* Mobile dropdown */}
80
- {mobileOpen && (
81
- <div className="border-t md:hidden">
82
- <div className="flex flex-col gap-1 px-4 py-3 sm:px-6">
83
- {links.map((link) => (
84
- <LinkEl
85
- key={link.href}
86
- href={link.href}
87
- onClick={() => setMobileOpen(false)}
88
- className="rounded-md px-3 py-2.5 text-sm font-medium text-muted-foreground no-underline transition-colors hover:bg-accent hover:text-brand"
89
- {...(link.external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
90
- >
91
- {link.label}
92
- </LinkEl>
93
- ))}
94
- {actions && <div className="px-3 py-2.5">{actions}</div>}
95
- </div>
96
- </div>
97
- )}
98
- </nav>
99
- );
100
- },
101
- );
102
- NavBar.displayName = "NavBar";
103
-
104
- export { NavBar };