ruler-components 0.1.1 → 0.1.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/dist/index.d.mts +51 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +534 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +498 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +21 -2
- package/AGENTS.md +0 -9
- package/CLAUDE.md +0 -1
- package/app/docs/[slug]/page.tsx +0 -147
- package/app/docs/layout.tsx +0 -26
- package/app/docs/page.tsx +0 -148
- package/app/favicon.ico +0 -0
- package/app/globals.css +0 -168
- package/app/icon.png +0 -0
- package/app/layout.tsx +0 -90
- package/app/opengraph-image.tsx +0 -10
- package/app/page.tsx +0 -34
- package/app/twitter-image.tsx +0 -10
- package/components/docs/accordion-doc-page.tsx +0 -352
- package/components/docs/alert-doc-page.tsx +0 -293
- package/components/docs/allinput-doc-page.tsx +0 -183
- package/components/docs/avatar-doc-page.tsx +0 -424
- package/components/docs/badge-doc-page.tsx +0 -363
- package/components/docs/button-doc-page.tsx +0 -406
- package/components/docs/card-doc-page.tsx +0 -364
- package/components/docs/checkbox-doc-page.tsx +0 -277
- package/components/docs/colors-doc-page.tsx +0 -430
- package/components/docs/dialog-doc-page.tsx +0 -364
- package/components/docs/docs-footer.tsx +0 -11
- package/components/docs/docs-mobile-menu-bar.tsx +0 -22
- package/components/docs/docs-mobile-nav-context.tsx +0 -27
- package/components/docs/docs-page.tsx +0 -263
- package/components/docs/docs-search.tsx +0 -303
- package/components/docs/docs-sidebar.tsx +0 -165
- package/components/docs/docs-topbar.tsx +0 -32
- package/components/docs/dropdown-doc-page.tsx +0 -522
- package/components/docs/getting-started-doc-page.tsx +0 -205
- package/components/docs/label-doc-page.tsx +0 -173
- package/components/docs/loaders-doc-page.tsx +0 -244
- package/components/docs/menu-doc-page.tsx +0 -373
- package/components/docs/modal-doc-page.tsx +0 -436
- package/components/docs/next-steps.tsx +0 -53
- package/components/docs/pagination-doc-page.tsx +0 -316
- package/components/docs/progress-doc-page.tsx +0 -387
- package/components/docs/radio-doc-page.tsx +0 -270
- package/components/docs/skeleton-doc-page.tsx +0 -230
- package/components/docs/stepper-doc-page.tsx +0 -309
- package/components/docs/switch-doc-page.tsx +0 -264
- package/components/docs/table-doc-page.tsx +0 -689
- package/components/docs/tabs-doc-page.tsx +0 -359
- package/components/docs/theming-doc-page.tsx +0 -243
- package/components/docs/tooltip-doc-page.tsx +0 -357
- package/components/docs/usage-section.tsx +0 -21
- package/components/icons/discord.tsx +0 -9
- package/components/icons/github.tsx +0 -9
- package/components/icons/x.tsx +0 -9
- package/components/installation-section.tsx +0 -34
- package/components/landing/feature-highlights.tsx +0 -105
- package/components/landing/footer-strip.tsx +0 -45
- package/components/landing/hero-card.tsx +0 -14
- package/components/landing/hero-spotlight.tsx +0 -126
- package/components/landing/hero.tsx +0 -64
- package/components/landing/navbar.tsx +0 -44
- package/components/landing/quick-start-section.tsx +0 -59
- package/components/landing/site-footer.tsx +0 -55
- package/components/theme-provider.tsx +0 -60
- package/components/ui/accordion.tsx +0 -174
- package/components/ui/alert.tsx +0 -103
- package/components/ui/allinput.tsx +0 -210
- package/components/ui/avatar.tsx +0 -179
- package/components/ui/badge.tsx +0 -52
- package/components/ui/button.tsx +0 -75
- package/components/ui/card.tsx +0 -105
- package/components/ui/checkbox.tsx +0 -130
- package/components/ui/code-block.tsx +0 -60
- package/components/ui/data-table.tsx +0 -235
- package/components/ui/dialog.tsx +0 -173
- package/components/ui/dropdown.tsx +0 -78
- package/components/ui/feature-card.tsx +0 -38
- package/components/ui/input.tsx +0 -44
- package/components/ui/label.tsx +0 -110
- package/components/ui/loaders.tsx +0 -139
- package/components/ui/menu.tsx +0 -118
- package/components/ui/modal.tsx +0 -399
- package/components/ui/package-manager-tabs.tsx +0 -40
- package/components/ui/pagination.tsx +0 -200
- package/components/ui/progress.tsx +0 -134
- package/components/ui/radio.tsx +0 -262
- package/components/ui/skeleton.tsx +0 -102
- package/components/ui/steppers.tsx +0 -309
- package/components/ui/switch.tsx +0 -153
- package/components/ui/table.tsx +0 -58
- package/components/ui/tabs.tsx +0 -166
- package/components/ui/theme-toggle.tsx +0 -60
- package/components/ui/tooltip.tsx +0 -238
- package/data/color-palette.ts +0 -35
- package/data/docs-nav.ts +0 -84
- package/eslint.config.mjs +0 -18
- package/index.ts +0 -8
- package/lib/cn.ts +0 -4
- package/lib/color.ts +0 -85
- package/lib/og-image.tsx +0 -138
- package/lib/theme.ts +0 -33
- package/next.config.ts +0 -7
- package/postcss.config.mjs +0 -7
- package/public/dark.png +0 -0
- package/public/dark1.png +0 -0
- package/public/dark2.png +0 -0
- package/public/file.svg +0 -1
- package/public/globe.svg +0 -1
- package/public/light.png +0 -0
- package/public/light1.png +0 -0
- package/public/next.svg +0 -1
- package/public/vercel.svg +0 -1
- package/public/video/hero-demo.mp4 +0 -0
- package/public/window.svg +0 -1
- package/tsconfig.json +0 -34
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import React, { useState } from "react";
|
|
4
|
-
import { Search, Eye, EyeOff, Check, type LucideIcon } from "lucide-react";
|
|
5
|
-
import { cn } from "@/lib/cn";
|
|
6
|
-
|
|
7
|
-
const fieldText =
|
|
8
|
-
"text-sm text-zinc-900 outline-none transition-all duration-150 placeholder:text-zinc-400 dark:text-zinc-100 dark:placeholder:text-zinc-500";
|
|
9
|
-
|
|
10
|
-
const fieldSurface =
|
|
11
|
-
"border-zinc-200 hover:border-zinc-300 focus:border-zinc-900 focus:ring-4 focus:ring-zinc-900/5 dark:border-zinc-800 dark:hover:border-zinc-700 dark:focus:border-zinc-400 dark:focus:ring-zinc-300/10";
|
|
12
|
-
|
|
13
|
-
export const InputStandard = ({ className, ...props }: React.InputHTMLAttributes<HTMLInputElement>) => (
|
|
14
|
-
<input
|
|
15
|
-
{...props}
|
|
16
|
-
className={cn("w-full rounded-xl border bg-white px-4 py-2.5 dark:bg-zinc-900", fieldText, fieldSurface, className)}
|
|
17
|
-
/>
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
export const InputFilled = ({ className, ...props }: React.InputHTMLAttributes<HTMLInputElement>) => (
|
|
21
|
-
<input
|
|
22
|
-
{...props}
|
|
23
|
-
className={cn(
|
|
24
|
-
"w-full rounded-xl border border-transparent bg-zinc-100 px-4 py-3 hover:bg-zinc-200/70 focus:border-zinc-900 focus:bg-white focus:ring-4 focus:ring-zinc-900/5 dark:bg-zinc-800 dark:hover:bg-zinc-700/70 dark:focus:border-zinc-400 dark:focus:bg-zinc-900 dark:focus:ring-zinc-300/10",
|
|
25
|
-
fieldText,
|
|
26
|
-
className,
|
|
27
|
-
)}
|
|
28
|
-
/>
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
export const InputUnderline = ({ className, ...props }: React.InputHTMLAttributes<HTMLInputElement>) => (
|
|
32
|
-
<div className="group relative">
|
|
33
|
-
<input
|
|
34
|
-
{...props}
|
|
35
|
-
className={cn(
|
|
36
|
-
"w-full border-b border-zinc-200 bg-transparent py-2 focus:border-zinc-900 dark:border-zinc-700 dark:focus:border-white",
|
|
37
|
-
fieldText,
|
|
38
|
-
className,
|
|
39
|
-
)}
|
|
40
|
-
/>
|
|
41
|
-
<div className="absolute bottom-0 left-0 h-[2px] w-0 bg-zinc-900 transition-all duration-300 group-focus-within:w-full dark:bg-white" />
|
|
42
|
-
</div>
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
export const InputFloating = ({
|
|
46
|
-
label,
|
|
47
|
-
className,
|
|
48
|
-
...props
|
|
49
|
-
}: { label: string } & React.InputHTMLAttributes<HTMLInputElement>) => {
|
|
50
|
-
const [value, setValue] = useState("");
|
|
51
|
-
const filled = Boolean(value || props.defaultValue);
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<div className="relative pt-4">
|
|
55
|
-
<input
|
|
56
|
-
{...props}
|
|
57
|
-
onChange={(e) => {
|
|
58
|
-
setValue(e.target.value);
|
|
59
|
-
props.onChange?.(e);
|
|
60
|
-
}}
|
|
61
|
-
className={cn(
|
|
62
|
-
"peer w-full border-b-2 border-zinc-200 bg-transparent py-2 focus:border-zinc-900 dark:border-zinc-700 dark:focus:border-white",
|
|
63
|
-
fieldText,
|
|
64
|
-
className,
|
|
65
|
-
)}
|
|
66
|
-
/>
|
|
67
|
-
<label
|
|
68
|
-
className={cn(
|
|
69
|
-
"absolute left-0 transition-all duration-200",
|
|
70
|
-
filled
|
|
71
|
-
? "-top-1 text-xs font-bold text-zinc-900 dark:text-white"
|
|
72
|
-
: "top-5 text-sm text-zinc-400 peer-focus:-top-1 peer-focus:text-xs peer-focus:font-bold peer-focus:text-zinc-900 dark:peer-focus:text-white",
|
|
73
|
-
)}
|
|
74
|
-
>
|
|
75
|
-
{label}
|
|
76
|
-
</label>
|
|
77
|
-
</div>
|
|
78
|
-
);
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
export const InputSearch = ({ className, ...props }: React.InputHTMLAttributes<HTMLInputElement>) => (
|
|
82
|
-
<div className="group relative">
|
|
83
|
-
<Search
|
|
84
|
-
size={16}
|
|
85
|
-
className="absolute left-4 top-1/2 -translate-y-1/2 text-zinc-400 transition-colors group-focus-within:text-zinc-900 dark:group-focus-within:text-white"
|
|
86
|
-
/>
|
|
87
|
-
<input
|
|
88
|
-
{...props}
|
|
89
|
-
type="text"
|
|
90
|
-
className={cn(
|
|
91
|
-
"w-full rounded-full border bg-zinc-50 py-2.5 pl-11 pr-4 focus:bg-white dark:bg-zinc-900 dark:focus:bg-zinc-950",
|
|
92
|
-
fieldText,
|
|
93
|
-
fieldSurface,
|
|
94
|
-
className,
|
|
95
|
-
)}
|
|
96
|
-
/>
|
|
97
|
-
</div>
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
export const InputPassword = ({ className, ...props }: React.InputHTMLAttributes<HTMLInputElement>) => {
|
|
101
|
-
const [show, setShow] = useState(false);
|
|
102
|
-
|
|
103
|
-
return (
|
|
104
|
-
<div className="relative">
|
|
105
|
-
<input
|
|
106
|
-
{...props}
|
|
107
|
-
type={show ? "text" : "password"}
|
|
108
|
-
className={cn("w-full rounded-xl border bg-white px-4 py-2.5 pr-11 dark:bg-zinc-900", fieldText, fieldSurface, className)}
|
|
109
|
-
/>
|
|
110
|
-
<button
|
|
111
|
-
type="button"
|
|
112
|
-
onClick={() => setShow(!show)}
|
|
113
|
-
aria-label={show ? "Hide password" : "Show password"}
|
|
114
|
-
className="absolute right-3 top-1/2 -translate-y-1/2 text-zinc-400 transition-colors hover:text-zinc-900 dark:hover:text-white"
|
|
115
|
-
>
|
|
116
|
-
{show ? <EyeOff size={18} /> : <Eye size={18} />}
|
|
117
|
-
</button>
|
|
118
|
-
</div>
|
|
119
|
-
);
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
export const InputAddon = ({
|
|
123
|
-
prefix,
|
|
124
|
-
suffix,
|
|
125
|
-
className,
|
|
126
|
-
...props
|
|
127
|
-
}: { prefix?: string; suffix?: string } & React.InputHTMLAttributes<HTMLInputElement>) => (
|
|
128
|
-
<div
|
|
129
|
-
className={cn(
|
|
130
|
-
"flex w-full overflow-hidden rounded-xl border border-zinc-200 bg-white transition-all focus-within:border-zinc-900 focus-within:ring-4 focus-within:ring-zinc-900/5 dark:border-zinc-800 dark:bg-zinc-900 dark:focus-within:border-zinc-400 dark:focus-within:ring-zinc-300/10",
|
|
131
|
-
className,
|
|
132
|
-
)}
|
|
133
|
-
>
|
|
134
|
-
{prefix && (
|
|
135
|
-
<span className="flex items-center border-r border-zinc-200 bg-zinc-50 px-3 text-sm font-medium text-zinc-500 dark:border-zinc-800 dark:bg-zinc-800 dark:text-zinc-400">
|
|
136
|
-
{prefix}
|
|
137
|
-
</span>
|
|
138
|
-
)}
|
|
139
|
-
<input {...props} className={cn("flex-1 bg-transparent px-4 py-2.5", fieldText)} />
|
|
140
|
-
{suffix && (
|
|
141
|
-
<span className="flex items-center border-l border-zinc-200 bg-zinc-50 px-3 text-sm font-medium text-zinc-500 dark:border-zinc-800 dark:bg-zinc-800 dark:text-zinc-400">
|
|
142
|
-
{suffix}
|
|
143
|
-
</span>
|
|
144
|
-
)}
|
|
145
|
-
</div>
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
export const InputIcon = ({
|
|
149
|
-
icon: Icon,
|
|
150
|
-
position = "left",
|
|
151
|
-
className,
|
|
152
|
-
...props
|
|
153
|
-
}: { icon: LucideIcon; position?: "left" | "right" } & React.InputHTMLAttributes<HTMLInputElement>) => (
|
|
154
|
-
<div className="relative">
|
|
155
|
-
<div
|
|
156
|
-
className={cn(
|
|
157
|
-
"pointer-events-none absolute top-1/2 -translate-y-1/2 text-zinc-400",
|
|
158
|
-
position === "left" ? "left-3.5" : "right-3.5",
|
|
159
|
-
)}
|
|
160
|
-
>
|
|
161
|
-
<Icon size={18} strokeWidth={1.5} />
|
|
162
|
-
</div>
|
|
163
|
-
<input
|
|
164
|
-
{...props}
|
|
165
|
-
className={cn(
|
|
166
|
-
"w-full rounded-xl border bg-white py-2.5 shadow-sm dark:bg-zinc-900",
|
|
167
|
-
position === "left" ? "pl-10 pr-4" : "pl-4 pr-10",
|
|
168
|
-
fieldText,
|
|
169
|
-
fieldSurface,
|
|
170
|
-
className,
|
|
171
|
-
)}
|
|
172
|
-
/>
|
|
173
|
-
</div>
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
export const InputOTP = () => (
|
|
177
|
-
<div className="flex gap-2.5">
|
|
178
|
-
{[1, 2, 3, 4].map((i) => (
|
|
179
|
-
<input
|
|
180
|
-
key={i}
|
|
181
|
-
maxLength={1}
|
|
182
|
-
aria-label={`Digit ${i}`}
|
|
183
|
-
className="h-12 w-12 rounded-xl border-2 border-zinc-200 bg-white text-center text-lg font-bold text-zinc-900 outline-none transition-all focus:border-zinc-900 focus:ring-4 focus:ring-zinc-900/5 dark:border-zinc-800 dark:bg-zinc-900 dark:text-white dark:focus:border-zinc-400 dark:focus:ring-zinc-300/10"
|
|
184
|
-
/>
|
|
185
|
-
))}
|
|
186
|
-
</div>
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
export const InputAutocomplete = ({
|
|
190
|
-
suggestions,
|
|
191
|
-
className,
|
|
192
|
-
...props
|
|
193
|
-
}: { suggestions: string[] } & React.InputHTMLAttributes<HTMLInputElement>) => (
|
|
194
|
-
<div className="relative">
|
|
195
|
-
<input
|
|
196
|
-
{...props}
|
|
197
|
-
className={cn("w-full rounded-xl border bg-white px-4 py-2.5 dark:bg-zinc-900", fieldText, fieldSurface, className)}
|
|
198
|
-
/>
|
|
199
|
-
<div className="absolute top-[calc(100%+0.5rem)] z-50 w-full rounded-xl border border-zinc-200 bg-white p-1 shadow-xl dark:border-zinc-800 dark:bg-zinc-900">
|
|
200
|
-
{suggestions.map((s) => (
|
|
201
|
-
<div
|
|
202
|
-
key={s}
|
|
203
|
-
className="flex cursor-pointer items-center justify-between rounded-lg px-3 py-2 text-sm text-zinc-700 hover:bg-zinc-50 dark:text-zinc-200 dark:hover:bg-zinc-800"
|
|
204
|
-
>
|
|
205
|
-
{s} <Check size={14} className="text-zinc-400" />
|
|
206
|
-
</div>
|
|
207
|
-
))}
|
|
208
|
-
</div>
|
|
209
|
-
</div>
|
|
210
|
-
);
|
package/components/ui/avatar.tsx
DELETED
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
5
|
-
import { cn } from "@/lib/cn";
|
|
6
|
-
|
|
7
|
-
const AVATAR_GRADIENTS = [
|
|
8
|
-
"from-violet-500 to-indigo-600",
|
|
9
|
-
"from-sky-500 to-blue-600",
|
|
10
|
-
"from-emerald-500 to-teal-600",
|
|
11
|
-
"from-amber-500 to-orange-500",
|
|
12
|
-
"from-rose-500 to-pink-600",
|
|
13
|
-
"from-fuchsia-500 to-purple-600",
|
|
14
|
-
"from-cyan-500 to-blue-500",
|
|
15
|
-
"from-lime-500 to-emerald-600",
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
const avatarVariants = cva(
|
|
19
|
-
[
|
|
20
|
-
"relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden rounded-full",
|
|
21
|
-
"ring-1 ring-zinc-900/5 shadow-sm shadow-zinc-900/10",
|
|
22
|
-
"dark:ring-white/10 dark:shadow-black/30",
|
|
23
|
-
],
|
|
24
|
-
{
|
|
25
|
-
variants: {
|
|
26
|
-
size: {
|
|
27
|
-
sm: "h-8 w-8 text-[10px]",
|
|
28
|
-
md: "h-10 w-10 text-xs",
|
|
29
|
-
lg: "h-12 w-12 text-sm",
|
|
30
|
-
xl: "h-16 w-16 text-base",
|
|
31
|
-
},
|
|
32
|
-
variant: {
|
|
33
|
-
default: "",
|
|
34
|
-
outline: "ring-2 ring-white dark:ring-zinc-950",
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
defaultVariants: {
|
|
38
|
-
size: "md",
|
|
39
|
-
variant: "default",
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
const statusVariants = cva(
|
|
45
|
-
[
|
|
46
|
-
"absolute rounded-full ring-2 ring-white dark:ring-zinc-950",
|
|
47
|
-
"shadow-sm",
|
|
48
|
-
],
|
|
49
|
-
{
|
|
50
|
-
variants: {
|
|
51
|
-
status: {
|
|
52
|
-
online: "bg-emerald-500",
|
|
53
|
-
offline: "bg-zinc-400 dark:bg-zinc-500",
|
|
54
|
-
busy: "bg-amber-500",
|
|
55
|
-
},
|
|
56
|
-
size: {
|
|
57
|
-
sm: "bottom-0 right-0 h-2 w-2",
|
|
58
|
-
md: "bottom-0 right-0 h-2.5 w-2.5",
|
|
59
|
-
lg: "bottom-0.5 right-0.5 h-2.5 w-2.5",
|
|
60
|
-
xl: "bottom-1 right-1 h-3 w-3",
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
function getInitials(name: string) {
|
|
67
|
-
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
68
|
-
if (parts.length === 0) return "?";
|
|
69
|
-
if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
|
|
70
|
-
return `${parts[0][0]}${parts[parts.length - 1][0]}`.toUpperCase();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function getGradientFromName(name: string) {
|
|
74
|
-
let hash = 0;
|
|
75
|
-
for (let i = 0; i < name.length; i += 1) {
|
|
76
|
-
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
|
77
|
-
}
|
|
78
|
-
return AVATAR_GRADIENTS[Math.abs(hash) % AVATAR_GRADIENTS.length];
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export interface AvatarProps
|
|
82
|
-
extends React.HTMLAttributes<HTMLSpanElement>,
|
|
83
|
-
VariantProps<typeof avatarVariants> {
|
|
84
|
-
src?: string;
|
|
85
|
-
alt?: string;
|
|
86
|
-
name?: string;
|
|
87
|
-
status?: "online" | "offline" | "busy" | null;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const Avatar = React.forwardRef<HTMLSpanElement, AvatarProps>(
|
|
91
|
-
({ className, size, variant, src, alt, name, status, children, ...props }, ref) => {
|
|
92
|
-
const [imageError, setImageError] = React.useState(false);
|
|
93
|
-
const showImage = src && !imageError;
|
|
94
|
-
const fallbackText = name ? getInitials(name) : children;
|
|
95
|
-
const gradient = name ? getGradientFromName(name) : "from-zinc-400 to-zinc-500";
|
|
96
|
-
|
|
97
|
-
return (
|
|
98
|
-
<span
|
|
99
|
-
ref={ref}
|
|
100
|
-
className={cn(avatarVariants({ size, variant }), className)}
|
|
101
|
-
{...props}
|
|
102
|
-
>
|
|
103
|
-
{showImage ? (
|
|
104
|
-
// eslint-disable-next-line @next/next/no-img-element
|
|
105
|
-
<img
|
|
106
|
-
src={src}
|
|
107
|
-
alt={alt ?? name ?? "Avatar"}
|
|
108
|
-
className="h-full w-full object-cover"
|
|
109
|
-
onError={() => setImageError(true)}
|
|
110
|
-
/>
|
|
111
|
-
) : (
|
|
112
|
-
<span
|
|
113
|
-
className={cn(
|
|
114
|
-
"flex h-full w-full items-center justify-center bg-gradient-to-br font-semibold uppercase tracking-tight text-white",
|
|
115
|
-
gradient,
|
|
116
|
-
)}
|
|
117
|
-
>
|
|
118
|
-
{fallbackText ?? "?"}
|
|
119
|
-
</span>
|
|
120
|
-
)}
|
|
121
|
-
{status && (
|
|
122
|
-
<span
|
|
123
|
-
className={cn(statusVariants({ status, size }))}
|
|
124
|
-
aria-hidden
|
|
125
|
-
/>
|
|
126
|
-
)}
|
|
127
|
-
</span>
|
|
128
|
-
);
|
|
129
|
-
},
|
|
130
|
-
);
|
|
131
|
-
Avatar.displayName = "Avatar";
|
|
132
|
-
|
|
133
|
-
export interface AvatarGroupProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
134
|
-
max?: number;
|
|
135
|
-
size?: VariantProps<typeof avatarVariants>["size"];
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function AvatarGroup({
|
|
139
|
-
className,
|
|
140
|
-
max = 5,
|
|
141
|
-
size = "md",
|
|
142
|
-
children,
|
|
143
|
-
...props
|
|
144
|
-
}: AvatarGroupProps) {
|
|
145
|
-
const avatars = React.Children.toArray(children).filter(React.isValidElement);
|
|
146
|
-
const visible = avatars.slice(0, max);
|
|
147
|
-
const remaining = avatars.length - visible.length;
|
|
148
|
-
|
|
149
|
-
return (
|
|
150
|
-
<div className={cn("flex items-center", className)} {...props}>
|
|
151
|
-
{visible.map((child, index) => (
|
|
152
|
-
<div
|
|
153
|
-
key={index}
|
|
154
|
-
className={cn(
|
|
155
|
-
"relative transition-transform duration-200 hover:z-10 hover:scale-110",
|
|
156
|
-
index > 0 && "-ml-3",
|
|
157
|
-
)}
|
|
158
|
-
>
|
|
159
|
-
{child}
|
|
160
|
-
</div>
|
|
161
|
-
))}
|
|
162
|
-
{remaining > 0 && (
|
|
163
|
-
<span
|
|
164
|
-
className={cn(
|
|
165
|
-
"-ml-3",
|
|
166
|
-
avatarVariants({ variant: "outline", size }),
|
|
167
|
-
"bg-zinc-100 text-zinc-600 ring-2 ring-white dark:bg-zinc-800 dark:text-zinc-200 dark:ring-zinc-950",
|
|
168
|
-
)}
|
|
169
|
-
>
|
|
170
|
-
<span className="flex h-full w-full items-center justify-center text-[10px] font-semibold">
|
|
171
|
-
+{remaining}
|
|
172
|
-
</span>
|
|
173
|
-
</span>
|
|
174
|
-
)}
|
|
175
|
-
</div>
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
export { Avatar, AvatarGroup, avatarVariants, getInitials, getGradientFromName };
|
package/components/ui/badge.tsx
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
-
import { cn } from "@/lib/cn";
|
|
4
|
-
|
|
5
|
-
const badgeVariants = cva(
|
|
6
|
-
"inline-flex items-center gap-1 rounded-md font-medium transition-colors",
|
|
7
|
-
{
|
|
8
|
-
variants: {
|
|
9
|
-
variant: {
|
|
10
|
-
default:
|
|
11
|
-
"bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-200",
|
|
12
|
-
info: "bg-[#0070BA]/10 text-[#0070BA] dark:bg-[#0070BA]/20 dark:text-[#4DA3E0]",
|
|
13
|
-
success:
|
|
14
|
-
"bg-[#28A745]/10 text-[#28A745] dark:bg-[#28A745]/20 dark:text-[#5CC975]",
|
|
15
|
-
warning:
|
|
16
|
-
"bg-[#E58E00]/10 text-[#E58E00] dark:bg-[#E58E00]/20 dark:text-[#F5B84A]",
|
|
17
|
-
error:
|
|
18
|
-
"bg-[#D93025]/10 text-[#D93025] dark:bg-[#D93025]/20 dark:text-[#F06B62]",
|
|
19
|
-
outline:
|
|
20
|
-
"border border-zinc-200 bg-transparent text-zinc-700 dark:border-zinc-700 dark:text-zinc-300",
|
|
21
|
-
},
|
|
22
|
-
size: {
|
|
23
|
-
sm: "px-1.5 py-0.5 text-[10px]",
|
|
24
|
-
md: "px-2 py-0.5 text-[11px]",
|
|
25
|
-
lg: "px-2.5 py-1 text-xs",
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
defaultVariants: {
|
|
29
|
-
variant: "default",
|
|
30
|
-
size: "md",
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
export interface BadgeProps
|
|
36
|
-
extends React.HTMLAttributes<HTMLSpanElement>,
|
|
37
|
-
VariantProps<typeof badgeVariants> {}
|
|
38
|
-
|
|
39
|
-
const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(
|
|
40
|
-
({ className, variant, size, ...props }, ref) => {
|
|
41
|
-
return (
|
|
42
|
-
<span
|
|
43
|
-
ref={ref}
|
|
44
|
-
className={cn(badgeVariants({ variant, size }), className)}
|
|
45
|
-
{...props}
|
|
46
|
-
/>
|
|
47
|
-
);
|
|
48
|
-
},
|
|
49
|
-
);
|
|
50
|
-
Badge.displayName = "Badge";
|
|
51
|
-
|
|
52
|
-
export { Badge, badgeVariants };
|
package/components/ui/button.tsx
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
-
import { cn } from "@/lib/cn";
|
|
4
|
-
|
|
5
|
-
const buttonVariants = cva(
|
|
6
|
-
[
|
|
7
|
-
"inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-xl",
|
|
8
|
-
"text-sm font-medium tracking-tight",
|
|
9
|
-
"transition-[color,background-color,border-color,box-shadow,transform] duration-200 ease-[cubic-bezier(0.16,1,0.3,1)]",
|
|
10
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-900/15 focus-visible:ring-offset-2 focus-visible:ring-offset-white",
|
|
11
|
-
"active:scale-[0.97] active:transition-[transform] active:duration-100",
|
|
12
|
-
"disabled:pointer-events-none disabled:opacity-40 disabled:shadow-none disabled:active:scale-100",
|
|
13
|
-
"dark:focus-visible:ring-white/20 dark:focus-visible:ring-offset-zinc-950",
|
|
14
|
-
"select-none",
|
|
15
|
-
],
|
|
16
|
-
{
|
|
17
|
-
variants: {
|
|
18
|
-
variant: {
|
|
19
|
-
primary: [
|
|
20
|
-
"bg-zinc-900 text-white",
|
|
21
|
-
"shadow-[0_1px_2px_rgba(0,0,0,0.06),0_4px_12px_rgba(0,0,0,0.08)]",
|
|
22
|
-
"hover:bg-zinc-800 hover:-translate-y-0.5",
|
|
23
|
-
"hover:shadow-[0_2px_4px_rgba(0,0,0,0.06),0_8px_20px_rgba(0,0,0,0.12)]",
|
|
24
|
-
"dark:bg-zinc-100 dark:text-zinc-900",
|
|
25
|
-
"dark:shadow-[0_1px_2px_rgba(255,255,255,0.06),0_4px_16px_rgba(0,0,0,0.35)]",
|
|
26
|
-
"dark:hover:bg-white dark:hover:shadow-[0_2px_8px_rgba(0,0,0,0.25),0_8px_24px_rgba(0,0,0,0.2)]",
|
|
27
|
-
],
|
|
28
|
-
white: [
|
|
29
|
-
"border border-zinc-200/80 bg-white text-zinc-900",
|
|
30
|
-
"shadow-[0_1px_2px_rgba(0,0,0,0.04),0_4px_12px_rgba(0,0,0,0.06)]",
|
|
31
|
-
"hover:border-zinc-300 hover:bg-zinc-50 hover:-translate-y-0.5",
|
|
32
|
-
"hover:shadow-[0_2px_4px_rgba(0,0,0,0.04),0_8px_20px_rgba(0,0,0,0.1)]",
|
|
33
|
-
],
|
|
34
|
-
outline: [
|
|
35
|
-
"border border-zinc-200 bg-white/70 text-zinc-700 backdrop-blur-sm",
|
|
36
|
-
"shadow-[0_1px_2px_rgba(0,0,0,0.03)]",
|
|
37
|
-
"hover:border-zinc-300 hover:bg-white hover:text-zinc-900 hover:-translate-y-0.5",
|
|
38
|
-
"hover:shadow-[0_2px_8px_rgba(0,0,0,0.06)]",
|
|
39
|
-
"dark:border-zinc-700 dark:bg-zinc-900/40 dark:text-zinc-200 dark:shadow-none",
|
|
40
|
-
"dark:hover:border-zinc-500 dark:hover:bg-zinc-800/80 dark:hover:text-white",
|
|
41
|
-
],
|
|
42
|
-
ghost: [
|
|
43
|
-
"text-zinc-600",
|
|
44
|
-
"hover:bg-zinc-100/90 hover:text-zinc-900",
|
|
45
|
-
"dark:text-zinc-400 dark:hover:bg-zinc-800/70 dark:hover:text-zinc-100",
|
|
46
|
-
],
|
|
47
|
-
},
|
|
48
|
-
size: {
|
|
49
|
-
sm: "h-8 gap-1.5 rounded-lg px-3.5 text-xs",
|
|
50
|
-
md: "h-10 px-4",
|
|
51
|
-
lg: "h-11 px-5 text-[15px]",
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
defaultVariants: { variant: "primary", size: "md" },
|
|
55
|
-
},
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
export interface ButtonProps
|
|
59
|
-
extends React.ComponentPropsWithoutRef<"button">,
|
|
60
|
-
VariantProps<typeof buttonVariants> {}
|
|
61
|
-
|
|
62
|
-
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
63
|
-
({ className, variant, size, ...props }, ref) => {
|
|
64
|
-
return (
|
|
65
|
-
<button
|
|
66
|
-
ref={ref}
|
|
67
|
-
className={cn(buttonVariants({ variant, size }), className)}
|
|
68
|
-
{...props}
|
|
69
|
-
/>
|
|
70
|
-
);
|
|
71
|
-
},
|
|
72
|
-
);
|
|
73
|
-
Button.displayName = "Button";
|
|
74
|
-
|
|
75
|
-
export { buttonVariants };
|
package/components/ui/card.tsx
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
-
import { cn } from "@/lib/cn";
|
|
4
|
-
|
|
5
|
-
const cardVariants = cva(
|
|
6
|
-
"rounded-2xl border bg-white text-zinc-900 transition-all duration-200 dark:bg-zinc-900 dark:text-zinc-100",
|
|
7
|
-
{
|
|
8
|
-
variants: {
|
|
9
|
-
variant: {
|
|
10
|
-
default:
|
|
11
|
-
"border-zinc-200/70 shadow-[0_2px_8px_rgba(0,0,0,0.06)] dark:border-zinc-800/80 dark:shadow-[0_2px_8px_rgba(0,0,0,0.25)]",
|
|
12
|
-
outline: "border-zinc-200 shadow-none dark:border-zinc-800",
|
|
13
|
-
elevated:
|
|
14
|
-
"border-zinc-200 shadow-[0_8px_30px_rgba(0,0,0,0.08)] dark:border-zinc-800 dark:shadow-[0_8px_30px_rgba(0,0,0,0.35)]",
|
|
15
|
-
interactive:
|
|
16
|
-
"cursor-pointer border-zinc-200/70 shadow-[0_2px_8px_rgba(0,0,0,0.06)] hover:-translate-y-0.5 hover:border-zinc-300 hover:shadow-[0_8px_24px_rgba(0,0,0,0.1)] dark:border-zinc-800/80 dark:shadow-[0_2px_8px_rgba(0,0,0,0.25)] dark:hover:border-zinc-700 dark:hover:shadow-[0_8px_24px_rgba(0,0,0,0.4)]",
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
defaultVariants: { variant: "default" },
|
|
20
|
-
},
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
export interface CardProps
|
|
24
|
-
extends React.HTMLAttributes<HTMLDivElement>,
|
|
25
|
-
VariantProps<typeof cardVariants> {}
|
|
26
|
-
|
|
27
|
-
const Card = React.forwardRef<HTMLDivElement, CardProps>(
|
|
28
|
-
({ className, variant, ...props }, ref) => (
|
|
29
|
-
<div
|
|
30
|
-
ref={ref}
|
|
31
|
-
className={cn(cardVariants({ variant }), className)}
|
|
32
|
-
{...props}
|
|
33
|
-
/>
|
|
34
|
-
),
|
|
35
|
-
);
|
|
36
|
-
Card.displayName = "Card";
|
|
37
|
-
|
|
38
|
-
const CardHeader = React.forwardRef<
|
|
39
|
-
HTMLDivElement,
|
|
40
|
-
React.HTMLAttributes<HTMLDivElement>
|
|
41
|
-
>(({ className, ...props }, ref) => (
|
|
42
|
-
<div
|
|
43
|
-
ref={ref}
|
|
44
|
-
className={cn("flex flex-col gap-1.5 p-6", className)}
|
|
45
|
-
{...props}
|
|
46
|
-
/>
|
|
47
|
-
));
|
|
48
|
-
CardHeader.displayName = "CardHeader";
|
|
49
|
-
|
|
50
|
-
const CardTitle = React.forwardRef<
|
|
51
|
-
HTMLHeadingElement,
|
|
52
|
-
React.HTMLAttributes<HTMLHeadingElement>
|
|
53
|
-
>(({ className, ...props }, ref) => (
|
|
54
|
-
<h3
|
|
55
|
-
ref={ref}
|
|
56
|
-
className={cn("text-base font-semibold leading-none tracking-tight text-zinc-900 dark:text-white", className)}
|
|
57
|
-
{...props}
|
|
58
|
-
/>
|
|
59
|
-
));
|
|
60
|
-
CardTitle.displayName = "CardTitle";
|
|
61
|
-
|
|
62
|
-
const CardDescription = React.forwardRef<
|
|
63
|
-
HTMLParagraphElement,
|
|
64
|
-
React.HTMLAttributes<HTMLParagraphElement>
|
|
65
|
-
>(({ className, ...props }, ref) => (
|
|
66
|
-
<p
|
|
67
|
-
ref={ref}
|
|
68
|
-
className={cn("text-sm leading-relaxed text-zinc-500 dark:text-zinc-400", className)}
|
|
69
|
-
{...props}
|
|
70
|
-
/>
|
|
71
|
-
));
|
|
72
|
-
CardDescription.displayName = "CardDescription";
|
|
73
|
-
|
|
74
|
-
const CardContent = React.forwardRef<
|
|
75
|
-
HTMLDivElement,
|
|
76
|
-
React.HTMLAttributes<HTMLDivElement>
|
|
77
|
-
>(({ className, ...props }, ref) => (
|
|
78
|
-
<div ref={ref} className={cn("px-6 pb-6 pt-0", className)} {...props} />
|
|
79
|
-
));
|
|
80
|
-
CardContent.displayName = "CardContent";
|
|
81
|
-
|
|
82
|
-
const CardFooter = React.forwardRef<
|
|
83
|
-
HTMLDivElement,
|
|
84
|
-
React.HTMLAttributes<HTMLDivElement>
|
|
85
|
-
>(({ className, ...props }, ref) => (
|
|
86
|
-
<div
|
|
87
|
-
ref={ref}
|
|
88
|
-
className={cn(
|
|
89
|
-
"flex items-center gap-2 border-t border-zinc-100 bg-zinc-50/60 px-6 py-4 dark:border-zinc-800 dark:bg-zinc-800/30",
|
|
90
|
-
className,
|
|
91
|
-
)}
|
|
92
|
-
{...props}
|
|
93
|
-
/>
|
|
94
|
-
));
|
|
95
|
-
CardFooter.displayName = "CardFooter";
|
|
96
|
-
|
|
97
|
-
export {
|
|
98
|
-
Card,
|
|
99
|
-
CardHeader,
|
|
100
|
-
CardTitle,
|
|
101
|
-
CardDescription,
|
|
102
|
-
CardContent,
|
|
103
|
-
CardFooter,
|
|
104
|
-
cardVariants,
|
|
105
|
-
};
|