@presencenet/create-pnet-stack 0.2.3 → 0.4.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.
Files changed (56) hide show
  1. package/bin/create-pnet-stack.js +79 -8
  2. package/package.json +1 -1
  3. package/templates/electron/apps/app/components.json +23 -0
  4. package/templates/electron/apps/app/package.json +7 -0
  5. package/templates/electron/apps/app/src/preload/index.ts +3 -1
  6. package/templates/electron/apps/app/src/renderer/index.html +1 -1
  7. package/templates/electron/apps/app/src/renderer/src/components/ui/button.tsx +63 -0
  8. package/templates/electron/apps/app/src/renderer/src/components/ui/card.tsx +91 -0
  9. package/templates/electron/apps/app/src/renderer/src/lib/utils.ts +1 -0
  10. package/templates/electron/apps/app/src/renderer/src/main.tsx +31 -8
  11. package/templates/electron/apps/app/src/renderer/src/style.css +120 -4
  12. package/templates/electron/apps/app/tsconfig.json +16 -0
  13. package/templates/electron/biome.json +26 -3
  14. package/templates/electron/gitignore +1 -0
  15. package/templates/electron/package.json +0 -1
  16. package/templates/mobile/apps/app/app/_layout.tsx +10 -9
  17. package/templates/mobile/apps/app/app/index.tsx +37 -11
  18. package/templates/mobile/apps/app/app.json +4 -1
  19. package/templates/mobile/apps/app/components/ui/button.tsx +123 -0
  20. package/templates/mobile/apps/app/components/ui/card.tsx +85 -0
  21. package/templates/mobile/apps/app/components/ui/text.tsx +95 -0
  22. package/templates/mobile/apps/app/components.json +19 -0
  23. package/templates/mobile/apps/app/css.d.ts +1 -0
  24. package/templates/mobile/apps/app/global.css +55 -0
  25. package/templates/mobile/apps/app/lib/theme.ts +85 -0
  26. package/templates/mobile/apps/app/lib/utils.ts +6 -0
  27. package/templates/mobile/apps/app/metro.config.js +1 -0
  28. package/templates/mobile/apps/app/package.json +11 -2
  29. package/templates/mobile/apps/app/tailwind.config.js +69 -3
  30. package/templates/mobile/biome.json +26 -3
  31. package/templates/mobile/package.json +0 -1
  32. package/templates/tauri/apps/app/components.json +23 -0
  33. package/templates/tauri/apps/app/index.html +1 -1
  34. package/templates/tauri/apps/app/package.json +8 -1
  35. package/templates/tauri/apps/app/src/components/ui/button.tsx +63 -0
  36. package/templates/tauri/apps/app/src/components/ui/card.tsx +91 -0
  37. package/templates/tauri/apps/app/src/lib/utils.ts +1 -0
  38. package/templates/tauri/apps/app/src/main.tsx +31 -8
  39. package/templates/tauri/apps/app/src/style.css +120 -4
  40. package/templates/tauri/apps/app/src-tauri/tauri.conf.json +7 -1
  41. package/templates/tauri/apps/app/tsconfig.json +6 -2
  42. package/templates/tauri/apps/app/vite.config.ts +4 -0
  43. package/templates/tauri/biome.json +26 -3
  44. package/templates/tauri/package.json +0 -1
  45. package/templates/web/apps/app/components.json +23 -0
  46. package/templates/web/apps/app/package.json +7 -0
  47. package/templates/web/apps/app/src/components/ui/button.tsx +63 -0
  48. package/templates/web/apps/app/src/components/ui/card.tsx +91 -0
  49. package/templates/web/apps/app/src/lib/utils.ts +1 -0
  50. package/templates/web/apps/app/src/routes/__root.tsx +7 -3
  51. package/templates/web/apps/app/src/routes/index.tsx +31 -8
  52. package/templates/web/apps/app/src/styles.css +123 -0
  53. package/templates/web/apps/app/tsconfig.json +4 -1
  54. package/templates/web/apps/app/vite.config.ts +4 -0
  55. package/templates/web/biome.json +29 -3
  56. package/templates/web/package.json +0 -1
@@ -1,7 +1,16 @@
1
1
  {
2
2
  "root": false,
3
3
  "$schema": "https://biomejs.dev/schemas/2.6.5/schema.json",
4
- "formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2 },
4
+ "vcs": {
5
+ "enabled": true,
6
+ "clientKind": "git",
7
+ "useIgnoreFile": true
8
+ },
9
+ "formatter": {
10
+ "enabled": true,
11
+ "indentStyle": "space",
12
+ "indentWidth": 2
13
+ },
5
14
  "linter": {
6
15
  "enabled": true,
7
16
  "rules": {
@@ -9,10 +18,24 @@
9
18
  "suspicious": {
10
19
  "noUnknownAtRules": {
11
20
  "level": "on",
12
- "options": { "ignore": ["tailwind"] }
21
+ "options": {
22
+ "ignore": ["tailwind"]
23
+ }
24
+ }
25
+ },
26
+ "correctness": {
27
+ "noReactNativeRawText": {
28
+ "level": "on",
29
+ "options": {
30
+ "skip": ["CardTitle", "CardDescription"]
31
+ }
13
32
  }
14
33
  }
15
34
  }
16
35
  },
17
- "javascript": { "formatter": { "quoteStyle": "double" } }
36
+ "javascript": {
37
+ "formatter": {
38
+ "quoteStyle": "double"
39
+ }
40
+ }
18
41
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "name": "{{projectName}}",
3
3
  "private": true,
4
- "packageManager": "bun@1.3.14",
5
4
  "workspaces": [
6
5
  "apps/*",
7
6
  "packages/*"
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "new-york",
4
+ "rsc": false,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "",
8
+ "css": "src/style.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
+ "registries": {}
23
+ }
@@ -1,2 +1,2 @@
1
1
  <!doctype html>
2
- <html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>{{projectName}}</title></head><body><div id="root"></div><script type="module" src="/src/main.tsx"></script></body></html>
2
+ <html lang="en" class="dark"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>{{projectName}}</title></head><body><div id="root"></div><script type="module" src="/src/main.tsx"></script></body></html>
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "@{{projectName}}/app",
3
+ "version": "0.0.0",
3
4
  "private": true,
4
5
  "type": "module",
5
6
  "scripts": {
@@ -12,16 +13,22 @@
12
13
  "dependencies": {
13
14
  "@tailwindcss/vite": "^4.3.4",
14
15
  "@tauri-apps/api": "^2.12.4",
16
+ "class-variance-authority": "^0.7.1",
17
+ "cn": "^0.5.2",
18
+ "lucide-react": "^1.70.0",
19
+ "radix-ui": "^1.8.1",
15
20
  "react": "^19.3.0",
16
21
  "react-dom": "^19.3.0",
17
22
  "tailwindcss": "^4.3.4"
18
23
  },
19
24
  "devDependencies": {
25
+ "@tauri-apps/cli": "^2.12.4",
20
26
  "@types/node": "^26.6.6",
21
27
  "@types/react": "^19.3.0",
22
28
  "@types/react-dom": "^19.3.0",
23
- "@tauri-apps/cli": "^2.12.4",
24
29
  "@vitejs/plugin-react": "^6.2.1",
30
+ "shadcn": "^4.23.0",
31
+ "tw-animate-css": "^1.4.0",
25
32
  "typescript": "^6.0.3",
26
33
  "vite": "^8.3.5"
27
34
  }
@@ -0,0 +1,63 @@
1
+ import { cva, type VariantProps } from "class-variance-authority";
2
+ import { cn } from "cn";
3
+ import { Slot } from "radix-ui";
4
+ import type * as React from "react";
5
+
6
+ const buttonVariants = cva(
7
+ "inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
12
+ destructive:
13
+ "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
14
+ outline:
15
+ "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
16
+ secondary:
17
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
18
+ ghost:
19
+ "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
20
+ link: "text-primary underline-offset-4 hover:underline",
21
+ },
22
+ size: {
23
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
24
+ xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
25
+ sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
26
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
27
+ icon: "size-9",
28
+ "icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
29
+ "icon-sm": "size-8",
30
+ "icon-lg": "size-10",
31
+ },
32
+ },
33
+ defaultVariants: {
34
+ variant: "default",
35
+ size: "default",
36
+ },
37
+ },
38
+ );
39
+
40
+ function Button({
41
+ className,
42
+ variant = "default",
43
+ size = "default",
44
+ asChild = false,
45
+ ...props
46
+ }: React.ComponentProps<"button"> &
47
+ VariantProps<typeof buttonVariants> & {
48
+ asChild?: boolean;
49
+ }) {
50
+ const Comp = asChild ? Slot.Root : "button";
51
+
52
+ return (
53
+ <Comp
54
+ data-slot="button"
55
+ data-variant={variant}
56
+ data-size={size}
57
+ className={cn(buttonVariants({ variant, size, className }))}
58
+ {...props}
59
+ />
60
+ );
61
+ }
62
+
63
+ export { Button, buttonVariants };
@@ -0,0 +1,91 @@
1
+ import { cn } from "cn";
2
+ import type * as React from "react";
3
+
4
+ function Card({ className, ...props }: React.ComponentProps<"div">) {
5
+ return (
6
+ <div
7
+ data-slot="card"
8
+ className={cn(
9
+ "flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm",
10
+ className,
11
+ )}
12
+ {...props}
13
+ />
14
+ );
15
+ }
16
+
17
+ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
18
+ return (
19
+ <div
20
+ data-slot="card-header"
21
+ className={cn(
22
+ "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
23
+ className,
24
+ )}
25
+ {...props}
26
+ />
27
+ );
28
+ }
29
+
30
+ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
31
+ return (
32
+ <div
33
+ data-slot="card-title"
34
+ className={cn("leading-none font-semibold", className)}
35
+ {...props}
36
+ />
37
+ );
38
+ }
39
+
40
+ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
41
+ return (
42
+ <div
43
+ data-slot="card-description"
44
+ className={cn("text-sm text-muted-foreground", className)}
45
+ {...props}
46
+ />
47
+ );
48
+ }
49
+
50
+ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
51
+ return (
52
+ <div
53
+ data-slot="card-action"
54
+ className={cn(
55
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
56
+ className,
57
+ )}
58
+ {...props}
59
+ />
60
+ );
61
+ }
62
+
63
+ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
64
+ return (
65
+ <div
66
+ data-slot="card-content"
67
+ className={cn("px-6", className)}
68
+ {...props}
69
+ />
70
+ );
71
+ }
72
+
73
+ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
74
+ return (
75
+ <div
76
+ data-slot="card-footer"
77
+ className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
78
+ {...props}
79
+ />
80
+ );
81
+ }
82
+
83
+ export {
84
+ Card,
85
+ CardAction,
86
+ CardContent,
87
+ CardDescription,
88
+ CardFooter,
89
+ CardHeader,
90
+ CardTitle,
91
+ };
@@ -0,0 +1 @@
1
+ export { cn } from "cn";
@@ -1,17 +1,40 @@
1
1
  import React from "react";
2
2
  import { createRoot } from "react-dom/client";
3
+ import { Button } from "@/components/ui/button";
4
+ import {
5
+ Card,
6
+ CardContent,
7
+ CardDescription,
8
+ CardFooter,
9
+ CardHeader,
10
+ CardTitle,
11
+ } from "@/components/ui/card";
3
12
  import "./style.css";
4
13
 
14
+ const app = {
15
+ name: "{{projectName}}",
16
+ };
17
+
5
18
  function App() {
6
19
  return (
7
- <main className="flex min-h-screen flex-col justify-center px-12">
8
- <p className="text-sm font-bold uppercase tracking-widest text-cyan-300">
9
- Presence-Net starter
10
- </p>
11
- <h1 className="mt-3 text-5xl font-bold">{"{{projectName}}"}</h1>
12
- <p className="mt-5 text-lg text-slate-300">
13
- Tauri, React, Tailwind, and a Bun-powered Turborepo workspace.
14
- </p>
20
+ <main className="flex min-h-screen items-center justify-center p-8">
21
+ <Card className="w-full max-w-xl">
22
+ <CardHeader>
23
+ <CardDescription>Presence-Net starter</CardDescription>
24
+ <CardTitle className="text-4xl tracking-tight">{app.name}</CardTitle>
25
+ </CardHeader>
26
+ <CardContent className="text-muted-foreground">
27
+ Tauri, React, Tailwind, shadcn/ui, and a Bun-powered Turborepo
28
+ workspace.
29
+ </CardContent>
30
+ <CardFooter>
31
+ <Button asChild>
32
+ <a href="https://ui.shadcn.com/docs/components">
33
+ Browse components
34
+ </a>
35
+ </Button>
36
+ </CardFooter>
37
+ </Card>
15
38
  </main>
16
39
  );
17
40
  }
@@ -1,8 +1,124 @@
1
1
  @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+ @import "shadcn/tailwind.css";
4
+
5
+ @custom-variant dark (&:is(.dark *));
2
6
 
3
7
  :root {
4
- color-scheme: dark;
5
- font-family: system-ui, sans-serif;
6
- background: #020617;
7
- color: white;
8
+ --radius: 0.625rem;
9
+ --background: oklch(1 0 0);
10
+ --foreground: oklch(0.145 0 0);
11
+ --card: oklch(1 0 0);
12
+ --card-foreground: oklch(0.145 0 0);
13
+ --popover: oklch(1 0 0);
14
+ --popover-foreground: oklch(0.145 0 0);
15
+ --primary: oklch(0.205 0 0);
16
+ --primary-foreground: oklch(0.985 0 0);
17
+ --secondary: oklch(0.97 0 0);
18
+ --secondary-foreground: oklch(0.205 0 0);
19
+ --muted: oklch(0.97 0 0);
20
+ --muted-foreground: oklch(0.556 0 0);
21
+ --accent: oklch(0.97 0 0);
22
+ --accent-foreground: oklch(0.205 0 0);
23
+ --destructive: oklch(0.577 0.245 27.325);
24
+ --border: oklch(0.922 0 0);
25
+ --input: oklch(0.922 0 0);
26
+ --ring: oklch(0.708 0 0);
27
+ --chart-1: oklch(0.87 0 0);
28
+ --chart-2: oklch(0.556 0 0);
29
+ --chart-3: oklch(0.439 0 0);
30
+ --chart-4: oklch(0.371 0 0);
31
+ --chart-5: oklch(0.269 0 0);
32
+ --sidebar: oklch(0.985 0 0);
33
+ --sidebar-foreground: oklch(0.145 0 0);
34
+ --sidebar-primary: oklch(0.205 0 0);
35
+ --sidebar-primary-foreground: oklch(0.985 0 0);
36
+ --sidebar-accent: oklch(0.97 0 0);
37
+ --sidebar-accent-foreground: oklch(0.205 0 0);
38
+ --sidebar-border: oklch(0.922 0 0);
39
+ --sidebar-ring: oklch(0.708 0 0);
40
+ }
41
+
42
+ @theme inline {
43
+ --radius-sm: calc(var(--radius) * 0.6);
44
+ --radius-md: calc(var(--radius) * 0.8);
45
+ --radius-lg: var(--radius);
46
+ --radius-xl: calc(var(--radius) * 1.4);
47
+ --radius-2xl: calc(var(--radius) * 1.8);
48
+ --radius-3xl: calc(var(--radius) * 2.2);
49
+ --radius-4xl: calc(var(--radius) * 2.6);
50
+ --color-background: var(--background);
51
+ --color-foreground: var(--foreground);
52
+ --color-card: var(--card);
53
+ --color-card-foreground: var(--card-foreground);
54
+ --color-popover: var(--popover);
55
+ --color-popover-foreground: var(--popover-foreground);
56
+ --color-primary: var(--primary);
57
+ --color-primary-foreground: var(--primary-foreground);
58
+ --color-secondary: var(--secondary);
59
+ --color-secondary-foreground: var(--secondary-foreground);
60
+ --color-muted: var(--muted);
61
+ --color-muted-foreground: var(--muted-foreground);
62
+ --color-accent: var(--accent);
63
+ --color-accent-foreground: var(--accent-foreground);
64
+ --color-destructive: var(--destructive);
65
+ --color-border: var(--border);
66
+ --color-input: var(--input);
67
+ --color-ring: var(--ring);
68
+ --color-chart-1: var(--chart-1);
69
+ --color-chart-2: var(--chart-2);
70
+ --color-chart-3: var(--chart-3);
71
+ --color-chart-4: var(--chart-4);
72
+ --color-chart-5: var(--chart-5);
73
+ --color-sidebar: var(--sidebar);
74
+ --color-sidebar-foreground: var(--sidebar-foreground);
75
+ --color-sidebar-primary: var(--sidebar-primary);
76
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
77
+ --color-sidebar-accent: var(--sidebar-accent);
78
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
79
+ --color-sidebar-border: var(--sidebar-border);
80
+ --color-sidebar-ring: var(--sidebar-ring);
81
+ }
82
+
83
+ .dark {
84
+ --background: oklch(0.145 0 0);
85
+ --foreground: oklch(0.985 0 0);
86
+ --card: oklch(0.205 0 0);
87
+ --card-foreground: oklch(0.985 0 0);
88
+ --popover: oklch(0.205 0 0);
89
+ --popover-foreground: oklch(0.985 0 0);
90
+ --primary: oklch(0.922 0 0);
91
+ --primary-foreground: oklch(0.205 0 0);
92
+ --secondary: oklch(0.269 0 0);
93
+ --secondary-foreground: oklch(0.985 0 0);
94
+ --muted: oklch(0.269 0 0);
95
+ --muted-foreground: oklch(0.708 0 0);
96
+ --accent: oklch(0.269 0 0);
97
+ --accent-foreground: oklch(0.985 0 0);
98
+ --destructive: oklch(0.704 0.191 22.216);
99
+ --border: oklch(1 0 0 / 10%);
100
+ --input: oklch(1 0 0 / 15%);
101
+ --ring: oklch(0.556 0 0);
102
+ --chart-1: oklch(0.87 0 0);
103
+ --chart-2: oklch(0.556 0 0);
104
+ --chart-3: oklch(0.439 0 0);
105
+ --chart-4: oklch(0.371 0 0);
106
+ --chart-5: oklch(0.269 0 0);
107
+ --sidebar: oklch(0.205 0 0);
108
+ --sidebar-foreground: oklch(0.985 0 0);
109
+ --sidebar-primary: oklch(0.488 0.243 264.376);
110
+ --sidebar-primary-foreground: oklch(0.985 0 0);
111
+ --sidebar-accent: oklch(0.269 0 0);
112
+ --sidebar-accent-foreground: oklch(0.985 0 0);
113
+ --sidebar-border: oklch(1 0 0 / 10%);
114
+ --sidebar-ring: oklch(0.556 0 0);
115
+ }
116
+
117
+ @layer base {
118
+ * {
119
+ @apply border-border outline-ring/50;
120
+ }
121
+ body {
122
+ @apply bg-background text-foreground;
123
+ }
8
124
  }
@@ -10,7 +10,13 @@
10
10
  "frontendDist": "../dist"
11
11
  },
12
12
  "app": {
13
- "windows": [{ "title": "{{projectName}}", "width": 1100, "height": 760 }],
13
+ "windows": [
14
+ {
15
+ "title": "{{projectName}}",
16
+ "width": 1100,
17
+ "height": 760
18
+ }
19
+ ],
14
20
  "security": { "csp": null }
15
21
  },
16
22
  "bundle": { "active": true, "targets": "all" }
@@ -6,7 +6,11 @@
6
6
  "moduleResolution": "Bundler",
7
7
  "jsx": "react-jsx",
8
8
  "strict": true,
9
- "skipLibCheck": true
9
+ "skipLibCheck": true,
10
+ "paths": {
11
+ "@/*": ["./src/*"]
12
+ },
13
+ "types": ["vite/client"]
10
14
  },
11
- "include": ["src"]
15
+ "include": ["src", "vite.config.ts"]
12
16
  }
@@ -1,3 +1,4 @@
1
+ import { fileURLToPath } from "node:url";
1
2
  import tailwindcss from "@tailwindcss/vite";
2
3
  import react from "@vitejs/plugin-react";
3
4
  import { defineConfig } from "vite";
@@ -10,6 +11,9 @@ export default defineConfig({
10
11
  strictPort: true,
11
12
  watch: { ignored: ["**/src-tauri/**"] },
12
13
  },
14
+ resolve: {
15
+ alias: { "@": fileURLToPath(new URL("./src", import.meta.url)) },
16
+ },
13
17
  plugins: [react(), tailwindcss()],
14
18
  build: {
15
19
  target:
@@ -1,7 +1,30 @@
1
1
  {
2
2
  "root": false,
3
3
  "$schema": "https://biomejs.dev/schemas/2.6.5/schema.json",
4
- "formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2 },
5
- "linter": { "enabled": true, "rules": { "preset": "recommended" } },
6
- "javascript": { "formatter": { "quoteStyle": "double" } }
4
+ "vcs": {
5
+ "enabled": true,
6
+ "clientKind": "git",
7
+ "useIgnoreFile": true
8
+ },
9
+ "formatter": {
10
+ "enabled": true,
11
+ "indentStyle": "space",
12
+ "indentWidth": 2
13
+ },
14
+ "linter": {
15
+ "enabled": true,
16
+ "rules": {
17
+ "preset": "recommended"
18
+ }
19
+ },
20
+ "javascript": {
21
+ "formatter": {
22
+ "quoteStyle": "double"
23
+ }
24
+ },
25
+ "css": {
26
+ "parser": {
27
+ "tailwindDirectives": true
28
+ }
29
+ }
7
30
  }
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "name": "{{projectName}}",
3
3
  "private": true,
4
- "packageManager": "bun@1.3.14",
5
4
  "workspaces": [
6
5
  "apps/*",
7
6
  "packages/*"
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "new-york",
4
+ "rsc": false,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "",
8
+ "css": "src/styles.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
+ "registries": {}
23
+ }
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "@{{projectName}}/app",
3
+ "version": "0.0.0",
3
4
  "private": true,
4
5
  "type": "module",
5
6
  "scripts": {
@@ -10,6 +11,10 @@
10
11
  "dependencies": {
11
12
  "@tanstack/react-router": "^1.170.46",
12
13
  "@tanstack/react-start": "^1.169.4",
14
+ "class-variance-authority": "^0.7.1",
15
+ "cn": "^0.5.2",
16
+ "lucide-react": "^1.70.0",
17
+ "radix-ui": "^1.8.1",
13
18
  "react": "^19.3.0",
14
19
  "react-dom": "^19.3.0"
15
20
  },
@@ -19,7 +24,9 @@
19
24
  "@types/react": "^19.3.0",
20
25
  "@types/react-dom": "^19.3.0",
21
26
  "@vitejs/plugin-react": "^6.2.1",
27
+ "shadcn": "^4.23.0",
22
28
  "tailwindcss": "^4.3.4",
29
+ "tw-animate-css": "^1.4.0",
23
30
  "typescript": "^6.0.3",
24
31
  "vite": "^8.3.5"
25
32
  }
@@ -0,0 +1,63 @@
1
+ import { cva, type VariantProps } from "class-variance-authority";
2
+ import { cn } from "cn";
3
+ import { Slot } from "radix-ui";
4
+ import type * as React from "react";
5
+
6
+ const buttonVariants = cva(
7
+ "inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
12
+ destructive:
13
+ "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
14
+ outline:
15
+ "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
16
+ secondary:
17
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
18
+ ghost:
19
+ "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
20
+ link: "text-primary underline-offset-4 hover:underline",
21
+ },
22
+ size: {
23
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
24
+ xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
25
+ sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
26
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
27
+ icon: "size-9",
28
+ "icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
29
+ "icon-sm": "size-8",
30
+ "icon-lg": "size-10",
31
+ },
32
+ },
33
+ defaultVariants: {
34
+ variant: "default",
35
+ size: "default",
36
+ },
37
+ },
38
+ );
39
+
40
+ function Button({
41
+ className,
42
+ variant = "default",
43
+ size = "default",
44
+ asChild = false,
45
+ ...props
46
+ }: React.ComponentProps<"button"> &
47
+ VariantProps<typeof buttonVariants> & {
48
+ asChild?: boolean;
49
+ }) {
50
+ const Comp = asChild ? Slot.Root : "button";
51
+
52
+ return (
53
+ <Comp
54
+ data-slot="button"
55
+ data-variant={variant}
56
+ data-size={size}
57
+ className={cn(buttonVariants({ variant, size, className }))}
58
+ {...props}
59
+ />
60
+ );
61
+ }
62
+
63
+ export { Button, buttonVariants };