@proofkit/cli 1.2.0-beta.2 → 2.0.0-beta.12

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.
Files changed (30) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/index.js +108 -98
  3. package/dist/index.js.map +1 -1
  4. package/package.json +46 -48
  5. package/template/extras/emailTemplates/auth-code.tsx +7 -26
  6. package/template/extras/emailTemplates/generic.tsx +8 -31
  7. package/template/extras/fmaddon-auth/emails/auth-code.tsx +7 -26
  8. package/template/extras/src/app/api/auth/[...nextauth]/route.ts +1 -1
  9. package/template/extras/src/server/next-auth/base.ts +3 -3
  10. package/template/nextjs-mantine/package.json +5 -4
  11. package/template/nextjs-shadcn/biome.json +18 -13
  12. package/template/nextjs-shadcn/next-env.d.ts +6 -0
  13. package/template/nextjs-shadcn/package.json +9 -7
  14. package/template/nextjs-shadcn/proofkit.json +1 -1
  15. package/template/nextjs-shadcn/src/components/mode-toggle.tsx +39 -0
  16. package/template/nextjs-shadcn/src/components/ui/button.tsx +61 -0
  17. package/template/nextjs-shadcn/src/components/ui/dropdown-menu.tsx +267 -0
  18. package/template/nextjs-shadcn/src/components/ui/sonner.tsx +31 -0
  19. package/template/pages/nextjs/table-infinite/actions.ts +1 -1
  20. package/template/pages/nextjs/table-infinite-edit/actions.ts +1 -1
  21. package/template/vite-wv/package.json +5 -2
  22. package/template/vite-wv/src/routeTree.gen.ts +1 -1
  23. package/template/vite-wv/src/routes/index.tsx +8 -20
  24. package/template/vite-wv/src/routes/secondary.tsx +4 -6
  25. package/template/extras/config/_eslint.js +0 -27
  26. package/template/extras/config/_prettier.config.js +0 -6
  27. package/template/nextjs-mantine/.prettierrc +0 -3
  28. package/template/nextjs-shadcn/.prettierrc +0 -3
  29. package/template/vite-wv/.prettierrc +0 -3
  30. /package/dist/{index.d.ts → index-BitR4XBZ.d.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proofkit/cli",
3
- "version": "1.2.0-beta.2",
3
+ "version": "2.0.0-beta.12",
4
4
  "description": "Create web application with the ProofKit stack",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -40,74 +40,74 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@better-fetch/fetch": "1.1.17",
43
- "@clack/core": "^0.3.4",
43
+ "@clack/core": "^0.3.5",
44
44
  "@clack/prompts": "^0.11.0",
45
- "@ianvs/prettier-plugin-sort-imports": "^4.4.1",
46
45
  "@types/glob": "^8.1.0",
47
- "axios": "^1.7.3",
46
+ "axios": "^1.13.2",
48
47
  "chalk": "5.4.1",
49
- "commander": "^14.0.0",
50
- "dotenv": "^16.5.0",
51
- "es-toolkit": "^1.15.1",
52
- "execa": "^9.5.1",
48
+ "commander": "^14.0.2",
49
+ "dotenv": "^16.6.1",
50
+ "es-toolkit": "^1.43.0",
51
+ "execa": "^9.6.1",
53
52
  "fast-glob": "^3.3.3",
54
- "fs-extra": "^11.3.0",
55
- "glob": "^11.0.1",
53
+ "fs-extra": "^11.3.3",
54
+ "glob": "^11.1.0",
56
55
  "gradient-string": "^2.0.2",
57
56
  "handlebars": "^4.7.8",
58
57
  "jiti": "^1.21.7",
59
58
  "jsonc-parser": "^3.3.1",
60
- "open": "^10.1.0",
59
+ "open": "^10.2.0",
61
60
  "ora": "6.3.1",
62
- "prettier": "^3.5.3",
63
- "prettier-plugin-tailwindcss": "^0.6.5",
64
- "randomstring": "^1.3.0",
65
- "semver": "^7.7.2",
61
+ "randomstring": "^1.3.1",
62
+ "semver": "^7.7.3",
66
63
  "shadcn": "^2.10.0",
67
- "sort-package-json": "^2.10.0",
64
+ "sort-package-json": "^2.15.1",
68
65
  "ts-morph": "^26.0.0",
69
- "@proofkit/typegen": "1.0.11-beta.0",
70
- "@proofkit/fmdapi": "5.0.3-beta.0"
66
+ "@proofkit/fmdapi": "5.0.3-beta.1",
67
+ "@proofkit/typegen": "1.1.0-beta.7"
71
68
  },
72
69
  "devDependencies": {
73
- "@auth/drizzle-adapter": "^1.1.0",
70
+ "@auth/drizzle-adapter": "^1.11.1",
74
71
  "@auth/prisma-adapter": "^1.6.0",
75
- "@libsql/client": "^0.6.0",
76
- "@planetscale/database": "^1.18.0",
77
- "@prisma/adapter-planetscale": "^5.14.0",
78
- "@prisma/client": "^5.14.0",
72
+ "@biomejs/biome": "2.3.11",
73
+ "@libsql/client": "^0.6.2",
74
+ "@planetscale/database": "^1.19.0",
75
+ "@prisma/adapter-planetscale": "^5.22.0",
76
+ "@prisma/client": "^5.22.0",
77
+ "@rollup/plugin-replace": "^6.0.3",
79
78
  "@t3-oss/env-nextjs": "^0.10.1",
80
- "@tanstack/react-query": "^5.49.2",
79
+ "@tanstack/react-query": "^5.90.16",
81
80
  "@trpc/client": "11.0.0-rc.441",
82
81
  "@trpc/next": "11.0.0-rc.441",
83
82
  "@trpc/react-query": "11.0.0-rc.441",
84
83
  "@trpc/server": "11.0.0-rc.441",
85
- "@types/axios": "^0.14.0",
84
+ "@types/axios": "^0.14.4",
86
85
  "@types/fs-extra": "^11.0.4",
87
86
  "@types/gradient-string": "^1.1.6",
88
- "@types/node": "^22.17.1",
87
+ "@types/node": "^22.19.5",
89
88
  "@types/randomstring": "^1.3.0",
90
- "@types/react": "^19.1.10",
91
- "@types/semver": "^7.7.0",
92
- "@vitest/coverage-v8": "^1.4.0",
89
+ "@types/react": "19.2.7",
90
+ "@types/semver": "^7.7.1",
91
+ "@vitest/coverage-v8": "^2.1.9",
93
92
  "drizzle-kit": "^0.21.4",
94
93
  "drizzle-orm": "^0.30.10",
95
- "mysql2": "^3.9.7",
96
- "next": "^15.4.6",
97
- "next-auth": "^4.24.7",
98
- "postgres": "^3.4.4",
99
- "prisma": "^5.14.0",
100
- "publint": "^0.3.12",
101
- "react": "^19.1.1",
102
- "react-dom": "^19.1.1",
103
- "superjson": "^2.2.1",
104
- "tailwindcss": "^4.1.11",
105
- "tsdown": "^0.14.1",
94
+ "mysql2": "^3.16.0",
95
+ "next": "16.1.1",
96
+ "next-auth": "^4.24.13",
97
+ "postgres": "^3.4.8",
98
+ "prisma": "^5.22.0",
99
+ "publint": "^0.3.16",
100
+ "react": "19.2.3",
101
+ "react-dom": "19.2.3",
102
+ "superjson": "^2.2.6",
103
+ "tailwindcss": "^4.1.18",
104
+ "tsdown": "^0.14.2",
106
105
  "type-fest": "^3.13.1",
107
- "typescript": "^5.9.2",
108
- "vitest": "^3.2.4",
109
- "zod": "3.25.64",
110
- "@proofkit/registry": "1.0.0"
106
+ "typescript": "^5.9.3",
107
+ "ultracite": "7.0.8",
108
+ "vitest": "^4.0.17",
109
+ "zod": "^4.3.5",
110
+ "@proofkit/registry": "1.0.1-beta.0"
111
111
  },
112
112
  "scripts": {
113
113
  "typecheck": "tsc",
@@ -115,10 +115,8 @@
115
115
  "dev": "tsdown --watch",
116
116
  "clean": "rm -rf dist .turbo node_modules",
117
117
  "start": "node dist/index.js",
118
- "lint": "eslint . --ext .ts,.tsx",
119
- "lint:fix": "pnpm lint --fix",
120
- "format": "prettier '**/*.{cjs,mjs,ts,tsx,md,json}' --ignore-path ../.gitignore --ignore-unknown --no-error-on-unmatched-pattern --write",
121
- "format:check": "prettier '**/*.{cjs,mjs,ts,tsx,md,json}' --ignore-path ../.gitignore --ignore-unknown --no-error-on-unmatched-pattern --check",
118
+ "lint": "biome check . --write",
119
+ "lint:summary": "biome check . --reporter=summary",
122
120
  "release": "changeset version",
123
121
  "pub:beta": "NODE_ENV=production pnpm build && npm publish --tag beta --access public",
124
122
  "pub:next": "NODE_ENV=production pnpm build && npm publish --tag next --access public",
@@ -1,14 +1,4 @@
1
- import {
2
- Body,
3
- Container,
4
- Head,
5
- Heading,
6
- Html,
7
- Img,
8
- Section,
9
- Text,
10
- } from "@react-email/components";
11
- import * as React from "react";
1
+ import { Body, Container, Head, Heading, Html, Img, Section, Text } from "@react-email/components";
12
2
 
13
3
  interface AuthCodeEmailProps {
14
4
  validationCode: string;
@@ -22,29 +12,20 @@ export const AuthCodeEmail = ({ validationCode, type }: AuthCodeEmailProps) => (
22
12
  <Container style={container}>
23
13
  <Img
24
14
  // TODO: Replace with your logo
25
- src="https://proofkit.dev/_astro/proofkit.DNcFg0_B_1JN3Dz.webp"
26
- width="238"
27
- height="175"
28
15
  alt="ProofKit"
16
+ height="175"
17
+ src="https://proofkit.dev/_astro/proofkit.DNcFg0_B_1JN3Dz.webp"
29
18
  style={logo}
19
+ width="238"
30
20
  />
31
- <Text style={tertiary}>
32
- {type === "verification"
33
- ? "Verify Your Email"
34
- : "Reset Your Password"}
35
- </Text>
21
+ <Text style={tertiary}>{type === "verification" ? "Verify Your Email" : "Reset Your Password"}</Text>
36
22
  <Heading style={secondary}>
37
- Enter the following code to{" "}
38
- {type === "verification"
39
- ? "verify your email"
40
- : "reset your password"}
23
+ Enter the following code to {type === "verification" ? "verify your email" : "reset your password"}
41
24
  </Heading>
42
25
  <Section style={codeContainer}>
43
26
  <Text style={code}>{validationCode}</Text>
44
27
  </Section>
45
- <Text style={paragraph}>
46
- If you did not request this code, you can ignore this email.
47
- </Text>
28
+ <Text style={paragraph}>If you did not request this code, you can ignore this email.</Text>
48
29
  </Container>
49
30
  </Body>
50
31
  </Html>
@@ -1,16 +1,4 @@
1
- import {
2
- Body,
3
- Button,
4
- Container,
5
- Head,
6
- Heading,
7
- Hr,
8
- Html,
9
- Img,
10
- Section,
11
- Text,
12
- } from "@react-email/components";
13
- import * as React from "react";
1
+ import { Body, Button, Container, Head, Heading, Hr, Html, Img, Section, Text } from "@react-email/components";
14
2
 
15
3
  export interface GenericEmailProps {
16
4
  title?: string;
@@ -20,30 +8,22 @@ export interface GenericEmailProps {
20
8
  footer?: string;
21
9
  }
22
10
 
23
- export const GenericEmail = ({
24
- title,
25
- description,
26
- ctaText,
27
- ctaHref,
28
- footer,
29
- }: GenericEmailProps) => (
11
+ export const GenericEmail = ({ title, description, ctaText, ctaHref, footer }: GenericEmailProps) => (
30
12
  <Html>
31
13
  <Head />
32
14
  <Body style={styles.main}>
33
15
  <Container style={styles.container}>
34
16
  <Img
35
- src="https://proofkit.dev/_astro/proofkit.DNcFg0_B_1JN3Dz.webp"
36
- width="238"
37
- height="175"
38
17
  alt="ProofKit"
18
+ height="175"
19
+ src="https://proofkit.dev/_astro/proofkit.DNcFg0_B_1JN3Dz.webp"
39
20
  style={styles.logo}
21
+ width="238"
40
22
  />
41
23
 
42
24
  {title ? <Heading style={styles.title}>{title}</Heading> : null}
43
25
 
44
- {description ? (
45
- <Text style={styles.description}>{description}</Text>
46
- ) : null}
26
+ {description ? <Text style={styles.description}>{description}</Text> : null}
47
27
 
48
28
  {ctaText && ctaHref ? (
49
29
  <Section style={styles.ctaSection}>
@@ -53,9 +33,7 @@ export const GenericEmail = ({
53
33
  </Section>
54
34
  ) : null}
55
35
 
56
- {(title || description || (ctaText && ctaHref)) && (
57
- <Hr style={styles.hr} />
58
- )}
36
+ {(title || description || (ctaText && ctaHref)) && <Hr style={styles.hr} />}
59
37
 
60
38
  {footer ? <Text style={styles.footer}>{footer}</Text> : null}
61
39
  </Container>
@@ -65,8 +43,7 @@ export const GenericEmail = ({
65
43
 
66
44
  GenericEmail.PreviewProps = {
67
45
  title: "Welcome to ProofKit",
68
- description:
69
- "Thanks for trying ProofKit. This is a sample email template you can customize.",
46
+ description: "Thanks for trying ProofKit. This is a sample email template you can customize.",
70
47
  ctaText: "Get Started",
71
48
  ctaHref: "https://proofkit.dev",
72
49
  footer: "You received this email because you signed up for updates.",
@@ -1,14 +1,4 @@
1
- import {
2
- Body,
3
- Container,
4
- Head,
5
- Heading,
6
- Html,
7
- Img,
8
- Section,
9
- Text,
10
- } from "@react-email/components";
11
- import * as React from "react";
1
+ import { Body, Container, Head, Heading, Html, Img, Section, Text } from "@react-email/components";
12
2
 
13
3
  interface AuthCodeEmailProps {
14
4
  validationCode: string;
@@ -22,29 +12,20 @@ export const AuthCodeEmail = ({ validationCode, type }: AuthCodeEmailProps) => (
22
12
  <Container style={container}>
23
13
  <Img
24
14
  // TODO: Replace with your logo
25
- src="https://proofkit.dev/_astro/proofkit.DNcFg0_B_1JN3Dz.webp"
26
- width="238"
27
- height="175"
28
15
  alt="ProofKit"
16
+ height="175"
17
+ src="https://proofkit.dev/_astro/proofkit.DNcFg0_B_1JN3Dz.webp"
29
18
  style={logo}
19
+ width="238"
30
20
  />
31
- <Text style={tertiary}>
32
- {type === "verification"
33
- ? "Verify Your Email"
34
- : "Reset Your Password"}
35
- </Text>
21
+ <Text style={tertiary}>{type === "verification" ? "Verify Your Email" : "Reset Your Password"}</Text>
36
22
  <Heading style={secondary}>
37
- Enter the following code to{" "}
38
- {type === "verification"
39
- ? "verify your email"
40
- : "reset your password"}
23
+ Enter the following code to {type === "verification" ? "verify your email" : "reset your password"}
41
24
  </Heading>
42
25
  <Section style={codeContainer}>
43
26
  <Text style={code}>{validationCode}</Text>
44
27
  </Section>
45
- <Text style={paragraph}>
46
- If you did not request this code, you can ignore this email.
47
- </Text>
28
+ <Text style={paragraph}>If you did not request this code, you can ignore this email.</Text>
48
29
  </Container>
49
30
  </Body>
50
31
  </Html>
@@ -1,4 +1,4 @@
1
1
  import { handlers } from "@/server/auth"; // Referring to the auth.ts we just created
2
2
 
3
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
3
+
4
4
  export const { GET, POST } = handlers;
@@ -1,6 +1,6 @@
1
- /* eslint-disable @typescript-eslint/no-unsafe-call */
2
- /* eslint-disable @typescript-eslint/no-unsafe-member-access */
3
- /* eslint-disable @typescript-eslint/no-unsafe-assignment */
1
+
2
+
3
+
4
4
 
5
5
  import { env } from "@/config/env";
6
6
  import { OttoAdapter } from "@proofkit/fmdapi";
@@ -6,7 +6,8 @@
6
6
  "dev": "next dev --turbopack",
7
7
  "build": "next build",
8
8
  "start": "next start",
9
- "lint": "next lint",
9
+ "lint": "biome check",
10
+ "format": "biome format --write",
10
11
  "proofkit": "proofkit",
11
12
  "typegen": "proofkit typegen",
12
13
  "deploy": "proofkit deploy"
@@ -25,7 +26,7 @@
25
26
  "mantine-react-table": "2.0.0-beta.9",
26
27
  "@t3-oss/env-nextjs": "^0.12.0",
27
28
  "dayjs": "^1.11.13",
28
- "next": "^15.2.3",
29
+ "next": "^15.2.7",
29
30
  "react": "19.0.0",
30
31
  "react-dom": "19.0.0",
31
32
  "zod": "^3.24.2"
@@ -34,9 +35,9 @@
34
35
  "@types/node": "^20",
35
36
  "@types/react": "npm:types-react@19.0.12",
36
37
  "@types/react-dom": "npm:types-react-dom@19.0.4",
37
- "eslint": "^9.14.0",
38
- "eslint-config-next": "15.2.3",
38
+ "@biomejs/biome": "2.3.11",
39
39
  "postcss": "^8.4.41",
40
+ "ultracite": "7.0.8",
40
41
  "postcss-preset-mantine": "^1.17.0",
41
42
  "postcss-simple-vars": "^7.0.1",
42
43
  "typescript": "^5"
@@ -1,5 +1,6 @@
1
1
  {
2
- "$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
2
+ "root": false,
3
+ "$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
3
4
  "vcs": {
4
5
  "enabled": true,
5
6
  "clientKind": "git",
@@ -7,13 +8,7 @@
7
8
  },
8
9
  "files": {
9
10
  "ignoreUnknown": true,
10
- "includes": [
11
- "**",
12
- "!node_modules",
13
- "!.next",
14
- "!dist",
15
- "!build"
16
- ]
11
+ "includes": ["**", "!node_modules", "!.next", "!dist", "!build"]
17
12
  },
18
13
  "formatter": {
19
14
  "enabled": true,
@@ -23,7 +18,19 @@
23
18
  "linter": {
24
19
  "enabled": true,
25
20
  "rules": {
26
- "recommended": true
21
+ "recommended": true,
22
+ "style": {
23
+ "noParameterAssign": "error",
24
+ "useAsConstAssertion": "error",
25
+ "useDefaultParameterLast": "error",
26
+ "useEnumInitializers": "error",
27
+ "useSelfClosingElements": "error",
28
+ "useSingleVarDeclarator": "error",
29
+ "noUnusedTemplateLiteral": "error",
30
+ "useNumberNamespace": "error",
31
+ "noInferrableTypes": "error",
32
+ "noUselessElse": "error"
33
+ }
27
34
  },
28
35
  "domains": {
29
36
  "next": "recommended",
@@ -37,7 +44,5 @@
37
44
  }
38
45
  }
39
46
  },
40
- "extends": [
41
- "ultracite"
42
- ]
43
- }
47
+ "extends": ["ultracite"]
48
+ }
@@ -0,0 +1,6 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+ /// <reference path="./.next/types/routes.d.ts" />
4
+
5
+ // NOTE: This file should not be edited
6
+ // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -11,18 +11,21 @@
11
11
  "format": "biome format --write"
12
12
  },
13
13
  "dependencies": {
14
+ "@radix-ui/react-slot": "^1.2.3",
14
15
  "@t3-oss/env-nextjs": "^0.13.8",
15
16
  "class-variance-authority": "^0.7.1",
16
17
  "clsx": "^2.1.1",
17
18
  "lucide-react": "^0.541.0",
18
- "next": "15.5.0",
19
+ "next": "^15.5.8",
19
20
  "next-themes": "^0.4.6",
20
- "react": "19.1.0",
21
- "react-dom": "19.1.0",
21
+ "radix-ui": "^1.4.2",
22
+ "react": "19.1.1",
23
+ "react-dom": "19.1.1",
24
+ "sonner": "^2.0.4",
22
25
  "tailwind-merge": "^3.3.1"
23
26
  },
24
27
  "devDependencies": {
25
- "@biomejs/biome": "2.2.0",
28
+ "@biomejs/biome": "2.3.11",
26
29
  "@tailwindcss/postcss": "^4",
27
30
  "@types/node": "^22",
28
31
  "@types/react": "^19",
@@ -30,7 +33,6 @@
30
33
  "tailwindcss": "^4",
31
34
  "tw-animate-css": "^1.3.7",
32
35
  "typescript": "^5",
33
- "ultracite": "5.2.4"
34
- },
35
- "packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748"
36
+ "ultracite": "5.4.5"
37
+ }
36
38
  }
@@ -2,5 +2,5 @@
2
2
  "ui": "shadcn",
3
3
  "envFile": ".env",
4
4
  "appType": "browser",
5
- "registryTemplates": ["utils/t3-env", "components/mode-toggle"]
5
+ "registryTemplates": ["utils/t3-env"]
6
6
  }
@@ -0,0 +1,39 @@
1
+ "use client";
2
+
3
+ import { Moon, Sun } from "lucide-react";
4
+ import { useTheme } from "next-themes";
5
+
6
+ import { Button } from "@/components/ui/button";
7
+ import {
8
+ DropdownMenu,
9
+ DropdownMenuContent,
10
+ DropdownMenuItem,
11
+ DropdownMenuTrigger,
12
+ } from "@/components/ui/dropdown-menu";
13
+
14
+ export function ModeToggle() {
15
+ const { setTheme } = useTheme();
16
+
17
+ return (
18
+ <DropdownMenu>
19
+ <DropdownMenuTrigger asChild>
20
+ <Button size="icon" variant="outline">
21
+ <Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
22
+ <Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
23
+ <span className="sr-only">Toggle theme</span>
24
+ </Button>
25
+ </DropdownMenuTrigger>
26
+ <DropdownMenuContent align="end">
27
+ <DropdownMenuItem onClick={() => setTheme("light")}>
28
+ Light
29
+ </DropdownMenuItem>
30
+ <DropdownMenuItem onClick={() => setTheme("dark")}>
31
+ Dark
32
+ </DropdownMenuItem>
33
+ <DropdownMenuItem onClick={() => setTheme("system")}>
34
+ System
35
+ </DropdownMenuItem>
36
+ </DropdownMenuContent>
37
+ </DropdownMenu>
38
+ );
39
+ }
@@ -0,0 +1,61 @@
1
+ import { Slot } from "@radix-ui/react-slot";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+ import type * as React from "react";
4
+
5
+ import { cn } from "@/lib/utils";
6
+
7
+ const buttonVariants = cva(
8
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default:
13
+ "bg-primary text-primary-foreground shadow hover:bg-primary/90",
14
+ destructive:
15
+ "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
16
+ outline:
17
+ "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
18
+ secondary:
19
+ "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
20
+ ghost: "hover:bg-accent hover:text-accent-foreground",
21
+ link: "text-primary underline-offset-4 hover:underline",
22
+ },
23
+ size: {
24
+ default: "h-9 px-4 py-2",
25
+ sm: "h-8 rounded-md px-3 text-xs",
26
+ lg: "h-10 rounded-md px-8",
27
+ icon: "h-9 w-9",
28
+ },
29
+ },
30
+ defaultVariants: {
31
+ variant: "default",
32
+ size: "default",
33
+ },
34
+ }
35
+ );
36
+
37
+ export interface ButtonProps
38
+ extends React.ButtonHTMLAttributes<HTMLButtonElement>,
39
+ VariantProps<typeof buttonVariants> {
40
+ asChild?: boolean;
41
+ }
42
+
43
+ function Button({
44
+ className,
45
+ variant,
46
+ size,
47
+ asChild = false,
48
+ ref,
49
+ ...props
50
+ }: ButtonProps & { ref?: React.Ref<HTMLButtonElement> }) {
51
+ const Comp = asChild ? Slot : "button";
52
+ return (
53
+ <Comp
54
+ className={cn(buttonVariants({ variant, size, className }))}
55
+ ref={ref}
56
+ {...props}
57
+ />
58
+ );
59
+ }
60
+
61
+ export { Button, buttonVariants };