shadcn-theme-menu 1.1.4 → 1.1.6
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 +27 -11
- package/dist/cinematic-theme-switcher.js +206 -0
- package/dist/components/ui/avatar.js +30 -0
- package/dist/components/ui/button.js +39 -0
- package/dist/components/ui/dropdown-menu.js +72 -0
- package/dist/components/ui/sidebar.js +31 -0
- package/dist/index.js +6 -0
- package/dist/lib/utils.js +8 -0
- package/dist/sidebar-user-menu.js +149 -0
- package/dist/theme-dropdown.js +488 -0
- package/dist/theme-provider.js +12 -0
- package/dist/theme-toggle.js +51 -0
- package/package.json +7 -5
- package/src/components/ui/avatar.tsx +36 -0
- package/src/components/ui/sidebar.tsx +30 -0
- package/src/sidebar-user-menu.tsx +12 -12
- package/src/theme-dropdown.tsx +199 -34
- package/src/themes-shadcn.css +1024 -44
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img width="350px" src="https://i.imgur.com/
|
|
2
|
+
<img width="350px" src="https://i.imgur.com/mgErPzk.png" />
|
|
3
3
|
<p align="center">
|
|
4
4
|
<a href="https://discord.gg/SJdBqBz3tV">
|
|
5
5
|
<img src="https://img.shields.io/discord/1110227955554209923.svg?label=Chat&logo=Discord&colorB=7289da&style=flat"
|
|
@@ -31,6 +31,17 @@
|
|
|
31
31
|
|
|
32
32
|
Beautiful theme components for shadcn/ui with 24+ color themes, dark/light mode, and animations.
|
|
33
33
|
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
- **24+ pre-made themes** – from minimal and elegant to cyberpunk and app-inspired designs
|
|
37
|
+
- **OKLCH colors** – modern color space for perceptually uniform colors and better accessibility
|
|
38
|
+
- **Drop-in components** – `ThemeToggle`, `ThemeDropdown`, and `CinematicThemeSwitcher` with particle effects
|
|
39
|
+
- **Fully type-safe** – complete TypeScript support with exported types
|
|
40
|
+
- **Customizable** – pass your own Button/DropdownMenu components or set themes programmatically
|
|
41
|
+
- **Persistent** – automatic `localStorage` support for color theme preferences
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
34
45
|
## Installation
|
|
35
46
|
|
|
36
47
|
```bash
|
|
@@ -75,6 +86,7 @@ Simple light/dark mode toggle.
|
|
|
75
86
|
```
|
|
76
87
|
|
|
77
88
|
**Props:**
|
|
89
|
+
|
|
78
90
|
- `mode?` - Include system option (default: `'light-dark-system'`)
|
|
79
91
|
- `Button?` - Custom Button component
|
|
80
92
|
- `DropdownMenu?` - Custom DropdownMenu components
|
|
@@ -93,6 +105,7 @@ Full dropdown with 24+ color themes and live preview.
|
|
|
93
105
|
```
|
|
94
106
|
|
|
95
107
|
**Props:**
|
|
108
|
+
|
|
96
109
|
- `iconSrc?` - Custom icon path (default: Palette icon)
|
|
97
110
|
- `Button?` - Custom Button component
|
|
98
111
|
- `DropdownMenu?` - Custom DropdownMenu components
|
|
@@ -116,8 +129,8 @@ Animated toggle with particle effects.
|
|
|
116
129
|
Pass your own Button or DropdownMenu components:
|
|
117
130
|
|
|
118
131
|
```tsx
|
|
119
|
-
import { Button } from
|
|
120
|
-
import * as DropdownMenu from
|
|
132
|
+
import { Button } from "@/components/ui/button";
|
|
133
|
+
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
|
121
134
|
|
|
122
135
|
<ThemeDropdown
|
|
123
136
|
Button={Button}
|
|
@@ -127,27 +140,29 @@ import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
|
|
|
127
140
|
Content: DropdownMenu.Content,
|
|
128
141
|
Item: DropdownMenu.Item,
|
|
129
142
|
Label: DropdownMenu.Label,
|
|
130
|
-
Separator: DropdownMenu.Separator
|
|
143
|
+
Separator: DropdownMenu.Separator,
|
|
131
144
|
}}
|
|
132
|
-
|
|
145
|
+
/>;
|
|
133
146
|
```
|
|
134
147
|
|
|
135
148
|
## Programmatic Usage
|
|
136
149
|
|
|
137
150
|
```tsx
|
|
138
|
-
import { themeNames, themeColors, formatThemeName } from
|
|
151
|
+
import { themeNames, themeColors, formatThemeName } from "shadcn-theme-menu";
|
|
139
152
|
|
|
140
153
|
// Set theme programmatically
|
|
141
154
|
const setTheme = (themeName: string) => {
|
|
142
|
-
localStorage.setItem(
|
|
143
|
-
themeNames.forEach(t =>
|
|
155
|
+
localStorage.setItem("color-theme", themeName);
|
|
156
|
+
themeNames.forEach((t) =>
|
|
157
|
+
document.documentElement.classList.remove(`theme-${t}`),
|
|
158
|
+
);
|
|
144
159
|
document.documentElement.classList.add(`theme-${themeName}`);
|
|
145
160
|
};
|
|
146
161
|
|
|
147
162
|
// Get theme info
|
|
148
163
|
console.log(themeNames); // Array of all theme names
|
|
149
|
-
console.log(themeColors[
|
|
150
|
-
console.log(formatThemeName(
|
|
164
|
+
console.log(themeColors["cyberpunk"]); // { primary: '#ff00c8', secondary: '#f0f0ff' }
|
|
165
|
+
console.log(formatThemeName("modern-minimal")); // 'Modern Minimal'
|
|
151
166
|
```
|
|
152
167
|
|
|
153
168
|
## TypeScript
|
|
@@ -155,7 +170,7 @@ console.log(formatThemeName('modern-minimal')); // 'Modern Minimal'
|
|
|
155
170
|
Full TypeScript support with exported types:
|
|
156
171
|
|
|
157
172
|
```tsx
|
|
158
|
-
import type { ThemeProviderProps } from
|
|
173
|
+
import type { ThemeProviderProps } from "shadcn-theme-menu";
|
|
159
174
|
```
|
|
160
175
|
|
|
161
176
|
## Demo
|
|
@@ -167,6 +182,7 @@ pnpm demo
|
|
|
167
182
|
```
|
|
168
183
|
|
|
169
184
|
Or manually:
|
|
185
|
+
|
|
170
186
|
```bash
|
|
171
187
|
cd demo
|
|
172
188
|
pnpm install
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useTheme as e } from "next-themes";
|
|
3
|
+
import { jsx as t, jsxs as n } from "react/jsx-runtime";
|
|
4
|
+
import { Moon as r, Sun as i } from "lucide-react";
|
|
5
|
+
import { useEffect as a, useRef as o, useState as s } from "react";
|
|
6
|
+
import { motion as c } from "framer-motion";
|
|
7
|
+
//#region src/cinematic-theme-switcher.tsx
|
|
8
|
+
function l() {
|
|
9
|
+
let { theme: l, setTheme: u, resolvedTheme: d } = e(), [f, p] = s(!1), [m, h] = s([]), [g, _] = s(!1), v = o(null), y = f && (l === "dark" || d === "dark");
|
|
10
|
+
a(() => {
|
|
11
|
+
p(!0);
|
|
12
|
+
}, []);
|
|
13
|
+
let b = () => {
|
|
14
|
+
let e = [];
|
|
15
|
+
for (let t = 0; t < 3; t++) e.push({
|
|
16
|
+
id: t,
|
|
17
|
+
delay: t * .1,
|
|
18
|
+
duration: .6 + t * .1
|
|
19
|
+
});
|
|
20
|
+
h(e), _(!0), setTimeout(() => {
|
|
21
|
+
_(!1), h([]);
|
|
22
|
+
}, 1e3);
|
|
23
|
+
};
|
|
24
|
+
return f ? /* @__PURE__ */ n("div", {
|
|
25
|
+
className: "relative inline-block",
|
|
26
|
+
children: [/* @__PURE__ */ t("svg", {
|
|
27
|
+
className: "absolute w-0 h-0",
|
|
28
|
+
children: /* @__PURE__ */ n("defs", { children: [/* @__PURE__ */ n("filter", {
|
|
29
|
+
id: "grain-light",
|
|
30
|
+
children: [
|
|
31
|
+
/* @__PURE__ */ t("feTurbulence", {
|
|
32
|
+
type: "fractalNoise",
|
|
33
|
+
baseFrequency: "0.9",
|
|
34
|
+
numOctaves: "4",
|
|
35
|
+
result: "noise"
|
|
36
|
+
}),
|
|
37
|
+
/* @__PURE__ */ t("feColorMatrix", {
|
|
38
|
+
in: "noise",
|
|
39
|
+
type: "saturate",
|
|
40
|
+
values: "0",
|
|
41
|
+
result: "desaturatedNoise"
|
|
42
|
+
}),
|
|
43
|
+
/* @__PURE__ */ t("feComponentTransfer", {
|
|
44
|
+
in: "desaturatedNoise",
|
|
45
|
+
result: "lightGrain",
|
|
46
|
+
children: /* @__PURE__ */ t("feFuncA", {
|
|
47
|
+
type: "linear",
|
|
48
|
+
slope: "0.3"
|
|
49
|
+
})
|
|
50
|
+
}),
|
|
51
|
+
/* @__PURE__ */ t("feBlend", {
|
|
52
|
+
in: "SourceGraphic",
|
|
53
|
+
in2: "lightGrain",
|
|
54
|
+
mode: "overlay"
|
|
55
|
+
})
|
|
56
|
+
]
|
|
57
|
+
}), /* @__PURE__ */ n("filter", {
|
|
58
|
+
id: "grain-dark",
|
|
59
|
+
children: [
|
|
60
|
+
/* @__PURE__ */ t("feTurbulence", {
|
|
61
|
+
type: "fractalNoise",
|
|
62
|
+
baseFrequency: "0.9",
|
|
63
|
+
numOctaves: "4",
|
|
64
|
+
result: "noise"
|
|
65
|
+
}),
|
|
66
|
+
/* @__PURE__ */ t("feColorMatrix", {
|
|
67
|
+
in: "noise",
|
|
68
|
+
type: "saturate",
|
|
69
|
+
values: "0",
|
|
70
|
+
result: "desaturatedNoise"
|
|
71
|
+
}),
|
|
72
|
+
/* @__PURE__ */ t("feComponentTransfer", {
|
|
73
|
+
in: "desaturatedNoise",
|
|
74
|
+
result: "darkGrain",
|
|
75
|
+
children: /* @__PURE__ */ t("feFuncA", {
|
|
76
|
+
type: "linear",
|
|
77
|
+
slope: "0.5"
|
|
78
|
+
})
|
|
79
|
+
}),
|
|
80
|
+
/* @__PURE__ */ t("feBlend", {
|
|
81
|
+
in: "SourceGraphic",
|
|
82
|
+
in2: "darkGrain",
|
|
83
|
+
mode: "overlay"
|
|
84
|
+
})
|
|
85
|
+
]
|
|
86
|
+
})] })
|
|
87
|
+
}), /* @__PURE__ */ n(c.button, {
|
|
88
|
+
ref: v,
|
|
89
|
+
onClick: () => {
|
|
90
|
+
b(), u(y ? "light" : "dark");
|
|
91
|
+
},
|
|
92
|
+
className: "relative flex h-[64px] w-[104px] items-center rounded-full p-[6px] transition-all duration-300 focus:outline-none",
|
|
93
|
+
style: {
|
|
94
|
+
background: y ? "radial-gradient(ellipse at top left, #1e293b 0%, #0f172a 40%, #020617 100%)" : "radial-gradient(ellipse at top left, #ffffff 0%, #f1f5f9 40%, #cbd5e1 100%)",
|
|
95
|
+
boxShadow: y ? "\n inset 5px 5px 12px rgba(0, 0, 0, 0.9),\n inset -5px -5px 12px rgba(71, 85, 105, 0.4),\n inset 8px 8px 16px rgba(0, 0, 0, 0.7),\n inset -8px -8px 16px rgba(100, 116, 139, 0.2),\n inset 0 2px 4px rgba(0, 0, 0, 1),\n inset 0 -2px 4px rgba(71, 85, 105, 0.4),\n inset 0 0 20px rgba(0, 0, 0, 0.6),\n 0 1px 1px rgba(255, 255, 255, 0.05),\n 0 2px 4px rgba(0, 0, 0, 0.4),\n 0 8px 16px rgba(0, 0, 0, 0.4),\n 0 16px 32px rgba(0, 0, 0, 0.3),\n 0 24px 48px rgba(0, 0, 0, 0.2)\n " : "\n inset 5px 5px 12px rgba(148, 163, 184, 0.5),\n inset -5px -5px 12px rgba(255, 255, 255, 1),\n inset 8px 8px 16px rgba(100, 116, 139, 0.3),\n inset -8px -8px 16px rgba(255, 255, 255, 0.9),\n inset 0 2px 4px rgba(148, 163, 184, 0.4),\n inset 0 -2px 4px rgba(255, 255, 255, 1),\n inset 0 0 20px rgba(203, 213, 225, 0.3),\n 0 1px 2px rgba(255, 255, 255, 1),\n 0 2px 4px rgba(0, 0, 0, 0.1),\n 0 8px 16px rgba(0, 0, 0, 0.08),\n 0 16px 32px rgba(0, 0, 0, 0.06),\n 0 24px 48px rgba(0, 0, 0, 0.04)\n ",
|
|
96
|
+
border: y ? "2px solid rgba(51, 65, 85, 0.6)" : "2px solid rgba(203, 213, 225, 0.6)",
|
|
97
|
+
position: "relative"
|
|
98
|
+
},
|
|
99
|
+
"aria-label": `Switch to ${y ? "light" : "dark"} mode`,
|
|
100
|
+
role: "switch",
|
|
101
|
+
"aria-checked": y,
|
|
102
|
+
whileTap: { scale: .98 },
|
|
103
|
+
children: [
|
|
104
|
+
/* @__PURE__ */ t("div", {
|
|
105
|
+
className: "absolute inset-[3px] rounded-full pointer-events-none",
|
|
106
|
+
style: { boxShadow: y ? "inset 0 2px 6px rgba(0, 0, 0, 0.9), inset 0 -1px 3px rgba(71, 85, 105, 0.3)" : "inset 0 2px 6px rgba(100, 116, 139, 0.4), inset 0 -1px 3px rgba(255, 255, 255, 0.8)" }
|
|
107
|
+
}),
|
|
108
|
+
/* @__PURE__ */ t("div", {
|
|
109
|
+
className: "absolute inset-0 rounded-full pointer-events-none",
|
|
110
|
+
style: {
|
|
111
|
+
background: y ? "\n radial-gradient(ellipse at top, rgba(71, 85, 105, 0.15) 0%, transparent 50%),\n linear-gradient(to bottom, rgba(71, 85, 105, 0.2) 0%, transparent 30%, transparent 70%, rgba(0, 0, 0, 0.3) 100%)\n " : "\n radial-gradient(ellipse at top, rgba(255, 255, 255, 0.8) 0%, transparent 50%),\n linear-gradient(to bottom, rgba(255, 255, 255, 0.7) 0%, transparent 30%, transparent 70%, rgba(148, 163, 184, 0.15) 100%)\n ",
|
|
112
|
+
mixBlendMode: "overlay"
|
|
113
|
+
}
|
|
114
|
+
}),
|
|
115
|
+
/* @__PURE__ */ t("div", {
|
|
116
|
+
className: "absolute inset-0 rounded-full pointer-events-none",
|
|
117
|
+
style: { boxShadow: y ? "inset 0 0 15px rgba(0, 0, 0, 0.5)" : "inset 0 0 15px rgba(148, 163, 184, 0.2)" }
|
|
118
|
+
}),
|
|
119
|
+
/* @__PURE__ */ n("div", {
|
|
120
|
+
className: "absolute inset-0 flex items-center justify-between px-4",
|
|
121
|
+
children: [/* @__PURE__ */ t(i, {
|
|
122
|
+
size: 20,
|
|
123
|
+
className: y ? "text-yellow-100" : "text-amber-600"
|
|
124
|
+
}), /* @__PURE__ */ t(r, {
|
|
125
|
+
size: 20,
|
|
126
|
+
className: y ? "text-yellow-100" : "text-slate-700"
|
|
127
|
+
})]
|
|
128
|
+
}),
|
|
129
|
+
/* @__PURE__ */ n(c.div, {
|
|
130
|
+
className: "relative z-10 flex h-[44px] w-[44px] items-center justify-center rounded-full overflow-hidden",
|
|
131
|
+
style: {
|
|
132
|
+
background: y ? "linear-gradient(145deg, #64748b 0%, #475569 50%, #334155 100%)" : "linear-gradient(145deg, #ffffff 0%, #fefefe 50%, #f8fafc 100%)",
|
|
133
|
+
boxShadow: y ? "\n inset 2px 2px 4px rgba(100, 116, 139, 0.4),\n inset -2px -2px 4px rgba(0, 0, 0, 0.8),\n inset 0 1px 1px rgba(255, 255, 255, 0.15),\n 0 1px 2px rgba(255, 255, 255, 0.1),\n 0 8px 32px rgba(0, 0, 0, 0.6),\n 0 4px 12px rgba(0, 0, 0, 0.5),\n 0 2px 4px rgba(0, 0, 0, 0.4)\n " : "\n inset 2px 2px 4px rgba(203, 213, 225, 0.3),\n inset -2px -2px 4px rgba(255, 255, 255, 1),\n inset 0 1px 2px rgba(255, 255, 255, 1),\n 0 1px 2px rgba(255, 255, 255, 1),\n 0 8px 32px rgba(0, 0, 0, 0.18),\n 0 4px 12px rgba(0, 0, 0, 0.12),\n 0 2px 4px rgba(0, 0, 0, 0.08)\n ",
|
|
134
|
+
border: y ? "2px solid rgba(148, 163, 184, 0.3)" : "2px solid rgba(255, 255, 255, 0.9)"
|
|
135
|
+
},
|
|
136
|
+
animate: { x: y ? 46 : 0 },
|
|
137
|
+
transition: {
|
|
138
|
+
type: "spring",
|
|
139
|
+
stiffness: 300,
|
|
140
|
+
damping: 20
|
|
141
|
+
},
|
|
142
|
+
children: [
|
|
143
|
+
/* @__PURE__ */ t("div", {
|
|
144
|
+
className: "absolute inset-0 rounded-full pointer-events-none",
|
|
145
|
+
style: {
|
|
146
|
+
background: "linear-gradient(to bottom, rgba(255, 255, 255, 0.4) 0%, transparent 40%, rgba(0, 0, 0, 0.1) 100%)",
|
|
147
|
+
mixBlendMode: "overlay"
|
|
148
|
+
}
|
|
149
|
+
}),
|
|
150
|
+
g && m.map((e) => /* @__PURE__ */ t(c.div, {
|
|
151
|
+
className: "absolute inset-0 flex items-center justify-center pointer-events-none",
|
|
152
|
+
children: /* @__PURE__ */ t(c.div, {
|
|
153
|
+
className: "absolute rounded-full",
|
|
154
|
+
style: {
|
|
155
|
+
width: "10px",
|
|
156
|
+
height: "10px",
|
|
157
|
+
background: y ? "radial-gradient(circle, rgba(147, 197, 253, 0.5) 0%, rgba(147, 197, 253, 0) 70%)" : "radial-gradient(circle, rgba(251, 191, 36, 0.7) 0%, rgba(251, 191, 36, 0) 70%)",
|
|
158
|
+
mixBlendMode: "normal"
|
|
159
|
+
},
|
|
160
|
+
initial: {
|
|
161
|
+
scale: 0,
|
|
162
|
+
opacity: 0
|
|
163
|
+
},
|
|
164
|
+
animate: {
|
|
165
|
+
scale: y ? 6 : 8,
|
|
166
|
+
opacity: [
|
|
167
|
+
0,
|
|
168
|
+
1,
|
|
169
|
+
0
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
transition: {
|
|
173
|
+
duration: y ? .5 : e.duration,
|
|
174
|
+
delay: e.delay,
|
|
175
|
+
ease: "easeOut"
|
|
176
|
+
},
|
|
177
|
+
children: /* @__PURE__ */ t("div", {
|
|
178
|
+
className: "absolute inset-0 rounded-full opacity-40",
|
|
179
|
+
style: {
|
|
180
|
+
backgroundImage: "url(\"data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E\")",
|
|
181
|
+
mixBlendMode: "overlay"
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
})
|
|
185
|
+
}, e.id)),
|
|
186
|
+
/* @__PURE__ */ t("div", {
|
|
187
|
+
className: "relative z-10",
|
|
188
|
+
children: y ? /* @__PURE__ */ t(r, {
|
|
189
|
+
size: 20,
|
|
190
|
+
className: "text-yellow-200"
|
|
191
|
+
}) : /* @__PURE__ */ t(i, {
|
|
192
|
+
size: 20,
|
|
193
|
+
className: "text-amber-500"
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
]
|
|
197
|
+
})
|
|
198
|
+
]
|
|
199
|
+
})]
|
|
200
|
+
}) : /* @__PURE__ */ t("div", {
|
|
201
|
+
className: "relative inline-block",
|
|
202
|
+
children: /* @__PURE__ */ t("div", { className: "relative flex h-[64px] w-[104px] items-center rounded-full bg-gray-200 p-1" })
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
//#endregion
|
|
206
|
+
export { l as default };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { cn as e } from "../../lib/utils.js";
|
|
2
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
3
|
+
import * as n from "react";
|
|
4
|
+
//#region src/components/ui/avatar.tsx
|
|
5
|
+
function r({ children: n, className: r, ...i }) {
|
|
6
|
+
return /* @__PURE__ */ t("div", {
|
|
7
|
+
className: e("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", r),
|
|
8
|
+
...i,
|
|
9
|
+
children: n
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function i({ src: r, alt: i, className: a, ...o }) {
|
|
13
|
+
let [s, c] = n.useState(!1);
|
|
14
|
+
return !r || s ? null : /* @__PURE__ */ t("img", {
|
|
15
|
+
src: r,
|
|
16
|
+
alt: i,
|
|
17
|
+
className: e("aspect-square h-full w-full object-cover", a),
|
|
18
|
+
onError: () => c(!0),
|
|
19
|
+
...o
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function a({ children: n, className: r, ...i }) {
|
|
23
|
+
return /* @__PURE__ */ t("div", {
|
|
24
|
+
className: e("flex h-full w-full items-center justify-center rounded-full bg-muted text-xs font-medium", r),
|
|
25
|
+
...i,
|
|
26
|
+
children: n
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { r as Avatar, a as AvatarFallback, i as AvatarImage };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { cn as e } from "../../lib/utils.js";
|
|
2
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
3
|
+
import * as n from "react";
|
|
4
|
+
import { Slot as r } from "@radix-ui/react-slot";
|
|
5
|
+
import { cva as i } from "class-variance-authority";
|
|
6
|
+
//#region src/components/ui/button.tsx
|
|
7
|
+
var a = i("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", {
|
|
8
|
+
variants: {
|
|
9
|
+
variant: {
|
|
10
|
+
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
11
|
+
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
12
|
+
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
13
|
+
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
14
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
15
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
16
|
+
},
|
|
17
|
+
size: {
|
|
18
|
+
default: "h-9 px-4 py-2",
|
|
19
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
20
|
+
lg: "h-10 rounded-md px-8",
|
|
21
|
+
icon: "h-9 w-9"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
defaultVariants: {
|
|
25
|
+
variant: "default",
|
|
26
|
+
size: "default"
|
|
27
|
+
}
|
|
28
|
+
}), o = n.forwardRef(({ className: n, variant: i, size: o, asChild: s = !1, ...c }, l) => /* @__PURE__ */ t(s ? r : "button", {
|
|
29
|
+
className: e(a({
|
|
30
|
+
variant: i,
|
|
31
|
+
size: o,
|
|
32
|
+
className: n
|
|
33
|
+
})),
|
|
34
|
+
ref: l,
|
|
35
|
+
...c
|
|
36
|
+
}));
|
|
37
|
+
o.displayName = "Button";
|
|
38
|
+
//#endregion
|
|
39
|
+
export { o as Button };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { cn as e } from "../../lib/utils.js";
|
|
2
|
+
import { jsx as t, jsxs as n } from "react/jsx-runtime";
|
|
3
|
+
import { Check as r, ChevronRight as i, Circle as a } from "lucide-react";
|
|
4
|
+
import * as o from "react";
|
|
5
|
+
import * as s from "@radix-ui/react-dropdown-menu";
|
|
6
|
+
//#region src/components/ui/dropdown-menu.tsx
|
|
7
|
+
var c = s.Root, l = s.Trigger, u = s.Portal, d = s.Sub, f = o.forwardRef(({ className: r, inset: a, children: o, ...c }, l) => /* @__PURE__ */ n(s.SubTrigger, {
|
|
8
|
+
ref: l,
|
|
9
|
+
className: e("flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent", a && "pl-8", r),
|
|
10
|
+
...c,
|
|
11
|
+
children: [o, /* @__PURE__ */ t(i, { className: "ml-auto h-4 w-4" })]
|
|
12
|
+
}));
|
|
13
|
+
f.displayName = s.SubTrigger.displayName;
|
|
14
|
+
var p = o.forwardRef(({ className: n, ...r }, i) => /* @__PURE__ */ t(s.SubContent, {
|
|
15
|
+
ref: i,
|
|
16
|
+
className: e("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", n),
|
|
17
|
+
...r
|
|
18
|
+
}));
|
|
19
|
+
p.displayName = s.SubContent.displayName;
|
|
20
|
+
var m = o.forwardRef(({ className: n, sideOffset: r = 4, ...i }, a) => /* @__PURE__ */ t(s.Portal, { children: /* @__PURE__ */ t(s.Content, {
|
|
21
|
+
ref: a,
|
|
22
|
+
sideOffset: r,
|
|
23
|
+
className: e("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", n),
|
|
24
|
+
...i
|
|
25
|
+
}) }));
|
|
26
|
+
m.displayName = s.Content.displayName;
|
|
27
|
+
var h = o.forwardRef(({ className: n, inset: r, ...i }, a) => /* @__PURE__ */ t(s.Item, {
|
|
28
|
+
ref: a,
|
|
29
|
+
className: e("relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", r && "pl-8", n),
|
|
30
|
+
...i
|
|
31
|
+
}));
|
|
32
|
+
h.displayName = s.Item.displayName;
|
|
33
|
+
var g = o.forwardRef(({ className: i, children: a, checked: o, ...c }, l) => /* @__PURE__ */ n(s.CheckboxItem, {
|
|
34
|
+
ref: l,
|
|
35
|
+
className: e("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", i),
|
|
36
|
+
checked: o,
|
|
37
|
+
...c,
|
|
38
|
+
children: [/* @__PURE__ */ t("span", {
|
|
39
|
+
className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center",
|
|
40
|
+
children: /* @__PURE__ */ t(s.ItemIndicator, { children: /* @__PURE__ */ t(r, { className: "h-4 w-4" }) })
|
|
41
|
+
}), a]
|
|
42
|
+
}));
|
|
43
|
+
g.displayName = s.CheckboxItem.displayName;
|
|
44
|
+
var _ = o.forwardRef(({ className: r, children: i, ...o }, c) => /* @__PURE__ */ n(s.RadioItem, {
|
|
45
|
+
ref: c,
|
|
46
|
+
className: e("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", r),
|
|
47
|
+
...o,
|
|
48
|
+
children: [/* @__PURE__ */ t("span", {
|
|
49
|
+
className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center",
|
|
50
|
+
children: /* @__PURE__ */ t(s.ItemIndicator, { children: /* @__PURE__ */ t(a, { className: "h-2 w-2 fill-current" }) })
|
|
51
|
+
}), i]
|
|
52
|
+
}));
|
|
53
|
+
_.displayName = s.RadioItem.displayName;
|
|
54
|
+
var v = o.forwardRef(({ className: n, inset: r, ...i }, a) => /* @__PURE__ */ t(s.Label, {
|
|
55
|
+
ref: a,
|
|
56
|
+
className: e("px-2 py-1.5 text-sm font-semibold", r && "pl-8", n),
|
|
57
|
+
...i
|
|
58
|
+
}));
|
|
59
|
+
v.displayName = s.Label.displayName;
|
|
60
|
+
var y = o.forwardRef(({ className: n, ...r }, i) => /* @__PURE__ */ t(s.Separator, {
|
|
61
|
+
ref: i,
|
|
62
|
+
className: e("-mx-1 my-1 h-px bg-muted", n),
|
|
63
|
+
...r
|
|
64
|
+
}));
|
|
65
|
+
y.displayName = s.Separator.displayName;
|
|
66
|
+
var b = ({ className: n, ...r }) => /* @__PURE__ */ t("span", {
|
|
67
|
+
className: e("ml-auto text-xs tracking-widest opacity-60", n),
|
|
68
|
+
...r
|
|
69
|
+
});
|
|
70
|
+
b.displayName = "DropdownMenuShortcut";
|
|
71
|
+
//#endregion
|
|
72
|
+
export { c as DropdownMenu, m as DropdownMenuContent, h as DropdownMenuItem, v as DropdownMenuLabel, u as DropdownMenuPortal, y as DropdownMenuSeparator, d as DropdownMenuSub, p as DropdownMenuSubContent, f as DropdownMenuSubTrigger, l as DropdownMenuTrigger };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { cn as e } from "../../lib/utils.js";
|
|
2
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
3
|
+
import * as n from "react";
|
|
4
|
+
//#region src/components/ui/sidebar.tsx
|
|
5
|
+
function r({ children: n, className: r, ...i }) {
|
|
6
|
+
return /* @__PURE__ */ t("ul", {
|
|
7
|
+
className: e("flex flex-col gap-1", r),
|
|
8
|
+
...i,
|
|
9
|
+
children: n
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function i({ children: n, className: r, ...i }) {
|
|
13
|
+
return /* @__PURE__ */ t("li", {
|
|
14
|
+
className: e("", r),
|
|
15
|
+
...i,
|
|
16
|
+
children: n
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function a({ children: r, className: i, size: a = "default", asChild: o, ...s }) {
|
|
20
|
+
let c = a === "lg" ? "h-12 text-sm" : a === "sm" ? "h-7 text-xs" : "h-8 text-sm";
|
|
21
|
+
return o && n.isValidElement(r) ? n.cloneElement(r, {
|
|
22
|
+
className: e("flex w-full items-center gap-2 rounded-md px-2 py-1.5 hover:bg-accent", c, i),
|
|
23
|
+
...s
|
|
24
|
+
}) : /* @__PURE__ */ t("button", {
|
|
25
|
+
className: e("flex w-full items-center gap-2 rounded-md px-2 py-1.5 hover:bg-accent", c, i),
|
|
26
|
+
...s,
|
|
27
|
+
children: r
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { r as SidebarMenu, a as SidebarMenuButton, i as SidebarMenuItem };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ThemeProvider as e } from "./theme-provider.js";
|
|
2
|
+
import { ThemeToggle as t } from "./theme-toggle.js";
|
|
3
|
+
import { ThemeDropdown as n, formatThemeName as r, themeColors as i, themeNames as a } from "./theme-dropdown.js";
|
|
4
|
+
import o from "./cinematic-theme-switcher.js";
|
|
5
|
+
import { SidebarUserMenu as s } from "./sidebar-user-menu.js";
|
|
6
|
+
export { o as CinematicThemeSwitcher, s as SidebarUserMenu, n as ThemeDropdown, e as ThemeProvider, t as ThemeToggle, r as formatThemeName, i as themeColors, a as themeNames };
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { DropdownMenu as e, DropdownMenuContent as t, DropdownMenuItem as n, DropdownMenuPortal as r, DropdownMenuSeparator as i, DropdownMenuSub as a, DropdownMenuSubContent as o, DropdownMenuSubTrigger as s, DropdownMenuTrigger as c } from "./components/ui/dropdown-menu.js";
|
|
3
|
+
import { formatThemeName as l, themeColors as u, themeNames as d } from "./theme-dropdown.js";
|
|
4
|
+
import f from "./cinematic-theme-switcher.js";
|
|
5
|
+
import { SidebarMenu as p, SidebarMenuButton as m, SidebarMenuItem as h } from "./components/ui/sidebar.js";
|
|
6
|
+
import { Avatar as g, AvatarFallback as _, AvatarImage as v } from "./components/ui/avatar.js";
|
|
7
|
+
import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
|
|
8
|
+
import { Bell as S, ChevronUp as C, CreditCard as w, LogOut as T, Palette as E, User2 as D } from "lucide-react";
|
|
9
|
+
import * as O from "react";
|
|
10
|
+
//#region src/sidebar-user-menu.tsx
|
|
11
|
+
function k({ trigger: e }) {
|
|
12
|
+
return /* @__PURE__ */ b(y, { children: e });
|
|
13
|
+
}
|
|
14
|
+
function A({ user: y, onSignOut: A } = {}) {
|
|
15
|
+
let j = y || {
|
|
16
|
+
name: "Guest User",
|
|
17
|
+
email: "guest@example.com",
|
|
18
|
+
image: null
|
|
19
|
+
}, [M, N] = O.useState("minimal"), [P, F] = O.useState(!1), [I, L] = O.useState(null);
|
|
20
|
+
O.useEffect(() => {
|
|
21
|
+
F(!0);
|
|
22
|
+
let e = localStorage.getItem("color-theme");
|
|
23
|
+
e && d.includes(e) && N(e);
|
|
24
|
+
}, []);
|
|
25
|
+
let R = (e) => {
|
|
26
|
+
N(e), localStorage.setItem("color-theme", e), document.cookie = `color-theme=${e}; path=/; max-age=31536000`, d.forEach((e) => document.documentElement.classList.remove(`theme-${e}`)), document.documentElement.classList.add(`theme-${e}`), L(null);
|
|
27
|
+
}, z = (e) => {
|
|
28
|
+
L(e), d.forEach((e) => document.documentElement.classList.remove(`theme-${e}`)), document.documentElement.classList.add(`theme-${e}`);
|
|
29
|
+
}, B = () => {
|
|
30
|
+
I && (d.forEach((e) => document.documentElement.classList.remove(`theme-${e}`)), document.documentElement.classList.add(`theme-${M}`), L(null));
|
|
31
|
+
}, V = j.name?.split(" ").map((e) => e[0]).join("").toUpperCase().substring(0, 2) || "GU";
|
|
32
|
+
return /* @__PURE__ */ b(p, { children: /* @__PURE__ */ b(h, { children: /* @__PURE__ */ x(e, {
|
|
33
|
+
onOpenChange: (e) => !e && B(),
|
|
34
|
+
children: [/* @__PURE__ */ b(c, {
|
|
35
|
+
asChild: !0,
|
|
36
|
+
children: /* @__PURE__ */ x(m, {
|
|
37
|
+
size: "lg",
|
|
38
|
+
className: "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
|
|
39
|
+
children: [
|
|
40
|
+
/* @__PURE__ */ x(g, {
|
|
41
|
+
className: "h-8 w-8 rounded-lg",
|
|
42
|
+
children: [/* @__PURE__ */ b(v, {
|
|
43
|
+
src: j.image || void 0,
|
|
44
|
+
alt: j.name || "User"
|
|
45
|
+
}), /* @__PURE__ */ b(_, {
|
|
46
|
+
className: "rounded-lg",
|
|
47
|
+
children: V
|
|
48
|
+
})]
|
|
49
|
+
}),
|
|
50
|
+
/* @__PURE__ */ x("div", {
|
|
51
|
+
className: "grid flex-1 text-left text-sm leading-tight group-data-[collapsible=icon]:hidden",
|
|
52
|
+
children: [/* @__PURE__ */ b("span", {
|
|
53
|
+
className: "truncate font-semibold",
|
|
54
|
+
children: j.name || "Guest"
|
|
55
|
+
}), /* @__PURE__ */ b("span", {
|
|
56
|
+
className: "truncate text-xs text-muted-foreground",
|
|
57
|
+
children: j.email
|
|
58
|
+
})]
|
|
59
|
+
}),
|
|
60
|
+
/* @__PURE__ */ b(C, { className: "ml-2 size-4 group-data-[collapsible=icon]:hidden" })
|
|
61
|
+
]
|
|
62
|
+
})
|
|
63
|
+
}), /* @__PURE__ */ x(t, {
|
|
64
|
+
className: "w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg",
|
|
65
|
+
side: "bottom",
|
|
66
|
+
align: "end",
|
|
67
|
+
sideOffset: 4,
|
|
68
|
+
children: [
|
|
69
|
+
/* @__PURE__ */ x("div", {
|
|
70
|
+
className: "flex items-center gap-2 px-1 py-1.5 text-left text-sm",
|
|
71
|
+
children: [/* @__PURE__ */ x(g, {
|
|
72
|
+
className: "h-8 w-8 rounded-lg",
|
|
73
|
+
children: [/* @__PURE__ */ b(v, {
|
|
74
|
+
src: j.image || void 0,
|
|
75
|
+
alt: j.name || "User"
|
|
76
|
+
}), /* @__PURE__ */ b(_, {
|
|
77
|
+
className: "rounded-lg",
|
|
78
|
+
children: V
|
|
79
|
+
})]
|
|
80
|
+
}), /* @__PURE__ */ x("div", {
|
|
81
|
+
className: "grid flex-1 text-left text-sm leading-tight",
|
|
82
|
+
children: [/* @__PURE__ */ b("span", {
|
|
83
|
+
className: "truncate font-semibold",
|
|
84
|
+
children: j.name || "Guest"
|
|
85
|
+
}), /* @__PURE__ */ b("span", {
|
|
86
|
+
className: "truncate text-xs text-muted-foreground",
|
|
87
|
+
children: j.email
|
|
88
|
+
})]
|
|
89
|
+
})]
|
|
90
|
+
}),
|
|
91
|
+
/* @__PURE__ */ b(i, {}),
|
|
92
|
+
/* @__PURE__ */ b(k, { trigger: /* @__PURE__ */ x(n, {
|
|
93
|
+
onSelect: (e) => e.preventDefault(),
|
|
94
|
+
children: [/* @__PURE__ */ b(D, { className: "mr-2 h-4 w-4" }), "Profile"]
|
|
95
|
+
}) }),
|
|
96
|
+
/* @__PURE__ */ x(n, { children: [/* @__PURE__ */ b(w, { className: "mr-2 h-4 w-4" }), "Billing"] }),
|
|
97
|
+
/* @__PURE__ */ x(n, { children: [/* @__PURE__ */ b(S, { className: "mr-2 h-4 w-4" }), "Notifications"] }),
|
|
98
|
+
/* @__PURE__ */ b(i, {}),
|
|
99
|
+
/* @__PURE__ */ x(a, { children: [/* @__PURE__ */ x(s, { children: [/* @__PURE__ */ b(E, { className: "mr-2 h-4 w-4" }), /* @__PURE__ */ b("span", { children: "Color Theme" })] }), /* @__PURE__ */ b(r, { children: /* @__PURE__ */ x(o, {
|
|
100
|
+
className: "max-h-[400px] overflow-y-auto",
|
|
101
|
+
children: [
|
|
102
|
+
/* @__PURE__ */ b("div", {
|
|
103
|
+
className: "px-2 py-1.5 flex items-center justify-center",
|
|
104
|
+
children: /* @__PURE__ */ b(f, {})
|
|
105
|
+
}),
|
|
106
|
+
/* @__PURE__ */ b(i, {}),
|
|
107
|
+
d.map((e) => {
|
|
108
|
+
let t = u[e];
|
|
109
|
+
return /* @__PURE__ */ b(n, {
|
|
110
|
+
onClick: () => R(e),
|
|
111
|
+
onMouseEnter: () => z(e),
|
|
112
|
+
onMouseLeave: B,
|
|
113
|
+
className: M === e ? "bg-accent" : "",
|
|
114
|
+
children: /* @__PURE__ */ x("div", {
|
|
115
|
+
className: "flex items-center justify-between w-full",
|
|
116
|
+
children: [/* @__PURE__ */ x("div", {
|
|
117
|
+
className: "flex items-center gap-2",
|
|
118
|
+
children: [t && /* @__PURE__ */ x("div", {
|
|
119
|
+
className: "flex items-center gap-1",
|
|
120
|
+
children: [/* @__PURE__ */ b("div", {
|
|
121
|
+
className: "w-3 h-3 rounded-full border border-border",
|
|
122
|
+
style: { backgroundColor: t.primary }
|
|
123
|
+
}), /* @__PURE__ */ b("div", {
|
|
124
|
+
className: "w-3 h-3 rounded-full border border-border",
|
|
125
|
+
style: { backgroundColor: t.secondary }
|
|
126
|
+
})]
|
|
127
|
+
}), /* @__PURE__ */ b("span", { children: l(e) })]
|
|
128
|
+
}), M === e && /* @__PURE__ */ b("span", {
|
|
129
|
+
className: "text-xs",
|
|
130
|
+
children: "✓"
|
|
131
|
+
})]
|
|
132
|
+
})
|
|
133
|
+
}, e);
|
|
134
|
+
})
|
|
135
|
+
]
|
|
136
|
+
}) })] }),
|
|
137
|
+
/* @__PURE__ */ b(i, {}),
|
|
138
|
+
/* @__PURE__ */ x(n, {
|
|
139
|
+
onClick: async () => {
|
|
140
|
+
await A?.();
|
|
141
|
+
},
|
|
142
|
+
children: [/* @__PURE__ */ b(T, { className: "mr-2 h-4 w-4" }), "Sign out"]
|
|
143
|
+
})
|
|
144
|
+
]
|
|
145
|
+
})]
|
|
146
|
+
}) }) });
|
|
147
|
+
}
|
|
148
|
+
//#endregion
|
|
149
|
+
export { A as SidebarUserMenu };
|