@olympusoss/canvas 2.20.2 → 4.0.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 (208) hide show
  1. package/package.json +41 -177
  2. package/src/cn.ts +3 -0
  3. package/src/index.ts +12 -603
  4. package/src/theme.ts +41 -0
  5. package/src/tokens.ts +11 -0
  6. package/styles/base.css +17 -0
  7. package/styles/canvas.css +69 -52
  8. package/styles/components/alert.css +66 -0
  9. package/styles/components/app-shell.css +46 -0
  10. package/styles/components/avatar.css +15 -0
  11. package/styles/components/badge.css +83 -0
  12. package/styles/components/breadcrumb.css +35 -0
  13. package/styles/components/button-group.css +23 -0
  14. package/styles/components/button.css +107 -0
  15. package/styles/components/calendar.css +73 -0
  16. package/styles/components/card.css +58 -0
  17. package/styles/components/checkbox.css +55 -0
  18. package/styles/components/code-block.css +18 -0
  19. package/styles/components/combobox.css +75 -0
  20. package/styles/components/command.css +94 -0
  21. package/styles/components/data-table.css +142 -0
  22. package/styles/components/dialog.css +72 -0
  23. package/styles/components/dropdown.css +54 -0
  24. package/styles/components/empty-state.css +17 -0
  25. package/styles/components/field.css +27 -0
  26. package/styles/components/filter-panel.css +58 -0
  27. package/styles/components/form.css +27 -0
  28. package/styles/components/icon.css +8 -0
  29. package/styles/components/input-group.css +45 -0
  30. package/styles/components/input.css +56 -0
  31. package/styles/components/kbd.css +15 -0
  32. package/styles/components/page-header.css +52 -0
  33. package/styles/components/pagination.css +48 -0
  34. package/styles/components/popover.css +14 -0
  35. package/styles/components/radio.css +28 -0
  36. package/styles/components/row-menu.css +69 -0
  37. package/styles/components/section-card.css +49 -0
  38. package/styles/components/select.css +57 -0
  39. package/styles/components/separator.css +32 -0
  40. package/styles/components/sheet.css +70 -0
  41. package/styles/components/sidebar.css +146 -0
  42. package/styles/components/skeleton.css +32 -0
  43. package/styles/components/spinner.css +26 -0
  44. package/styles/components/stat-card.css +71 -0
  45. package/styles/components/stepper.css +63 -0
  46. package/styles/components/switch.css +45 -0
  47. package/styles/components/tabs.css +40 -0
  48. package/styles/components/textarea.css +31 -0
  49. package/styles/components/toast.css +95 -0
  50. package/styles/components/tooltip.css +53 -0
  51. package/styles/components/topbar.css +24 -0
  52. package/styles/components/typography.css +105 -0
  53. package/styles/patterns/backdrops.css +35 -0
  54. package/styles/patterns/density.css +66 -0
  55. package/styles/patterns/focus.css +38 -0
  56. package/styles/patterns/glass.css +85 -0
  57. package/styles/patterns/high-contrast.css +70 -0
  58. package/styles/patterns/reduced-motion.css +12 -0
  59. package/styles/patterns/scrollbar.css +10 -0
  60. package/styles/reset.css +89 -0
  61. package/styles/tokens/colors.css +106 -0
  62. package/styles/tokens/motion.css +33 -0
  63. package/styles/tokens/radius.css +10 -0
  64. package/styles/tokens/shadows.css +35 -0
  65. package/styles/tokens/spacing.css +19 -0
  66. package/styles/tokens/typography.css +6 -0
  67. package/styles/tokens/z-index.css +12 -0
  68. package/tsconfig.json +20 -21
  69. package/README.md +0 -60
  70. package/src/components/atoms/README.md +0 -11
  71. package/src/components/atoms/aspect-ratio.tsx +0 -32
  72. package/src/components/atoms/avatar.tsx +0 -98
  73. package/src/components/atoms/badge.tsx +0 -44
  74. package/src/components/atoms/brand-mark.tsx +0 -74
  75. package/src/components/atoms/button.tsx +0 -105
  76. package/src/components/atoms/checkbox.tsx +0 -63
  77. package/src/components/atoms/flex-box.tsx +0 -105
  78. package/src/components/atoms/icon.tsx +0 -34
  79. package/src/components/atoms/input.tsx +0 -92
  80. package/src/components/atoms/label.tsx +0 -41
  81. package/src/components/atoms/logo.tsx +0 -89
  82. package/src/components/atoms/progress.tsx +0 -55
  83. package/src/components/atoms/radio-group.tsx +0 -122
  84. package/src/components/atoms/scroll-area.tsx +0 -106
  85. package/src/components/atoms/section.tsx +0 -48
  86. package/src/components/atoms/separator.tsx +0 -45
  87. package/src/components/atoms/skeleton.tsx +0 -17
  88. package/src/components/atoms/slider.tsx +0 -93
  89. package/src/components/atoms/spinner.tsx +0 -47
  90. package/src/components/atoms/switch.tsx +0 -60
  91. package/src/components/atoms/textarea.tsx +0 -78
  92. package/src/components/atoms/toggle.tsx +0 -80
  93. package/src/components/charts/activity-heatmap.tsx +0 -186
  94. package/src/components/charts/axes.tsx +0 -21
  95. package/src/components/charts/chart-container.tsx +0 -254
  96. package/src/components/charts/chart-legend.tsx +0 -67
  97. package/src/components/charts/chart-tooltip.tsx +0 -161
  98. package/src/components/charts/chart-types.tsx +0 -49
  99. package/src/components/charts/containers.tsx +0 -11
  100. package/src/components/charts/data.tsx +0 -16
  101. package/src/components/charts/details.tsx +0 -25
  102. package/src/components/charts/dot-pulse.tsx +0 -61
  103. package/src/components/charts/gauge.tsx +0 -106
  104. package/src/components/charts/grids.tsx +0 -8
  105. package/src/components/charts/index.ts +0 -62
  106. package/src/components/charts/labeled-bar-list.tsx +0 -85
  107. package/src/components/charts/metric-breakdown.tsx +0 -316
  108. package/src/components/charts/references.tsx +0 -8
  109. package/src/components/charts/service-health-list.tsx +0 -85
  110. package/src/components/charts/sparkline-area.tsx +0 -80
  111. package/src/components/charts/sparkline.tsx +0 -52
  112. package/src/components/charts/stacked-bar.tsx +0 -104
  113. package/src/components/charts/text.tsx +0 -10
  114. package/src/components/charts/world-heat-map-inner.tsx +0 -317
  115. package/src/components/charts/world-heat-map.tsx +0 -184
  116. package/src/components/molecules/README.md +0 -12
  117. package/src/components/molecules/action-bar.tsx +0 -73
  118. package/src/components/molecules/activity-item.tsx +0 -74
  119. package/src/components/molecules/alert.tsx +0 -86
  120. package/src/components/molecules/animated-background.tsx +0 -92
  121. package/src/components/molecules/auth-shell.tsx +0 -95
  122. package/src/components/molecules/brand-lockup.tsx +0 -48
  123. package/src/components/molecules/breadcrumb.tsx +0 -157
  124. package/src/components/molecules/button-group.tsx +0 -104
  125. package/src/components/molecules/calendar.tsx +0 -217
  126. package/src/components/molecules/card.tsx +0 -102
  127. package/src/components/molecules/client-brand.tsx +0 -95
  128. package/src/components/molecules/code-block.tsx +0 -86
  129. package/src/components/molecules/countdown-button.tsx +0 -92
  130. package/src/components/molecules/empty-state.tsx +0 -56
  131. package/src/components/molecules/error-state.tsx +0 -42
  132. package/src/components/molecules/field-display.tsx +0 -35
  133. package/src/components/molecules/input-otp.tsx +0 -74
  134. package/src/components/molecules/launcher-card.tsx +0 -152
  135. package/src/components/molecules/loading-state.tsx +0 -36
  136. package/src/components/molecules/notification-item.tsx +0 -67
  137. package/src/components/molecules/notification-list.tsx +0 -45
  138. package/src/components/molecules/number-badge.tsx +0 -53
  139. package/src/components/molecules/or-separator.tsx +0 -38
  140. package/src/components/molecules/page-header.tsx +0 -88
  141. package/src/components/molecules/page-tabs.tsx +0 -94
  142. package/src/components/molecules/pagination.tsx +0 -150
  143. package/src/components/molecules/password-input.tsx +0 -83
  144. package/src/components/molecules/password-strength-meter.tsx +0 -104
  145. package/src/components/molecules/phone-input.tsx +0 -200
  146. package/src/components/molecules/search-bar.tsx +0 -64
  147. package/src/components/molecules/secret-field.tsx +0 -158
  148. package/src/components/molecules/section-card.tsx +0 -91
  149. package/src/components/molecules/social-buttons.tsx +0 -165
  150. package/src/components/molecules/stat-card.tsx +0 -100
  151. package/src/components/molecules/status-badge.tsx +0 -42
  152. package/src/components/molecules/stepper.tsx +0 -96
  153. package/src/components/molecules/table.tsx +0 -157
  154. package/src/components/molecules/terminal.tsx +0 -74
  155. package/src/components/molecules/toggle-group.tsx +0 -145
  156. package/src/components/molecules/tooltip.tsx +0 -155
  157. package/src/components/molecules/user-avatar-chip.tsx +0 -71
  158. package/src/components/organisms/README.md +0 -14
  159. package/src/components/organisms/accordion.tsx +0 -154
  160. package/src/components/organisms/alert-dialog.tsx +0 -277
  161. package/src/components/organisms/carousel.tsx +0 -244
  162. package/src/components/organisms/collapsible.tsx +0 -69
  163. package/src/components/organisms/command.tsx +0 -144
  164. package/src/components/organisms/context-menu.tsx +0 -339
  165. package/src/components/organisms/dashboard-grid.tsx +0 -369
  166. package/src/components/organisms/data-table.tsx +0 -330
  167. package/src/components/organisms/dialog.tsx +0 -312
  168. package/src/components/organisms/drawer.tsx +0 -123
  169. package/src/components/organisms/dropdown-menu.tsx +0 -440
  170. package/src/components/organisms/editors/code-editor.tsx +0 -144
  171. package/src/components/organisms/editors/index.ts +0 -4
  172. package/src/components/organisms/editors/markdown-editor.tsx +0 -153
  173. package/src/components/organisms/editors/markdown-renderer.ts +0 -27
  174. package/src/components/organisms/editors/prose-canvas-classes.ts +0 -45
  175. package/src/components/organisms/editors/rich-text-editor.tsx +0 -126
  176. package/src/components/organisms/editors/toolbar/md-toolbar.tsx +0 -129
  177. package/src/components/organisms/editors/toolbar/rte-toolbar.tsx +0 -211
  178. package/src/components/organisms/editors/toolbar/toolbar-shell.tsx +0 -45
  179. package/src/components/organisms/editors/use-codemirror-theme.ts +0 -61
  180. package/src/components/organisms/error-boundary.tsx +0 -61
  181. package/src/components/organisms/form.tsx +0 -174
  182. package/src/components/organisms/hover-card.tsx +0 -115
  183. package/src/components/organisms/menubar.tsx +0 -498
  184. package/src/components/organisms/navbar.tsx +0 -104
  185. package/src/components/organisms/navigation-menu.tsx +0 -235
  186. package/src/components/organisms/popover.tsx +0 -149
  187. package/src/components/organisms/resizable.tsx +0 -58
  188. package/src/components/organisms/schema-form.tsx +0 -232
  189. package/src/components/organisms/select.tsx +0 -309
  190. package/src/components/organisms/sheet.tsx +0 -265
  191. package/src/components/organisms/sidebar.tsx +0 -1040
  192. package/src/components/organisms/sonner.tsx +0 -96
  193. package/src/components/organisms/tabs.tsx +0 -133
  194. package/src/components/organisms/theme-provider.tsx +0 -101
  195. package/src/hooks/use-mobile.tsx +0 -19
  196. package/src/lib/portal-container.tsx +0 -35
  197. package/src/lib/utils.ts +0 -6
  198. package/src/native.ts +0 -23
  199. package/src/tokens/colors.ts +0 -91
  200. package/src/tokens/index.ts +0 -3
  201. package/src/tokens/spacing.ts +0 -55
  202. package/src/tokens/typography.ts +0 -27
  203. package/styles/dashboard-grid.css +0 -47
  204. package/styles/fonts/Roboto-VariableFont_wdth_wght.ttf +0 -0
  205. package/styles/glass.css +0 -175
  206. package/styles/leaflet.css +0 -13
  207. package/styles/tokens.css +0 -317
  208. package/tailwind.config.ts +0 -70
@@ -1,154 +0,0 @@
1
- "use client";
2
-
3
- import * as AccordionPrimitive from "@radix-ui/react-accordion";
4
- import { ChevronDown } from "lucide-react";
5
- import * as React from "react";
6
-
7
- import { cn } from "../../lib/utils";
8
-
9
- export interface AccordionProps {
10
- /**
11
- * Selection mode. `"single"` allows one item open at a time;
12
- * `"multiple"` allows multiple items open simultaneously.
13
- */
14
- type: "single" | "multiple";
15
- /**
16
- * Controlled value. For `type="single"` it's a string (id of the open
17
- * item); for `type="multiple"` it's a string array.
18
- */
19
- value?: string | string[];
20
- /** Initial value for uncontrolled usage. */
21
- defaultValue?: string | string[];
22
- /** Fires when the user opens/closes an item. */
23
- onValueChange?: (value: string & string[]) => void;
24
- /**
25
- * For `type="single"` only — when true, an open item can be collapsed
26
- * by clicking it again.
27
- * @default false
28
- */
29
- collapsible?: boolean;
30
- /**
31
- * Disable the entire accordion.
32
- * @default false
33
- */
34
- disabled?: boolean;
35
- /**
36
- * Reading direction. Affects keyboard arrow navigation.
37
- * @default "ltr"
38
- */
39
- dir?: "ltr" | "rtl";
40
- /**
41
- * Layout direction.
42
- * @default "vertical"
43
- */
44
- orientation?: "vertical" | "horizontal";
45
- /**
46
- * Render as a Radix Slot.
47
- * @default false
48
- */
49
- asChild?: boolean;
50
- /** A list of `<AccordionItem>`s. */
51
- children?: React.ReactNode;
52
- className?: string;
53
- }
54
-
55
- const Accordion = AccordionPrimitive.Root as React.ForwardRefExoticComponent<
56
- AccordionProps & React.RefAttributes<HTMLDivElement>
57
- >;
58
-
59
- export interface AccordionItemProps
60
- extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item> {
61
- /** Required — unique value identifying this item. */
62
- value: string;
63
- /**
64
- * Disable only this item.
65
- * @default false
66
- */
67
- disabled?: boolean;
68
- /**
69
- * Render as a Radix Slot.
70
- * @default false
71
- */
72
- asChild?: boolean;
73
- /** A `<AccordionTrigger>` + `<AccordionContent>`. */
74
- children?: React.ReactNode;
75
- className?: string;
76
- }
77
-
78
- const AccordionItem = React.forwardRef<
79
- React.ElementRef<typeof AccordionPrimitive.Item>,
80
- AccordionItemProps
81
- >(({ className, ...props }, ref) => (
82
- <AccordionPrimitive.Item
83
- ref={ref}
84
- data-slot="accordion-item"
85
- className={cn("border-b", className)}
86
- {...props}
87
- />
88
- ));
89
- AccordionItem.displayName = "AccordionItem";
90
-
91
- export interface AccordionTriggerProps
92
- extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger> {
93
- /**
94
- * Render as a Radix Slot.
95
- * @default false
96
- */
97
- asChild?: boolean;
98
- /** Trigger label — typically a section heading. */
99
- children?: React.ReactNode;
100
- className?: string;
101
- }
102
-
103
- const AccordionTrigger = React.forwardRef<
104
- React.ElementRef<typeof AccordionPrimitive.Trigger>,
105
- AccordionTriggerProps
106
- >(({ className, children, ...props }, ref) => (
107
- <AccordionPrimitive.Header className="flex">
108
- <AccordionPrimitive.Trigger
109
- ref={ref}
110
- className={cn(
111
- "flex flex-1 items-center justify-between py-4 text-sm font-medium transition-colors hover:text-brand text-left [&[data-state=open]>svg]:rotate-180",
112
- className,
113
- )}
114
- {...props}
115
- >
116
- {children}
117
- <ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" />
118
- </AccordionPrimitive.Trigger>
119
- </AccordionPrimitive.Header>
120
- ));
121
- AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
122
-
123
- export interface AccordionContentProps
124
- extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content> {
125
- /**
126
- * Force the content to mount even when collapsed.
127
- * @default false
128
- */
129
- forceMount?: true;
130
- /**
131
- * Render as a Radix Slot.
132
- * @default false
133
- */
134
- asChild?: boolean;
135
- /** Item body. */
136
- children?: React.ReactNode;
137
- className?: string;
138
- }
139
-
140
- const AccordionContent = React.forwardRef<
141
- React.ElementRef<typeof AccordionPrimitive.Content>,
142
- AccordionContentProps
143
- >(({ className, children, ...props }, ref) => (
144
- <AccordionPrimitive.Content
145
- ref={ref}
146
- className="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
147
- {...props}
148
- >
149
- <div className={cn("pb-4 pt-0", className)}>{children}</div>
150
- </AccordionPrimitive.Content>
151
- ));
152
- AccordionContent.displayName = AccordionPrimitive.Content.displayName;
153
-
154
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };
@@ -1,277 +0,0 @@
1
- "use client";
2
-
3
- import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
4
- import * as React from "react";
5
-
6
- import { usePortalContainer } from "../../lib/portal-container";
7
- import { cn } from "../../lib/utils";
8
- import { buttonVariants } from "../atoms/button";
9
-
10
- export interface AlertDialogProps extends React.ComponentProps<typeof AlertDialogPrimitive.Root> {
11
- /** Controlled open state. Pair with `onOpenChange`. */
12
- open?: boolean;
13
- /**
14
- * Initial open state for uncontrolled usage.
15
- * @default false
16
- */
17
- defaultOpen?: boolean;
18
- /** Fires whenever the dialog opens or closes. */
19
- onOpenChange?: (open: boolean) => void;
20
- /** Trigger + Content. */
21
- children?: React.ReactNode;
22
- }
23
-
24
- const AlertDialog = AlertDialogPrimitive.Root as React.FC<AlertDialogProps>;
25
-
26
- export interface AlertDialogTriggerProps
27
- extends React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Trigger> {
28
- /**
29
- * Render as a Radix Slot — forwards props onto the immediate child.
30
- * @default false
31
- */
32
- asChild?: boolean;
33
- /** The button (or slot) that opens the alert. */
34
- children?: React.ReactNode;
35
- /** Tailwind / CSS classes merged via `cn()`. */
36
- className?: string;
37
- }
38
-
39
- const AlertDialogTrigger = AlertDialogPrimitive.Trigger as React.ForwardRefExoticComponent<
40
- AlertDialogTriggerProps & React.RefAttributes<HTMLButtonElement>
41
- >;
42
-
43
- export interface AlertDialogPortalProps
44
- extends React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Portal> {
45
- /** DOM element to portal into. Defaults to `document.body`. */
46
- container?: HTMLElement | null;
47
- /**
48
- * Force the portal to mount its children even when closed.
49
- * @default false
50
- */
51
- forceMount?: true;
52
- children?: React.ReactNode;
53
- }
54
-
55
- const AlertDialogPortal = AlertDialogPrimitive.Portal as React.FC<AlertDialogPortalProps>;
56
-
57
- export interface AlertDialogOverlayProps
58
- extends React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay> {
59
- /**
60
- * Render as a Radix Slot — forwards props onto the immediate child.
61
- * @default false
62
- */
63
- asChild?: boolean;
64
- /**
65
- * Force the overlay to mount even when closed.
66
- * @default false
67
- */
68
- forceMount?: true;
69
- /** Tailwind / CSS classes merged via `cn()`. */
70
- className?: string;
71
- }
72
-
73
- const AlertDialogOverlay = React.forwardRef<
74
- React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
75
- AlertDialogOverlayProps
76
- >(({ className, ...props }, ref) => (
77
- <AlertDialogPrimitive.Overlay
78
- className={cn(
79
- "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
80
- className,
81
- )}
82
- {...props}
83
- ref={ref}
84
- />
85
- ));
86
- AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
87
-
88
- export interface AlertDialogContentProps
89
- extends React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content> {
90
- /**
91
- * Render as a Radix Slot — forwards props onto the immediate child.
92
- * @default false
93
- */
94
- asChild?: boolean;
95
- /**
96
- * Force the content to mount even when closed. Useful for
97
- * exit animations.
98
- * @default false
99
- */
100
- forceMount?: true;
101
- /** Fires when focus enters the dialog after it opens. */
102
- onOpenAutoFocus?: (event: Event) => void;
103
- /** Fires when focus leaves the dialog after it closes. */
104
- onCloseAutoFocus?: (event: Event) => void;
105
- /** Fires when the Escape key is pressed. */
106
- onEscapeKeyDown?: (event: KeyboardEvent) => void;
107
- /**
108
- * Title + Description + Footer (with `<AlertDialogAction>` and
109
- * `<AlertDialogCancel>`).
110
- */
111
- children?: React.ReactNode;
112
- /** Tailwind / CSS classes merged via `cn()`. */
113
- className?: string;
114
- }
115
-
116
- const AlertDialogContent = React.forwardRef<
117
- React.ElementRef<typeof AlertDialogPrimitive.Content>,
118
- AlertDialogContentProps
119
- >(({ className, ...props }, ref) => {
120
- const container = usePortalContainer();
121
- return (
122
- <AlertDialogPortal container={container ?? undefined}>
123
- <AlertDialogOverlay />
124
- <AlertDialogPrimitive.Content
125
- ref={ref}
126
- data-slot="alert-dialog-content"
127
- className={cn(
128
- "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border border-border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
129
- className,
130
- )}
131
- {...props}
132
- />
133
- </AlertDialogPortal>
134
- );
135
- });
136
- AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
137
-
138
- export interface AlertDialogHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
139
- /** Title + optional description. */
140
- children?: React.ReactNode;
141
- /** Tailwind / CSS classes merged via `cn()`. */
142
- className?: string;
143
- }
144
-
145
- const AlertDialogHeader = ({ className, ...props }: AlertDialogHeaderProps) => (
146
- <div className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...props} />
147
- );
148
- AlertDialogHeader.displayName = "AlertDialogHeader";
149
-
150
- export interface AlertDialogFooterProps extends React.HTMLAttributes<HTMLDivElement> {
151
- /** Action + Cancel buttons. */
152
- children?: React.ReactNode;
153
- /** Tailwind / CSS classes merged via `cn()`. */
154
- className?: string;
155
- }
156
-
157
- const AlertDialogFooter = ({ className, ...props }: AlertDialogFooterProps) => (
158
- <div
159
- className={cn(
160
- "flex flex-col-reverse gap-2 sm:flex-row sm:items-center sm:justify-end",
161
- className,
162
- )}
163
- {...props}
164
- />
165
- );
166
- AlertDialogFooter.displayName = "AlertDialogFooter";
167
-
168
- export interface AlertDialogTitleProps
169
- extends React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title> {
170
- /**
171
- * Render as a Radix Slot — useful to swap the heading level.
172
- * @default false
173
- */
174
- asChild?: boolean;
175
- /** Title text. */
176
- children?: React.ReactNode;
177
- /** Tailwind / CSS classes merged via `cn()`. */
178
- className?: string;
179
- }
180
-
181
- const AlertDialogTitle = React.forwardRef<
182
- React.ElementRef<typeof AlertDialogPrimitive.Title>,
183
- AlertDialogTitleProps
184
- >(({ className, ...props }, ref) => (
185
- <AlertDialogPrimitive.Title
186
- ref={ref}
187
- className={cn("text-lg font-semibold", className)}
188
- {...props}
189
- />
190
- ));
191
- AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
192
-
193
- export interface AlertDialogDescriptionProps
194
- extends React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description> {
195
- /**
196
- * Render as a Radix Slot.
197
- * @default false
198
- */
199
- asChild?: boolean;
200
- /** Description text shown below the title. */
201
- children?: React.ReactNode;
202
- /** Tailwind / CSS classes merged via `cn()`. */
203
- className?: string;
204
- }
205
-
206
- const AlertDialogDescription = React.forwardRef<
207
- React.ElementRef<typeof AlertDialogPrimitive.Description>,
208
- AlertDialogDescriptionProps
209
- >(({ className, ...props }, ref) => (
210
- <AlertDialogPrimitive.Description
211
- ref={ref}
212
- className={cn("text-sm text-muted-foreground", className)}
213
- {...props}
214
- />
215
- ));
216
- AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
217
-
218
- export interface AlertDialogActionProps
219
- extends React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action> {
220
- /**
221
- * Render as a Radix Slot — wrap a custom button while still hooking the
222
- * dialog's commit behaviour.
223
- * @default false
224
- */
225
- asChild?: boolean;
226
- /** Action label (e.g. "Delete", "Confirm"). */
227
- children?: React.ReactNode;
228
- /** Tailwind / CSS classes merged via `cn()`. Defaults to canvas's primary button. */
229
- className?: string;
230
- }
231
-
232
- const AlertDialogAction = React.forwardRef<
233
- React.ElementRef<typeof AlertDialogPrimitive.Action>,
234
- AlertDialogActionProps
235
- >(({ className, ...props }, ref) => (
236
- <AlertDialogPrimitive.Action ref={ref} className={cn(buttonVariants(), className)} {...props} />
237
- ));
238
- AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
239
-
240
- export interface AlertDialogCancelProps
241
- extends React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel> {
242
- /**
243
- * Render as a Radix Slot.
244
- * @default false
245
- */
246
- asChild?: boolean;
247
- /** Cancel label (e.g. "Cancel", "Keep editing"). */
248
- children?: React.ReactNode;
249
- /** Tailwind / CSS classes merged via `cn()`. Defaults to canvas's outline button. */
250
- className?: string;
251
- }
252
-
253
- const AlertDialogCancel = React.forwardRef<
254
- React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
255
- AlertDialogCancelProps
256
- >(({ className, ...props }, ref) => (
257
- <AlertDialogPrimitive.Cancel
258
- ref={ref}
259
- className={cn(buttonVariants({ variant: "outline" }), className)}
260
- {...props}
261
- />
262
- ));
263
- AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
264
-
265
- export {
266
- AlertDialog,
267
- AlertDialogAction,
268
- AlertDialogCancel,
269
- AlertDialogContent,
270
- AlertDialogDescription,
271
- AlertDialogFooter,
272
- AlertDialogHeader,
273
- AlertDialogOverlay,
274
- AlertDialogPortal,
275
- AlertDialogTitle,
276
- AlertDialogTrigger,
277
- };
@@ -1,244 +0,0 @@
1
- "use client";
2
-
3
- import useEmblaCarousel, { type UseEmblaCarouselType } from "embla-carousel-react";
4
- import { ArrowLeft, ArrowRight } from "lucide-react";
5
- import * as React from "react";
6
-
7
- import { cn } from "../../lib/utils";
8
- import { Button } from "../atoms/button";
9
-
10
- type CarouselApi = UseEmblaCarouselType[1];
11
- type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
12
- type CarouselOptions = UseCarouselParameters[0];
13
- type CarouselPlugin = UseCarouselParameters[1];
14
-
15
- type CarouselProps = {
16
- opts?: CarouselOptions;
17
- plugins?: CarouselPlugin;
18
- orientation?: "horizontal" | "vertical";
19
- setApi?: (api: CarouselApi) => void;
20
- };
21
-
22
- type CarouselContextProps = {
23
- carouselRef: ReturnType<typeof useEmblaCarousel>[0];
24
- api: ReturnType<typeof useEmblaCarousel>[1];
25
- scrollPrev: () => void;
26
- scrollNext: () => void;
27
- canScrollPrev: boolean;
28
- canScrollNext: boolean;
29
- } & CarouselProps;
30
-
31
- const CarouselContext = React.createContext<CarouselContextProps | null>(null);
32
-
33
- function useCarousel() {
34
- const context = React.useContext(CarouselContext);
35
-
36
- if (!context) {
37
- throw new Error("useCarousel must be used within a <Carousel />");
38
- }
39
-
40
- return context;
41
- }
42
-
43
- const Carousel = React.forwardRef<
44
- HTMLDivElement,
45
- React.HTMLAttributes<HTMLDivElement> & CarouselProps
46
- >(({ orientation = "horizontal", opts, setApi, plugins, className, children, ...props }, ref) => {
47
- const [carouselRef, api] = useEmblaCarousel(
48
- {
49
- ...opts,
50
- axis: orientation === "horizontal" ? "x" : "y",
51
- },
52
- plugins,
53
- );
54
- const [canScrollPrev, setCanScrollPrev] = React.useState(false);
55
- const [canScrollNext, setCanScrollNext] = React.useState(false);
56
-
57
- const onSelect = React.useCallback((api: CarouselApi) => {
58
- /* c8 ignore next 3 -- defensive guard: Embla always provides api in the onSelect handler */
59
- if (!api) {
60
- return;
61
- }
62
-
63
- setCanScrollPrev(api.canScrollPrev());
64
- setCanScrollNext(api.canScrollNext());
65
- }, []);
66
-
67
- const scrollPrev = React.useCallback(() => {
68
- api?.scrollPrev();
69
- }, [api]);
70
-
71
- const scrollNext = React.useCallback(() => {
72
- api?.scrollNext();
73
- }, [api]);
74
-
75
- const handleKeyDown = React.useCallback(
76
- (event: React.KeyboardEvent<HTMLDivElement>) => {
77
- if (event.key === "ArrowLeft") {
78
- event.preventDefault();
79
- scrollPrev();
80
- } else if (event.key === "ArrowRight") {
81
- event.preventDefault();
82
- scrollNext();
83
- }
84
- },
85
- [scrollPrev, scrollNext],
86
- );
87
-
88
- React.useEffect(() => {
89
- if (!api || !setApi) {
90
- return;
91
- }
92
-
93
- setApi(api);
94
- }, [api, setApi]);
95
-
96
- React.useEffect(() => {
97
- if (!api) {
98
- return;
99
- }
100
-
101
- onSelect(api);
102
- api.on("reInit", onSelect);
103
- api.on("select", onSelect);
104
-
105
- return () => {
106
- api?.off("select", onSelect);
107
- };
108
- }, [api, onSelect]);
109
-
110
- return (
111
- <CarouselContext.Provider
112
- value={{
113
- carouselRef,
114
- api: api,
115
- opts,
116
- // `orientation` is always defined (default: "horizontal"). No fallback needed.
117
- orientation,
118
- scrollPrev,
119
- scrollNext,
120
- canScrollPrev,
121
- canScrollNext,
122
- }}
123
- >
124
- <div
125
- ref={ref}
126
- onKeyDownCapture={handleKeyDown}
127
- className={cn("relative", className)}
128
- role="region"
129
- aria-roledescription="carousel"
130
- {...props}
131
- >
132
- {children}
133
- </div>
134
- </CarouselContext.Provider>
135
- );
136
- });
137
- Carousel.displayName = "Carousel";
138
-
139
- const CarouselContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
140
- ({ className, ...props }, ref) => {
141
- const { carouselRef, orientation } = useCarousel();
142
-
143
- return (
144
- <div ref={carouselRef} className="overflow-hidden">
145
- <div
146
- ref={ref}
147
- className={cn(
148
- "flex",
149
- orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
150
- className,
151
- )}
152
- {...props}
153
- />
154
- </div>
155
- );
156
- },
157
- );
158
- CarouselContent.displayName = "CarouselContent";
159
-
160
- const CarouselItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
161
- ({ className, ...props }, ref) => {
162
- const { orientation } = useCarousel();
163
-
164
- return (
165
- <div
166
- ref={ref}
167
- role="group"
168
- aria-roledescription="slide"
169
- className={cn(
170
- "min-w-0 shrink-0 grow-0 basis-full",
171
- orientation === "horizontal" ? "pl-4" : "pt-4",
172
- className,
173
- )}
174
- {...props}
175
- />
176
- );
177
- },
178
- );
179
- CarouselItem.displayName = "CarouselItem";
180
-
181
- const CarouselPrevious = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(
182
- ({ className, variant = "outline", size = "icon", ...props }, ref) => {
183
- const { orientation, scrollPrev, canScrollPrev } = useCarousel();
184
-
185
- return (
186
- <Button
187
- ref={ref}
188
- variant={variant}
189
- size={size}
190
- className={cn(
191
- "absolute h-8 w-8 rounded-full",
192
- orientation === "horizontal"
193
- ? "-left-12 top-1/2 -translate-y-1/2"
194
- : "-top-10 left-1/2 -translate-x-1/2 rotate-90",
195
- className,
196
- )}
197
- disabled={!canScrollPrev}
198
- onClick={scrollPrev}
199
- {...props}
200
- >
201
- <ArrowLeft className="h-4 w-4" />
202
- <span className="sr-only">Previous slide</span>
203
- </Button>
204
- );
205
- },
206
- );
207
- CarouselPrevious.displayName = "CarouselPrevious";
208
-
209
- const CarouselNext = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(
210
- ({ className, variant = "outline", size = "icon", ...props }, ref) => {
211
- const { orientation, scrollNext, canScrollNext } = useCarousel();
212
-
213
- return (
214
- <Button
215
- ref={ref}
216
- variant={variant}
217
- size={size}
218
- className={cn(
219
- "absolute h-8 w-8 rounded-full",
220
- orientation === "horizontal"
221
- ? "-right-12 top-1/2 -translate-y-1/2"
222
- : "-bottom-10 left-1/2 -translate-x-1/2 rotate-90",
223
- className,
224
- )}
225
- disabled={!canScrollNext}
226
- onClick={scrollNext}
227
- {...props}
228
- >
229
- <ArrowRight className="h-4 w-4" />
230
- <span className="sr-only">Next slide</span>
231
- </Button>
232
- );
233
- },
234
- );
235
- CarouselNext.displayName = "CarouselNext";
236
-
237
- export {
238
- Carousel,
239
- type CarouselApi,
240
- CarouselContent,
241
- CarouselItem,
242
- CarouselNext,
243
- CarouselPrevious,
244
- };