@etherealui/react 0.0.0-stage → 0.0.2
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/LICENSE +21 -0
- package/README.md +62 -2
- package/dist/index.d.mts +583 -0
- package/dist/index.d.ts +583 -0
- package/dist/index.js +5189 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +5189 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +83 -3
- package/src/blocks/app-shell.tsx +441 -0
- package/src/blocks/billing-card.tsx +2 -0
- package/src/blocks/data-table.tsx +479 -0
- package/src/blocks/filter-bar.tsx +134 -0
- package/src/blocks/header-navbar.tsx +7 -0
- package/src/blocks/metric-grid.tsx +5 -0
- package/src/blocks/profile-form.tsx +2 -0
- package/src/blocks/security-settings.tsx +2 -0
- package/src/blocks/settings-blocks.tsx +406 -0
- package/src/blocks/sidebar.tsx +6 -0
- package/src/blocks/stat-card.tsx +7 -0
- package/src/blocks/stat-cards.tsx +212 -0
- package/src/blocks/team-members.tsx +5 -0
- package/src/index.ts +114 -0
- package/src/primitives/accordion.tsx +61 -0
- package/src/primitives/announcement.tsx +33 -0
- package/src/primitives/avatar.tsx +156 -0
- package/src/primitives/badge.tsx +108 -0
- package/src/primitives/breadcrumb.tsx +45 -0
- package/src/primitives/button-group.tsx +79 -0
- package/src/primitives/button.tsx +165 -0
- package/src/primitives/carousel.tsx +84 -0
- package/src/primitives/chart.tsx +831 -0
- package/src/primitives/checkbox.tsx +26 -0
- package/src/primitives/chip.tsx +37 -0
- package/src/primitives/close-button.tsx +29 -0
- package/src/primitives/color-picker.tsx +62 -0
- package/src/primitives/combobox.tsx +123 -0
- package/src/primitives/command-palette.tsx +216 -0
- package/src/primitives/context-menu.tsx +84 -0
- package/src/primitives/date-calendar.tsx +76 -0
- package/src/primitives/date-picker.tsx +400 -0
- package/src/primitives/dialog.tsx +279 -0
- package/src/primitives/divider.tsx +31 -0
- package/src/primitives/drawer.tsx +95 -0
- package/src/primitives/dropdown-menu.tsx +164 -0
- package/src/primitives/file-upload.tsx +123 -0
- package/src/primitives/icon-button.tsx +23 -0
- package/src/primitives/input.tsx +124 -0
- package/src/primitives/modal.tsx +26 -0
- package/src/primitives/pagination.tsx +58 -0
- package/src/primitives/popover.tsx +28 -0
- package/src/primitives/progress.tsx +145 -0
- package/src/primitives/radio-group.tsx +63 -0
- package/src/primitives/select.tsx +207 -0
- package/src/primitives/skeleton.tsx +61 -0
- package/src/primitives/slider.tsx +44 -0
- package/src/primitives/switch.tsx +146 -0
- package/src/primitives/table.tsx +47 -0
- package/src/primitives/tabs.tsx +86 -0
- package/src/primitives/textarea.tsx +40 -0
- package/src/primitives/toast.tsx +71 -0
- package/src/primitives/tooltip.tsx +58 -0
- package/src/styles/globals.css +49 -0
- package/src/templates/control-tower.tsx +41 -0
- package/src/templates/executive-analytics.tsx +272 -0
- package/src/templates/workspace-settings.tsx +179 -0
- package/src/utils/cn.ts +7 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Slot } from "@radix-ui/react-slot"
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
4
|
+
import { Loader2, X } from "lucide-react"
|
|
5
|
+
import { cn } from "../utils/cn"
|
|
6
|
+
|
|
7
|
+
const buttonVariants = cva(
|
|
8
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/30 disabled:pointer-events-none disabled:opacity-50 cursor-pointer select-none",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default:
|
|
13
|
+
"bg-zinc-900 text-white hover:bg-zinc-800 dark:bg-zinc-100 dark:text-zinc-900 dark:hover:bg-zinc-200 shadow-2xs",
|
|
14
|
+
primary:
|
|
15
|
+
"bg-blue-600 text-white hover:bg-blue-700 dark:bg-blue-600 dark:hover:bg-blue-500 shadow-2xs",
|
|
16
|
+
glow:
|
|
17
|
+
"bg-blue-600 text-white hover:bg-blue-700 dark:bg-blue-600 dark:hover:bg-blue-500 shadow-2xs",
|
|
18
|
+
secondary:
|
|
19
|
+
"bg-zinc-100 text-zinc-900 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-100 dark:hover:bg-zinc-700",
|
|
20
|
+
outline:
|
|
21
|
+
"border border-zinc-200 bg-white text-zinc-700 hover:bg-zinc-50 hover:text-zinc-900 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100 dark:hover:bg-zinc-800",
|
|
22
|
+
ghost:
|
|
23
|
+
"text-zinc-600 hover:bg-zinc-100 hover:text-zinc-900 dark:text-zinc-400 dark:hover:bg-zinc-800 dark:hover:text-zinc-100",
|
|
24
|
+
destructive:
|
|
25
|
+
"bg-rose-600 text-white hover:bg-rose-700 dark:bg-rose-600 dark:hover:bg-rose-500",
|
|
26
|
+
},
|
|
27
|
+
size: {
|
|
28
|
+
default: "h-9 px-3.5 py-2 text-xs",
|
|
29
|
+
sm: "h-8 rounded-md px-2.5 text-xs",
|
|
30
|
+
lg: "h-10 rounded-lg px-5 text-sm",
|
|
31
|
+
icon: "h-8 w-8",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
defaultVariants: {
|
|
35
|
+
variant: "default",
|
|
36
|
+
size: "default",
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
export interface ButtonProps
|
|
42
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
43
|
+
VariantProps<typeof buttonVariants> {
|
|
44
|
+
asChild?: boolean
|
|
45
|
+
loading?: boolean
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
49
|
+
({ className, variant, size, asChild = false, loading = false, children, disabled, ...props }, ref) => {
|
|
50
|
+
const Comp = asChild ? Slot : "button"
|
|
51
|
+
return (
|
|
52
|
+
<Comp
|
|
53
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
54
|
+
ref={ref}
|
|
55
|
+
disabled={disabled || loading}
|
|
56
|
+
{...props}
|
|
57
|
+
>
|
|
58
|
+
{loading && <Loader2 className="h-3.5 w-3.5 animate-spin shrink-0" />}
|
|
59
|
+
{children}
|
|
60
|
+
</Comp>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
Button.displayName = "Button"
|
|
65
|
+
|
|
66
|
+
export interface CloseButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
67
|
+
size?: "sm" | "default"
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const CloseButton = React.forwardRef<HTMLButtonElement, CloseButtonProps>(
|
|
71
|
+
({ className, size = "default", ...props }, ref) => (
|
|
72
|
+
<button
|
|
73
|
+
ref={ref}
|
|
74
|
+
type="button"
|
|
75
|
+
aria-label="Close"
|
|
76
|
+
className={cn(
|
|
77
|
+
"inline-flex items-center justify-center rounded-lg text-zinc-400 transition-colors hover:bg-zinc-100 hover:text-zinc-700 dark:hover:bg-zinc-800 dark:hover:text-zinc-200 cursor-pointer",
|
|
78
|
+
size === "sm" ? "h-6 w-6" : "h-8 w-8",
|
|
79
|
+
className
|
|
80
|
+
)}
|
|
81
|
+
{...props}
|
|
82
|
+
>
|
|
83
|
+
<X className={size === "sm" ? "h-3.5 w-3.5" : "h-4 w-4"} />
|
|
84
|
+
</button>
|
|
85
|
+
)
|
|
86
|
+
)
|
|
87
|
+
CloseButton.displayName = "CloseButton"
|
|
88
|
+
|
|
89
|
+
export interface ButtonGroupProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
90
|
+
attached?: boolean
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const ButtonGroup = React.forwardRef<HTMLDivElement, ButtonGroupProps>(
|
|
94
|
+
({ className, attached = true, ...props }, ref) => (
|
|
95
|
+
<div
|
|
96
|
+
ref={ref}
|
|
97
|
+
role="group"
|
|
98
|
+
className={cn(
|
|
99
|
+
"inline-flex items-center",
|
|
100
|
+
attached
|
|
101
|
+
? "rounded-lg border border-zinc-200 bg-white dark:border-zinc-800 dark:bg-zinc-900 p-0.5 [&>button]:border-0 [&>button]:rounded-md [&>button]:shadow-none"
|
|
102
|
+
: "gap-2",
|
|
103
|
+
className
|
|
104
|
+
)}
|
|
105
|
+
{...props}
|
|
106
|
+
/>
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
ButtonGroup.displayName = "ButtonGroup"
|
|
110
|
+
|
|
111
|
+
export interface ToggleGroupItem {
|
|
112
|
+
value: string
|
|
113
|
+
label: React.ReactNode
|
|
114
|
+
icon?: React.ReactNode
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface ToggleGroupProps {
|
|
118
|
+
items: ToggleGroupItem[]
|
|
119
|
+
value: string
|
|
120
|
+
onValueChange: (value: string) => void
|
|
121
|
+
size?: "sm" | "default"
|
|
122
|
+
className?: string
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const ToggleGroup: React.FC<ToggleGroupProps> = ({
|
|
126
|
+
items,
|
|
127
|
+
value,
|
|
128
|
+
onValueChange,
|
|
129
|
+
size = "default",
|
|
130
|
+
className,
|
|
131
|
+
}) => {
|
|
132
|
+
return (
|
|
133
|
+
<div
|
|
134
|
+
role="group"
|
|
135
|
+
className={cn(
|
|
136
|
+
"inline-flex items-center rounded-lg border border-zinc-200 bg-zinc-100/80 dark:border-zinc-800 dark:bg-zinc-900 p-0.5 gap-0.5",
|
|
137
|
+
className
|
|
138
|
+
)}
|
|
139
|
+
>
|
|
140
|
+
{items.map((item) => {
|
|
141
|
+
const active = item.value === value
|
|
142
|
+
return (
|
|
143
|
+
<button
|
|
144
|
+
key={item.value}
|
|
145
|
+
type="button"
|
|
146
|
+
onClick={() => onValueChange(item.value)}
|
|
147
|
+
className={cn(
|
|
148
|
+
"inline-flex items-center gap-1.5 rounded-md font-medium transition-all cursor-pointer",
|
|
149
|
+
size === "sm" ? "px-2.5 py-1 text-xs" : "px-3 py-1.5 text-xs",
|
|
150
|
+
active
|
|
151
|
+
? "bg-white text-zinc-900 shadow-2xs dark:bg-zinc-800 dark:text-zinc-100"
|
|
152
|
+
: "text-zinc-500 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200"
|
|
153
|
+
)}
|
|
154
|
+
>
|
|
155
|
+
{item.icon}
|
|
156
|
+
{item.label}
|
|
157
|
+
</button>
|
|
158
|
+
)
|
|
159
|
+
})}
|
|
160
|
+
</div>
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
ToggleGroup.displayName = "ToggleGroup"
|
|
164
|
+
|
|
165
|
+
export { Button, CloseButton, ButtonGroup, ToggleGroup, buttonVariants }
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { ChevronLeft, ChevronRight } from "lucide-react"
|
|
3
|
+
import { cn } from "../utils/cn"
|
|
4
|
+
|
|
5
|
+
export interface CarouselSlide {
|
|
6
|
+
title: string
|
|
7
|
+
subtitle: string
|
|
8
|
+
metric: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface CarouselProps {
|
|
12
|
+
slides?: CarouselSlide[]
|
|
13
|
+
className?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const Carousel: React.FC<CarouselProps> = ({
|
|
17
|
+
slides = [
|
|
18
|
+
{
|
|
19
|
+
title: "Q4 Revenue Velocity",
|
|
20
|
+
subtitle: "Net dollar retention across enterprise accounts",
|
|
21
|
+
metric: "128.4%",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
title: "Global Checkout Conversion",
|
|
25
|
+
subtitle: "30-day rolling average across 14 currencies",
|
|
26
|
+
metric: "4.82%",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
title: "Customer Support SLA",
|
|
30
|
+
subtitle: "Median first response time for priority tickets",
|
|
31
|
+
metric: "3m 12s",
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
className,
|
|
35
|
+
}) => {
|
|
36
|
+
const [idx, setIdx] = React.useState(0)
|
|
37
|
+
const current = slides[idx]
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div
|
|
41
|
+
className={cn(
|
|
42
|
+
"w-full max-w-md rounded-2xl border border-zinc-200 bg-white p-5 dark:border-zinc-800 dark:bg-zinc-900",
|
|
43
|
+
className
|
|
44
|
+
)}
|
|
45
|
+
>
|
|
46
|
+
<div className="flex items-center justify-between">
|
|
47
|
+
<span className="text-[11px] font-medium text-zinc-400">
|
|
48
|
+
Slide {idx + 1} of {slides.length}
|
|
49
|
+
</span>
|
|
50
|
+
<div className="flex items-center gap-1">
|
|
51
|
+
<button
|
|
52
|
+
type="button"
|
|
53
|
+
onClick={() =>
|
|
54
|
+
setIdx((p) => (p - 1 + slides.length) % slides.length)
|
|
55
|
+
}
|
|
56
|
+
className="rounded-lg border border-zinc-200 p-1 text-zinc-500 hover:bg-zinc-50 dark:border-zinc-800 dark:hover:bg-zinc-800 cursor-pointer"
|
|
57
|
+
>
|
|
58
|
+
<ChevronLeft className="h-3.5 w-3.5" />
|
|
59
|
+
</button>
|
|
60
|
+
<button
|
|
61
|
+
type="button"
|
|
62
|
+
onClick={() => setIdx((p) => (p + 1) % slides.length)}
|
|
63
|
+
className="rounded-lg border border-zinc-200 p-1 text-zinc-500 hover:bg-zinc-50 dark:border-zinc-800 dark:hover:bg-zinc-800 cursor-pointer"
|
|
64
|
+
>
|
|
65
|
+
<ChevronRight className="h-3.5 w-3.5" />
|
|
66
|
+
</button>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
<div className="mt-4 space-y-1">
|
|
70
|
+
<div className="text-2xl font-semibold text-zinc-900 dark:text-zinc-100">
|
|
71
|
+
{current.metric}
|
|
72
|
+
</div>
|
|
73
|
+
<div className="text-xs font-medium text-zinc-800 dark:text-zinc-200">
|
|
74
|
+
{current.title}
|
|
75
|
+
</div>
|
|
76
|
+
<p className="text-xs text-zinc-500 dark:text-zinc-400">
|
|
77
|
+
{current.subtitle}
|
|
78
|
+
</p>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
Carousel.displayName = "Carousel"
|
|
84
|
+
|