@autono/create-open-pages 0.4.0 → 0.6.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/dist/cli.js +30 -2
- package/package.json +1 -1
- package/template/.agents/skills/create-page/SKILL.md +1 -1
- package/template/.agents/skills/page-authoring/SKILL.md +2 -2
- package/template/.agents/skills/page-authoring/references/interactivity.md +13 -21
- package/template/README.md +2 -1
- package/template/components.json +19 -3
- package/template/package.json +7 -7
- package/template/styles/globals.css +83 -66
- package/template/ui/accordion.tsx +22 -7
- package/template/ui/alert-dialog.tsx +22 -21
- package/template/ui/alert.tsx +15 -5
- package/template/ui/avatar.tsx +7 -4
- package/template/ui/badge.tsx +8 -7
- package/template/ui/breadcrumb.tsx +21 -8
- package/template/ui/button-group.tsx +5 -5
- package/template/ui/button.tsx +18 -15
- package/template/ui/calendar.tsx +28 -24
- package/template/ui/card.tsx +17 -6
- package/template/ui/carousel.tsx +10 -11
- package/template/ui/chart.tsx +1 -2
- package/template/ui/checkbox.tsx +5 -6
- package/template/ui/collapsible.tsx +2 -0
- package/template/ui/combobox.tsx +9 -20
- package/template/ui/command.tsx +39 -26
- package/template/ui/context-menu.tsx +69 -60
- package/template/ui/dialog.tsx +26 -14
- package/template/ui/drawer.tsx +8 -9
- package/template/ui/dropdown-menu.tsx +34 -22
- package/template/ui/empty.tsx +8 -8
- package/template/ui/field.tsx +15 -25
- package/template/ui/hover-card.tsx +1 -1
- package/template/ui/input-group.tsx +10 -24
- package/template/ui/input-otp.tsx +16 -6
- package/template/ui/input.tsx +1 -3
- package/template/ui/item.tsx +17 -14
- package/template/ui/kbd.tsx +1 -3
- package/template/ui/menubar.tsx +28 -24
- package/template/ui/message-scroller.tsx +5 -4
- package/template/ui/native-select.tsx +13 -14
- package/template/ui/navigation-menu.tsx +8 -12
- package/template/ui/pagination.tsx +35 -33
- package/template/ui/popover.tsx +5 -5
- package/template/ui/progress.tsx +2 -2
- package/template/ui/radio-group.tsx +4 -5
- package/template/ui/resizable.tsx +2 -5
- package/template/ui/scroll-area.tsx +2 -5
- package/template/ui/select.tsx +26 -24
- package/template/ui/separator.tsx +1 -1
- package/template/ui/sheet.tsx +20 -16
- package/template/ui/sidebar.tsx +39 -63
- package/template/ui/skeleton.tsx +1 -1
- package/template/ui/slider.tsx +6 -8
- package/template/ui/sonner.tsx +21 -14
- package/template/ui/spinner.tsx +2 -8
- package/template/ui/switch.tsx +4 -4
- package/template/ui/table.tsx +2 -4
- package/template/ui/tabs.tsx +9 -8
- package/template/ui/textarea.tsx +1 -1
- package/template/ui/toggle-group.tsx +14 -8
- package/template/ui/toggle.tsx +8 -10
- package/template/ui/tooltip.tsx +4 -2
- package/template/ui/form.tsx +0 -167
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { cp, mkdir, readFile, readdir, rm, symlink, writeFile } from "node:fs/promises";
|
|
4
|
-
import { basename, dirname, join, resolve } from "node:path";
|
|
4
|
+
import { basename, dirname, join, resolve, sep } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { Command } from "commander";
|
|
7
7
|
import prompts from "prompts";
|
|
8
8
|
import { spawn } from "node:child_process";
|
|
9
|
+
import { createHash } from "node:crypto";
|
|
9
10
|
import { existsSync } from "node:fs";
|
|
10
11
|
|
|
11
12
|
//#region src/git.ts
|
|
@@ -102,7 +103,7 @@ async function isDirNonEmpty(target) {
|
|
|
102
103
|
return entries.some((e) => !e.startsWith("."));
|
|
103
104
|
}
|
|
104
105
|
function coreVersionRange() {
|
|
105
|
-
return `^0.
|
|
106
|
+
return `^0.6.0`;
|
|
106
107
|
}
|
|
107
108
|
async function linkOrCopy(relSrc, dst) {
|
|
108
109
|
await rm(dst, {
|
|
@@ -128,6 +129,32 @@ async function materializeTemplateLinks(target) {
|
|
|
128
129
|
await linkOrCopy(join("..", "..", ".agents", "skills", entry.name), join(claudeSkills, entry.name));
|
|
129
130
|
}
|
|
130
131
|
}
|
|
132
|
+
async function writeUiManifest(target) {
|
|
133
|
+
const manifest = {};
|
|
134
|
+
for (const entry of [
|
|
135
|
+
"ui",
|
|
136
|
+
"lib",
|
|
137
|
+
"hooks"
|
|
138
|
+
]) {
|
|
139
|
+
const root = join(target, entry);
|
|
140
|
+
if (!existsSync(root)) continue;
|
|
141
|
+
for (const rel of await collectFiles(root)) {
|
|
142
|
+
const wsRel = join(entry, rel).split(sep).join("/");
|
|
143
|
+
manifest[wsRel] = createHash("sha256").update(await readFile(join(root, rel))).digest("hex");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const sorted = Object.fromEntries(Object.entries(manifest).sort(([a], [b]) => a.localeCompare(b)));
|
|
147
|
+
await writeFile(join(target, "ui", ".sync-manifest.json"), `${JSON.stringify(sorted, null, 2)}\n`);
|
|
148
|
+
}
|
|
149
|
+
async function collectFiles(dir, prefix = "") {
|
|
150
|
+
const out = [];
|
|
151
|
+
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
|
152
|
+
const rel = prefix ? join(prefix, entry.name) : entry.name;
|
|
153
|
+
if (entry.isDirectory()) out.push(...await collectFiles(join(dir, entry.name), rel));
|
|
154
|
+
else if (entry.isFile()) out.push(rel);
|
|
155
|
+
}
|
|
156
|
+
return out;
|
|
157
|
+
}
|
|
131
158
|
async function runInstall(pm, cwd) {
|
|
132
159
|
await new Promise((res, rej) => {
|
|
133
160
|
const child = spawn(pm, ["install"], {
|
|
@@ -147,6 +174,7 @@ async function init(opts) {
|
|
|
147
174
|
if (await isDirNonEmpty(target) && !force) throw new Error(`Target ${target} is not empty. Pass --force to scaffold into it anyway.`);
|
|
148
175
|
await cp(TEMPLATE_DIR, target, { recursive: true });
|
|
149
176
|
await materializeTemplateLinks(target);
|
|
177
|
+
await writeUiManifest(target);
|
|
150
178
|
const pkgPath = join(target, "package.json");
|
|
151
179
|
if (existsSync(pkgPath)) {
|
|
152
180
|
const pkg = JSON.parse(await readFile(pkgPath, "utf8"));
|
package/package.json
CHANGED
|
@@ -77,7 +77,7 @@ Before writing code, map every planned section to the shadcn components it shoul
|
|
|
77
77
|
| --- | --- |
|
|
78
78
|
| Landing / marketing | `navigation-menu` or plain links + `sheet` for mobile nav, `button` (CTAs), `badge` (eyebrows), `card` (features, pricing tiers), `tabs` or `switch` (billing toggle), `accordion` (FAQ), `separator` |
|
|
79
79
|
| Dashboard / app UI | `sidebar` (`SidebarProvider` + `SidebarInset`), `table`, `chart`, `card` (KPIs), `tabs`, `select`, `dropdown-menu`, `badge` (status), `skeleton`, `empty` |
|
|
80
|
-
| Form / signup | `
|
|
80
|
+
| Form / signup | `field`, `input`, `select`, `checkbox`, `radio-group`, `switch`, `textarea`, `button`, `alert` |
|
|
81
81
|
| Docs / long-form | `sidebar` or a sticky `scroll-area` TOC, `breadcrumb`, prose in a `max-w-[65ch]` column, `kbd`, `table`, `alert` (callouts) |
|
|
82
82
|
| Portfolio / gallery | `carousel`, `aspect-ratio`, `card`, `dialog` (lightbox), `hover-card` |
|
|
83
83
|
| Internal tool | `command` (palette), `combobox`, `resizable`, `context-menu`, `tooltip`, `sonner` (toasts), `alert-dialog` (confirm) |
|
|
@@ -25,10 +25,10 @@ Every workspace is a shadcn/ui project out of the box. Nothing needs installing:
|
|
|
25
25
|
| `lib/utils.ts` | `cn()` for merging class names. Import as `@/lib/utils`. |
|
|
26
26
|
| `hooks/use-mobile.ts` | `useIsMobile()` breakpoint hook. Import as `@/hooks/use-mobile`. |
|
|
27
27
|
| `styles/globals.css` | Tailwind v4 entry: `@source` for `pages/ ui/ lib/ hooks/ themes/`, the `dark` variant, `:root`/`.dark` OKLCH tokens, `@theme inline`, base layer. Loaded into every page automatically. |
|
|
28
|
-
| `components.json` | shadcn config (style `
|
|
28
|
+
| `components.json` | shadcn config (style `radix-nova`, aliases `@/ui`, `@/lib/utils`, `@/hooks`, `@/components`). Activates the `shadcn` skill and CLI lookups. |
|
|
29
29
|
| `themes/<id>.css` | Optional token overrides a page opts into with `meta.theme` (see Themes). |
|
|
30
30
|
|
|
31
|
-
Installed deps you may import directly: `lucide-react` (icons), `radix-ui`, `class-variance-authority`, `clsx`, `tailwind-merge`, `cmdk`, `sonner`, `vaul`, `recharts`, `react-day-picker`, `date-fns`, `
|
|
31
|
+
Installed deps you may import directly: `lucide-react` (icons), `radix-ui`, `class-variance-authority`, `clsx`, `tailwind-merge`, `cmdk`, `sonner`, `vaul`, `recharts`, `react-day-picker`, `date-fns`, `input-otp`, `embla-carousel-react`, `react-resizable-panels`, `next-themes`. Nothing else.
|
|
32
32
|
|
|
33
33
|
`npx shadcn@latest add <item>` is only for **blocks** (`dashboard-01`, `login-03`, …) or third-party registries; every core component is already under `ui/`. For lookups use `npx shadcn@latest docs <component> --json`, `view`, `search` — details in the `shadcn` skill.
|
|
34
34
|
|
|
@@ -35,32 +35,24 @@ const [billing, setBilling] = useState<'monthly' | 'yearly'>('monthly');
|
|
|
35
35
|
|
|
36
36
|
Simple forms: `<form onSubmit>` with `@/ui/field`, `@/ui/input`, `@/ui/label`,
|
|
37
37
|
`@/ui/select`, `@/ui/checkbox`, `@/ui/textarea`, `@/ui/button`. Validated
|
|
38
|
-
forms:
|
|
38
|
+
forms: native form state (or your own) presented with `@/ui/field`:
|
|
39
39
|
|
|
40
40
|
```tsx
|
|
41
|
-
import { zodResolver } from '@hookform/resolvers/zod';
|
|
42
|
-
import { useForm } from 'react-hook-form';
|
|
43
|
-
import { z } from 'zod';
|
|
44
41
|
import { Button } from '@/ui/button';
|
|
45
|
-
import {
|
|
42
|
+
import { Field, FieldDescription, FieldError, FieldGroup, FieldLabel } from '@/ui/field';
|
|
46
43
|
import { Input } from '@/ui/input';
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
</FormItem>
|
|
60
|
-
)} />
|
|
61
|
-
<Button type="submit">Join the waitlist</Button>
|
|
62
|
-
</form>
|
|
63
|
-
</Form>
|
|
45
|
+
<form onSubmit={handleSubmit}>
|
|
46
|
+
<FieldGroup>
|
|
47
|
+
<Field>
|
|
48
|
+
<FieldLabel htmlFor="email">Work email</FieldLabel>
|
|
49
|
+
<Input id="email" name="email" type="email" required />
|
|
50
|
+
<FieldDescription>We never share it.</FieldDescription>
|
|
51
|
+
{error && <FieldError>{error}</FieldError>}
|
|
52
|
+
</Field>
|
|
53
|
+
<Button type="submit">Create account</Button>
|
|
54
|
+
</FieldGroup>
|
|
55
|
+
</form>
|
|
64
56
|
```
|
|
65
57
|
|
|
66
58
|
- Every input has a label (`<Label htmlFor>` or `<FormLabel>`), a `name`, and
|
package/template/README.md
CHANGED
|
@@ -31,7 +31,8 @@ Then open `http://localhost:5173`, edit `pages/getting-started/index.tsx`, or cr
|
|
|
31
31
|
| `npm run export` | Build pages into `export/<id>/`, one deployable folder per page. |
|
|
32
32
|
| `npm run preview` | Preview the built workspace locally. |
|
|
33
33
|
| `npm run sync:skills` | Sync the bundled agent skills into the workspace. |
|
|
34
|
-
| `
|
|
34
|
+
| `npx open-pages sync:ui` | Update `ui/`, `lib/`, and `hooks/` to the installed runtime's set; files you edited are kept (`--force` to overwrite). |
|
|
35
|
+
| `npm run update` | Update `@autono/open-pages` and sync skills and UI. |
|
|
35
36
|
|
|
36
37
|
## Authoring a page
|
|
37
38
|
|
package/template/components.json
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
-
"style": "
|
|
3
|
+
"style": "radix-nova",
|
|
4
4
|
"rsc": false,
|
|
5
5
|
"tsx": true,
|
|
6
|
-
"tailwind": {
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "",
|
|
8
|
+
"css": "styles/globals.css",
|
|
9
|
+
"baseColor": "neutral",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
7
13
|
"iconLibrary": "lucide",
|
|
8
|
-
"
|
|
14
|
+
"rtl": false,
|
|
15
|
+
"aliases": {
|
|
16
|
+
"components": "@/components",
|
|
17
|
+
"utils": "@/lib/utils",
|
|
18
|
+
"ui": "@/ui",
|
|
19
|
+
"lib": "@/lib",
|
|
20
|
+
"hooks": "@/hooks"
|
|
21
|
+
},
|
|
22
|
+
"menuColor": "default",
|
|
23
|
+
"menuAccent": "subtle",
|
|
24
|
+
"registries": {}
|
|
9
25
|
}
|
package/template/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"react": "^19.2.0",
|
|
17
17
|
"react-dom": "^19.2.0",
|
|
18
18
|
"@base-ui/react": "^1.7.0",
|
|
19
|
-
"@
|
|
19
|
+
"@fontsource-variable/geist": "^5.3.0",
|
|
20
20
|
"@shadcn/react": "^0.3.0",
|
|
21
21
|
"class-variance-authority": "^0.7.1",
|
|
22
22
|
"clsx": "^2.1.1",
|
|
@@ -24,23 +24,23 @@
|
|
|
24
24
|
"date-fns": "^4.4.0",
|
|
25
25
|
"embla-carousel-react": "^8.6.0",
|
|
26
26
|
"input-otp": "^1.5.0",
|
|
27
|
-
"lucide-react": "^1.
|
|
27
|
+
"lucide-react": "^1.37.0",
|
|
28
28
|
"next-themes": "^0.4.6",
|
|
29
29
|
"radix-ui": "^1.6.7",
|
|
30
30
|
"react-day-picker": "^10.0.1",
|
|
31
|
-
"react-hook-form": "^7.86.0",
|
|
32
31
|
"react-resizable-panels": "^4.12.3",
|
|
33
|
-
"recharts": "3.8.0",
|
|
32
|
+
"recharts": "^3.8.0",
|
|
33
|
+
"shadcn": "^4.19.0",
|
|
34
34
|
"sonner": "^2.0.8",
|
|
35
35
|
"tailwind-merge": "^3.6.0",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
36
|
+
"tw-animate-css": "^1.4.0",
|
|
37
|
+
"vaul": "^1.1.2"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/react": "^19.2.0",
|
|
41
41
|
"@types/react-dom": "^19.2.0",
|
|
42
42
|
"vite": "^6.4.3",
|
|
43
|
-
"tailwindcss": "^4.
|
|
43
|
+
"tailwindcss": "^4.3.3",
|
|
44
44
|
"typescript": "^5.9.3"
|
|
45
45
|
}
|
|
46
46
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
@import "tailwindcss" source(none);
|
|
2
|
+
@import "tw-animate-css";
|
|
3
|
+
@import "shadcn/tailwind.css";
|
|
4
|
+
@import "@fontsource-variable/geist";
|
|
2
5
|
@source "../pages";
|
|
3
6
|
@source "../ui";
|
|
4
7
|
@source "../lib";
|
|
@@ -7,15 +10,50 @@
|
|
|
7
10
|
|
|
8
11
|
@custom-variant dark (&:is(.dark *));
|
|
9
12
|
|
|
13
|
+
@theme inline {
|
|
14
|
+
--font-heading: var(--font-sans);
|
|
15
|
+
--font-sans: 'Geist Variable', sans-serif;
|
|
16
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
17
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
18
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
19
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
20
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
21
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
22
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
23
|
+
--color-sidebar: var(--sidebar);
|
|
24
|
+
--color-chart-5: var(--chart-5);
|
|
25
|
+
--color-chart-4: var(--chart-4);
|
|
26
|
+
--color-chart-3: var(--chart-3);
|
|
27
|
+
--color-chart-2: var(--chart-2);
|
|
28
|
+
--color-chart-1: var(--chart-1);
|
|
29
|
+
--color-ring: var(--ring);
|
|
30
|
+
--color-input: var(--input);
|
|
31
|
+
--color-border: var(--border);
|
|
32
|
+
--color-destructive: var(--destructive);
|
|
33
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
34
|
+
--color-accent: var(--accent);
|
|
35
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
36
|
+
--color-muted: var(--muted);
|
|
37
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
38
|
+
--color-secondary: var(--secondary);
|
|
39
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
40
|
+
--color-primary: var(--primary);
|
|
41
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
42
|
+
--color-popover: var(--popover);
|
|
43
|
+
--color-card-foreground: var(--card-foreground);
|
|
44
|
+
--color-card: var(--card);
|
|
45
|
+
--color-foreground: var(--foreground);
|
|
46
|
+
--color-background: var(--background);
|
|
47
|
+
--radius-sm: calc(var(--radius) * 0.6);
|
|
48
|
+
--radius-md: calc(var(--radius) * 0.8);
|
|
49
|
+
--radius-lg: var(--radius);
|
|
50
|
+
--radius-xl: calc(var(--radius) * 1.4);
|
|
51
|
+
--radius-2xl: calc(var(--radius) * 1.8);
|
|
52
|
+
--radius-3xl: calc(var(--radius) * 2.2);
|
|
53
|
+
--radius-4xl: calc(var(--radius) * 2.6);
|
|
54
|
+
}
|
|
55
|
+
|
|
10
56
|
:root {
|
|
11
|
-
--sidebar: oklch(0.985 0 0);
|
|
12
|
-
--sidebar-foreground: oklch(0.145 0 0);
|
|
13
|
-
--sidebar-primary: oklch(0.205 0 0);
|
|
14
|
-
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
15
|
-
--sidebar-accent: oklch(0.97 0 0);
|
|
16
|
-
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
17
|
-
--sidebar-border: oklch(0.922 0 0);
|
|
18
|
-
--sidebar-ring: oklch(0.708 0 0);
|
|
19
57
|
--background: oklch(1 0 0);
|
|
20
58
|
--foreground: oklch(0.145 0 0);
|
|
21
59
|
--card: oklch(1 0 0);
|
|
@@ -34,23 +72,23 @@
|
|
|
34
72
|
--border: oklch(0.922 0 0);
|
|
35
73
|
--input: oklch(0.922 0 0);
|
|
36
74
|
--ring: oklch(0.708 0 0);
|
|
37
|
-
--chart-1: oklch(0.
|
|
38
|
-
--chart-2: oklch(0.
|
|
39
|
-
--chart-3: oklch(0.
|
|
40
|
-
--chart-4: oklch(0.
|
|
41
|
-
--chart-5: oklch(0.
|
|
75
|
+
--chart-1: oklch(0.87 0 0);
|
|
76
|
+
--chart-2: oklch(0.556 0 0);
|
|
77
|
+
--chart-3: oklch(0.439 0 0);
|
|
78
|
+
--chart-4: oklch(0.371 0 0);
|
|
79
|
+
--chart-5: oklch(0.269 0 0);
|
|
42
80
|
--radius: 0.625rem;
|
|
81
|
+
--sidebar: oklch(0.985 0 0);
|
|
82
|
+
--sidebar-foreground: oklch(0.145 0 0);
|
|
83
|
+
--sidebar-primary: oklch(0.205 0 0);
|
|
84
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
85
|
+
--sidebar-accent: oklch(0.97 0 0);
|
|
86
|
+
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
87
|
+
--sidebar-border: oklch(0.922 0 0);
|
|
88
|
+
--sidebar-ring: oklch(0.708 0 0);
|
|
43
89
|
}
|
|
44
90
|
|
|
45
91
|
.dark {
|
|
46
|
-
--sidebar: oklch(0.205 0 0);
|
|
47
|
-
--sidebar-foreground: oklch(0.985 0 0);
|
|
48
|
-
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
49
|
-
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
50
|
-
--sidebar-accent: oklch(0.269 0 0);
|
|
51
|
-
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
52
|
-
--sidebar-border: oklch(1 0 0 / 10%);
|
|
53
|
-
--sidebar-ring: oklch(0.556 0 0);
|
|
54
92
|
--background: oklch(0.145 0 0);
|
|
55
93
|
--foreground: oklch(0.985 0 0);
|
|
56
94
|
--card: oklch(0.205 0 0);
|
|
@@ -69,50 +107,29 @@
|
|
|
69
107
|
--border: oklch(1 0 0 / 10%);
|
|
70
108
|
--input: oklch(1 0 0 / 15%);
|
|
71
109
|
--ring: oklch(0.556 0 0);
|
|
72
|
-
--chart-1: oklch(0.
|
|
73
|
-
--chart-2: oklch(0.
|
|
74
|
-
--chart-3: oklch(0.
|
|
75
|
-
--chart-4: oklch(0.
|
|
76
|
-
--chart-5: oklch(0.
|
|
110
|
+
--chart-1: oklch(0.87 0 0);
|
|
111
|
+
--chart-2: oklch(0.556 0 0);
|
|
112
|
+
--chart-3: oklch(0.439 0 0);
|
|
113
|
+
--chart-4: oklch(0.371 0 0);
|
|
114
|
+
--chart-5: oklch(0.269 0 0);
|
|
115
|
+
--sidebar: oklch(0.205 0 0);
|
|
116
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
117
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
118
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
119
|
+
--sidebar-accent: oklch(0.269 0 0);
|
|
120
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
121
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
122
|
+
--sidebar-ring: oklch(0.556 0 0);
|
|
77
123
|
}
|
|
78
124
|
|
|
79
|
-
@
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
--color-chart-3: var(--chart-3);
|
|
91
|
-
--color-chart-2: var(--chart-2);
|
|
92
|
-
--color-chart-1: var(--chart-1);
|
|
93
|
-
--color-ring: var(--ring);
|
|
94
|
-
--color-input: var(--input);
|
|
95
|
-
--color-border: var(--border);
|
|
96
|
-
--color-destructive: var(--destructive);
|
|
97
|
-
--color-accent-foreground: var(--accent-foreground);
|
|
98
|
-
--color-accent: var(--accent);
|
|
99
|
-
--color-muted-foreground: var(--muted-foreground);
|
|
100
|
-
--color-muted: var(--muted);
|
|
101
|
-
--color-secondary-foreground: var(--secondary-foreground);
|
|
102
|
-
--color-secondary: var(--secondary);
|
|
103
|
-
--color-primary-foreground: var(--primary-foreground);
|
|
104
|
-
--color-primary: var(--primary);
|
|
105
|
-
--color-popover-foreground: var(--popover-foreground);
|
|
106
|
-
--color-popover: var(--popover);
|
|
107
|
-
--color-card-foreground: var(--card-foreground);
|
|
108
|
-
--color-card: var(--card);
|
|
109
|
-
--color-foreground: var(--foreground);
|
|
110
|
-
--color-background: var(--background);
|
|
111
|
-
--radius-sm: calc(var(--radius) * 0.6);
|
|
112
|
-
--radius-md: calc(var(--radius) * 0.8);
|
|
113
|
-
--radius-lg: var(--radius);
|
|
114
|
-
--radius-xl: calc(var(--radius) * 1.4);
|
|
115
|
-
--radius-2xl: calc(var(--radius) * 1.8);
|
|
116
|
-
--radius-3xl: calc(var(--radius) * 2.2);
|
|
117
|
-
--radius-4xl: calc(var(--radius) * 2.6);
|
|
118
|
-
}
|
|
125
|
+
@layer base {
|
|
126
|
+
* {
|
|
127
|
+
@apply border-border outline-ring/50;
|
|
128
|
+
}
|
|
129
|
+
body {
|
|
130
|
+
@apply bg-background text-foreground;
|
|
131
|
+
}
|
|
132
|
+
html {
|
|
133
|
+
@apply font-sans;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
|
-
import { ChevronDownIcon } from "lucide-react"
|
|
3
2
|
import { Accordion as AccordionPrimitive } from "radix-ui"
|
|
4
3
|
|
|
5
4
|
import { cn } from "@/lib/utils"
|
|
5
|
+
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
|
6
6
|
|
|
7
7
|
function Accordion({
|
|
8
|
+
className,
|
|
8
9
|
...props
|
|
9
10
|
}: React.ComponentProps<typeof AccordionPrimitive.Root>) {
|
|
10
|
-
return
|
|
11
|
+
return (
|
|
12
|
+
<AccordionPrimitive.Root
|
|
13
|
+
data-slot="accordion"
|
|
14
|
+
className={cn("flex w-full flex-col", className)}
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
)
|
|
11
18
|
}
|
|
12
19
|
|
|
13
20
|
function AccordionItem({
|
|
@@ -17,7 +24,7 @@ function AccordionItem({
|
|
|
17
24
|
return (
|
|
18
25
|
<AccordionPrimitive.Item
|
|
19
26
|
data-slot="accordion-item"
|
|
20
|
-
className={cn("
|
|
27
|
+
className={cn("not-last:border-b", className)}
|
|
21
28
|
{...props}
|
|
22
29
|
/>
|
|
23
30
|
)
|
|
@@ -33,13 +40,14 @@ function AccordionTrigger({
|
|
|
33
40
|
<AccordionPrimitive.Trigger
|
|
34
41
|
data-slot="accordion-trigger"
|
|
35
42
|
className={cn(
|
|
36
|
-
"flex flex-1 items-start justify-between
|
|
43
|
+
"group/accordion-trigger relative flex flex-1 items-start justify-between rounded-lg border border-transparent py-2.5 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:after:border-ring disabled:pointer-events-none disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground",
|
|
37
44
|
className
|
|
38
45
|
)}
|
|
39
46
|
{...props}
|
|
40
47
|
>
|
|
41
48
|
{children}
|
|
42
|
-
<ChevronDownIcon className="pointer-events-none
|
|
49
|
+
<ChevronDownIcon data-slot="accordion-trigger-icon" className="pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden" />
|
|
50
|
+
<ChevronUpIcon data-slot="accordion-trigger-icon" className="pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline" />
|
|
43
51
|
</AccordionPrimitive.Trigger>
|
|
44
52
|
</AccordionPrimitive.Header>
|
|
45
53
|
)
|
|
@@ -53,10 +61,17 @@ function AccordionContent({
|
|
|
53
61
|
return (
|
|
54
62
|
<AccordionPrimitive.Content
|
|
55
63
|
data-slot="accordion-content"
|
|
56
|
-
className="overflow-hidden text-sm data-
|
|
64
|
+
className="overflow-hidden text-sm data-open:animate-accordion-down data-closed:animate-accordion-up"
|
|
57
65
|
{...props}
|
|
58
66
|
>
|
|
59
|
-
<div
|
|
67
|
+
<div
|
|
68
|
+
className={cn(
|
|
69
|
+
"h-(--radix-accordion-content-height) pt-0 pb-2.5 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
|
|
70
|
+
className
|
|
71
|
+
)}
|
|
72
|
+
>
|
|
73
|
+
{children}
|
|
74
|
+
</div>
|
|
60
75
|
</AccordionPrimitive.Content>
|
|
61
76
|
)
|
|
62
77
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
1
|
import * as React from "react"
|
|
4
2
|
import { AlertDialog as AlertDialogPrimitive } from "radix-ui"
|
|
5
3
|
|
|
@@ -36,7 +34,7 @@ function AlertDialogOverlay({
|
|
|
36
34
|
<AlertDialogPrimitive.Overlay
|
|
37
35
|
data-slot="alert-dialog-overlay"
|
|
38
36
|
className={cn(
|
|
39
|
-
"fixed inset-0 z-50 bg-black/
|
|
37
|
+
"fixed inset-0 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",
|
|
40
38
|
className
|
|
41
39
|
)}
|
|
42
40
|
{...props}
|
|
@@ -58,7 +56,7 @@ function AlertDialogContent({
|
|
|
58
56
|
data-slot="alert-dialog-content"
|
|
59
57
|
data-size={size}
|
|
60
58
|
className={cn(
|
|
61
|
-
"group/alert-dialog-content fixed top-
|
|
59
|
+
"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",
|
|
62
60
|
className
|
|
63
61
|
)}
|
|
64
62
|
{...props}
|
|
@@ -75,7 +73,7 @@ function AlertDialogHeader({
|
|
|
75
73
|
<div
|
|
76
74
|
data-slot="alert-dialog-header"
|
|
77
75
|
className={cn(
|
|
78
|
-
"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-
|
|
76
|
+
"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]",
|
|
79
77
|
className
|
|
80
78
|
)}
|
|
81
79
|
{...props}
|
|
@@ -91,7 +89,7 @@ function AlertDialogFooter({
|
|
|
91
89
|
<div
|
|
92
90
|
data-slot="alert-dialog-footer"
|
|
93
91
|
className={cn(
|
|
94
|
-
"flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
|
|
92
|
+
"-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",
|
|
95
93
|
className
|
|
96
94
|
)}
|
|
97
95
|
{...props}
|
|
@@ -99,15 +97,15 @@ function AlertDialogFooter({
|
|
|
99
97
|
)
|
|
100
98
|
}
|
|
101
99
|
|
|
102
|
-
function
|
|
100
|
+
function AlertDialogMedia({
|
|
103
101
|
className,
|
|
104
102
|
...props
|
|
105
|
-
}: React.ComponentProps<
|
|
103
|
+
}: React.ComponentProps<"div">) {
|
|
106
104
|
return (
|
|
107
|
-
<
|
|
108
|
-
data-slot="alert-dialog-
|
|
105
|
+
<div
|
|
106
|
+
data-slot="alert-dialog-media"
|
|
109
107
|
className={cn(
|
|
110
|
-
"
|
|
108
|
+
"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",
|
|
111
109
|
className
|
|
112
110
|
)}
|
|
113
111
|
{...props}
|
|
@@ -115,28 +113,31 @@ function AlertDialogTitle({
|
|
|
115
113
|
)
|
|
116
114
|
}
|
|
117
115
|
|
|
118
|
-
function
|
|
116
|
+
function AlertDialogTitle({
|
|
119
117
|
className,
|
|
120
118
|
...props
|
|
121
|
-
}: React.ComponentProps<typeof AlertDialogPrimitive.
|
|
119
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
|
|
122
120
|
return (
|
|
123
|
-
<AlertDialogPrimitive.
|
|
124
|
-
data-slot="alert-dialog-
|
|
125
|
-
className={cn(
|
|
121
|
+
<AlertDialogPrimitive.Title
|
|
122
|
+
data-slot="alert-dialog-title"
|
|
123
|
+
className={cn(
|
|
124
|
+
"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",
|
|
125
|
+
className
|
|
126
|
+
)}
|
|
126
127
|
{...props}
|
|
127
128
|
/>
|
|
128
129
|
)
|
|
129
130
|
}
|
|
130
131
|
|
|
131
|
-
function
|
|
132
|
+
function AlertDialogDescription({
|
|
132
133
|
className,
|
|
133
134
|
...props
|
|
134
|
-
}: React.ComponentProps<
|
|
135
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
|
|
135
136
|
return (
|
|
136
|
-
<
|
|
137
|
-
data-slot="alert-dialog-
|
|
137
|
+
<AlertDialogPrimitive.Description
|
|
138
|
+
data-slot="alert-dialog-description"
|
|
138
139
|
className={cn(
|
|
139
|
-
"
|
|
140
|
+
"text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
|
|
140
141
|
className
|
|
141
142
|
)}
|
|
142
143
|
{...props}
|
package/template/ui/alert.tsx
CHANGED
|
@@ -4,13 +4,13 @@ import { cva, type VariantProps } from "class-variance-authority"
|
|
|
4
4
|
import { cn } from "@/lib/utils"
|
|
5
5
|
|
|
6
6
|
const alertVariants = cva(
|
|
7
|
-
"relative grid w-full
|
|
7
|
+
"group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4",
|
|
8
8
|
{
|
|
9
9
|
variants: {
|
|
10
10
|
variant: {
|
|
11
11
|
default: "bg-card text-card-foreground",
|
|
12
12
|
destructive:
|
|
13
|
-
"bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 [
|
|
13
|
+
"bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current",
|
|
14
14
|
},
|
|
15
15
|
},
|
|
16
16
|
defaultVariants: {
|
|
@@ -39,7 +39,7 @@ function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
|
39
39
|
<div
|
|
40
40
|
data-slot="alert-title"
|
|
41
41
|
className={cn(
|
|
42
|
-
"col-start-2
|
|
42
|
+
"font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground",
|
|
43
43
|
className
|
|
44
44
|
)}
|
|
45
45
|
{...props}
|
|
@@ -55,7 +55,7 @@ function AlertDescription({
|
|
|
55
55
|
<div
|
|
56
56
|
data-slot="alert-description"
|
|
57
57
|
className={cn(
|
|
58
|
-
"
|
|
58
|
+
"text-sm text-balance text-muted-foreground md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
|
|
59
59
|
className
|
|
60
60
|
)}
|
|
61
61
|
{...props}
|
|
@@ -63,4 +63,14 @@ function AlertDescription({
|
|
|
63
63
|
)
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
67
|
+
return (
|
|
68
|
+
<div
|
|
69
|
+
data-slot="alert-action"
|
|
70
|
+
className={cn("absolute top-2 right-2", className)}
|
|
71
|
+
{...props}
|
|
72
|
+
/>
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { Alert, AlertTitle, AlertDescription, AlertAction }
|