ucode-agent 1.3.0 → 1.5.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/README.md +42 -12
- package/package.json +5 -3
- package/skills/build-app/SKILL.md +23 -3
- package/skills/ui-ux/SKILL.md +5 -1
- package/src/core/loop.js +181 -20
- package/src/core/provider.js +40 -12
- package/src/core/updater.js +95 -0
- package/src/tools/browser.js +258 -0
- package/src/tools/index.js +51 -1
- package/src/tools/scaffold.js +130 -0
- package/src/tools/shell.js +8 -1
- package/src/ui/screen.js +20 -6
- package/templates/next-shadcn/AGENTS.md +9 -0
- package/templates/next-shadcn/README.md +9 -0
- package/templates/next-shadcn/TEMPLATE.md +39 -0
- package/templates/next-shadcn/_gitignore +41 -0
- package/templates/next-shadcn/_package-lock.json +10278 -0
- package/templates/next-shadcn/components.json +25 -0
- package/templates/next-shadcn/eslint.config.mjs +18 -0
- package/templates/next-shadcn/next-env.d.ts +5 -0
- package/templates/next-shadcn/next.config.ts +7 -0
- package/templates/next-shadcn/package.json +37 -0
- package/templates/next-shadcn/postcss.config.mjs +7 -0
- package/templates/next-shadcn/src/app/favicon.ico +0 -0
- package/templates/next-shadcn/src/app/globals.css +155 -0
- package/templates/next-shadcn/src/app/layout.tsx +42 -0
- package/templates/next-shadcn/src/app/page.tsx +14 -0
- package/templates/next-shadcn/src/components/theme-provider.tsx +7 -0
- package/templates/next-shadcn/src/components/theme-toggle.tsx +27 -0
- package/templates/next-shadcn/src/components/ui/alert-dialog.tsx +187 -0
- package/templates/next-shadcn/src/components/ui/avatar.tsx +108 -0
- package/templates/next-shadcn/src/components/ui/badge.tsx +51 -0
- package/templates/next-shadcn/src/components/ui/button.tsx +57 -0
- package/templates/next-shadcn/src/components/ui/calendar.tsx +221 -0
- package/templates/next-shadcn/src/components/ui/card.tsx +102 -0
- package/templates/next-shadcn/src/components/ui/checkbox.tsx +28 -0
- package/templates/next-shadcn/src/components/ui/command.tsx +196 -0
- package/templates/next-shadcn/src/components/ui/dialog.tsx +160 -0
- package/templates/next-shadcn/src/components/ui/dropdown-menu.tsx +267 -0
- package/templates/next-shadcn/src/components/ui/input-group.tsx +158 -0
- package/templates/next-shadcn/src/components/ui/input.tsx +19 -0
- package/templates/next-shadcn/src/components/ui/label.tsx +19 -0
- package/templates/next-shadcn/src/components/ui/popover.tsx +89 -0
- package/templates/next-shadcn/src/components/ui/progress.tsx +82 -0
- package/templates/next-shadcn/src/components/ui/scroll-area.tsx +54 -0
- package/templates/next-shadcn/src/components/ui/select.tsx +200 -0
- package/templates/next-shadcn/src/components/ui/separator.tsx +24 -0
- package/templates/next-shadcn/src/components/ui/sheet.tsx +138 -0
- package/templates/next-shadcn/src/components/ui/skeleton.tsx +13 -0
- package/templates/next-shadcn/src/components/ui/sonner.tsx +49 -0
- package/templates/next-shadcn/src/components/ui/switch.tsx +31 -0
- package/templates/next-shadcn/src/components/ui/tabs.tsx +81 -0
- package/templates/next-shadcn/src/components/ui/textarea.tsx +17 -0
- package/templates/next-shadcn/src/components/ui/tooltip.tsx +65 -0
- package/templates/next-shadcn/src/lib/utils.ts +1 -0
- package/templates/next-shadcn/tsconfig.json +34 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "base-nova",
|
|
4
|
+
"rsc": true,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "",
|
|
8
|
+
"css": "src/app/globals.css",
|
|
9
|
+
"baseColor": "neutral",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
13
|
+
"iconLibrary": "lucide",
|
|
14
|
+
"rtl": false,
|
|
15
|
+
"aliases": {
|
|
16
|
+
"components": "@/components",
|
|
17
|
+
"utils": "@/lib/utils",
|
|
18
|
+
"ui": "@/components/ui",
|
|
19
|
+
"lib": "@/lib",
|
|
20
|
+
"hooks": "@/hooks"
|
|
21
|
+
},
|
|
22
|
+
"menuColor": "default",
|
|
23
|
+
"menuAccent": "subtle",
|
|
24
|
+
"registries": {}
|
|
25
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineConfig, globalIgnores } from "eslint/config";
|
|
2
|
+
import nextVitals from "eslint-config-next/core-web-vitals";
|
|
3
|
+
import nextTs from "eslint-config-next/typescript";
|
|
4
|
+
|
|
5
|
+
const eslintConfig = defineConfig([
|
|
6
|
+
...nextVitals,
|
|
7
|
+
...nextTs,
|
|
8
|
+
// Override default ignores of eslint-config-next.
|
|
9
|
+
globalIgnores([
|
|
10
|
+
// Default ignores of eslint-config-next:
|
|
11
|
+
".next/**",
|
|
12
|
+
"out/**",
|
|
13
|
+
"build/**",
|
|
14
|
+
"next-env.d.ts",
|
|
15
|
+
]),
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
export default eslintConfig;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__APP_SLUG__",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "next dev",
|
|
7
|
+
"build": "next build",
|
|
8
|
+
"start": "next start",
|
|
9
|
+
"lint": "eslint"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@base-ui/react": "^1.8.0",
|
|
13
|
+
"class-variance-authority": "^0.7.1",
|
|
14
|
+
"cmdk": "^1.1.1",
|
|
15
|
+
"cn": "^0.2.6",
|
|
16
|
+
"date-fns": "^4.4.0",
|
|
17
|
+
"lucide-react": "^1.44.0",
|
|
18
|
+
"next": "16.3.4",
|
|
19
|
+
"next-themes": "^0.4.6",
|
|
20
|
+
"react": "19.2.8",
|
|
21
|
+
"react-day-picker": "^10.0.1",
|
|
22
|
+
"react-dom": "19.2.8",
|
|
23
|
+
"shadcn": "^4.21.0",
|
|
24
|
+
"sonner": "^2.0.8",
|
|
25
|
+
"tw-animate-css": "^1.4.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@tailwindcss/postcss": "^4",
|
|
29
|
+
"@types/node": "^20",
|
|
30
|
+
"@types/react": "^19",
|
|
31
|
+
"@types/react-dom": "^19",
|
|
32
|
+
"eslint": "^9",
|
|
33
|
+
"eslint-config-next": "16.3.4",
|
|
34
|
+
"tailwindcss": "^4",
|
|
35
|
+
"typescript": "^5"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Design tokens. This palette is a considered starting point, not a finished
|
|
3
|
+
* look: re-tint --primary, --accent and the neutrals (the third number in each
|
|
4
|
+
* oklch() is the hue) so each app has its own direction.
|
|
5
|
+
*/
|
|
6
|
+
@import "tailwindcss";
|
|
7
|
+
@import "tw-animate-css";
|
|
8
|
+
@import "shadcn/tailwind.css";
|
|
9
|
+
|
|
10
|
+
@custom-variant dark (&:is(.dark *));
|
|
11
|
+
|
|
12
|
+
@theme inline {
|
|
13
|
+
--color-background: var(--background);
|
|
14
|
+
--color-foreground: var(--foreground);
|
|
15
|
+
--font-sans: var(--font-sans);
|
|
16
|
+
--font-mono: var(--font-geist-mono);
|
|
17
|
+
--font-heading: var(--font-sans);
|
|
18
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
19
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
20
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
21
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
22
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
23
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
24
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
25
|
+
--color-sidebar: var(--sidebar);
|
|
26
|
+
--color-chart-5: var(--chart-5);
|
|
27
|
+
--color-chart-4: var(--chart-4);
|
|
28
|
+
--color-chart-3: var(--chart-3);
|
|
29
|
+
--color-chart-2: var(--chart-2);
|
|
30
|
+
--color-chart-1: var(--chart-1);
|
|
31
|
+
--color-ring: var(--ring);
|
|
32
|
+
--color-input: var(--input);
|
|
33
|
+
--color-border: var(--border);
|
|
34
|
+
--color-destructive: var(--destructive);
|
|
35
|
+
--color-success: var(--success);
|
|
36
|
+
--color-warning: var(--warning);
|
|
37
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
38
|
+
--color-accent: var(--accent);
|
|
39
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
40
|
+
--color-muted: var(--muted);
|
|
41
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
42
|
+
--color-secondary: var(--secondary);
|
|
43
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
44
|
+
--color-primary: var(--primary);
|
|
45
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
46
|
+
--color-popover: var(--popover);
|
|
47
|
+
--color-card-foreground: var(--card-foreground);
|
|
48
|
+
--color-card: var(--card);
|
|
49
|
+
--radius-sm: calc(var(--radius) * 0.6);
|
|
50
|
+
--radius-md: calc(var(--radius) * 0.8);
|
|
51
|
+
--radius-lg: var(--radius);
|
|
52
|
+
--radius-xl: calc(var(--radius) * 1.4);
|
|
53
|
+
--radius-2xl: calc(var(--radius) * 1.8);
|
|
54
|
+
--radius-3xl: calc(var(--radius) * 2.2);
|
|
55
|
+
--radius-4xl: calc(var(--radius) * 2.6);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
:root {
|
|
59
|
+
--background: oklch(0.985 0.004 255);
|
|
60
|
+
--foreground: oklch(0.21 0.02 262);
|
|
61
|
+
--card: oklch(1 0 0);
|
|
62
|
+
--card-foreground: oklch(0.21 0.02 262);
|
|
63
|
+
--popover: oklch(1 0 0);
|
|
64
|
+
--popover-foreground: oklch(0.21 0.02 262);
|
|
65
|
+
--primary: oklch(0.53 0.2 264);
|
|
66
|
+
--primary-foreground: oklch(0.99 0 0);
|
|
67
|
+
--secondary: oklch(0.955 0.008 255);
|
|
68
|
+
--secondary-foreground: oklch(0.27 0.03 262);
|
|
69
|
+
--muted: oklch(0.96 0.006 255);
|
|
70
|
+
--muted-foreground: oklch(0.52 0.02 262);
|
|
71
|
+
--accent: oklch(0.95 0.025 264);
|
|
72
|
+
--accent-foreground: oklch(0.36 0.13 264);
|
|
73
|
+
--destructive: oklch(0.577 0.215 27);
|
|
74
|
+
--success: oklch(0.6 0.15 155);
|
|
75
|
+
--warning: oklch(0.74 0.15 72);
|
|
76
|
+
--border: oklch(0.915 0.008 255);
|
|
77
|
+
--input: oklch(0.9 0.01 255);
|
|
78
|
+
--ring: oklch(0.53 0.2 264);
|
|
79
|
+
--chart-1: oklch(0.53 0.2 264);
|
|
80
|
+
--chart-2: oklch(0.6 0.15 155);
|
|
81
|
+
--chart-3: oklch(0.74 0.15 72);
|
|
82
|
+
--chart-4: oklch(0.62 0.19 330);
|
|
83
|
+
--chart-5: oklch(0.52 0.02 262);
|
|
84
|
+
--radius: 0.75rem;
|
|
85
|
+
--sidebar: oklch(0.975 0.006 255);
|
|
86
|
+
--sidebar-foreground: oklch(0.21 0.02 262);
|
|
87
|
+
--sidebar-primary: oklch(0.53 0.2 264);
|
|
88
|
+
--sidebar-primary-foreground: oklch(0.99 0 0);
|
|
89
|
+
--sidebar-accent: oklch(0.95 0.025 264);
|
|
90
|
+
--sidebar-accent-foreground: oklch(0.36 0.13 264);
|
|
91
|
+
--sidebar-border: oklch(0.915 0.008 255);
|
|
92
|
+
--sidebar-ring: oklch(0.53 0.2 264);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.dark {
|
|
96
|
+
--background: oklch(0.165 0.012 262);
|
|
97
|
+
--foreground: oklch(0.95 0.008 262);
|
|
98
|
+
--card: oklch(0.2 0.014 262);
|
|
99
|
+
--card-foreground: oklch(0.95 0.008 262);
|
|
100
|
+
--popover: oklch(0.215 0.015 262);
|
|
101
|
+
--popover-foreground: oklch(0.95 0.008 262);
|
|
102
|
+
--primary: oklch(0.7 0.16 264);
|
|
103
|
+
--primary-foreground: oklch(0.17 0.02 262);
|
|
104
|
+
--secondary: oklch(0.25 0.015 262);
|
|
105
|
+
--secondary-foreground: oklch(0.93 0.01 262);
|
|
106
|
+
--muted: oklch(0.24 0.014 262);
|
|
107
|
+
--muted-foreground: oklch(0.7 0.02 262);
|
|
108
|
+
--accent: oklch(0.28 0.045 264);
|
|
109
|
+
--accent-foreground: oklch(0.9 0.05 264);
|
|
110
|
+
--destructive: oklch(0.7 0.19 22);
|
|
111
|
+
--success: oklch(0.72 0.15 155);
|
|
112
|
+
--warning: oklch(0.8 0.14 75);
|
|
113
|
+
--border: oklch(1 0 0 / 9%);
|
|
114
|
+
--input: oklch(1 0 0 / 13%);
|
|
115
|
+
--ring: oklch(0.7 0.16 264);
|
|
116
|
+
--chart-1: oklch(0.7 0.16 264);
|
|
117
|
+
--chart-2: oklch(0.72 0.15 155);
|
|
118
|
+
--chart-3: oklch(0.8 0.14 75);
|
|
119
|
+
--chart-4: oklch(0.72 0.17 330);
|
|
120
|
+
--chart-5: oklch(0.7 0.02 262);
|
|
121
|
+
--sidebar: oklch(0.185 0.013 262);
|
|
122
|
+
--sidebar-foreground: oklch(0.95 0.008 262);
|
|
123
|
+
--sidebar-primary: oklch(0.7 0.16 264);
|
|
124
|
+
--sidebar-primary-foreground: oklch(0.17 0.02 262);
|
|
125
|
+
--sidebar-accent: oklch(0.28 0.045 264);
|
|
126
|
+
--sidebar-accent-foreground: oklch(0.9 0.05 264);
|
|
127
|
+
--sidebar-border: oklch(1 0 0 / 9%);
|
|
128
|
+
--sidebar-ring: oklch(0.7 0.16 264);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@layer base {
|
|
132
|
+
* {
|
|
133
|
+
@apply border-border outline-ring/50;
|
|
134
|
+
}
|
|
135
|
+
body {
|
|
136
|
+
@apply bg-background text-foreground;
|
|
137
|
+
}
|
|
138
|
+
html {
|
|
139
|
+
@apply font-sans;
|
|
140
|
+
}
|
|
141
|
+
h1, h2, h3 {
|
|
142
|
+
letter-spacing: -0.02em;
|
|
143
|
+
text-wrap: balance;
|
|
144
|
+
}
|
|
145
|
+
p {
|
|
146
|
+
text-wrap: pretty;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@media (prefers-reduced-motion: reduce) {
|
|
151
|
+
*, *::before, *::after {
|
|
152
|
+
animation-duration: 1ms !important;
|
|
153
|
+
transition-duration: 1ms !important;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Metadata } from "next";
|
|
2
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
3
|
+
import { ThemeProvider } from "@/components/theme-provider";
|
|
4
|
+
import { Toaster } from "@/components/ui/sonner";
|
|
5
|
+
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
6
|
+
import "./globals.css";
|
|
7
|
+
|
|
8
|
+
// Registered as --font-sans, which is the variable globals.css and every
|
|
9
|
+
// shadcn component read. Swap Geist for the font the app's direction calls for.
|
|
10
|
+
const sans = Geist({
|
|
11
|
+
variable: "--font-sans",
|
|
12
|
+
subsets: ["latin"],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const mono = Geist_Mono({
|
|
16
|
+
variable: "--font-geist-mono",
|
|
17
|
+
subsets: ["latin"],
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const metadata: Metadata = {
|
|
21
|
+
title: "__APP_NAME__",
|
|
22
|
+
description: "__APP_DESCRIPTION__",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
|
|
26
|
+
return (
|
|
27
|
+
<html
|
|
28
|
+
lang="en"
|
|
29
|
+
suppressHydrationWarning
|
|
30
|
+
className={`${sans.variable} ${mono.variable} h-full antialiased`}
|
|
31
|
+
>
|
|
32
|
+
<body className="min-h-full flex flex-col">
|
|
33
|
+
<ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange>
|
|
34
|
+
<TooltipProvider>
|
|
35
|
+
{children}
|
|
36
|
+
<Toaster richColors closeButton />
|
|
37
|
+
</TooltipProvider>
|
|
38
|
+
</ThemeProvider>
|
|
39
|
+
</body>
|
|
40
|
+
</html>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ThemeToggle } from "@/components/theme-toggle";
|
|
2
|
+
|
|
3
|
+
// Placeholder — replace this whole page with the app.
|
|
4
|
+
export default function Home() {
|
|
5
|
+
return (
|
|
6
|
+
<main className="flex flex-1 items-center justify-center p-8">
|
|
7
|
+
<div className="space-y-3 text-center">
|
|
8
|
+
<h1 className="text-3xl font-semibold tracking-tight">__APP_NAME__</h1>
|
|
9
|
+
<p className="text-muted-foreground">Replace src/app/page.tsx with the app.</p>
|
|
10
|
+
<ThemeToggle />
|
|
11
|
+
</div>
|
|
12
|
+
</main>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { ThemeProvider as NextThemesProvider } from "next-themes";
|
|
4
|
+
|
|
5
|
+
export function ThemeProvider({ children, ...props }: React.ComponentProps<typeof NextThemesProvider>) {
|
|
6
|
+
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { useTheme } from "next-themes";
|
|
5
|
+
import { MoonIcon, SunIcon } from "lucide-react";
|
|
6
|
+
import { Button } from "@/components/ui/button";
|
|
7
|
+
|
|
8
|
+
/** Light / dark switch. Renders a same-size placeholder until mounted, so nothing shifts. */
|
|
9
|
+
export function ThemeToggle() {
|
|
10
|
+
const { resolvedTheme, setTheme } = useTheme();
|
|
11
|
+
const [mounted, setMounted] = useState(false);
|
|
12
|
+
useEffect(() => setMounted(true), []);
|
|
13
|
+
|
|
14
|
+
if (!mounted) return <span aria-hidden className="inline-block size-8" />;
|
|
15
|
+
|
|
16
|
+
const dark = resolvedTheme === "dark";
|
|
17
|
+
return (
|
|
18
|
+
<Button
|
|
19
|
+
variant="ghost"
|
|
20
|
+
size="icon"
|
|
21
|
+
aria-label={dark ? "Switch to light mode" : "Switch to dark mode"}
|
|
22
|
+
onClick={() => setTheme(dark ? "light" : "dark")}
|
|
23
|
+
>
|
|
24
|
+
{dark ? <SunIcon /> : <MoonIcon />}
|
|
25
|
+
</Button>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog"
|
|
5
|
+
import { cn } from "cn"
|
|
6
|
+
|
|
7
|
+
import { Button } from "@/components/ui/button"
|
|
8
|
+
|
|
9
|
+
function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {
|
|
10
|
+
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {
|
|
14
|
+
return (
|
|
15
|
+
<AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {
|
|
20
|
+
return (
|
|
21
|
+
<AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function AlertDialogOverlay({
|
|
26
|
+
className,
|
|
27
|
+
...props
|
|
28
|
+
}: AlertDialogPrimitive.Backdrop.Props) {
|
|
29
|
+
return (
|
|
30
|
+
<AlertDialogPrimitive.Backdrop
|
|
31
|
+
data-slot="alert-dialog-overlay"
|
|
32
|
+
className={cn(
|
|
33
|
+
"fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
|
|
34
|
+
className
|
|
35
|
+
)}
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function AlertDialogContent({
|
|
42
|
+
className,
|
|
43
|
+
size = "default",
|
|
44
|
+
...props
|
|
45
|
+
}: AlertDialogPrimitive.Popup.Props & {
|
|
46
|
+
size?: "default" | "sm"
|
|
47
|
+
}) {
|
|
48
|
+
return (
|
|
49
|
+
<AlertDialogPortal>
|
|
50
|
+
<AlertDialogOverlay />
|
|
51
|
+
<AlertDialogPrimitive.Popup
|
|
52
|
+
data-slot="alert-dialog-content"
|
|
53
|
+
data-size={size}
|
|
54
|
+
className={cn(
|
|
55
|
+
"group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
56
|
+
className
|
|
57
|
+
)}
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
</AlertDialogPortal>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function AlertDialogHeader({
|
|
65
|
+
className,
|
|
66
|
+
...props
|
|
67
|
+
}: React.ComponentProps<"div">) {
|
|
68
|
+
return (
|
|
69
|
+
<div
|
|
70
|
+
data-slot="alert-dialog-header"
|
|
71
|
+
className={cn(
|
|
72
|
+
"grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",
|
|
73
|
+
className
|
|
74
|
+
)}
|
|
75
|
+
{...props}
|
|
76
|
+
/>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function AlertDialogFooter({
|
|
81
|
+
className,
|
|
82
|
+
...props
|
|
83
|
+
}: React.ComponentProps<"div">) {
|
|
84
|
+
return (
|
|
85
|
+
<div
|
|
86
|
+
data-slot="alert-dialog-footer"
|
|
87
|
+
className={cn(
|
|
88
|
+
"-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
|
|
89
|
+
className
|
|
90
|
+
)}
|
|
91
|
+
{...props}
|
|
92
|
+
/>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function AlertDialogMedia({
|
|
97
|
+
className,
|
|
98
|
+
...props
|
|
99
|
+
}: React.ComponentProps<"div">) {
|
|
100
|
+
return (
|
|
101
|
+
<div
|
|
102
|
+
data-slot="alert-dialog-media"
|
|
103
|
+
className={cn(
|
|
104
|
+
"mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6",
|
|
105
|
+
className
|
|
106
|
+
)}
|
|
107
|
+
{...props}
|
|
108
|
+
/>
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function AlertDialogTitle({
|
|
113
|
+
className,
|
|
114
|
+
...props
|
|
115
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
|
|
116
|
+
return (
|
|
117
|
+
<AlertDialogPrimitive.Title
|
|
118
|
+
data-slot="alert-dialog-title"
|
|
119
|
+
className={cn(
|
|
120
|
+
"font-heading text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",
|
|
121
|
+
className
|
|
122
|
+
)}
|
|
123
|
+
{...props}
|
|
124
|
+
/>
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function AlertDialogDescription({
|
|
129
|
+
className,
|
|
130
|
+
...props
|
|
131
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
|
|
132
|
+
return (
|
|
133
|
+
<AlertDialogPrimitive.Description
|
|
134
|
+
data-slot="alert-dialog-description"
|
|
135
|
+
className={cn(
|
|
136
|
+
"text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
|
|
137
|
+
className
|
|
138
|
+
)}
|
|
139
|
+
{...props}
|
|
140
|
+
/>
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function AlertDialogAction({
|
|
145
|
+
className,
|
|
146
|
+
...props
|
|
147
|
+
}: React.ComponentProps<typeof Button>) {
|
|
148
|
+
return (
|
|
149
|
+
<Button
|
|
150
|
+
data-slot="alert-dialog-action"
|
|
151
|
+
className={cn(className)}
|
|
152
|
+
{...props}
|
|
153
|
+
/>
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function AlertDialogCancel({
|
|
158
|
+
className,
|
|
159
|
+
variant = "outline",
|
|
160
|
+
size = "default",
|
|
161
|
+
...props
|
|
162
|
+
}: AlertDialogPrimitive.Close.Props &
|
|
163
|
+
Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
|
|
164
|
+
return (
|
|
165
|
+
<AlertDialogPrimitive.Close
|
|
166
|
+
data-slot="alert-dialog-cancel"
|
|
167
|
+
className={cn(className)}
|
|
168
|
+
render={<Button variant={variant} size={size} />}
|
|
169
|
+
{...props}
|
|
170
|
+
/>
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export {
|
|
175
|
+
AlertDialog,
|
|
176
|
+
AlertDialogAction,
|
|
177
|
+
AlertDialogCancel,
|
|
178
|
+
AlertDialogContent,
|
|
179
|
+
AlertDialogDescription,
|
|
180
|
+
AlertDialogFooter,
|
|
181
|
+
AlertDialogHeader,
|
|
182
|
+
AlertDialogMedia,
|
|
183
|
+
AlertDialogOverlay,
|
|
184
|
+
AlertDialogPortal,
|
|
185
|
+
AlertDialogTitle,
|
|
186
|
+
AlertDialogTrigger,
|
|
187
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar"
|
|
5
|
+
import { cn } from "cn"
|
|
6
|
+
|
|
7
|
+
function Avatar({
|
|
8
|
+
className,
|
|
9
|
+
size = "default",
|
|
10
|
+
...props
|
|
11
|
+
}: AvatarPrimitive.Root.Props & {
|
|
12
|
+
size?: "default" | "sm" | "lg"
|
|
13
|
+
}) {
|
|
14
|
+
return (
|
|
15
|
+
<AvatarPrimitive.Root
|
|
16
|
+
data-slot="avatar"
|
|
17
|
+
data-size={size}
|
|
18
|
+
className={cn(
|
|
19
|
+
"group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten",
|
|
20
|
+
className
|
|
21
|
+
)}
|
|
22
|
+
{...props}
|
|
23
|
+
/>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) {
|
|
28
|
+
return (
|
|
29
|
+
<AvatarPrimitive.Image
|
|
30
|
+
data-slot="avatar-image"
|
|
31
|
+
className={cn(
|
|
32
|
+
"aspect-square size-full rounded-full object-cover",
|
|
33
|
+
className
|
|
34
|
+
)}
|
|
35
|
+
{...props}
|
|
36
|
+
/>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function AvatarFallback({
|
|
41
|
+
className,
|
|
42
|
+
...props
|
|
43
|
+
}: AvatarPrimitive.Fallback.Props) {
|
|
44
|
+
return (
|
|
45
|
+
<AvatarPrimitive.Fallback
|
|
46
|
+
data-slot="avatar-fallback"
|
|
47
|
+
className={cn(
|
|
48
|
+
"flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs",
|
|
49
|
+
className
|
|
50
|
+
)}
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) {
|
|
57
|
+
return (
|
|
58
|
+
<span
|
|
59
|
+
data-slot="avatar-badge"
|
|
60
|
+
className={cn(
|
|
61
|
+
"absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none",
|
|
62
|
+
"group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden",
|
|
63
|
+
"group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2",
|
|
64
|
+
"group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2",
|
|
65
|
+
className
|
|
66
|
+
)}
|
|
67
|
+
{...props}
|
|
68
|
+
/>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function AvatarGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
73
|
+
return (
|
|
74
|
+
<div
|
|
75
|
+
data-slot="avatar-group"
|
|
76
|
+
className={cn(
|
|
77
|
+
"group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background",
|
|
78
|
+
className
|
|
79
|
+
)}
|
|
80
|
+
{...props}
|
|
81
|
+
/>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function AvatarGroupCount({
|
|
86
|
+
className,
|
|
87
|
+
...props
|
|
88
|
+
}: React.ComponentProps<"div">) {
|
|
89
|
+
return (
|
|
90
|
+
<div
|
|
91
|
+
data-slot="avatar-group-count"
|
|
92
|
+
className={cn(
|
|
93
|
+
"relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3",
|
|
94
|
+
className
|
|
95
|
+
)}
|
|
96
|
+
{...props}
|
|
97
|
+
/>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
Avatar,
|
|
103
|
+
AvatarImage,
|
|
104
|
+
AvatarFallback,
|
|
105
|
+
AvatarGroup,
|
|
106
|
+
AvatarGroupCount,
|
|
107
|
+
AvatarBadge,
|
|
108
|
+
}
|