@olympusoss/canvas 2.20.2 → 3.2.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 +73 -35
  2. package/package.json +46 -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/atoms/avatar.css +22 -0
  8. package/styles/atoms/badge.css +83 -0
  9. package/styles/atoms/breadcrumb.css +35 -0
  10. package/styles/atoms/button-group.css +23 -0
  11. package/styles/atoms/button.css +107 -0
  12. package/styles/atoms/checkbox.css +55 -0
  13. package/styles/atoms/combobox.css +75 -0
  14. package/styles/atoms/dropdown.css +54 -0
  15. package/styles/atoms/icon.css +8 -0
  16. package/styles/atoms/input-group.css +45 -0
  17. package/styles/atoms/input.css +56 -0
  18. package/styles/atoms/kbd.css +15 -0
  19. package/styles/atoms/pagination.css +48 -0
  20. package/styles/atoms/popover.css +14 -0
  21. package/styles/atoms/radio.css +28 -0
  22. package/styles/atoms/select.css +57 -0
  23. package/styles/atoms/separator.css +32 -0
  24. package/styles/atoms/skeleton.css +32 -0
  25. package/styles/atoms/spinner.css +26 -0
  26. package/styles/atoms/switch.css +45 -0
  27. package/styles/atoms/textarea.css +31 -0
  28. package/styles/atoms/tooltip.css +53 -0
  29. package/styles/atoms/typography.css +105 -0
  30. package/styles/base.css +17 -0
  31. package/styles/canvas.css +77 -52
  32. package/styles/molecules/alert.css +66 -0
  33. package/styles/molecules/card.css +58 -0
  34. package/styles/molecules/code-block.css +18 -0
  35. package/styles/molecules/empty-state.css +17 -0
  36. package/styles/molecules/field.css +27 -0
  37. package/styles/molecules/form.css +27 -0
  38. package/styles/molecules/page-header.css +52 -0
  39. package/styles/molecules/section-card.css +49 -0
  40. package/styles/molecules/stat-card.css +71 -0
  41. package/styles/molecules/toast.css +95 -0
  42. package/styles/organisms/app-shell.css +46 -0
  43. package/styles/organisms/calendar.css +73 -0
  44. package/styles/organisms/command.css +94 -0
  45. package/styles/organisms/data-table.css +142 -0
  46. package/styles/organisms/dialog.css +72 -0
  47. package/styles/organisms/filter-panel.css +58 -0
  48. package/styles/organisms/row-menu.css +69 -0
  49. package/styles/organisms/sheet.css +70 -0
  50. package/styles/organisms/sidebar.css +146 -0
  51. package/styles/organisms/stepper.css +63 -0
  52. package/styles/organisms/tabs.css +40 -0
  53. package/styles/organisms/topbar.css +24 -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 -175
  212. package/styles/leaflet.css +0 -13
  213. package/styles/tokens.css +0 -317
  214. package/tailwind.config.ts +0 -70
@@ -1,235 +0,0 @@
1
- "use client";
2
-
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 * as React from "react";
7
-
8
- import { cn } from "../../lib/utils";
9
-
10
- export interface NavigationMenuProps
11
- extends React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root> {
12
- /** Controlled active item value. */
13
- value?: string;
14
- /** Initial value for uncontrolled usage. */
15
- defaultValue?: string;
16
- /** Fires when the active item changes. */
17
- onValueChange?: (value: string) => void;
18
- /**
19
- * Delay (ms) before opening on hover.
20
- * @default 200
21
- */
22
- delayDuration?: number;
23
- /**
24
- * Delay (ms) for skipping subsequent open delays once one menu is open.
25
- * @default 300
26
- */
27
- skipDelayDuration?: number;
28
- /**
29
- * Reading direction.
30
- * @default "ltr"
31
- */
32
- dir?: "ltr" | "rtl";
33
- /**
34
- * Layout direction.
35
- * @default "horizontal"
36
- */
37
- orientation?: "horizontal" | "vertical";
38
- /** List + Indicator + Viewport. */
39
- children?: React.ReactNode;
40
- className?: string;
41
- }
42
-
43
- const NavigationMenu = React.forwardRef<
44
- React.ElementRef<typeof NavigationMenuPrimitive.Root>,
45
- NavigationMenuProps
46
- >(({ className, children, ...props }, ref) => (
47
- <NavigationMenuPrimitive.Root
48
- ref={ref}
49
- className={cn("relative z-10 flex max-w-max flex-1 items-center justify-center", className)}
50
- {...props}
51
- >
52
- {children}
53
- <NavigationMenuViewport />
54
- </NavigationMenuPrimitive.Root>
55
- ));
56
- NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName;
57
-
58
- export interface NavigationMenuListProps
59
- extends React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List> {
60
- asChild?: boolean;
61
- /** A list of `<NavigationMenuItem>`s. */
62
- children?: React.ReactNode;
63
- className?: string;
64
- }
65
-
66
- const NavigationMenuList = React.forwardRef<
67
- React.ElementRef<typeof NavigationMenuPrimitive.List>,
68
- NavigationMenuListProps
69
- >(({ className, ...props }, ref) => (
70
- <NavigationMenuPrimitive.List
71
- ref={ref}
72
- className={cn("group flex flex-1 list-none items-center justify-center space-x-1", className)}
73
- {...props}
74
- />
75
- ));
76
- NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;
77
-
78
- export interface NavigationMenuItemProps
79
- extends React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Item> {
80
- /** Required for controlled menus — unique id of this item. */
81
- value?: string;
82
- /** Trigger + Content (or Link). */
83
- children?: React.ReactNode;
84
- className?: string;
85
- }
86
-
87
- const NavigationMenuItem = NavigationMenuPrimitive.Item as React.ForwardRefExoticComponent<
88
- NavigationMenuItemProps & React.RefAttributes<HTMLLIElement>
89
- >;
90
-
91
- const navigationMenuTriggerStyle = cva(
92
- "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-[state=open]:text-accent-foreground data-[state=open]:bg-accent/50 data-[state=open]:hover:bg-accent data-[state=open]:focus:bg-accent",
93
- );
94
-
95
- export interface NavigationMenuTriggerProps
96
- extends React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger> {
97
- asChild?: boolean;
98
- /** Trigger label. */
99
- children?: React.ReactNode;
100
- className?: string;
101
- }
102
-
103
- const NavigationMenuTrigger = React.forwardRef<
104
- React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,
105
- NavigationMenuTriggerProps
106
- >(({ className, children, ...props }, ref) => (
107
- <NavigationMenuPrimitive.Trigger
108
- ref={ref}
109
- className={cn(navigationMenuTriggerStyle(), "group", className)}
110
- {...props}
111
- >
112
- {children}{" "}
113
- <ChevronDown
114
- className="relative top-[1px] ml-1 h-3 w-3 transition duration-300 group-data-[state=open]:rotate-180"
115
- aria-hidden="true"
116
- />
117
- </NavigationMenuPrimitive.Trigger>
118
- ));
119
- NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName;
120
-
121
- export interface NavigationMenuContentProps
122
- extends React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content> {
123
- /**
124
- * Force the content to mount even when not active. Useful for
125
- * preserving form state during transitions.
126
- * @default false
127
- */
128
- forceMount?: true;
129
- /** Fires when focus enters the content. */
130
- onFocusOutside?: (event: Event) => void;
131
- /** Fires on pointer event outside the content. */
132
- onPointerDownOutside?: (event: CustomEvent<{ originalEvent: PointerEvent }>) => void;
133
- asChild?: boolean;
134
- /** Sub-menu content. */
135
- children?: React.ReactNode;
136
- className?: string;
137
- }
138
-
139
- const NavigationMenuContent = React.forwardRef<
140
- React.ElementRef<typeof NavigationMenuPrimitive.Content>,
141
- NavigationMenuContentProps
142
- >(({ className, ...props }, ref) => (
143
- <NavigationMenuPrimitive.Content
144
- ref={ref}
145
- className={cn(
146
- "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 ",
147
- className,
148
- )}
149
- {...props}
150
- />
151
- ));
152
- NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName;
153
-
154
- export interface NavigationMenuLinkProps
155
- extends React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Link> {
156
- /**
157
- * Mark as the current/active link.
158
- * @default false
159
- */
160
- active?: boolean;
161
- /** Fires when the link is selected (click, Enter, Space). */
162
- onSelect?: (event: Event) => void;
163
- asChild?: boolean;
164
- /** Anchor target. */
165
- href?: string;
166
- children?: React.ReactNode;
167
- className?: string;
168
- }
169
-
170
- const NavigationMenuLink = NavigationMenuPrimitive.Link as React.ForwardRefExoticComponent<
171
- NavigationMenuLinkProps & React.RefAttributes<HTMLAnchorElement>
172
- >;
173
-
174
- export interface NavigationMenuViewportProps
175
- extends React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport> {
176
- /** Force the viewport to mount even when no content is open. */
177
- forceMount?: true;
178
- asChild?: boolean;
179
- className?: string;
180
- }
181
-
182
- const NavigationMenuViewport = React.forwardRef<
183
- React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
184
- NavigationMenuViewportProps
185
- >(({ className, ...props }, ref) => (
186
- <div className={cn("absolute left-0 top-full flex justify-center")}>
187
- <NavigationMenuPrimitive.Viewport
188
- data-slot="navigation-menu-viewport"
189
- className={cn(
190
- "origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow 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)]",
191
- className,
192
- )}
193
- ref={ref}
194
- {...props}
195
- />
196
- </div>
197
- ));
198
- NavigationMenuViewport.displayName = NavigationMenuPrimitive.Viewport.displayName;
199
-
200
- export interface NavigationMenuIndicatorProps
201
- extends React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator> {
202
- /** Force the indicator to mount even when no content is open. */
203
- forceMount?: true;
204
- asChild?: boolean;
205
- className?: string;
206
- }
207
-
208
- const NavigationMenuIndicator = React.forwardRef<
209
- React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
210
- NavigationMenuIndicatorProps
211
- >(({ className, ...props }, ref) => (
212
- <NavigationMenuPrimitive.Indicator
213
- ref={ref}
214
- className={cn(
215
- "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",
216
- className,
217
- )}
218
- {...props}
219
- >
220
- <div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
221
- </NavigationMenuPrimitive.Indicator>
222
- ));
223
- NavigationMenuIndicator.displayName = NavigationMenuPrimitive.Indicator.displayName;
224
-
225
- export {
226
- NavigationMenu,
227
- NavigationMenuContent,
228
- NavigationMenuIndicator,
229
- NavigationMenuItem,
230
- NavigationMenuLink,
231
- NavigationMenuList,
232
- NavigationMenuTrigger,
233
- NavigationMenuViewport,
234
- navigationMenuTriggerStyle,
235
- };
@@ -1,149 +0,0 @@
1
- "use client";
2
-
3
- import * as PopoverPrimitive from "@radix-ui/react-popover";
4
- import * as React from "react";
5
-
6
- import { usePortalContainer } from "../../lib/portal-container";
7
- import { cn } from "../../lib/utils";
8
-
9
- export interface PopoverProps extends React.ComponentProps<typeof PopoverPrimitive.Root> {
10
- /** Controlled open state. Pair with `onOpenChange`. */
11
- open?: boolean;
12
- /**
13
- * Initial open state for uncontrolled usage.
14
- * @default false
15
- */
16
- defaultOpen?: boolean;
17
- /** Fires whenever the popover opens or closes. */
18
- onOpenChange?: (open: boolean) => void;
19
- /**
20
- * When true, blocks focus from leaving the popover.
21
- * @default false
22
- */
23
- modal?: boolean;
24
- /** Trigger + Content. */
25
- children?: React.ReactNode;
26
- }
27
-
28
- const Popover = PopoverPrimitive.Root as React.FC<PopoverProps>;
29
-
30
- export interface PopoverTriggerProps
31
- extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Trigger> {
32
- /**
33
- * Render as a Radix Slot — wrap a custom button while keeping the
34
- * popover's trigger behaviour.
35
- * @default false
36
- */
37
- asChild?: boolean;
38
- children?: React.ReactNode;
39
- className?: string;
40
- }
41
-
42
- const PopoverTrigger = PopoverPrimitive.Trigger as React.ForwardRefExoticComponent<
43
- PopoverTriggerProps & React.RefAttributes<HTMLButtonElement>
44
- >;
45
-
46
- export interface PopoverAnchorProps
47
- extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Anchor> {
48
- /**
49
- * Render as a Radix Slot. Use to anchor the popover to an element other
50
- * than the trigger (e.g. a parent input while the trigger is a button).
51
- * @default false
52
- */
53
- asChild?: boolean;
54
- children?: React.ReactNode;
55
- }
56
-
57
- const PopoverAnchor = PopoverPrimitive.Anchor as React.ForwardRefExoticComponent<
58
- PopoverAnchorProps & React.RefAttributes<HTMLDivElement>
59
- >;
60
-
61
- export interface PopoverContentProps
62
- extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> {
63
- /**
64
- * Distance in pixels between the anchor and the popover.
65
- * @default 4
66
- */
67
- sideOffset?: number;
68
- /**
69
- * Distance from the alignment edge.
70
- * @default 0
71
- */
72
- alignOffset?: number;
73
- /**
74
- * Preferred side of the anchor to render on.
75
- * @default "bottom"
76
- */
77
- side?: "top" | "right" | "bottom" | "left";
78
- /**
79
- * Alignment along the chosen side.
80
- * @default "center"
81
- */
82
- align?: "start" | "center" | "end";
83
- /**
84
- * Avoid colliding with the viewport edges by flipping/shifting.
85
- * @default true
86
- */
87
- avoidCollisions?: boolean;
88
- /**
89
- * Padding kept from collision boundaries.
90
- * @default 0
91
- */
92
- collisionPadding?: number | { top?: number; right?: number; bottom?: number; left?: number };
93
- /**
94
- * Stick to the trigger or partially follow on scroll.
95
- * @default "partial"
96
- */
97
- sticky?: "partial" | "always";
98
- /** Hide the content when the trigger is detached or covered. */
99
- hideWhenDetached?: boolean;
100
- /** Fires when focus enters the popover after it opens. */
101
- onOpenAutoFocus?: (event: Event) => void;
102
- /** Fires when focus leaves the popover after it closes. */
103
- onCloseAutoFocus?: (event: Event) => void;
104
- /** Fires when the Escape key is pressed inside the popover. */
105
- onEscapeKeyDown?: (event: KeyboardEvent) => void;
106
- /** Fires on pointer event outside the popover. */
107
- onPointerDownOutside?: (event: CustomEvent<{ originalEvent: PointerEvent }>) => void;
108
- /** Fires on any interaction outside (focus + pointer). */
109
- onInteractOutside?: (event: Event) => void;
110
- /**
111
- * Force the content to mount even when closed.
112
- * @default false
113
- */
114
- forceMount?: true;
115
- /**
116
- * Render as a Radix Slot.
117
- * @default false
118
- */
119
- asChild?: boolean;
120
- /** Popover body. */
121
- children?: React.ReactNode;
122
- /** Tailwind / CSS classes merged via `cn()`. */
123
- className?: string;
124
- }
125
-
126
- const PopoverContent = React.forwardRef<
127
- React.ElementRef<typeof PopoverPrimitive.Content>,
128
- PopoverContentProps
129
- >(({ className, align = "center", sideOffset = 4, ...props }, ref) => {
130
- const container = usePortalContainer();
131
- return (
132
- <PopoverPrimitive.Portal container={container ?? undefined}>
133
- <PopoverPrimitive.Content
134
- ref={ref}
135
- data-slot="popover-content"
136
- align={align}
137
- sideOffset={sideOffset}
138
- className={cn(
139
- "z-50 w-72 rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md outline-none 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-popover-content-transform-origin)]",
140
- className,
141
- )}
142
- {...props}
143
- />
144
- </PopoverPrimitive.Portal>
145
- );
146
- });
147
- PopoverContent.displayName = PopoverPrimitive.Content.displayName;
148
-
149
- export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };
@@ -1,58 +0,0 @@
1
- "use client";
2
-
3
- import { GripVertical } from "lucide-react";
4
- import { Group, Panel, Separator } from "react-resizable-panels";
5
-
6
- import { cn } from "../../lib/utils";
7
-
8
- /**
9
- * `react-resizable-panels` v4 emits `data-group` on the panel group and forces
10
- * inline `height: 100%; width: 100%`, which means a `className="h-32"` passed
11
- * directly to the group is ignored. The library expects the parent to size it.
12
- *
13
- * To keep `<ResizablePanelGroup className="h-32">` ergonomic for consumers, we
14
- * wrap the library's `Group` in a sizing container — `className` lands on that
15
- * wrapper, the inner `Group` then fills 100%.
16
- *
17
- * Orientation note: the library only emits `aria-orientation` on the
18
- * `Separator` (and the separator's orientation is OPPOSITE the group's — a
19
- * horizontal group has vertical separators). So group flex direction is set
20
- * here in JS from the prop, while separator dimension styles key off
21
- * `aria-orientation=horizontal` (separator inside a `vertical` group).
22
- */
23
- const ResizablePanelGroup = ({
24
- className,
25
- orientation,
26
- style,
27
- ...props
28
- }: React.ComponentProps<typeof Group>) => (
29
- <div className={cn("flex h-full w-full", className)} style={style}>
30
- <Group orientation={orientation} {...props} />
31
- </div>
32
- );
33
-
34
- const ResizablePanel = Panel;
35
-
36
- const ResizableHandle = ({
37
- withHandle,
38
- className,
39
- ...props
40
- }: React.ComponentProps<typeof Separator> & {
41
- withHandle?: boolean;
42
- }) => (
43
- <Separator
44
- className={cn(
45
- "relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 aria-[orientation=horizontal]:h-px aria-[orientation=horizontal]:w-full aria-[orientation=horizontal]:after:left-0 aria-[orientation=horizontal]:after:h-1 aria-[orientation=horizontal]:after:w-full aria-[orientation=horizontal]:after:-translate-y-1/2 aria-[orientation=horizontal]:after:translate-x-0 [&[aria-orientation=horizontal]>div]:rotate-90",
46
- className,
47
- )}
48
- {...props}
49
- >
50
- {withHandle && (
51
- <div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
52
- <GripVertical className="h-2.5 w-2.5" />
53
- </div>
54
- )}
55
- </Separator>
56
- );
57
-
58
- export { ResizableHandle, ResizablePanel, ResizablePanelGroup };
@@ -1,232 +0,0 @@
1
- "use client";
2
-
3
- import Form, { type IChangeEvent, type FormProps as RJSFFormProps } from "@rjsf/core";
4
- import type {
5
- FieldTemplateProps,
6
- ObjectFieldTemplateProps,
7
- RegistryWidgetsType,
8
- RJSFSchema,
9
- SubmitButtonProps,
10
- TemplatesType,
11
- UiSchema,
12
- WidgetProps,
13
- } from "@rjsf/utils";
14
- import validator from "@rjsf/validator-ajv8";
15
- import type * as React from "react";
16
-
17
- import { cn } from "../../lib/utils";
18
- import { Input } from "../atoms/input";
19
- import { Label } from "../atoms/label";
20
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select";
21
-
22
- /* ────────────────────────────────────────────────────────────────
23
- Default widgets — Canvas-styled inputs for RJSF
24
- ──────────────────────────────────────────────────────────────── */
25
-
26
- const TextWidget: React.FC<WidgetProps> = ({
27
- id,
28
- value,
29
- onChange,
30
- onBlur,
31
- onFocus,
32
- placeholder,
33
- disabled,
34
- readonly,
35
- required,
36
- label,
37
- schema,
38
- }) => {
39
- const isEmail = schema.format === "email";
40
- const inputType = isEmail ? "email" : "text";
41
- const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
42
- /* c8 ignore next -- clearing branch: user-driven and out of scope for widget unit tests */
43
- onChange(e.target.value === "" ? undefined : e.target.value);
44
- };
45
- /* c8 ignore next -- onBlur is optional from rjsf; undefined branch wires to Input without a handler */
46
- const handleBlur = onBlur ? () => onBlur(id, value) : undefined;
47
- /* c8 ignore next -- onFocus is optional from rjsf; undefined branch wires to Input without a handler */
48
- const handleFocus = onFocus ? () => onFocus(id, value) : undefined;
49
- return (
50
- <div className="space-y-1.5">
51
- {label && (
52
- <Label htmlFor={id}>
53
- {label}
54
- {required && <span className="ml-0.5 text-destructive">*</span>}
55
- </Label>
56
- )}
57
- <Input
58
- id={id}
59
- type={inputType}
60
- value={value ?? ""}
61
- onChange={handleChange}
62
- onBlur={handleBlur}
63
- onFocus={handleFocus}
64
- placeholder={placeholder}
65
- disabled={disabled}
66
- readOnly={readonly}
67
- />
68
- </div>
69
- );
70
- };
71
-
72
- const SelectWidget: React.FC<WidgetProps> = ({
73
- id,
74
- value,
75
- onChange,
76
- disabled,
77
- readonly,
78
- required,
79
- options,
80
- label,
81
- placeholder,
82
- }) => {
83
- /* c8 ignore next -- enumOptions is always populated for enum schemas; ?? [] is a type-narrowing guard */
84
- const enumOptions = (options.enumOptions as Array<{ value: unknown; label: string }>) ?? [];
85
- const handleValueChange = (v: string) => {
86
- /* c8 ignore next -- rjsf Select clears via undefined, so the "" branch of the coalesce is unreachable */
87
- onChange(v === "" ? undefined : v);
88
- };
89
- /* c8 ignore next -- `placeholder` is optional; "Select…" is the default fallback */
90
- const placeholderText = placeholder ?? "Select…";
91
- return (
92
- <div className="space-y-1.5">
93
- {label && (
94
- <Label htmlFor={id}>
95
- {label}
96
- {required && <span className="ml-0.5 text-destructive">*</span>}
97
- </Label>
98
- )}
99
- <Select
100
- value={value ? String(value) : undefined}
101
- onValueChange={handleValueChange}
102
- disabled={disabled || readonly}
103
- >
104
- <SelectTrigger id={id}>
105
- <SelectValue placeholder={placeholderText} />
106
- </SelectTrigger>
107
- <SelectContent>
108
- {enumOptions.map((opt) => (
109
- <SelectItem key={String(opt.value)} value={String(opt.value)}>
110
- {opt.label}
111
- </SelectItem>
112
- ))}
113
- </SelectContent>
114
- </Select>
115
- </div>
116
- );
117
- };
118
-
119
- /* ────────────────────────────────────────────────────────────────
120
- Default templates
121
- ──────────────────────────────────────────────────────────────── */
122
-
123
- const FieldTemplate: React.FC<FieldTemplateProps> = ({
124
- children,
125
- description,
126
- errors,
127
- help,
128
- hidden,
129
- }) => {
130
- /* c8 ignore next -- defensive: hidden fields are filtered upstream in rjsf before rendering */
131
- if (hidden) return null;
132
- return (
133
- <div className="space-y-1">
134
- {children}
135
- {description && <div className="text-xs text-muted-foreground">{description}</div>}
136
- {errors && <div className="text-xs text-destructive">{errors}</div>}
137
- {help && <div className="text-xs text-muted-foreground">{help}</div>}
138
- </div>
139
- );
140
- };
141
-
142
- const ObjectFieldTemplate: React.FC<ObjectFieldTemplateProps> = ({
143
- title,
144
- description,
145
- properties,
146
- }) => (
147
- <div className="space-y-4">
148
- {title && <h3 className="text-base font-semibold">{title}</h3>}
149
- {description && <p className="text-sm text-muted-foreground">{description}</p>}
150
- {properties.map((p) => (
151
- <div key={p.name}>{p.content}</div>
152
- ))}
153
- </div>
154
- );
155
-
156
- const SubmitButton: React.FC<SubmitButtonProps> = () => null;
157
-
158
- /* ────────────────────────────────────────────────────────────────
159
- Exported widget/template packs
160
- ──────────────────────────────────────────────────────────────── */
161
-
162
- export const canvasSchemaFormWidgets: RegistryWidgetsType = {
163
- TextWidget,
164
- EmailWidget: TextWidget,
165
- URLWidget: TextWidget,
166
- SelectWidget,
167
- };
168
-
169
- /* c8 ignore start -- null-returning button templates: rjsf calls these for array/clear ops we don't expose in Canvas */
170
- const nullButton = () => null;
171
- /* c8 ignore stop */
172
-
173
- export const canvasSchemaFormTemplates: Partial<TemplatesType> = {
174
- FieldTemplate,
175
- ObjectFieldTemplate,
176
- ButtonTemplates: {
177
- SubmitButton,
178
- AddButton: nullButton,
179
- MoveDownButton: nullButton,
180
- MoveUpButton: nullButton,
181
- RemoveButton: nullButton,
182
- CopyButton: nullButton,
183
- ClearButton: nullButton,
184
- },
185
- };
186
-
187
- /* ────────────────────────────────────────────────────────────────
188
- SchemaForm — RJSF wrapper with Canvas defaults
189
- ──────────────────────────────────────────────────────────────── */
190
-
191
- export interface SchemaFormProps<T = unknown>
192
- extends Omit<RJSFFormProps<T>, "validator" | "widgets" | "templates"> {
193
- schema: RJSFSchema;
194
- uiSchema?: UiSchema;
195
- /** Override or extend Canvas's default widget set. */
196
- widgets?: RegistryWidgetsType;
197
- /** Override or extend Canvas's default template set. */
198
- templates?: Partial<TemplatesType>;
199
- /** Supply a different RJSF validator (defaults to ajv8). */
200
- validator?: RJSFFormProps<T>["validator"];
201
- className?: string;
202
- }
203
-
204
- export function SchemaForm<T = unknown>({
205
- schema,
206
- uiSchema,
207
- widgets,
208
- templates,
209
- validator: customValidator,
210
- className,
211
- children,
212
- ...rest
213
- }: SchemaFormProps<T>) {
214
- return (
215
- <div className={cn("space-y-4", className)}>
216
- <Form<T>
217
- schema={schema}
218
- uiSchema={uiSchema}
219
- validator={customValidator ?? validator}
220
- widgets={{ ...canvasSchemaFormWidgets, ...widgets }}
221
- templates={{ ...canvasSchemaFormTemplates, ...templates }}
222
- {...rest}
223
- >
224
- {children}
225
- </Form>
226
- </div>
227
- );
228
- }
229
-
230
- SchemaForm.displayName = "SchemaForm";
231
-
232
- export type { IChangeEvent, RJSFSchema, UiSchema, WidgetProps };