@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.
- package/package.json +41 -177
- package/src/cn.ts +3 -0
- package/src/index.ts +12 -603
- package/src/theme.ts +41 -0
- package/src/tokens.ts +11 -0
- package/styles/base.css +17 -0
- package/styles/canvas.css +69 -52
- package/styles/components/alert.css +66 -0
- package/styles/components/app-shell.css +46 -0
- package/styles/components/avatar.css +15 -0
- package/styles/components/badge.css +83 -0
- package/styles/components/breadcrumb.css +35 -0
- package/styles/components/button-group.css +23 -0
- package/styles/components/button.css +107 -0
- package/styles/components/calendar.css +73 -0
- package/styles/components/card.css +58 -0
- package/styles/components/checkbox.css +55 -0
- package/styles/components/code-block.css +18 -0
- package/styles/components/combobox.css +75 -0
- package/styles/components/command.css +94 -0
- package/styles/components/data-table.css +142 -0
- package/styles/components/dialog.css +72 -0
- package/styles/components/dropdown.css +54 -0
- package/styles/components/empty-state.css +17 -0
- package/styles/components/field.css +27 -0
- package/styles/components/filter-panel.css +58 -0
- package/styles/components/form.css +27 -0
- package/styles/components/icon.css +8 -0
- package/styles/components/input-group.css +45 -0
- package/styles/components/input.css +56 -0
- package/styles/components/kbd.css +15 -0
- package/styles/components/page-header.css +52 -0
- package/styles/components/pagination.css +48 -0
- package/styles/components/popover.css +14 -0
- package/styles/components/radio.css +28 -0
- package/styles/components/row-menu.css +69 -0
- package/styles/components/section-card.css +49 -0
- package/styles/components/select.css +57 -0
- package/styles/components/separator.css +32 -0
- package/styles/components/sheet.css +70 -0
- package/styles/components/sidebar.css +146 -0
- package/styles/components/skeleton.css +32 -0
- package/styles/components/spinner.css +26 -0
- package/styles/components/stat-card.css +71 -0
- package/styles/components/stepper.css +63 -0
- package/styles/components/switch.css +45 -0
- package/styles/components/tabs.css +40 -0
- package/styles/components/textarea.css +31 -0
- package/styles/components/toast.css +95 -0
- package/styles/components/tooltip.css +53 -0
- package/styles/components/topbar.css +24 -0
- package/styles/components/typography.css +105 -0
- package/styles/patterns/backdrops.css +35 -0
- package/styles/patterns/density.css +66 -0
- package/styles/patterns/focus.css +38 -0
- package/styles/patterns/glass.css +85 -0
- package/styles/patterns/high-contrast.css +70 -0
- package/styles/patterns/reduced-motion.css +12 -0
- package/styles/patterns/scrollbar.css +10 -0
- package/styles/reset.css +89 -0
- package/styles/tokens/colors.css +106 -0
- package/styles/tokens/motion.css +33 -0
- package/styles/tokens/radius.css +10 -0
- package/styles/tokens/shadows.css +35 -0
- package/styles/tokens/spacing.css +19 -0
- package/styles/tokens/typography.css +6 -0
- package/styles/tokens/z-index.css +12 -0
- package/tsconfig.json +20 -21
- package/README.md +0 -60
- package/src/components/atoms/README.md +0 -11
- package/src/components/atoms/aspect-ratio.tsx +0 -32
- package/src/components/atoms/avatar.tsx +0 -98
- package/src/components/atoms/badge.tsx +0 -44
- package/src/components/atoms/brand-mark.tsx +0 -74
- package/src/components/atoms/button.tsx +0 -105
- package/src/components/atoms/checkbox.tsx +0 -63
- package/src/components/atoms/flex-box.tsx +0 -105
- package/src/components/atoms/icon.tsx +0 -34
- package/src/components/atoms/input.tsx +0 -92
- package/src/components/atoms/label.tsx +0 -41
- package/src/components/atoms/logo.tsx +0 -89
- package/src/components/atoms/progress.tsx +0 -55
- package/src/components/atoms/radio-group.tsx +0 -122
- package/src/components/atoms/scroll-area.tsx +0 -106
- package/src/components/atoms/section.tsx +0 -48
- package/src/components/atoms/separator.tsx +0 -45
- package/src/components/atoms/skeleton.tsx +0 -17
- package/src/components/atoms/slider.tsx +0 -93
- package/src/components/atoms/spinner.tsx +0 -47
- package/src/components/atoms/switch.tsx +0 -60
- package/src/components/atoms/textarea.tsx +0 -78
- package/src/components/atoms/toggle.tsx +0 -80
- package/src/components/charts/activity-heatmap.tsx +0 -186
- package/src/components/charts/axes.tsx +0 -21
- package/src/components/charts/chart-container.tsx +0 -254
- package/src/components/charts/chart-legend.tsx +0 -67
- package/src/components/charts/chart-tooltip.tsx +0 -161
- package/src/components/charts/chart-types.tsx +0 -49
- package/src/components/charts/containers.tsx +0 -11
- package/src/components/charts/data.tsx +0 -16
- package/src/components/charts/details.tsx +0 -25
- package/src/components/charts/dot-pulse.tsx +0 -61
- package/src/components/charts/gauge.tsx +0 -106
- package/src/components/charts/grids.tsx +0 -8
- package/src/components/charts/index.ts +0 -62
- package/src/components/charts/labeled-bar-list.tsx +0 -85
- package/src/components/charts/metric-breakdown.tsx +0 -316
- package/src/components/charts/references.tsx +0 -8
- package/src/components/charts/service-health-list.tsx +0 -85
- package/src/components/charts/sparkline-area.tsx +0 -80
- package/src/components/charts/sparkline.tsx +0 -52
- package/src/components/charts/stacked-bar.tsx +0 -104
- package/src/components/charts/text.tsx +0 -10
- package/src/components/charts/world-heat-map-inner.tsx +0 -317
- package/src/components/charts/world-heat-map.tsx +0 -184
- package/src/components/molecules/README.md +0 -12
- package/src/components/molecules/action-bar.tsx +0 -73
- package/src/components/molecules/activity-item.tsx +0 -74
- package/src/components/molecules/alert.tsx +0 -86
- package/src/components/molecules/animated-background.tsx +0 -92
- package/src/components/molecules/auth-shell.tsx +0 -95
- package/src/components/molecules/brand-lockup.tsx +0 -48
- package/src/components/molecules/breadcrumb.tsx +0 -157
- package/src/components/molecules/button-group.tsx +0 -104
- package/src/components/molecules/calendar.tsx +0 -217
- package/src/components/molecules/card.tsx +0 -102
- package/src/components/molecules/client-brand.tsx +0 -95
- package/src/components/molecules/code-block.tsx +0 -86
- package/src/components/molecules/countdown-button.tsx +0 -92
- package/src/components/molecules/empty-state.tsx +0 -56
- package/src/components/molecules/error-state.tsx +0 -42
- package/src/components/molecules/field-display.tsx +0 -35
- package/src/components/molecules/input-otp.tsx +0 -74
- package/src/components/molecules/launcher-card.tsx +0 -152
- package/src/components/molecules/loading-state.tsx +0 -36
- package/src/components/molecules/notification-item.tsx +0 -67
- package/src/components/molecules/notification-list.tsx +0 -45
- package/src/components/molecules/number-badge.tsx +0 -53
- package/src/components/molecules/or-separator.tsx +0 -38
- package/src/components/molecules/page-header.tsx +0 -88
- package/src/components/molecules/page-tabs.tsx +0 -94
- package/src/components/molecules/pagination.tsx +0 -150
- package/src/components/molecules/password-input.tsx +0 -83
- package/src/components/molecules/password-strength-meter.tsx +0 -104
- package/src/components/molecules/phone-input.tsx +0 -200
- package/src/components/molecules/search-bar.tsx +0 -64
- package/src/components/molecules/secret-field.tsx +0 -158
- package/src/components/molecules/section-card.tsx +0 -91
- package/src/components/molecules/social-buttons.tsx +0 -165
- package/src/components/molecules/stat-card.tsx +0 -100
- package/src/components/molecules/status-badge.tsx +0 -42
- package/src/components/molecules/stepper.tsx +0 -96
- package/src/components/molecules/table.tsx +0 -157
- package/src/components/molecules/terminal.tsx +0 -74
- package/src/components/molecules/toggle-group.tsx +0 -145
- package/src/components/molecules/tooltip.tsx +0 -155
- package/src/components/molecules/user-avatar-chip.tsx +0 -71
- package/src/components/organisms/README.md +0 -14
- package/src/components/organisms/accordion.tsx +0 -154
- package/src/components/organisms/alert-dialog.tsx +0 -277
- package/src/components/organisms/carousel.tsx +0 -244
- package/src/components/organisms/collapsible.tsx +0 -69
- package/src/components/organisms/command.tsx +0 -144
- package/src/components/organisms/context-menu.tsx +0 -339
- package/src/components/organisms/dashboard-grid.tsx +0 -369
- package/src/components/organisms/data-table.tsx +0 -330
- package/src/components/organisms/dialog.tsx +0 -312
- package/src/components/organisms/drawer.tsx +0 -123
- package/src/components/organisms/dropdown-menu.tsx +0 -440
- package/src/components/organisms/editors/code-editor.tsx +0 -144
- package/src/components/organisms/editors/index.ts +0 -4
- package/src/components/organisms/editors/markdown-editor.tsx +0 -153
- package/src/components/organisms/editors/markdown-renderer.ts +0 -27
- package/src/components/organisms/editors/prose-canvas-classes.ts +0 -45
- package/src/components/organisms/editors/rich-text-editor.tsx +0 -126
- package/src/components/organisms/editors/toolbar/md-toolbar.tsx +0 -129
- package/src/components/organisms/editors/toolbar/rte-toolbar.tsx +0 -211
- package/src/components/organisms/editors/toolbar/toolbar-shell.tsx +0 -45
- package/src/components/organisms/editors/use-codemirror-theme.ts +0 -61
- package/src/components/organisms/error-boundary.tsx +0 -61
- package/src/components/organisms/form.tsx +0 -174
- package/src/components/organisms/hover-card.tsx +0 -115
- package/src/components/organisms/menubar.tsx +0 -498
- package/src/components/organisms/navbar.tsx +0 -104
- package/src/components/organisms/navigation-menu.tsx +0 -235
- package/src/components/organisms/popover.tsx +0 -149
- package/src/components/organisms/resizable.tsx +0 -58
- package/src/components/organisms/schema-form.tsx +0 -232
- package/src/components/organisms/select.tsx +0 -309
- package/src/components/organisms/sheet.tsx +0 -265
- package/src/components/organisms/sidebar.tsx +0 -1040
- package/src/components/organisms/sonner.tsx +0 -96
- package/src/components/organisms/tabs.tsx +0 -133
- package/src/components/organisms/theme-provider.tsx +0 -101
- package/src/hooks/use-mobile.tsx +0 -19
- package/src/lib/portal-container.tsx +0 -35
- package/src/lib/utils.ts +0 -6
- package/src/native.ts +0 -23
- package/src/tokens/colors.ts +0 -91
- package/src/tokens/index.ts +0 -3
- package/src/tokens/spacing.ts +0 -55
- package/src/tokens/typography.ts +0 -27
- package/styles/dashboard-grid.css +0 -47
- package/styles/fonts/Roboto-VariableFont_wdth_wght.ttf +0 -0
- package/styles/glass.css +0 -171
- package/styles/leaflet.css +0 -13
- package/styles/tokens.css +0 -317
- package/tailwind.config.ts +0 -70
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
|
|
4
|
-
import { cn } from "../../lib/utils";
|
|
5
|
-
|
|
6
|
-
const alertVariants = cva(
|
|
7
|
-
"relative w-full rounded-lg border border-border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
|
|
8
|
-
{
|
|
9
|
-
variants: {
|
|
10
|
-
variant: {
|
|
11
|
-
default: "bg-background text-foreground",
|
|
12
|
-
destructive:
|
|
13
|
-
"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
defaultVariants: {
|
|
17
|
-
variant: "default",
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
export interface AlertProps
|
|
23
|
-
extends React.HTMLAttributes<HTMLDivElement>,
|
|
24
|
-
VariantProps<typeof alertVariants> {
|
|
25
|
-
/**
|
|
26
|
-
* Visual emphasis preset. `default` is informational, `destructive`
|
|
27
|
-
* uses the danger palette for errors and warnings.
|
|
28
|
-
* @default "default"
|
|
29
|
-
*/
|
|
30
|
-
variant?: "default" | "destructive";
|
|
31
|
-
/**
|
|
32
|
-
* Optional leading icon (lucide-react), `<AlertTitle>`, and
|
|
33
|
-
* `<AlertDescription>`. The icon — when present as a direct child —
|
|
34
|
-
* is auto-positioned in the top-left.
|
|
35
|
-
*/
|
|
36
|
-
children?: React.ReactNode;
|
|
37
|
-
/** Tailwind / CSS classes merged onto the alert via `cn()`. */
|
|
38
|
-
className?: string;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
|
|
42
|
-
({ className, variant, ...props }, ref) => (
|
|
43
|
-
<div
|
|
44
|
-
ref={ref}
|
|
45
|
-
role="alert"
|
|
46
|
-
data-slot="alert"
|
|
47
|
-
className={cn(alertVariants({ variant }), className)}
|
|
48
|
-
{...props}
|
|
49
|
-
/>
|
|
50
|
-
),
|
|
51
|
-
);
|
|
52
|
-
Alert.displayName = "Alert";
|
|
53
|
-
|
|
54
|
-
export interface AlertTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {
|
|
55
|
-
/** The alert headline. Renders as an `<h5>`. */
|
|
56
|
-
children?: React.ReactNode;
|
|
57
|
-
/** Tailwind / CSS classes merged onto the title via `cn()`. */
|
|
58
|
-
className?: string;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const AlertTitle = React.forwardRef<HTMLParagraphElement, AlertTitleProps>(
|
|
62
|
-
({ className, ...props }, ref) => (
|
|
63
|
-
<h5
|
|
64
|
-
ref={ref}
|
|
65
|
-
className={cn("mb-1 font-medium leading-none tracking-tight", className)}
|
|
66
|
-
{...props}
|
|
67
|
-
/>
|
|
68
|
-
),
|
|
69
|
-
);
|
|
70
|
-
AlertTitle.displayName = "AlertTitle";
|
|
71
|
-
|
|
72
|
-
export interface AlertDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {
|
|
73
|
-
/** Body copy of the alert. Renders as a `<div>` so it can hold paragraphs and lists. */
|
|
74
|
-
children?: React.ReactNode;
|
|
75
|
-
/** Tailwind / CSS classes merged onto the description via `cn()`. */
|
|
76
|
-
className?: string;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const AlertDescription = React.forwardRef<HTMLParagraphElement, AlertDescriptionProps>(
|
|
80
|
-
({ className, ...props }, ref) => (
|
|
81
|
-
<div ref={ref} className={cn("text-sm [&_p]:leading-relaxed", className)} {...props} />
|
|
82
|
-
),
|
|
83
|
-
);
|
|
84
|
-
AlertDescription.displayName = "AlertDescription";
|
|
85
|
-
|
|
86
|
-
export { Alert, AlertDescription, AlertTitle };
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { cn } from "../../lib/utils";
|
|
2
|
-
|
|
3
|
-
export interface AnimatedBackgroundOrb {
|
|
4
|
-
/** CSS color for the radial gradient (hex / rgb / hsl / token). */
|
|
5
|
-
color: string;
|
|
6
|
-
/**
|
|
7
|
-
* Diameter in pixels.
|
|
8
|
-
* @default 500
|
|
9
|
-
*/
|
|
10
|
-
size?: number;
|
|
11
|
-
/**
|
|
12
|
-
* Opacity 0–1. Lower values let more of the page bg bleed through.
|
|
13
|
-
* @default 0.2
|
|
14
|
-
*/
|
|
15
|
-
opacity?: number;
|
|
16
|
-
/**
|
|
17
|
-
* Gaussian blur radius in pixels. Larger values produce softer orbs.
|
|
18
|
-
* @default 100
|
|
19
|
-
*/
|
|
20
|
-
blur?: number;
|
|
21
|
-
/** Tailwind position classes, e.g. `"-top-32 -right-32"` or `"left-1/2 top-1/3"`. */
|
|
22
|
-
position?: string;
|
|
23
|
-
/**
|
|
24
|
-
* CSS `animation` shorthand. Pair with the `orb-float-1` / `orb-float-2`
|
|
25
|
-
* keyframes shipped in canvas's tokens, or your own.
|
|
26
|
-
*/
|
|
27
|
-
animation?: string;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface AnimatedBackgroundProps {
|
|
31
|
-
/**
|
|
32
|
-
* Orbs to render. Defaults to a 3-orb indigo/purple/cyan composition
|
|
33
|
-
* that mirrors the auth-screen backdrop. Pass an empty array `[]` to
|
|
34
|
-
* render no orbs (useful for testing).
|
|
35
|
-
*/
|
|
36
|
-
orbs?: AnimatedBackgroundOrb[];
|
|
37
|
-
/**
|
|
38
|
-
* Tailwind / CSS classes merged onto the root container via `cn()`.
|
|
39
|
-
* Defaults to `pointer-events-none fixed inset-0 overflow-hidden`.
|
|
40
|
-
*/
|
|
41
|
-
className?: string;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const DEFAULT_ORBS: AnimatedBackgroundOrb[] = [
|
|
45
|
-
{
|
|
46
|
-
color: "#6366f1",
|
|
47
|
-
size: 500,
|
|
48
|
-
opacity: 0.2,
|
|
49
|
-
blur: 120,
|
|
50
|
-
position: "-top-32 -right-32",
|
|
51
|
-
animation: "orb-float-1 8s ease-in-out infinite",
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
color: "#8b5cf6",
|
|
55
|
-
size: 400,
|
|
56
|
-
opacity: 0.15,
|
|
57
|
-
blur: 100,
|
|
58
|
-
position: "-bottom-32 -left-32",
|
|
59
|
-
animation: "orb-float-2 10s ease-in-out infinite",
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
color: "#06b6d4",
|
|
63
|
-
size: 300,
|
|
64
|
-
opacity: 0.1,
|
|
65
|
-
blur: 80,
|
|
66
|
-
position: "left-1/2 top-1/3 -translate-x-1/2",
|
|
67
|
-
animation: "orb-float-1 12s ease-in-out 2s infinite",
|
|
68
|
-
},
|
|
69
|
-
];
|
|
70
|
-
|
|
71
|
-
export function AnimatedBackground({ orbs = DEFAULT_ORBS, className }: AnimatedBackgroundProps) {
|
|
72
|
-
return (
|
|
73
|
-
<div className={cn("pointer-events-none fixed inset-0 overflow-hidden", className)}>
|
|
74
|
-
{orbs.map((orb, i) => (
|
|
75
|
-
<div
|
|
76
|
-
key={i}
|
|
77
|
-
className={cn("absolute rounded-full", orb.position)}
|
|
78
|
-
style={{
|
|
79
|
-
width: orb.size ?? 500,
|
|
80
|
-
height: orb.size ?? 500,
|
|
81
|
-
opacity: orb.opacity ?? 0.2,
|
|
82
|
-
filter: `blur(${orb.blur ?? 100}px)`,
|
|
83
|
-
background: `radial-gradient(circle, ${orb.color} 0%, transparent 70%)`,
|
|
84
|
-
animation: orb.animation,
|
|
85
|
-
}}
|
|
86
|
-
/>
|
|
87
|
-
))}
|
|
88
|
-
</div>
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
AnimatedBackground.displayName = "AnimatedBackground";
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
|
|
5
|
-
import { cn } from "../../lib/utils";
|
|
6
|
-
import { Card, CardContent, CardHeader } from "./card";
|
|
7
|
-
|
|
8
|
-
export interface AuthShellProps {
|
|
9
|
-
/**
|
|
10
|
-
* Brand lockup rendered above the card. Compose a `ClientBrand` (or
|
|
11
|
-
* your own component) and pass it in. Slot is left empty to keep this
|
|
12
|
-
* shell unaware of OAuth2 / Hydra specifics.
|
|
13
|
-
*/
|
|
14
|
-
brand?: React.ReactNode;
|
|
15
|
-
/** Card title. Pairs with `subtitle`. */
|
|
16
|
-
title?: React.ReactNode;
|
|
17
|
-
/** Optional one-line subtitle shown beneath `title`. */
|
|
18
|
-
subtitle?: React.ReactNode;
|
|
19
|
-
/** Card body content. */
|
|
20
|
-
children?: React.ReactNode;
|
|
21
|
-
/**
|
|
22
|
-
* Optional footer line beneath the card (legal / privacy / support).
|
|
23
|
-
*/
|
|
24
|
-
footer?: React.ReactNode;
|
|
25
|
-
/**
|
|
26
|
-
* Card width preset. `default` = 408px (single-column flows like login,
|
|
27
|
-
* recovery), `wide` = 460px (multi-step or denser flows like consent).
|
|
28
|
-
* @default "default"
|
|
29
|
-
*/
|
|
30
|
-
width?: "default" | "wide";
|
|
31
|
-
/**
|
|
32
|
-
* Allow children to break the card frame (useful for full-bleed flow
|
|
33
|
-
* pickers or media). When `false` the card content gets the standard
|
|
34
|
-
* `p-6` padding.
|
|
35
|
-
* @default false
|
|
36
|
-
*/
|
|
37
|
-
flush?: boolean;
|
|
38
|
-
/** Tailwind / CSS classes merged onto the outer wrapper via `cn()`. */
|
|
39
|
-
className?: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Centered single-card layout for auth flows.
|
|
44
|
-
*
|
|
45
|
-
* Renders, top to bottom:
|
|
46
|
-
* 1. Brand slot (`brand`) above the card
|
|
47
|
-
* 2. Card with optional centred title + subtitle, then `children`
|
|
48
|
-
* 3. Optional footer line beneath the card
|
|
49
|
-
*
|
|
50
|
-
* Layout is intentionally narrow and prescriptive: this is the
|
|
51
|
-
* agreed-upon shape for every Olympus auth screen (login, register,
|
|
52
|
-
* recovery, reset, verify, OTP, consent, logout, status). For app shells
|
|
53
|
-
* with sidebars or multi-pane layouts, compose your own flex shell
|
|
54
|
-
* directly (see `Sidebar` + `SidebarInset`).
|
|
55
|
-
*/
|
|
56
|
-
const AuthShell = React.forwardRef<HTMLDivElement, AuthShellProps>(
|
|
57
|
-
(
|
|
58
|
-
{ brand, title, subtitle, children, footer, width = "default", flush = false, className },
|
|
59
|
-
ref,
|
|
60
|
-
) => (
|
|
61
|
-
<div
|
|
62
|
-
ref={ref}
|
|
63
|
-
className={cn(
|
|
64
|
-
"relative z-10 flex min-h-screen flex-col items-center justify-center px-6 py-12",
|
|
65
|
-
className,
|
|
66
|
-
)}
|
|
67
|
-
>
|
|
68
|
-
{brand && <div className="mb-7">{brand}</div>}
|
|
69
|
-
|
|
70
|
-
<Card
|
|
71
|
-
className={cn(
|
|
72
|
-
"w-full shadow-lg shadow-black/5 dark:shadow-black/30",
|
|
73
|
-
width === "wide" ? "max-w-[460px]" : "max-w-[408px]",
|
|
74
|
-
)}
|
|
75
|
-
>
|
|
76
|
-
{title && (
|
|
77
|
-
<CardHeader className={cn("text-center", subtitle ? "pb-3" : "pb-4")}>
|
|
78
|
-
<h1 className="text-xl font-semibold tracking-tight">{title}</h1>
|
|
79
|
-
{subtitle && <p className="mt-1.5 text-sm text-muted-foreground">{subtitle}</p>}
|
|
80
|
-
</CardHeader>
|
|
81
|
-
)}
|
|
82
|
-
<CardContent className={cn(flush ? "p-0" : "pt-0", !title && !flush && "pt-6")}>
|
|
83
|
-
{children}
|
|
84
|
-
</CardContent>
|
|
85
|
-
</Card>
|
|
86
|
-
|
|
87
|
-
{footer && (
|
|
88
|
-
<div className="mt-6 max-w-[460px] text-center text-xs text-muted-foreground">{footer}</div>
|
|
89
|
-
)}
|
|
90
|
-
</div>
|
|
91
|
-
),
|
|
92
|
-
);
|
|
93
|
-
AuthShell.displayName = "AuthShell";
|
|
94
|
-
|
|
95
|
-
export { AuthShell };
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
|
|
3
|
-
import { cn } from "../../lib/utils";
|
|
4
|
-
|
|
5
|
-
export interface BrandLockupProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
6
|
-
/**
|
|
7
|
-
* Logo node rendered to the left of the wordmark — typically `<Logo />`
|
|
8
|
-
* for the canvas Olympus ring, or any other brand mark of the consumer's
|
|
9
|
-
* choosing. Required so canvas stays brand-agnostic.
|
|
10
|
-
*/
|
|
11
|
-
logo: React.ReactNode;
|
|
12
|
-
/** Wordmark next to the logo (e.g. "Athena", "Hera"). */
|
|
13
|
-
productName: string;
|
|
14
|
-
/** Optional secondary line under the wordmark. */
|
|
15
|
-
subtitle?: string;
|
|
16
|
-
/** Visual size — sm = sidebar collapsed, md = sidebar expanded, lg = hero. */
|
|
17
|
-
size?: "sm" | "md" | "lg";
|
|
18
|
-
/** When true, renders only the logo without the wordmark or subtitle. */
|
|
19
|
-
collapsed?: boolean;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const SIZE: Record<NonNullable<BrandLockupProps["size"]>, { name: string; sub: string }> = {
|
|
23
|
-
sm: { name: "text-[13px]", sub: "text-[10px]" },
|
|
24
|
-
md: { name: "text-sm", sub: "text-[11px]" },
|
|
25
|
-
lg: { name: "text-2xl", sub: "text-xs" },
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const BrandLockup = React.forwardRef<HTMLDivElement, BrandLockupProps>(
|
|
29
|
-
({ logo, productName, subtitle, size = "md", collapsed = false, className, ...props }, ref) => {
|
|
30
|
-
const sz = SIZE[size];
|
|
31
|
-
return (
|
|
32
|
-
<div ref={ref} className={cn("flex items-center gap-2.5", className)} {...props}>
|
|
33
|
-
<span className="shrink-0">{logo}</span>
|
|
34
|
-
{!collapsed && (
|
|
35
|
-
<div className="flex flex-col leading-tight">
|
|
36
|
-
<span className={cn(sz.name, "font-semibold tracking-tight text-foreground")}>
|
|
37
|
-
{productName}
|
|
38
|
-
</span>
|
|
39
|
-
{subtitle && (
|
|
40
|
-
<span className={cn(sz.sub, "font-mono text-muted-foreground")}>{subtitle}</span>
|
|
41
|
-
)}
|
|
42
|
-
</div>
|
|
43
|
-
)}
|
|
44
|
-
</div>
|
|
45
|
-
);
|
|
46
|
-
},
|
|
47
|
-
);
|
|
48
|
-
BrandLockup.displayName = "BrandLockup";
|
|
@@ -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 };
|