create-z3 0.0.28 → 0.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2618,17 +2618,18 @@ program.name("create-z3").version(packageJson.version).description("CLI for scaf
2618
2618
  console.log(chalk2.yellow(" Your app will have no user authentication."));
2619
2619
  console.log();
2620
2620
  }
2621
+ console.log();
2622
+ console.log(chalk2.dim("\u{1F4A1} TweakCN themes: Visit https://tweakcn.com/themes/[theme-id]"));
2623
+ console.log(chalk2.dim(' Click "Code" button, copy the CSS, then paste in the editor.'));
2621
2624
  const applyTheme = await confirm({
2622
- message: "Apply a custom TweakCN theme?",
2625
+ message: "Apply a custom TweakCN theme? (will open your text editor)",
2623
2626
  default: false
2624
2627
  });
2625
2628
  let tweakcnTheme;
2626
2629
  if (applyTheme) {
2627
2630
  console.log();
2628
- console.log(chalk2.cyan("\u{1F4DD} Opening editor for theme CSS..."));
2629
- console.log(chalk2.dim('\u{1F4A1} Tip: Visit a TweakCN theme, click the "Code" button, copy the CSS.'));
2630
- console.log(chalk2.dim(" Paste it in the editor, save and close to continue."));
2631
- console.log(chalk2.dim(" Example: https://tweakcn.com/themes/[theme-id]"));
2631
+ console.log(chalk2.cyan("\u{1F4DD} Opening your text editor..."));
2632
+ console.log(chalk2.dim(" Paste the CSS, save, and close the editor to continue."));
2632
2633
  console.log();
2633
2634
  const tweakcnThemeInput = await editor({
2634
2635
  message: "Enter TweakCN theme CSS:",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-z3",
3
- "version": "0.0.28",
3
+ "version": "0.0.29",
4
4
  "type": "module",
5
5
  "description": "CLI for scaffolding Z3 Stack applications (TanStack/Next.js + Convex + Better Auth)",
6
6
  "bin": {
@@ -26,6 +26,7 @@
26
26
  "convex-helpers": "^0.1.111",
27
27
  "lucide-react": "^0.562.0",
28
28
  "next": "16.1.2",
29
+ "next-themes": "^0.4.6",
29
30
  "nuqs": "^2.8.6",
30
31
  "react": "19.2.3",
31
32
  "react-dom": "19.2.3",
@@ -66,10 +66,12 @@ import {
66
66
  } from "~/components/ui/select"
67
67
  import { Textarea } from "~/components/ui/textarea"
68
68
  import { PlusIcon, BluetoothIcon, MoreVerticalIcon, FileIcon, FolderIcon, FolderOpenIcon, FileCodeIcon, MoreHorizontalIcon, FolderSearchIcon, SaveIcon, DownloadIcon, EyeIcon, LayoutIcon, PaletteIcon, SunIcon, MoonIcon, MonitorIcon, UserIcon, CreditCardIcon, SettingsIcon, KeyboardIcon, LanguagesIcon, BellIcon, MailIcon, ShieldIcon, HelpCircleIcon, FileTextIcon, LogOutIcon } from "lucide-react"
69
+ import { ThemeToggle } from "~/components/ui/theme-toggle"
69
70
 
70
71
  export function ComponentExample() {
71
72
  return (
72
73
  <ExampleWrapper>
74
+ <ThemeToggle className="absolute top-10 right-10" />
73
75
  <CardExample />
74
76
  <FormExample />
75
77
  </ExampleWrapper>
@@ -1,14 +1,20 @@
1
1
  import { NuqsAdapter } from "nuqs/adapters/next/app"
2
- import { type PropsWithChildren } from "react";
2
+ import { type PropsWithChildren } from "react"
3
3
 
4
- import ConvexClientProvider from "./convex";
4
+ import ConvexClientProvider from "./convex"
5
+ import { ThemeProvider } from "./theme"
5
6
 
6
7
  export default function ServerProviders({ children }: PropsWithChildren) {
7
- return (
8
- <ConvexClientProvider>
9
- <NuqsAdapter>
10
- {children}
11
- </NuqsAdapter>
12
- </ConvexClientProvider>
13
- )
8
+ return (
9
+ <ThemeProvider
10
+ attribute="class"
11
+ defaultTheme="system"
12
+ disableTransitionOnChange
13
+ enableSystem
14
+ >
15
+ <ConvexClientProvider>
16
+ <NuqsAdapter>{children}</NuqsAdapter>
17
+ </ConvexClientProvider>
18
+ </ThemeProvider>
19
+ )
14
20
  }
@@ -0,0 +1,11 @@
1
+ "use client"
2
+
3
+ import { ThemeProvider as NextThemesProvider } from "next-themes"
4
+ import * as React from "react"
5
+
6
+ export function ThemeProvider({
7
+ children,
8
+ ...props
9
+ }: React.ComponentProps<typeof NextThemesProvider>) {
10
+ return <NextThemesProvider {...props}>{children}</NextThemesProvider>
11
+ }
@@ -0,0 +1,65 @@
1
+ "use client"
2
+
3
+ import { Moon, Sun } from "lucide-react";
4
+ import { useTheme } from "next-themes";
5
+ import { type ComponentPropsWithRef } from "react";
6
+
7
+ import { Button } from "~/components/ui/button";
8
+ import {
9
+ DropdownMenu,
10
+ DropdownMenuCheckboxItem,
11
+ DropdownMenuContent,
12
+ DropdownMenuTrigger
13
+ } from "~/components/ui/dropdown-menu";
14
+
15
+ export function ThemeToggle({ ...divProps }: ComponentPropsWithRef<"div">) {
16
+ const { setTheme, theme, resolvedTheme } = useTheme()
17
+
18
+ return (
19
+ <div {...divProps}>
20
+ <DropdownMenu>
21
+ <DropdownMenuTrigger render={<Button size="icon" variant="outline" />} suppressHydrationWarning>
22
+ <Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
23
+ <Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
24
+ <span className="sr-only">Toggle theme</span>
25
+ </DropdownMenuTrigger>
26
+ <DropdownMenuContent>
27
+ <DropdownMenuCheckboxItem
28
+ checked={Boolean(theme && theme === "light")}
29
+ disabled={Boolean(theme && theme === "light")}
30
+ onCheckedChange={(val) => {
31
+ if (val) {
32
+ setTheme("light")
33
+ }
34
+ }}
35
+ >
36
+ Light
37
+ </DropdownMenuCheckboxItem>
38
+ <DropdownMenuCheckboxItem
39
+ checked={Boolean(theme && theme === "dark")}
40
+ disabled={Boolean(theme && theme === "dark")}
41
+ onCheckedChange={(val) => {
42
+ if (val) {
43
+ setTheme("dark")
44
+ }
45
+ }}
46
+ >
47
+ Dark
48
+ </DropdownMenuCheckboxItem>
49
+ <DropdownMenuCheckboxItem
50
+ checked={Boolean(theme && theme === "system")}
51
+ disabled={Boolean(theme && theme === "system")}
52
+ onCheckedChange={(val) => {
53
+ if (val) {
54
+ setTheme("system")
55
+ }
56
+ }}
57
+ >
58
+ System
59
+ </DropdownMenuCheckboxItem>
60
+ </DropdownMenuContent>
61
+ </DropdownMenu>
62
+ </div >
63
+ )
64
+ }
65
+
@@ -0,0 +1,27 @@
1
+ import { Moon, Sun, SunMoon } from "lucide-react";
2
+ import { ComponentPropsWithRef } from "react";
3
+ import { Button } from "~/components/ui/button";
4
+ import { useTheme } from "~/lib/theme";
5
+
6
+ export function ThemeToggle({ onClick, ...buttonProps }: ComponentPropsWithRef<"button">) {
7
+ const { userTheme, setTheme } = useTheme()
8
+
9
+ function toggleTheme() {
10
+ setTheme(userTheme === "light" ? "dark" : userTheme === "dark" ? "system" : "light")
11
+ }
12
+
13
+ return (
14
+ <Button
15
+ onClick={(e) => {
16
+ toggleTheme()
17
+ if (onClick) {
18
+ onClick(e)
19
+ }
20
+ }}
21
+ aria-label="Toggle Theme"
22
+ {...buttonProps}
23
+ >
24
+ {userTheme === "light" ? <Sun /> : userTheme === "dark" ? <Moon /> : <SunMoon />}
25
+ </Button>
26
+ )
27
+ }
@@ -90,10 +90,12 @@ import {
90
90
  SelectValue,
91
91
  } from '~/components/ui/select'
92
92
  import { Textarea } from '~/components/ui/textarea'
93
+ import { ThemeToggle } from './ThemeToggle'
93
94
 
94
95
  export function ComponentExample() {
95
96
  return (
96
97
  <ExampleWrapper>
98
+ <ThemeToggle className="absolute -top-10 right-0" />
97
99
  <CardExample />
98
100
  <FormExample />
99
101
  </ExampleWrapper>