@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,45 +0,0 @@
1
- "use client";
2
-
3
- /* c8 ignore file -- Editor toolbar shell is only used inside editor
4
- * components which are jsdom-incompatible. */
5
-
6
- import * as React from "react";
7
-
8
- import { cn } from "../../../../lib/utils";
9
-
10
- export interface ToolbarShellProps extends React.HTMLAttributes<HTMLDivElement> {
11
- children: React.ReactNode;
12
- }
13
-
14
- /**
15
- * Layout chrome shared by every editor toolbar: a horizontal flex bar with
16
- * `--border` separator below, `--card` background tint, padding tuned for
17
- * canvas's button/icon size. Per-engine toolbars compose canvas atoms
18
- * (Button, Toggle, Icon, ToggleGroup) inside this shell.
19
- *
20
- * Children are arranged with `gap-1` between groups; use `<ToolbarDivider />`
21
- * to insert a thin vertical separator between conceptual groups.
22
- */
23
- export const ToolbarShell = React.forwardRef<HTMLDivElement, ToolbarShellProps>(
24
- ({ children, className, ...props }, ref) => {
25
- return (
26
- <div
27
- ref={ref}
28
- role="toolbar"
29
- className={cn(
30
- "flex flex-wrap items-center gap-1 border-b border-border bg-card/50 px-2 py-1.5",
31
- className,
32
- )}
33
- {...props}
34
- >
35
- {children}
36
- </div>
37
- );
38
- },
39
- );
40
- ToolbarShell.displayName = "ToolbarShell";
41
-
42
- /** Thin vertical separator between toolbar button groups. */
43
- export function ToolbarDivider() {
44
- return <div role="separator" className="mx-1 h-5 w-px bg-border" aria-hidden />;
45
- }
@@ -1,61 +0,0 @@
1
- "use client";
2
-
3
- /* c8 ignore file -- CodeMirror EditorView requires real DOM; jsdom-incompatible. */
4
-
5
- import { EditorView } from "@codemirror/view";
6
- import { useMemo } from "react";
7
-
8
- import { useTheme } from "../theme-provider";
9
-
10
- /**
11
- * Build a CodeMirror 6 theme that resolves canvas's CSS-variable tokens to
12
- * literal `hsl(...)` strings. CodeMirror does not honour CSS variables inside
13
- * its `<canvas>`-style internals, so the bridge is read-once-per-theme.
14
- *
15
- * Re-runs whenever `useTheme().resolvedTheme` flips, which means
16
- * `<MarkdownEditor>` / `<CodeEditor>` automatically reskin on dark/light toggle.
17
- */
18
- export function useCodemirrorTheme() {
19
- const { resolvedTheme } = useTheme();
20
- return useMemo(() => {
21
- // Defer DOM access to runtime — typeof window guard keeps SSR happy.
22
- if (typeof window === "undefined") return EditorView.theme({});
23
- const root = getComputedStyle(document.documentElement);
24
- const v = (name: string) => `hsl(${root.getPropertyValue(name).trim()})`;
25
- const hsla = (name: string, alpha: number) =>
26
- `hsl(${root.getPropertyValue(name).trim()} / ${alpha})`;
27
- return EditorView.theme(
28
- {
29
- "&": {
30
- color: v("--foreground"),
31
- backgroundColor: "transparent",
32
- fontFamily:
33
- "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace",
34
- fontSize: "13px",
35
- },
36
- ".cm-content": {
37
- caretColor: v("--foreground"),
38
- padding: "12px 0",
39
- },
40
- ".cm-line": {
41
- padding: "0 12px",
42
- },
43
- ".cm-gutters": {
44
- backgroundColor: "transparent",
45
- color: v("--muted-foreground"),
46
- borderRightColor: v("--border"),
47
- },
48
- ".cm-activeLine": { backgroundColor: hsla("--muted", 0.4) },
49
- ".cm-activeLineGutter": { backgroundColor: "transparent" },
50
- ".cm-cursor": { borderLeftColor: v("--brand"), borderLeftWidth: "2px" },
51
- "&.cm-focused .cm-selectionBackground, ::selection, .cm-selectionBackground": {
52
- backgroundColor: hsla("--brand", 0.25),
53
- },
54
- "&.cm-focused": { outline: "none" },
55
- ".cm-scroller": { fontFamily: "inherit" },
56
- },
57
- { dark: resolvedTheme === "dark" },
58
- );
59
- // `resolvedTheme` drives the memo; ESLint doesn't see that getComputedStyle reads from the DOM.
60
- }, [resolvedTheme]);
61
- }
@@ -1,61 +0,0 @@
1
- "use client";
2
-
3
- import * as React from "react";
4
-
5
- import { Button } from "../atoms/button";
6
- import { Icon } from "../atoms/icon";
7
-
8
- export interface ErrorBoundaryProps {
9
- children: React.ReactNode;
10
- /** Custom fallback — receives the error and a reset function. */
11
- fallback?: (error: Error, reset: () => void) => React.ReactNode;
12
- /** Called when an error is captured. Useful for error reporting. */
13
- onError?: (error: Error, info: React.ErrorInfo) => void;
14
- /** Label for the built-in reset button (ignored when `fallback` is provided). */
15
- resetLabel?: string;
16
- }
17
-
18
- interface State {
19
- error: Error | null;
20
- }
21
-
22
- export class ErrorBoundary extends React.Component<ErrorBoundaryProps, State> {
23
- static displayName = "ErrorBoundary";
24
-
25
- state: State = { error: null };
26
-
27
- static getDerivedStateFromError(error: Error): State {
28
- return { error };
29
- }
30
-
31
- componentDidCatch(error: Error, info: React.ErrorInfo) {
32
- this.props.onError?.(error, info);
33
- }
34
-
35
- reset = () => this.setState({ error: null });
36
-
37
- render() {
38
- const { error } = this.state;
39
- if (!error) return this.props.children;
40
-
41
- if (this.props.fallback) return this.props.fallback(error, this.reset);
42
-
43
- return (
44
- <div className="flex flex-col items-center justify-center gap-4 p-8 text-center">
45
- <Icon name="TriangleAlert" className="h-10 w-10 text-destructive" />
46
- <h2 className="text-lg font-semibold text-foreground">Something went wrong</h2>
47
- <p className="max-w-md text-sm text-muted-foreground">
48
- {error.message || "An unexpected error occurred."}
49
- </p>
50
- {error.stack && (
51
- <pre className="max-h-40 max-w-lg overflow-auto whitespace-pre-wrap text-left text-xs text-muted-foreground/60">
52
- {error.stack}
53
- </pre>
54
- )}
55
- <Button onClick={this.reset} size="sm">
56
- {this.props.resetLabel ?? "Try again"}
57
- </Button>
58
- </div>
59
- );
60
- }
61
- }
@@ -1,174 +0,0 @@
1
- "use client";
2
-
3
- import type * as LabelPrimitive from "@radix-ui/react-label";
4
- import { Slot } from "@radix-ui/react-slot";
5
- import * as React from "react";
6
- import {
7
- Controller,
8
- type ControllerProps,
9
- type FieldPath,
10
- type FieldValues,
11
- FormProvider,
12
- useFormContext,
13
- } from "react-hook-form";
14
-
15
- import { cn } from "../../lib/utils";
16
- import { Label } from "../atoms/label";
17
-
18
- const Form = FormProvider;
19
-
20
- type FormFieldContextValue<
21
- TFieldValues extends FieldValues = FieldValues,
22
- TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
23
- > = {
24
- name: TName;
25
- };
26
-
27
- const FormFieldContext = React.createContext<FormFieldContextValue | null>(null);
28
-
29
- const FormField = <
30
- TFieldValues extends FieldValues = FieldValues,
31
- TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
32
- >({
33
- ...props
34
- }: ControllerProps<TFieldValues, TName>) => {
35
- return (
36
- <FormFieldContext.Provider value={{ name: props.name }}>
37
- <Controller {...props} />
38
- </FormFieldContext.Provider>
39
- );
40
- };
41
-
42
- const useFormField = () => {
43
- const fieldContext = React.useContext(FormFieldContext);
44
- const itemContext = React.useContext(FormItemContext);
45
- const { getFieldState, formState } = useFormContext();
46
-
47
- if (!fieldContext) {
48
- throw new Error("useFormField should be used within <FormField>");
49
- }
50
-
51
- if (!itemContext) {
52
- throw new Error("useFormField should be used within <FormItem>");
53
- }
54
-
55
- const fieldState = getFieldState(fieldContext.name, formState);
56
-
57
- const { id } = itemContext;
58
-
59
- return {
60
- id,
61
- name: fieldContext.name,
62
- formItemId: `${id}-form-item`,
63
- formDescriptionId: `${id}-form-item-description`,
64
- formMessageId: `${id}-form-item-message`,
65
- ...fieldState,
66
- };
67
- };
68
-
69
- type FormItemContextValue = {
70
- id: string;
71
- };
72
-
73
- const FormItemContext = React.createContext<FormItemContextValue | null>(null);
74
-
75
- const FormItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
76
- ({ className, ...props }, ref) => {
77
- const id = React.useId();
78
-
79
- return (
80
- <FormItemContext.Provider value={{ id }}>
81
- <div ref={ref} className={cn("space-y-2", className)} {...props} />
82
- </FormItemContext.Provider>
83
- );
84
- },
85
- );
86
- FormItem.displayName = "FormItem";
87
-
88
- const FormLabel = React.forwardRef<
89
- React.ElementRef<typeof LabelPrimitive.Root>,
90
- React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
91
- >(({ className, ...props }, ref) => {
92
- const { error, formItemId } = useFormField();
93
-
94
- return (
95
- <Label
96
- ref={ref}
97
- className={cn(error && "text-destructive", className)}
98
- htmlFor={formItemId}
99
- {...props}
100
- />
101
- );
102
- });
103
- FormLabel.displayName = "FormLabel";
104
-
105
- const FormControl = React.forwardRef<
106
- React.ElementRef<typeof Slot>,
107
- React.ComponentPropsWithoutRef<typeof Slot>
108
- >(({ ...props }, ref) => {
109
- const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
110
-
111
- return (
112
- <Slot
113
- ref={ref}
114
- id={formItemId}
115
- aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}
116
- aria-invalid={!!error}
117
- {...props}
118
- />
119
- );
120
- });
121
- FormControl.displayName = "FormControl";
122
-
123
- const FormDescription = React.forwardRef<
124
- HTMLParagraphElement,
125
- React.HTMLAttributes<HTMLParagraphElement>
126
- >(({ className, ...props }, ref) => {
127
- const { formDescriptionId } = useFormField();
128
-
129
- return (
130
- <p
131
- ref={ref}
132
- id={formDescriptionId}
133
- className={cn("text-[0.8rem] text-muted-foreground", className)}
134
- {...props}
135
- />
136
- );
137
- });
138
- FormDescription.displayName = "FormDescription";
139
-
140
- const FormMessage = React.forwardRef<
141
- HTMLParagraphElement,
142
- React.HTMLAttributes<HTMLParagraphElement>
143
- >(({ className, children, ...props }, ref) => {
144
- const { error, formMessageId } = useFormField();
145
- /* c8 ignore next -- error.message is always a string for react-hook-form rules; the ?? "" fallback only triggers for exotic error shapes */
146
- const body = error ? String(error?.message ?? "") : children;
147
-
148
- if (!body) {
149
- return null;
150
- }
151
-
152
- return (
153
- <p
154
- ref={ref}
155
- id={formMessageId}
156
- className={cn("text-[0.8rem] font-medium text-destructive", className)}
157
- {...props}
158
- >
159
- {body}
160
- </p>
161
- );
162
- });
163
- FormMessage.displayName = "FormMessage";
164
-
165
- export {
166
- Form,
167
- FormControl,
168
- FormDescription,
169
- FormField,
170
- FormItem,
171
- FormLabel,
172
- FormMessage,
173
- useFormField,
174
- };
@@ -1,115 +0,0 @@
1
- "use client";
2
-
3
- import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
4
- import * as React from "react";
5
-
6
- import { cn } from "../../lib/utils";
7
-
8
- export interface HoverCardProps extends React.ComponentProps<typeof HoverCardPrimitive.Root> {
9
- /** Controlled open state. Pair with `onOpenChange`. */
10
- open?: boolean;
11
- /**
12
- * Initial open state for uncontrolled usage.
13
- * @default false
14
- */
15
- defaultOpen?: boolean;
16
- /** Fires whenever the hover card opens or closes. */
17
- onOpenChange?: (open: boolean) => void;
18
- /**
19
- * Delay in ms before the card opens after the user hovers the trigger.
20
- * @default 700
21
- */
22
- openDelay?: number;
23
- /**
24
- * Delay in ms before the card closes after the cursor leaves.
25
- * @default 300
26
- */
27
- closeDelay?: number;
28
- /** Trigger + Content. */
29
- children?: React.ReactNode;
30
- }
31
-
32
- const HoverCard = HoverCardPrimitive.Root as React.FC<HoverCardProps>;
33
-
34
- export interface HoverCardTriggerProps
35
- extends React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Trigger> {
36
- /**
37
- * Render as a Radix Slot.
38
- * @default false
39
- */
40
- asChild?: boolean;
41
- children?: React.ReactNode;
42
- className?: string;
43
- }
44
-
45
- const HoverCardTrigger = HoverCardPrimitive.Trigger as React.ForwardRefExoticComponent<
46
- HoverCardTriggerProps & React.RefAttributes<HTMLAnchorElement>
47
- >;
48
-
49
- export interface HoverCardContentProps
50
- extends React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content> {
51
- /**
52
- * Distance in pixels between the trigger and the card.
53
- * @default 4
54
- */
55
- sideOffset?: number;
56
- /**
57
- * Distance from the alignment edge.
58
- * @default 0
59
- */
60
- alignOffset?: number;
61
- /**
62
- * Preferred side of the trigger to render on.
63
- * @default "bottom"
64
- */
65
- side?: "top" | "right" | "bottom" | "left";
66
- /**
67
- * Alignment along the chosen side.
68
- * @default "center"
69
- */
70
- align?: "start" | "center" | "end";
71
- /**
72
- * Avoid colliding with the viewport edges.
73
- * @default true
74
- */
75
- avoidCollisions?: boolean;
76
- /**
77
- * Padding kept from collision boundaries.
78
- * @default 0
79
- */
80
- collisionPadding?: number | { top?: number; right?: number; bottom?: number; left?: number };
81
- /**
82
- * Force the content to mount even when closed.
83
- * @default false
84
- */
85
- forceMount?: true;
86
- /**
87
- * Render as a Radix Slot.
88
- * @default false
89
- */
90
- asChild?: boolean;
91
- /** Card body. */
92
- children?: React.ReactNode;
93
- /** Tailwind / CSS classes merged via `cn()`. */
94
- className?: string;
95
- }
96
-
97
- const HoverCardContent = React.forwardRef<
98
- React.ElementRef<typeof HoverCardPrimitive.Content>,
99
- HoverCardContentProps
100
- >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
101
- <HoverCardPrimitive.Content
102
- ref={ref}
103
- data-slot="hover-card-content"
104
- align={align}
105
- sideOffset={sideOffset}
106
- className={cn(
107
- "z-50 w-64 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-hover-card-content-transform-origin)]",
108
- className,
109
- )}
110
- {...props}
111
- />
112
- ));
113
- HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;
114
-
115
- export { HoverCard, HoverCardContent, HoverCardTrigger };