@olympusoss/canvas 2.20.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/README.md +69 -35
  2. package/package.json +45 -177
  3. package/src/cn.ts +3 -0
  4. package/src/index.ts +12 -603
  5. package/src/theme.ts +62 -0
  6. package/src/tokens.ts +11 -0
  7. package/styles/base.css +17 -0
  8. package/styles/canvas.css +77 -52
  9. package/styles/components/alert.css +66 -0
  10. package/styles/components/app-shell.css +46 -0
  11. package/styles/components/avatar.css +22 -0
  12. package/styles/components/badge.css +83 -0
  13. package/styles/components/breadcrumb.css +35 -0
  14. package/styles/components/button-group.css +23 -0
  15. package/styles/components/button.css +107 -0
  16. package/styles/components/calendar.css +73 -0
  17. package/styles/components/card.css +58 -0
  18. package/styles/components/checkbox.css +55 -0
  19. package/styles/components/code-block.css +18 -0
  20. package/styles/components/combobox.css +75 -0
  21. package/styles/components/command.css +94 -0
  22. package/styles/components/data-table.css +142 -0
  23. package/styles/components/dialog.css +72 -0
  24. package/styles/components/dropdown.css +54 -0
  25. package/styles/components/empty-state.css +17 -0
  26. package/styles/components/field.css +27 -0
  27. package/styles/components/filter-panel.css +58 -0
  28. package/styles/components/form.css +27 -0
  29. package/styles/components/icon.css +8 -0
  30. package/styles/components/input-group.css +45 -0
  31. package/styles/components/input.css +56 -0
  32. package/styles/components/kbd.css +15 -0
  33. package/styles/components/page-header.css +52 -0
  34. package/styles/components/pagination.css +48 -0
  35. package/styles/components/popover.css +14 -0
  36. package/styles/components/radio.css +28 -0
  37. package/styles/components/row-menu.css +69 -0
  38. package/styles/components/section-card.css +49 -0
  39. package/styles/components/select.css +57 -0
  40. package/styles/components/separator.css +32 -0
  41. package/styles/components/sheet.css +70 -0
  42. package/styles/components/sidebar.css +146 -0
  43. package/styles/components/skeleton.css +32 -0
  44. package/styles/components/spinner.css +26 -0
  45. package/styles/components/stat-card.css +71 -0
  46. package/styles/components/stepper.css +63 -0
  47. package/styles/components/switch.css +45 -0
  48. package/styles/components/tabs.css +40 -0
  49. package/styles/components/textarea.css +31 -0
  50. package/styles/components/toast.css +95 -0
  51. package/styles/components/tooltip.css +53 -0
  52. package/styles/components/topbar.css +24 -0
  53. package/styles/components/typography.css +105 -0
  54. package/styles/patterns/backdrops.css +35 -0
  55. package/styles/patterns/density.css +66 -0
  56. package/styles/patterns/focus.css +22 -0
  57. package/styles/patterns/glass.css +85 -0
  58. package/styles/patterns/high-contrast.css +70 -0
  59. package/styles/patterns/reduced-motion.css +12 -0
  60. package/styles/patterns/scrollbar.css +10 -0
  61. package/styles/reset.css +89 -0
  62. package/styles/tokens/colors.css +106 -0
  63. package/styles/tokens/motion.css +33 -0
  64. package/styles/tokens/radius.css +10 -0
  65. package/styles/tokens/shadows.css +35 -0
  66. package/styles/tokens/spacing.css +19 -0
  67. package/styles/tokens/typography.css +6 -0
  68. package/styles/tokens/z-index.css +12 -0
  69. package/styles/utilities/display.css +66 -0
  70. package/styles/utilities/flexbox.css +240 -0
  71. package/styles/utilities/gap.css +288 -0
  72. package/styles/utilities/grid.css +138 -0
  73. package/styles/utilities/position.css +78 -0
  74. package/styles/utilities/sizing.css +138 -0
  75. package/tsconfig.json +20 -21
  76. package/src/components/atoms/README.md +0 -11
  77. package/src/components/atoms/aspect-ratio.tsx +0 -32
  78. package/src/components/atoms/avatar.tsx +0 -98
  79. package/src/components/atoms/badge.tsx +0 -44
  80. package/src/components/atoms/brand-mark.tsx +0 -74
  81. package/src/components/atoms/button.tsx +0 -105
  82. package/src/components/atoms/checkbox.tsx +0 -63
  83. package/src/components/atoms/flex-box.tsx +0 -105
  84. package/src/components/atoms/icon.tsx +0 -34
  85. package/src/components/atoms/input.tsx +0 -92
  86. package/src/components/atoms/label.tsx +0 -41
  87. package/src/components/atoms/logo.tsx +0 -89
  88. package/src/components/atoms/progress.tsx +0 -55
  89. package/src/components/atoms/radio-group.tsx +0 -122
  90. package/src/components/atoms/scroll-area.tsx +0 -106
  91. package/src/components/atoms/section.tsx +0 -48
  92. package/src/components/atoms/separator.tsx +0 -45
  93. package/src/components/atoms/skeleton.tsx +0 -17
  94. package/src/components/atoms/slider.tsx +0 -93
  95. package/src/components/atoms/spinner.tsx +0 -47
  96. package/src/components/atoms/switch.tsx +0 -60
  97. package/src/components/atoms/textarea.tsx +0 -78
  98. package/src/components/atoms/toggle.tsx +0 -80
  99. package/src/components/charts/activity-heatmap.tsx +0 -186
  100. package/src/components/charts/axes.tsx +0 -21
  101. package/src/components/charts/chart-container.tsx +0 -254
  102. package/src/components/charts/chart-legend.tsx +0 -67
  103. package/src/components/charts/chart-tooltip.tsx +0 -161
  104. package/src/components/charts/chart-types.tsx +0 -49
  105. package/src/components/charts/containers.tsx +0 -11
  106. package/src/components/charts/data.tsx +0 -16
  107. package/src/components/charts/details.tsx +0 -25
  108. package/src/components/charts/dot-pulse.tsx +0 -61
  109. package/src/components/charts/gauge.tsx +0 -106
  110. package/src/components/charts/grids.tsx +0 -8
  111. package/src/components/charts/index.ts +0 -62
  112. package/src/components/charts/labeled-bar-list.tsx +0 -85
  113. package/src/components/charts/metric-breakdown.tsx +0 -316
  114. package/src/components/charts/references.tsx +0 -8
  115. package/src/components/charts/service-health-list.tsx +0 -85
  116. package/src/components/charts/sparkline-area.tsx +0 -80
  117. package/src/components/charts/sparkline.tsx +0 -52
  118. package/src/components/charts/stacked-bar.tsx +0 -104
  119. package/src/components/charts/text.tsx +0 -10
  120. package/src/components/charts/world-heat-map-inner.tsx +0 -317
  121. package/src/components/charts/world-heat-map.tsx +0 -184
  122. package/src/components/molecules/README.md +0 -12
  123. package/src/components/molecules/action-bar.tsx +0 -73
  124. package/src/components/molecules/activity-item.tsx +0 -74
  125. package/src/components/molecules/alert.tsx +0 -86
  126. package/src/components/molecules/animated-background.tsx +0 -92
  127. package/src/components/molecules/auth-shell.tsx +0 -95
  128. package/src/components/molecules/brand-lockup.tsx +0 -48
  129. package/src/components/molecules/breadcrumb.tsx +0 -157
  130. package/src/components/molecules/button-group.tsx +0 -104
  131. package/src/components/molecules/calendar.tsx +0 -217
  132. package/src/components/molecules/card.tsx +0 -102
  133. package/src/components/molecules/client-brand.tsx +0 -95
  134. package/src/components/molecules/code-block.tsx +0 -86
  135. package/src/components/molecules/countdown-button.tsx +0 -92
  136. package/src/components/molecules/empty-state.tsx +0 -56
  137. package/src/components/molecules/error-state.tsx +0 -42
  138. package/src/components/molecules/field-display.tsx +0 -35
  139. package/src/components/molecules/input-otp.tsx +0 -74
  140. package/src/components/molecules/launcher-card.tsx +0 -152
  141. package/src/components/molecules/loading-state.tsx +0 -36
  142. package/src/components/molecules/notification-item.tsx +0 -67
  143. package/src/components/molecules/notification-list.tsx +0 -45
  144. package/src/components/molecules/number-badge.tsx +0 -53
  145. package/src/components/molecules/or-separator.tsx +0 -38
  146. package/src/components/molecules/page-header.tsx +0 -88
  147. package/src/components/molecules/page-tabs.tsx +0 -94
  148. package/src/components/molecules/pagination.tsx +0 -150
  149. package/src/components/molecules/password-input.tsx +0 -83
  150. package/src/components/molecules/password-strength-meter.tsx +0 -104
  151. package/src/components/molecules/phone-input.tsx +0 -200
  152. package/src/components/molecules/search-bar.tsx +0 -64
  153. package/src/components/molecules/secret-field.tsx +0 -158
  154. package/src/components/molecules/section-card.tsx +0 -91
  155. package/src/components/molecules/social-buttons.tsx +0 -165
  156. package/src/components/molecules/stat-card.tsx +0 -100
  157. package/src/components/molecules/status-badge.tsx +0 -42
  158. package/src/components/molecules/stepper.tsx +0 -96
  159. package/src/components/molecules/table.tsx +0 -157
  160. package/src/components/molecules/terminal.tsx +0 -74
  161. package/src/components/molecules/toggle-group.tsx +0 -145
  162. package/src/components/molecules/tooltip.tsx +0 -155
  163. package/src/components/molecules/user-avatar-chip.tsx +0 -71
  164. package/src/components/organisms/README.md +0 -14
  165. package/src/components/organisms/accordion.tsx +0 -154
  166. package/src/components/organisms/alert-dialog.tsx +0 -277
  167. package/src/components/organisms/carousel.tsx +0 -244
  168. package/src/components/organisms/collapsible.tsx +0 -69
  169. package/src/components/organisms/command.tsx +0 -144
  170. package/src/components/organisms/context-menu.tsx +0 -339
  171. package/src/components/organisms/dashboard-grid.tsx +0 -369
  172. package/src/components/organisms/data-table.tsx +0 -330
  173. package/src/components/organisms/dialog.tsx +0 -312
  174. package/src/components/organisms/drawer.tsx +0 -123
  175. package/src/components/organisms/dropdown-menu.tsx +0 -440
  176. package/src/components/organisms/editors/code-editor.tsx +0 -144
  177. package/src/components/organisms/editors/index.ts +0 -4
  178. package/src/components/organisms/editors/markdown-editor.tsx +0 -153
  179. package/src/components/organisms/editors/markdown-renderer.ts +0 -27
  180. package/src/components/organisms/editors/prose-canvas-classes.ts +0 -45
  181. package/src/components/organisms/editors/rich-text-editor.tsx +0 -126
  182. package/src/components/organisms/editors/toolbar/md-toolbar.tsx +0 -129
  183. package/src/components/organisms/editors/toolbar/rte-toolbar.tsx +0 -211
  184. package/src/components/organisms/editors/toolbar/toolbar-shell.tsx +0 -45
  185. package/src/components/organisms/editors/use-codemirror-theme.ts +0 -61
  186. package/src/components/organisms/error-boundary.tsx +0 -61
  187. package/src/components/organisms/form.tsx +0 -174
  188. package/src/components/organisms/hover-card.tsx +0 -115
  189. package/src/components/organisms/menubar.tsx +0 -498
  190. package/src/components/organisms/navbar.tsx +0 -104
  191. package/src/components/organisms/navigation-menu.tsx +0 -235
  192. package/src/components/organisms/popover.tsx +0 -149
  193. package/src/components/organisms/resizable.tsx +0 -58
  194. package/src/components/organisms/schema-form.tsx +0 -232
  195. package/src/components/organisms/select.tsx +0 -309
  196. package/src/components/organisms/sheet.tsx +0 -265
  197. package/src/components/organisms/sidebar.tsx +0 -1040
  198. package/src/components/organisms/sonner.tsx +0 -96
  199. package/src/components/organisms/tabs.tsx +0 -133
  200. package/src/components/organisms/theme-provider.tsx +0 -101
  201. package/src/hooks/use-mobile.tsx +0 -19
  202. package/src/lib/portal-container.tsx +0 -35
  203. package/src/lib/utils.ts +0 -6
  204. package/src/native.ts +0 -23
  205. package/src/tokens/colors.ts +0 -91
  206. package/src/tokens/index.ts +0 -3
  207. package/src/tokens/spacing.ts +0 -55
  208. package/src/tokens/typography.ts +0 -27
  209. package/styles/dashboard-grid.css +0 -47
  210. package/styles/fonts/Roboto-VariableFont_wdth_wght.ttf +0 -0
  211. package/styles/glass.css +0 -171
  212. package/styles/leaflet.css +0 -13
  213. package/styles/tokens.css +0 -317
  214. package/tailwind.config.ts +0 -70
@@ -1,157 +0,0 @@
1
- import { Slot } from "@radix-ui/react-slot";
2
- import { ChevronRight, MoreHorizontal } from "lucide-react";
3
- import * as React from "react";
4
-
5
- import { cn } from "../../lib/utils";
6
-
7
- export interface BreadcrumbProps extends React.ComponentPropsWithoutRef<"nav"> {
8
- /**
9
- * Custom separator element used between items. Defaults to a chevron
10
- * via `<BreadcrumbSeparator>`.
11
- */
12
- separator?: React.ReactNode;
13
- /** A `<BreadcrumbList>` containing items. */
14
- children?: React.ReactNode;
15
- /** Tailwind / CSS classes merged onto the `<nav>` via `cn()`. */
16
- className?: string;
17
- }
18
-
19
- const Breadcrumb = React.forwardRef<HTMLElement, BreadcrumbProps>(({ ...props }, ref) => (
20
- <nav ref={ref} aria-label="breadcrumb" {...props} />
21
- ));
22
- Breadcrumb.displayName = "Breadcrumb";
23
-
24
- export interface BreadcrumbListProps extends React.ComponentPropsWithoutRef<"ol"> {
25
- /** A flat list of `<BreadcrumbItem>`s, separated by `<BreadcrumbSeparator>`. */
26
- children?: React.ReactNode;
27
- /** Tailwind / CSS classes merged onto the `<ol>` via `cn()`. */
28
- className?: string;
29
- }
30
-
31
- const BreadcrumbList = React.forwardRef<HTMLOListElement, BreadcrumbListProps>(
32
- ({ className, ...props }, ref) => (
33
- <ol
34
- ref={ref}
35
- className={cn(
36
- "flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5",
37
- className,
38
- )}
39
- {...props}
40
- />
41
- ),
42
- );
43
- BreadcrumbList.displayName = "BreadcrumbList";
44
-
45
- export interface BreadcrumbItemProps extends React.ComponentPropsWithoutRef<"li"> {
46
- /** Typically a `<BreadcrumbLink>` or `<BreadcrumbPage>`. */
47
- children?: React.ReactNode;
48
- /** Tailwind / CSS classes merged onto the `<li>` via `cn()`. */
49
- className?: string;
50
- }
51
-
52
- const BreadcrumbItem = React.forwardRef<HTMLLIElement, BreadcrumbItemProps>(
53
- ({ className, ...props }, ref) => (
54
- <li ref={ref} className={cn("inline-flex items-center gap-1.5", className)} {...props} />
55
- ),
56
- );
57
- BreadcrumbItem.displayName = "BreadcrumbItem";
58
-
59
- export interface BreadcrumbLinkProps extends React.ComponentPropsWithoutRef<"a"> {
60
- /**
61
- * Render as a Radix Slot — useful for wrapping a router `<Link>` so
62
- * it inherits breadcrumb styling.
63
- * @default false
64
- */
65
- asChild?: boolean;
66
- /** Anchor target. Used when not in `asChild` mode. */
67
- href?: string;
68
- /** Link label. */
69
- children?: React.ReactNode;
70
- /** Tailwind / CSS classes merged onto the link via `cn()`. */
71
- className?: string;
72
- }
73
-
74
- const BreadcrumbLink = React.forwardRef<HTMLAnchorElement, BreadcrumbLinkProps>(
75
- ({ asChild, className, ...props }, ref) => {
76
- const Comp = asChild ? Slot : "a";
77
-
78
- return (
79
- <Comp ref={ref} className={cn("transition-colors hover:text-brand", className)} {...props} />
80
- );
81
- },
82
- );
83
- BreadcrumbLink.displayName = "BreadcrumbLink";
84
-
85
- export interface BreadcrumbPageProps extends React.ComponentPropsWithoutRef<"span"> {
86
- /**
87
- * Label of the current page. This is the last breadcrumb item and is
88
- * non-clickable; sets `aria-current="page"` for assistive tech.
89
- */
90
- children?: React.ReactNode;
91
- /** Tailwind / CSS classes merged onto the page span via `cn()`. */
92
- className?: string;
93
- }
94
-
95
- const BreadcrumbPage = React.forwardRef<HTMLSpanElement, BreadcrumbPageProps>(
96
- ({ className, ...props }, ref) => (
97
- <span
98
- ref={ref}
99
- role="link"
100
- aria-disabled="true"
101
- aria-current="page"
102
- className={cn("font-normal text-foreground", className)}
103
- {...props}
104
- />
105
- ),
106
- );
107
- BreadcrumbPage.displayName = "BreadcrumbPage";
108
-
109
- export interface BreadcrumbSeparatorProps extends React.ComponentProps<"li"> {
110
- /**
111
- * Override the default chevron with a custom node (e.g. a slash, an
112
- * arrow icon).
113
- */
114
- children?: React.ReactNode;
115
- /** Tailwind / CSS classes merged onto the separator via `cn()`. */
116
- className?: string;
117
- }
118
-
119
- const BreadcrumbSeparator = ({ children, className, ...props }: BreadcrumbSeparatorProps) => (
120
- <li
121
- role="presentation"
122
- aria-hidden="true"
123
- className={cn("[&>svg]:w-3.5 [&>svg]:h-3.5", className)}
124
- {...props}
125
- >
126
- {children ?? <ChevronRight />}
127
- </li>
128
- );
129
- BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
130
-
131
- export interface BreadcrumbEllipsisProps extends React.ComponentProps<"span"> {
132
- /** Tailwind / CSS classes merged onto the ellipsis via `cn()`. */
133
- className?: string;
134
- }
135
-
136
- const BreadcrumbEllipsis = ({ className, ...props }: BreadcrumbEllipsisProps) => (
137
- <span
138
- role="presentation"
139
- aria-hidden="true"
140
- className={cn("flex h-9 w-9 items-center justify-center", className)}
141
- {...props}
142
- >
143
- <MoreHorizontal className="h-4 w-4" />
144
- <span className="sr-only">More</span>
145
- </span>
146
- );
147
- BreadcrumbEllipsis.displayName = "BreadcrumbElipssis";
148
-
149
- export {
150
- Breadcrumb,
151
- BreadcrumbEllipsis,
152
- BreadcrumbItem,
153
- BreadcrumbLink,
154
- BreadcrumbList,
155
- BreadcrumbPage,
156
- BreadcrumbSeparator,
157
- };
@@ -1,104 +0,0 @@
1
- import { Slot } from "@radix-ui/react-slot";
2
- import { cva, type VariantProps } from "class-variance-authority";
3
- import type * as React from "react";
4
-
5
- import { cn } from "../../lib/utils";
6
- import { Separator } from "../atoms/separator";
7
-
8
- const buttonGroupVariants = cva(
9
- "flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
10
- {
11
- variants: {
12
- orientation: {
13
- horizontal:
14
- "[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
15
- vertical:
16
- "flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",
17
- },
18
- },
19
- defaultVariants: {
20
- orientation: "horizontal",
21
- },
22
- },
23
- );
24
-
25
- export interface ButtonGroupProps
26
- extends React.ComponentProps<"div">,
27
- VariantProps<typeof buttonGroupVariants> {
28
- /**
29
- * `horizontal` (default) lays buttons left-to-right with shared borders;
30
- * `vertical` stacks them with shared horizontal borders.
31
- * @default "horizontal"
32
- */
33
- orientation?: "horizontal" | "vertical";
34
- /** A row/column of `<Button>`s, `<ButtonGroupText>`s, or separators. */
35
- children?: React.ReactNode;
36
- className?: string;
37
- }
38
-
39
- function ButtonGroup({ className, orientation, ...props }: ButtonGroupProps) {
40
- return (
41
- <div
42
- role="group"
43
- data-slot="button-group"
44
- data-orientation={orientation}
45
- className={cn(buttonGroupVariants({ orientation }), className)}
46
- {...props}
47
- />
48
- );
49
- }
50
-
51
- export interface ButtonGroupTextProps extends React.ComponentProps<"div"> {
52
- /**
53
- * Render as a Radix Slot — useful for wrapping a label or icon as the
54
- * group's text element.
55
- * @default false
56
- */
57
- asChild?: boolean;
58
- /** Text or icon content. */
59
- children?: React.ReactNode;
60
- className?: string;
61
- }
62
-
63
- function ButtonGroupText({ className, asChild = false, ...props }: ButtonGroupTextProps) {
64
- const Comp = asChild ? Slot : "div";
65
-
66
- return (
67
- <Comp
68
- className={cn(
69
- "bg-muted shadow-xs flex items-center gap-2 rounded-md border border-border px-4 text-sm font-medium [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
70
- className,
71
- )}
72
- {...props}
73
- />
74
- );
75
- }
76
-
77
- export interface ButtonGroupSeparatorProps extends React.ComponentProps<typeof Separator> {
78
- /**
79
- * Layout direction.
80
- * @default "vertical"
81
- */
82
- orientation?: "horizontal" | "vertical";
83
- className?: string;
84
- }
85
-
86
- function ButtonGroupSeparator({
87
- className,
88
- orientation = "vertical",
89
- ...props
90
- }: ButtonGroupSeparatorProps) {
91
- return (
92
- <Separator
93
- data-slot="button-group-separator"
94
- orientation={orientation}
95
- className={cn(
96
- "bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto",
97
- className,
98
- )}
99
- {...props}
100
- />
101
- );
102
- }
103
-
104
- export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupVariants };
@@ -1,217 +0,0 @@
1
- "use client";
2
-
3
- import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
4
- import * as React from "react";
5
- import { type DayButton, DayPicker, getDefaultClassNames } from "react-day-picker";
6
-
7
- import { cn } from "../../lib/utils";
8
- import { Button, buttonVariants } from "../atoms/button";
9
-
10
- export type CalendarProps = React.ComponentProps<typeof DayPicker> & {
11
- /**
12
- * Variant applied to the prev/next month nav buttons. Maps to the
13
- * `Button` atom's variants.
14
- * @default "ghost"
15
- */
16
- buttonVariant?: React.ComponentProps<typeof Button>["variant"];
17
- /**
18
- * Show days from the previous/next month as faded entries to fill the
19
- * grid.
20
- * @default true
21
- */
22
- showOutsideDays?: boolean;
23
- /**
24
- * How the month/year heading renders. `label` is plain text, the
25
- * dropdown variants render selectable controls.
26
- * @default "label"
27
- */
28
- captionLayout?: "label" | "dropdown" | "dropdown-months" | "dropdown-years";
29
- className?: string;
30
- };
31
-
32
- function Calendar({
33
- className,
34
- classNames,
35
- showOutsideDays = true,
36
- captionLayout = "label",
37
- buttonVariant = "ghost",
38
- formatters,
39
- components,
40
- ...props
41
- }: CalendarProps) {
42
- const defaultClassNames = getDefaultClassNames();
43
-
44
- return (
45
- <DayPicker
46
- showOutsideDays={showOutsideDays}
47
- data-slot="calendar"
48
- className={cn(
49
- "bg-background group/calendar p-4 [--cell-size:2rem] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
50
- String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
51
- String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
52
- className,
53
- )}
54
- captionLayout={captionLayout}
55
- formatters={{
56
- formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
57
- ...formatters,
58
- }}
59
- classNames={{
60
- root: cn("w-fit", defaultClassNames.root),
61
- months: cn("relative flex flex-col gap-4 md:flex-row", defaultClassNames.months),
62
- month: cn("flex w-full flex-col gap-3", defaultClassNames.month),
63
- nav: cn(
64
- "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
65
- defaultClassNames.nav,
66
- ),
67
- button_previous: cn(
68
- buttonVariants({ variant: buttonVariant }),
69
- "h-[var(--cell-size)] w-[var(--cell-size)] select-none p-0 aria-disabled:opacity-50",
70
- defaultClassNames.button_previous,
71
- ),
72
- button_next: cn(
73
- buttonVariants({ variant: buttonVariant }),
74
- "h-[var(--cell-size)] w-[var(--cell-size)] select-none p-0 aria-disabled:opacity-50",
75
- defaultClassNames.button_next,
76
- ),
77
- month_caption: cn(
78
- "flex h-[var(--cell-size)] w-full items-center justify-center px-[var(--cell-size)]",
79
- defaultClassNames.month_caption,
80
- ),
81
- dropdowns: cn(
82
- "flex h-[var(--cell-size)] w-full items-center justify-center gap-1.5 text-sm font-medium",
83
- defaultClassNames.dropdowns,
84
- ),
85
- dropdown_root: cn(
86
- "has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border",
87
- defaultClassNames.dropdown_root,
88
- ),
89
- dropdown: cn("bg-popover absolute inset-0 opacity-0", defaultClassNames.dropdown),
90
- caption_label: cn(
91
- "select-none font-semibold tracking-tight text-foreground",
92
- captionLayout === "label"
93
- ? "text-sm"
94
- : "[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5",
95
- defaultClassNames.caption_label,
96
- ),
97
- table: "w-full border-collapse",
98
- weekdays: cn("flex border-b border-border pb-1.5", defaultClassNames.weekdays),
99
- weekday: cn(
100
- "text-muted-foreground flex-1 select-none rounded-md text-[0.7rem] font-medium uppercase tracking-wider",
101
- defaultClassNames.weekday,
102
- ),
103
- week: cn("mt-1.5 flex w-full", defaultClassNames.week),
104
- week_number_header: cn(
105
- "w-[var(--cell-size)] select-none",
106
- defaultClassNames.week_number_header,
107
- ),
108
- week_number: cn(
109
- "text-muted-foreground select-none text-[0.8rem]",
110
- defaultClassNames.week_number,
111
- ),
112
- day: cn(
113
- "group/day relative aspect-square h-full w-full select-none p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md",
114
- defaultClassNames.day,
115
- ),
116
- range_start: cn("bg-brand/10 rounded-l-md", defaultClassNames.range_start),
117
- range_middle: cn("bg-brand/10 rounded-none", defaultClassNames.range_middle),
118
- range_end: cn("bg-brand/10 rounded-r-md", defaultClassNames.range_end),
119
- today: cn(
120
- "text-brand font-semibold data-[selected=true]:rounded-none",
121
- defaultClassNames.today,
122
- ),
123
- outside: cn(
124
- "text-muted-foreground/50 aria-selected:text-muted-foreground",
125
- defaultClassNames.outside,
126
- ),
127
- disabled: cn("text-muted-foreground opacity-40", defaultClassNames.disabled),
128
- hidden: cn("invisible", defaultClassNames.hidden),
129
- ...classNames,
130
- }}
131
- components={{
132
- Root: ({ className, rootRef, ...props }) => {
133
- return <div data-slot="calendar" ref={rootRef} className={cn(className)} {...props} />;
134
- },
135
- Chevron: ({ className, orientation, ...props }) => {
136
- if (orientation === "left") {
137
- return <ChevronLeftIcon className={cn("size-4", className)} {...props} />;
138
- }
139
-
140
- if (orientation === "right") {
141
- return <ChevronRightIcon className={cn("size-4", className)} {...props} />;
142
- }
143
-
144
- return <ChevronDownIcon className={cn("size-4", className)} {...props} />;
145
- },
146
- DayButton: CalendarDayButton,
147
- WeekNumber: ({ children, ...props }) => {
148
- return (
149
- <td {...props}>
150
- <div className="flex size-[var(--cell-size)] items-center justify-center text-center">
151
- {children}
152
- </div>
153
- </td>
154
- );
155
- },
156
- ...components,
157
- }}
158
- {...props}
159
- />
160
- );
161
- }
162
-
163
- function CalendarDayButton({
164
- className,
165
- day,
166
- modifiers,
167
- ...props
168
- }: React.ComponentProps<typeof DayButton>) {
169
- const defaultClassNames = getDefaultClassNames();
170
-
171
- const ref = React.useRef<HTMLButtonElement>(null);
172
- React.useEffect(() => {
173
- if (modifiers.focused) ref.current?.focus();
174
- }, [modifiers.focused]);
175
-
176
- return (
177
- <Button
178
- ref={ref}
179
- variant="ghost"
180
- size="icon"
181
- data-day={day.date.toLocaleDateString()}
182
- data-selected-single={
183
- modifiers.selected &&
184
- !modifiers.range_start &&
185
- !modifiers.range_end &&
186
- !modifiers.range_middle
187
- }
188
- data-range-start={modifiers.range_start}
189
- data-range-end={modifiers.range_end}
190
- data-range-middle={modifiers.range_middle}
191
- className={cn(
192
- // base size + typography (small inner inset so adjacent dates breathe)
193
- "m-0.5 flex aspect-square h-auto w-[calc(100%-0.25rem)] min-w-[calc(var(--cell-size)-0.25rem)] items-center justify-center rounded-md text-sm font-normal leading-none transition-colors",
194
- // hover (when not selected)
195
- "hover:bg-accent hover:text-accent-foreground",
196
- // today: keep brand text colour from row classNames; add subtle ring
197
- "group-[[data-today=true]]/day:ring-1 group-[[data-today=true]]/day:ring-brand/40",
198
- // single selection: brand fill, white text, full rounding
199
- "data-[selected-single=true]:bg-brand data-[selected-single=true]:text-brand-foreground data-[selected-single=true]:hover:bg-brand/90 data-[selected-single=true]:hover:text-brand-foreground",
200
- // range endpoints: brand fill, only outer corners rounded
201
- "data-[range-start=true]:bg-brand data-[range-start=true]:text-brand-foreground data-[range-start=true]:hover:bg-brand/90 data-[range-start=true]:hover:text-brand-foreground data-[range-start=true]:rounded-r-none",
202
- "data-[range-end=true]:bg-brand data-[range-end=true]:text-brand-foreground data-[range-end=true]:hover:bg-brand/90 data-[range-end=true]:hover:text-brand-foreground data-[range-end=true]:rounded-l-none",
203
- // range middle: foreground stays default, no rounding
204
- "data-[range-middle=true]:bg-transparent data-[range-middle=true]:text-foreground data-[range-middle=true]:rounded-none",
205
- // focus ring (for keyboard nav)
206
- "group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-brand/40 group-data-[focused=true]/day:border-brand",
207
- // modifier label (e.g. holidays) sub-line
208
- "[&>span]:text-xs [&>span]:opacity-70",
209
- defaultClassNames.day,
210
- className,
211
- )}
212
- {...props}
213
- />
214
- );
215
- }
216
-
217
- export { Calendar, CalendarDayButton };
@@ -1,102 +0,0 @@
1
- import * as React from "react";
2
-
3
- import { cn } from "../../lib/utils";
4
-
5
- export interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
6
- /** `<CardHeader>`, `<CardContent>`, `<CardFooter>` (or any custom layout). */
7
- children?: React.ReactNode;
8
- /**
9
- * Tailwind / CSS classes merged onto the card via `cn()`. Default
10
- * styling: `rounded-xl` (12px), `border`, `bg-card`, `shadow`.
11
- */
12
- className?: string;
13
- }
14
-
15
- const Card = React.forwardRef<HTMLDivElement, CardProps>(({ className, ...props }, ref) => (
16
- <div
17
- ref={ref}
18
- data-slot="card"
19
- className={cn("rounded-xl border border-border bg-card text-card-foreground shadow", className)}
20
- {...props}
21
- />
22
- ));
23
- Card.displayName = "Card";
24
-
25
- export interface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
26
- /** Typically `<CardTitle>` + `<CardDescription>`. */
27
- children?: React.ReactNode;
28
- /** Tailwind / CSS classes merged onto the header via `cn()`. Default: `p-6 space-y-1.5`. */
29
- className?: string;
30
- }
31
-
32
- const CardHeader = React.forwardRef<HTMLDivElement, CardHeaderProps>(
33
- ({ className, ...props }, ref) => (
34
- <div ref={ref} className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} />
35
- ),
36
- );
37
- CardHeader.displayName = "CardHeader";
38
-
39
- export interface CardTitleProps extends React.HTMLAttributes<HTMLDivElement> {
40
- /** The card heading. */
41
- children?: React.ReactNode;
42
- /** Tailwind / CSS classes merged onto the title via `cn()`. */
43
- className?: string;
44
- }
45
-
46
- const CardTitle = React.forwardRef<HTMLDivElement, CardTitleProps>(
47
- ({ className, ...props }, ref) => (
48
- <div
49
- ref={ref}
50
- className={cn("font-semibold leading-none tracking-tight", className)}
51
- {...props}
52
- />
53
- ),
54
- );
55
- CardTitle.displayName = "CardTitle";
56
-
57
- export interface CardDescriptionProps extends React.HTMLAttributes<HTMLDivElement> {
58
- /** Subtitle / supporting copy below the title. */
59
- children?: React.ReactNode;
60
- /** Tailwind / CSS classes merged onto the description via `cn()`. */
61
- className?: string;
62
- }
63
-
64
- const CardDescription = React.forwardRef<HTMLDivElement, CardDescriptionProps>(
65
- ({ className, ...props }, ref) => (
66
- <div ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
67
- ),
68
- );
69
- CardDescription.displayName = "CardDescription";
70
-
71
- export interface CardContentProps extends React.HTMLAttributes<HTMLDivElement> {
72
- /** Card body. */
73
- children?: React.ReactNode;
74
- /** Tailwind / CSS classes merged onto the content via `cn()`. Default: `p-6 pt-0`. */
75
- className?: string;
76
- }
77
-
78
- const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(
79
- ({ className, ...props }, ref) => (
80
- <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
81
- ),
82
- );
83
- CardContent.displayName = "CardContent";
84
-
85
- export interface CardFooterProps extends React.HTMLAttributes<HTMLDivElement> {
86
- /** Card actions / metadata row. */
87
- children?: React.ReactNode;
88
- /**
89
- * Tailwind / CSS classes merged onto the footer via `cn()`. Default:
90
- * `flex items-center p-6 pt-0`.
91
- */
92
- className?: string;
93
- }
94
-
95
- const CardFooter = React.forwardRef<HTMLDivElement, CardFooterProps>(
96
- ({ className, ...props }, ref) => (
97
- <div ref={ref} className={cn("flex items-center p-6 pt-0", className)} {...props} />
98
- ),
99
- );
100
- CardFooter.displayName = "CardFooter";
101
-
102
- export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };
@@ -1,95 +0,0 @@
1
- "use client";
2
-
3
- import * as React from "react";
4
-
5
- import { cn } from "../../lib/utils";
6
-
7
- export interface ClientBrandProps {
8
- /** OAuth2 client display name (e.g. "Questrade", "Athena"). */
9
- clientName: string;
10
- /**
11
- * Optional logo URI. Renders as an `<img>` next to the wordmark when
12
- * present. When absent, a tinted monogram tile is rendered using the
13
- * first letter of `clientName`.
14
- */
15
- clientLogoUri?: string;
16
- /**
17
- * Pixel size of the logo/monogram tile.
18
- * @default 36
19
- */
20
- size?: number;
21
- /**
22
- * Show the wordmark next to the logo.
23
- * @default true
24
- */
25
- showWordmark?: boolean;
26
- /**
27
- * Background colour applied to the monogram fallback tile. Honours
28
- * Tailwind classes or a raw CSS colour.
29
- * @default "bg-foreground text-background"
30
- */
31
- monogramClassName?: string;
32
- /** Tailwind / CSS classes merged onto the root via `cn()`. */
33
- className?: string;
34
- }
35
-
36
- /**
37
- * OAuth2 client lockup. Renders the requesting application's logo + name
38
- * so users see "you're signing in to [App]", not the identity-provider
39
- * platform underneath.
40
- *
41
- * Provide `clientLogoUri` to render the client's logo image. Falls back to
42
- * a monogram tile when no URI is supplied or the image fails to load.
43
- *
44
- * Designed for the brand slot of `AuthShell` / sign-in pages. Stays a thin
45
- * presentation primitive: no client-registry lookups, no fetches. Pass the
46
- * shaped data in from your auth backend.
47
- */
48
- const ClientBrand = React.forwardRef<HTMLDivElement, ClientBrandProps>(
49
- (
50
- { clientName, clientLogoUri, size = 36, showWordmark = true, monogramClassName, className },
51
- ref,
52
- ) => {
53
- const [imgFailed, setImgFailed] = React.useState(false);
54
- const showImage = !!clientLogoUri && !imgFailed;
55
- const initial = (clientName?.trim()?.[0] || "?").toUpperCase();
56
-
57
- return (
58
- <div
59
- ref={ref}
60
- role="img"
61
- aria-label={`Signing in to ${clientName}`}
62
- className={cn("flex items-center gap-2.5", className)}
63
- >
64
- {showImage ? (
65
- <img
66
- src={clientLogoUri}
67
- alt=""
68
- width={size}
69
- height={size}
70
- className="shrink-0 rounded-lg object-contain"
71
- style={{ width: size, height: size }}
72
- onError={() => setImgFailed(true)}
73
- />
74
- ) : (
75
- <div
76
- className={cn(
77
- "flex shrink-0 items-center justify-center rounded-lg font-semibold",
78
- monogramClassName || "bg-foreground text-background",
79
- )}
80
- style={{ width: size, height: size, fontSize: Math.round(size * 0.5) }}
81
- aria-hidden
82
- >
83
- {initial}
84
- </div>
85
- )}
86
- {showWordmark && (
87
- <span className="text-lg font-semibold tracking-tight text-foreground">{clientName}</span>
88
- )}
89
- </div>
90
- );
91
- },
92
- );
93
- ClientBrand.displayName = "ClientBrand";
94
-
95
- export { ClientBrand };