@olympusoss/canvas 2.20.1 → 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 -171
  206. package/styles/leaflet.css +0 -13
  207. package/styles/tokens.css +0 -317
  208. package/tailwind.config.ts +0 -70
@@ -1,44 +0,0 @@
1
- import { cva, type VariantProps } from "class-variance-authority";
2
- import type * as React from "react";
3
-
4
- import { cn } from "../../lib/utils";
5
-
6
- const badgeVariants = cva(
7
- "inline-flex items-center rounded-md border border-border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
8
- {
9
- variants: {
10
- variant: {
11
- default: "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
12
- secondary:
13
- "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
14
- destructive:
15
- "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
16
- outline: "text-foreground",
17
- },
18
- },
19
- defaultVariants: {
20
- variant: "default",
21
- },
22
- },
23
- );
24
-
25
- export interface BadgeProps
26
- extends React.HTMLAttributes<HTMLDivElement>,
27
- VariantProps<typeof badgeVariants> {
28
- /**
29
- * Visual style. `default` is filled brand colour, `secondary` is a muted
30
- * neutral, `outline` is bordered with no fill, `destructive` flags an
31
- * error or warning state.
32
- * @default "default"
33
- */
34
- variant?: "default" | "secondary" | "destructive" | "outline";
35
- /** Badge label or any nested elements. */
36
- children?: React.ReactNode;
37
- className?: string;
38
- }
39
-
40
- function Badge({ className, variant, ...props }: BadgeProps) {
41
- return <div className={cn(badgeVariants({ variant }), className)} {...props} />;
42
- }
43
-
44
- export { Badge, badgeVariants };
@@ -1,74 +0,0 @@
1
- "use client";
2
-
3
- import * as React from "react";
4
-
5
- import { cn } from "../../lib/utils";
6
-
7
- export interface BrandMarkProps extends React.SVGAttributes<SVGSVGElement> {
8
- /**
9
- * SVG path data (`d` attribute) for the brand mark. Required — canvas
10
- * does not ship a default brand shape; consuming apps supply their own.
11
- */
12
- path: string;
13
- /**
14
- * SVG `viewBox` matching the path's coordinate space.
15
- * @default "0 0 24 24"
16
- */
17
- viewBox?: string;
18
- /**
19
- * Optional inner `transform` applied to the path's `<g>` group — useful
20
- * when the path coordinates need to be translated, rotated, or scaled
21
- * relative to the viewBox.
22
- */
23
- transform?: string;
24
- /**
25
- * Gradient start colour. When omitted, the path is filled with
26
- * `currentColor` and no gradient is generated.
27
- */
28
- from?: string;
29
- /**
30
- * Gradient end colour. Required when `from` is set.
31
- */
32
- to?: string;
33
- }
34
-
35
- /**
36
- * Generic brand-mark primitive. Renders a single SVG `path` either with
37
- * `currentColor` (the default) or with a two-stop linear gradient when both
38
- * `from` and `to` are provided. Sizing is controlled via `className`
39
- * (`h-10 w-auto`); the SVG honours its `viewBox` aspect ratio.
40
- *
41
- * Apps consuming canvas typically build a thin wrapper around this component
42
- * that hard-codes their own brand path / gradient — see the docs site's
43
- * `OlympusLogo` for a worked example.
44
- */
45
- const BrandMark = React.forwardRef<SVGSVGElement, BrandMarkProps>(
46
- ({ path, viewBox = "0 0 24 24", transform, from, to, className, ...props }, ref) => {
47
- const gradientId = React.useId();
48
- const useGradient = from !== undefined && to !== undefined;
49
- const fill = useGradient ? `url(#${gradientId})` : "currentColor";
50
- const pathEl = <path d={path} fill={fill} fillRule="evenodd" />;
51
- return (
52
- <svg
53
- ref={ref}
54
- xmlns="http://www.w3.org/2000/svg"
55
- viewBox={viewBox}
56
- className={cn("shrink-0", className)}
57
- {...props}
58
- >
59
- {useGradient && (
60
- <defs>
61
- <linearGradient id={gradientId} x1="1" y1="1" x2="0" y2="0">
62
- <stop offset="0%" stopColor={from} />
63
- <stop offset="100%" stopColor={to} />
64
- </linearGradient>
65
- </defs>
66
- )}
67
- {transform ? <g transform={transform}>{pathEl}</g> : pathEl}
68
- </svg>
69
- );
70
- },
71
- );
72
- BrandMark.displayName = "BrandMark";
73
-
74
- export { BrandMark };
@@ -1,105 +0,0 @@
1
- import { Slot } from "@radix-ui/react-slot";
2
- import { cva, type VariantProps } from "class-variance-authority";
3
- import * as React from "react";
4
-
5
- import { cn } from "../../lib/utils";
6
-
7
- const buttonVariants = cva(
8
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
9
- {
10
- variants: {
11
- variant: {
12
- default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
13
- destructive: "bg-destructive text-destructive-foreground shadow hover:bg-destructive/90",
14
- outline:
15
- "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
16
- secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
17
- ghost: "hover:bg-accent hover:text-accent-foreground",
18
- link: "text-primary hover:text-brand",
19
- },
20
- size: {
21
- default: "h-9 px-4 py-2",
22
- sm: "h-8 rounded-md px-3 text-xs",
23
- lg: "h-10 rounded-md px-8",
24
- icon: "h-9 w-9",
25
- },
26
- },
27
- defaultVariants: {
28
- variant: "default",
29
- size: "default",
30
- },
31
- },
32
- );
33
-
34
- export interface ButtonProps
35
- extends React.ButtonHTMLAttributes<HTMLButtonElement>,
36
- VariantProps<typeof buttonVariants> {
37
- /**
38
- * Visual emphasis preset. `default` is the primary action, `destructive`
39
- * is for irreversible actions, `outline` and `secondary` are quieter,
40
- * `ghost` is borderless, `link` looks like body-text with a soft
41
- * color shift on hover (no underline).
42
- * @default "default"
43
- */
44
- variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link";
45
- /**
46
- * Height + horizontal padding preset. `sm` is 32px, `default` is 36px,
47
- * `lg` is 40px, `icon` is square 36×36 for icon-only buttons (always
48
- * pair with `aria-label`).
49
- * @default "default"
50
- */
51
- size?: "default" | "sm" | "lg" | "icon";
52
- /**
53
- * Render as a Radix Slot — forwards className and behaviour onto the
54
- * immediate child element instead of rendering a wrapper `<button>`.
55
- * Common pattern for using a router `<Link>` while keeping the Button
56
- * styling.
57
- * @default false
58
- */
59
- asChild?: boolean;
60
- /** Visible label or any nested elements (icons, badges). */
61
- children?: React.ReactNode;
62
- /** Tailwind / CSS classes merged onto the root element via `cn()`. */
63
- className?: string;
64
- /**
65
- * When true, dims the button to 50% opacity and blocks pointer/keyboard
66
- * input.
67
- * @default false
68
- */
69
- disabled?: boolean;
70
- /**
71
- * Native HTML button type. `submit` triggers parent form submission;
72
- * `reset` resets parent form fields; `button` does neither.
73
- * @default "button"
74
- */
75
- type?: "button" | "submit" | "reset";
76
- /** Click handler. Receives a `MouseEvent<HTMLButtonElement>`. */
77
- onClick?: React.MouseEventHandler<HTMLButtonElement>;
78
- /** Form name when this button submits/resets a form (for forms with multiple buttons). */
79
- name?: string;
80
- /** Form value sent with the form when this button is the submitter. */
81
- value?: string | number | readonly string[];
82
- /**
83
- * ID of the form this button belongs to, when the button sits outside
84
- * the `<form>` element.
85
- */
86
- form?: string;
87
- /** Tab order. Default behaviour is one of native `<button>` tab focus. */
88
- tabIndex?: number;
89
- /** Accessible label, required for icon-only buttons (`size="icon"`). */
90
- "aria-label"?: string;
91
- /** ID of an element that describes the button's purpose. */
92
- "aria-describedby"?: string;
93
- }
94
-
95
- const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
96
- ({ className, variant, size, asChild = false, ...props }, ref) => {
97
- const Comp = asChild ? Slot : "button";
98
- return (
99
- <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />
100
- );
101
- },
102
- );
103
- Button.displayName = "Button";
104
-
105
- export { Button, buttonVariants };
@@ -1,63 +0,0 @@
1
- "use client";
2
-
3
- import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
4
- import { Check } from "lucide-react";
5
- import * as React from "react";
6
-
7
- import { cn } from "../../lib/utils";
8
-
9
- export interface CheckboxProps
10
- extends React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> {
11
- /**
12
- * Controlled checked state. Pass `'indeterminate'` to render the dash
13
- * glyph instead of the check.
14
- */
15
- checked?: boolean | "indeterminate";
16
- /**
17
- * Initial state for uncontrolled usage.
18
- * @default false
19
- */
20
- defaultChecked?: boolean | "indeterminate";
21
- /** Fires when the user toggles the checkbox. Use this instead of `onChange`. */
22
- onCheckedChange?: (checked: boolean | "indeterminate") => void;
23
- /**
24
- * Dims to 50% and blocks input.
25
- * @default false
26
- */
27
- disabled?: boolean;
28
- /**
29
- * Block native form submit unless the box is checked.
30
- * @default false
31
- */
32
- required?: boolean;
33
- /** Form field name for native form submission. */
34
- name?: string;
35
- /** Form field value when submitted. */
36
- value?: string;
37
- asChild?: boolean;
38
- className?: string;
39
- }
40
-
41
- /**
42
- * Wraps Radix's `Checkbox.Root`. The check glyph is rendered inside
43
- * automatically.
44
- */
45
- const Checkbox = React.forwardRef<React.ElementRef<typeof CheckboxPrimitive.Root>, CheckboxProps>(
46
- ({ className, ...props }, ref) => (
47
- <CheckboxPrimitive.Root
48
- ref={ref}
49
- className={cn(
50
- "grid place-content-center peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
51
- className,
52
- )}
53
- {...props}
54
- >
55
- <CheckboxPrimitive.Indicator className={cn("grid place-content-center text-current")}>
56
- <Check className="h-4 w-4" />
57
- </CheckboxPrimitive.Indicator>
58
- </CheckboxPrimitive.Root>
59
- ),
60
- );
61
- Checkbox.displayName = CheckboxPrimitive.Root.displayName;
62
-
63
- export { Checkbox };
@@ -1,105 +0,0 @@
1
- import * as React from "react";
2
-
3
- import { cn } from "../../lib/utils";
4
-
5
- export interface FlexBoxProps extends React.HTMLAttributes<HTMLDivElement> {
6
- /**
7
- * Maps to `flex-direction`.
8
- * @default "row"
9
- */
10
- direction?: "row" | "column";
11
- /**
12
- * Maps to `align-items`.
13
- * @default "flex-start"
14
- */
15
- align?: "flex-start" | "center" | "flex-end" | "stretch" | "baseline";
16
- /**
17
- * Maps to `justify-content`.
18
- * @default "flex-start"
19
- */
20
- justify?:
21
- | "flex-start"
22
- | "center"
23
- | "flex-end"
24
- | "space-between"
25
- | "space-around"
26
- | "space-evenly";
27
- /** Tailwind gap step (0–6) or a raw CSS value. */
28
- gap?: number | string;
29
- /**
30
- * Maps to `flex-wrap`. Pass `true` for `flex-wrap`, `false` for
31
- * `flex-nowrap`.
32
- * @default false
33
- */
34
- wrap?: boolean;
35
- children?: React.ReactNode;
36
- className?: string;
37
- }
38
-
39
- const DIRECTION: Record<NonNullable<FlexBoxProps["direction"]>, string> = {
40
- row: "flex-row",
41
- column: "flex-col",
42
- };
43
-
44
- const ALIGN: Record<NonNullable<FlexBoxProps["align"]>, string> = {
45
- "flex-start": "items-start",
46
- center: "items-center",
47
- "flex-end": "items-end",
48
- stretch: "items-stretch",
49
- baseline: "items-baseline",
50
- };
51
-
52
- const JUSTIFY: Record<NonNullable<FlexBoxProps["justify"]>, string> = {
53
- "flex-start": "justify-start",
54
- center: "justify-center",
55
- "flex-end": "justify-end",
56
- "space-between": "justify-between",
57
- "space-around": "justify-around",
58
- "space-evenly": "justify-evenly",
59
- };
60
-
61
- const GAP: Record<number, string> = {
62
- 0: "gap-0",
63
- 1: "gap-2",
64
- 2: "gap-4",
65
- 3: "gap-6",
66
- 4: "gap-8",
67
- 5: "gap-10",
68
- 6: "gap-12",
69
- };
70
-
71
- export const FlexBox = React.forwardRef<HTMLDivElement, FlexBoxProps>(
72
- (
73
- {
74
- direction = "row",
75
- align = "flex-start",
76
- justify = "flex-start",
77
- gap,
78
- wrap = false,
79
- className,
80
- style,
81
- ...rest
82
- },
83
- ref,
84
- ) => {
85
- const gapClass = typeof gap === "number" ? (GAP[gap] ?? "") : "";
86
- const gapStyle = typeof gap === "string" ? { gap } : undefined;
87
- return (
88
- <div
89
- ref={ref}
90
- className={cn(
91
- "flex",
92
- DIRECTION[direction],
93
- ALIGN[align],
94
- JUSTIFY[justify],
95
- gapClass,
96
- wrap && "flex-wrap",
97
- className,
98
- )}
99
- style={gapStyle ? { ...gapStyle, ...style } : style}
100
- {...rest}
101
- />
102
- );
103
- },
104
- );
105
- FlexBox.displayName = "FlexBox";
@@ -1,34 +0,0 @@
1
- import { icons, type LucideIcon } from "lucide-react";
2
- import * as React from "react";
3
-
4
- import { cn } from "../../lib/utils";
5
-
6
- export type IconName = keyof typeof icons;
7
-
8
- export const iconNames = Object.keys(icons) as IconName[];
9
-
10
- export interface IconProps extends React.SVGAttributes<SVGSVGElement> {
11
- /**
12
- * Lucide icon name (PascalCase, e.g. `ChevronRight`, `Mail`). Only icons
13
- * re-exported through `lucide-react` are valid.
14
- */
15
- name: IconName;
16
- /**
17
- * Pixel size of the rendered SVG. Defaults to 16; pass any number to
18
- * override (e.g. 20, 24).
19
- * @default 16
20
- */
21
- size?: number;
22
- className?: string;
23
- }
24
-
25
- const Icon = React.forwardRef<SVGSVGElement, IconProps>(
26
- ({ name, size = 16, className, ...props }, ref) => {
27
- const LucideIcon: LucideIcon = icons[name];
28
- if (!LucideIcon) return null;
29
- return <LucideIcon ref={ref} size={size} className={cn("shrink-0", className)} {...props} />;
30
- },
31
- );
32
- Icon.displayName = "Icon";
33
-
34
- export { Icon };
@@ -1,92 +0,0 @@
1
- import * as React from "react";
2
-
3
- import { cn } from "../../lib/utils";
4
-
5
- export interface InputProps extends React.ComponentProps<"input"> {
6
- /**
7
- * Native input type. Drives keyboard, validation, and on iOS the
8
- * picker.
9
- * @default "text"
10
- */
11
- type?: React.HTMLInputTypeAttribute;
12
- /**
13
- * Controlled value. Pair with `onChange`. For uncontrolled inputs use
14
- * `defaultValue` instead.
15
- */
16
- value?: string | number | readonly string[];
17
- /** Initial value for an uncontrolled input. Ignored if `value` is also passed. */
18
- defaultValue?: string | number | readonly string[];
19
- /** Hint text shown when the input is empty. Renders in `text-muted-foreground`. */
20
- placeholder?: string;
21
- /**
22
- * Visually dims to 50% and blocks all input. Pair with `Label` so the
23
- * dim cascades.
24
- * @default false
25
- */
26
- disabled?: boolean;
27
- /**
28
- * Selectable but not editable. Useful for displaying server-set values.
29
- * @default false
30
- */
31
- readOnly?: boolean;
32
- /**
33
- * Block native form submit unless the input has a value.
34
- * @default false
35
- */
36
- required?: boolean;
37
- /** Form field name. Required when relying on uncontrolled native form submission. */
38
- name?: string;
39
- /** DOM id. Match this from `<Label htmlFor>` for screen-reader association. */
40
- id?: string;
41
- /** Browser autofill hint. See MDN for the full token list. */
42
- autoComplete?: string;
43
- /**
44
- * Focus the input on mount. Use sparingly — surprises keyboard users.
45
- * @default false
46
- */
47
- autoFocus?: boolean;
48
- /** Native HTML5 validation regex. Triggers `:invalid` if the value doesn't match. */
49
- pattern?: string;
50
- /** Character count limit for text inputs. */
51
- maxLength?: number;
52
- /** Minimum character count for text inputs. */
53
- minLength?: number;
54
- /** Numeric / date lower bound. Honoured by `type="number"` / `"date"` / `"time"` / `"range"`. */
55
- min?: string | number;
56
- /** Numeric / date upper bound. */
57
- max?: string | number;
58
- /** Step increment for `number` / `range` / `date` types. */
59
- step?: string | number;
60
- /** Fires on every keystroke. Read `e.target.value`. Required if you pass `value`. */
61
- onChange?: React.ChangeEventHandler<HTMLInputElement>;
62
- /** Focus event. Common for focus-driven typeahead lookups. */
63
- onFocus?: React.FocusEventHandler<HTMLInputElement>;
64
- /** Blur event. Common for blur-validation. */
65
- onBlur?: React.FocusEventHandler<HTMLInputElement>;
66
- className?: string;
67
- }
68
-
69
- /**
70
- * Styled wrapper around the native `<input>` — 36px tall, rounded-md, 1px
71
- * border, transparent background, canvas focus ring. Forwards every native
72
- * input attribute through to the underlying element.
73
- */
74
- const Input = React.forwardRef<HTMLInputElement, InputProps>(
75
- ({ className, type, ...props }, ref) => {
76
- return (
77
- <input
78
- type={type}
79
- data-slot="input"
80
- className={cn(
81
- "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
82
- className,
83
- )}
84
- ref={ref}
85
- {...props}
86
- />
87
- );
88
- },
89
- );
90
- Input.displayName = "Input";
91
-
92
- export { Input };
@@ -1,41 +0,0 @@
1
- "use client";
2
-
3
- import * as LabelPrimitive from "@radix-ui/react-label";
4
- import { cva, type VariantProps } from "class-variance-authority";
5
- import * as React from "react";
6
-
7
- import { cn } from "../../lib/utils";
8
-
9
- const labelVariants = cva(
10
- "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
11
- );
12
-
13
- export interface LabelProps
14
- extends React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>,
15
- VariantProps<typeof labelVariants> {
16
- /**
17
- * ID of the form control this label describes. Sets `for` on the
18
- * underlying `<label>` so screen readers and click-to-focus work.
19
- * Match this with the input's `id`.
20
- */
21
- htmlFor?: string;
22
- /**
23
- * Render as a Radix Slot — forwards props onto the immediate child
24
- * element instead of rendering a wrapper `<label>`.
25
- * @default false
26
- */
27
- asChild?: boolean;
28
- /** Label text. Can include nested elements (icons, helper text). */
29
- children?: React.ReactNode;
30
- /** Tailwind / CSS classes merged onto the label via `cn()`. */
31
- className?: string;
32
- }
33
-
34
- const Label = React.forwardRef<React.ElementRef<typeof LabelPrimitive.Root>, LabelProps>(
35
- ({ className, ...props }, ref) => (
36
- <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />
37
- ),
38
- );
39
- Label.displayName = LabelPrimitive.Root.displayName;
40
-
41
- export { Label };
@@ -1,89 +0,0 @@
1
- "use client";
2
-
3
- import * as React from "react";
4
-
5
- import { cn } from "../../lib/utils";
6
-
7
- export interface LogoProps extends React.HTMLAttributes<HTMLElement> {
8
- /**
9
- * Custom logo image. When provided, renders an `<img>` instead of the
10
- * default Olympus ring mark. Apps consuming canvas pass their own brand
11
- * here.
12
- */
13
- src?: string;
14
- /** Alt text for the custom-image variant. Required when `src` is set. */
15
- alt?: string;
16
- /** Pixel size for the custom-image variant only. Default 24. */
17
- size?: number;
18
- }
19
-
20
- const OlympusRing = React.forwardRef<SVGSVGElement, React.SVGAttributes<SVGSVGElement>>(
21
- ({ className, ...props }, ref) => {
22
- const gradientId = React.useId();
23
- return (
24
- <svg
25
- ref={ref}
26
- xmlns="http://www.w3.org/2000/svg"
27
- viewBox="0 0 440 736"
28
- className={className}
29
- {...props}
30
- >
31
- <defs>
32
- <linearGradient id={gradientId} x1="1" y1="1" x2="0" y2="0">
33
- <stop offset="0%" stopColor="#1E40AF" />
34
- <stop offset="100%" stopColor="#60A5FA" />
35
- </linearGradient>
36
- </defs>
37
- <g transform="translate(220, 368) rotate(90) translate(-700, -510)">
38
- <path
39
- fill={`url(#${gradientId})`}
40
- fillRule="evenodd"
41
- d="M 552 300 H 848 A 210 210 0 0 1 1058 510 A 210 210 0 0 1 848 720 H 552 A 210 210 0 0 1 342 510 A 210 210 0 0 1 552 300 Z M 582 386 H 818 A 124 124 0 0 1 942 510 A 124 124 0 0 1 818 634 H 582 A 124 124 0 0 1 458 510 A 124 124 0 0 1 582 386 Z"
42
- />
43
- </g>
44
- </svg>
45
- );
46
- },
47
- );
48
- OlympusRing.displayName = "Logo.OlympusRing";
49
-
50
- /**
51
- * Brand-agnostic logo slot.
52
- *
53
- * - With no `src`: renders the Olympus gradient-ring mark (the canonical
54
- * brand mark — viewBox 0 0 440 736, blue-gradient stadium). Size via
55
- * `className` (e.g. `className="h-10 w-auto"`) — the SVG honours its
56
- * non-square viewBox aspect ratio.
57
- * - With `src`: renders an `<img>` so consumers can drop in their own brand.
58
- *
59
- * The deprecated sideways-O ellipse mark and `showText` wordmark lockup
60
- * have been removed. Use `<BrandLockup logo={…} productName="…" />` for
61
- * the lockup.
62
- */
63
- const Logo = React.forwardRef<HTMLElement, LogoProps>(
64
- ({ src, alt = "", size = 24, className, ...props }, ref) => {
65
- if (src) {
66
- return (
67
- <img
68
- ref={ref as React.Ref<HTMLImageElement>}
69
- src={src}
70
- alt={alt}
71
- width={size}
72
- height={size}
73
- className={cn("shrink-0", className)}
74
- {...(props as React.ImgHTMLAttributes<HTMLImageElement>)}
75
- />
76
- );
77
- }
78
- return (
79
- <OlympusRing
80
- ref={ref as React.Ref<SVGSVGElement>}
81
- className={className}
82
- {...(props as React.SVGAttributes<SVGSVGElement>)}
83
- />
84
- );
85
- },
86
- );
87
- Logo.displayName = "Logo";
88
-
89
- export { Logo };