@naeil/ui 0.2.0 → 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.
- package/CHANGELOG.md +28 -0
- package/DESIGN.md +194 -0
- package/LICENSE +21 -0
- package/README.md +77 -53
- package/THIRD_PARTY_NOTICES.md +51 -0
- package/dist/{chunk-SYI3IKIC.js → chunk-QKVN6Q6C.js} +102 -19
- package/dist/components/index.d.ts +17 -8
- package/dist/components/index.js +1278 -251
- package/dist/components/ui/index.d.ts +27 -5
- package/dist/components/ui/index.js +288 -33
- package/dist/source/components/brand-artwork.generated.d.ts +162 -0
- package/dist/source/components/brand-artwork.generated.js +1103 -0
- package/dist/source/components/footer.d.ts +15 -0
- package/dist/source/components/footer.js +128 -0
- package/dist/source/components/index.d.ts +11 -0
- package/dist/source/components/index.js +26 -0
- package/dist/source/components/locale-switcher.d.ts +17 -0
- package/dist/source/components/locale-switcher.js +66 -0
- package/dist/source/components/logo.d.ts +18 -0
- package/dist/source/components/logo.js +91 -0
- package/dist/source/components/nav.d.ts +39 -0
- package/dist/source/components/nav.js +375 -0
- package/dist/source/components/theme-provider.d.ts +6 -0
- package/dist/source/components/theme-provider.js +45 -0
- package/dist/source/components/theme-toggle-icon.d.ts +5 -0
- package/dist/source/components/theme-toggle-icon.js +62 -0
- package/dist/source/components/theme-toggle.d.ts +5 -0
- package/dist/source/components/theme-toggle.js +34 -0
- package/dist/source/components/typography.d.ts +12 -0
- package/dist/source/components/typography.js +49 -0
- package/dist/source/components/ui/avatar.d.ts +14 -0
- package/dist/source/components/ui/avatar.js +137 -0
- package/dist/source/components/ui/badge.d.ts +13 -0
- package/dist/source/components/ui/badge.js +76 -0
- package/dist/source/components/ui/button.d.ts +14 -0
- package/dist/source/components/ui/button.js +88 -0
- package/dist/source/components/ui/card.d.ts +13 -0
- package/dist/source/components/ui/card.js +135 -0
- package/dist/source/components/ui/checkbox.d.ts +7 -0
- package/dist/source/components/ui/checkbox.js +58 -0
- package/dist/source/components/ui/dialog.d.ts +20 -0
- package/dist/source/components/ui/dialog.js +182 -0
- package/dist/source/components/ui/dropdown-menu.d.ts +28 -0
- package/dist/source/components/ui/dropdown-menu.js +282 -0
- package/dist/source/components/ui/index.d.ts +19 -0
- package/dist/source/components/ui/index.js +131 -0
- package/dist/source/components/ui/input.d.ts +6 -0
- package/dist/source/components/ui/input.js +49 -0
- package/dist/source/components/ui/select.d.ts +16 -0
- package/dist/source/components/ui/select.js +197 -0
- package/dist/source/components/ui/sonner.d.ts +6 -0
- package/dist/source/components/ui/sonner.js +80 -0
- package/dist/source/components/ui/switch.d.ts +7 -0
- package/dist/source/components/ui/switch.js +54 -0
- package/dist/source/components/ui/tabs.d.ts +10 -0
- package/dist/source/components/ui/tabs.js +57 -0
- package/dist/source/components/ui/textarea.d.ts +6 -0
- package/dist/source/components/ui/textarea.js +46 -0
- package/dist/source/i18n/config.d.ts +6 -0
- package/dist/source/i18n/config.js +12 -0
- package/dist/source/i18n/routing.d.ts +371 -0
- package/dist/source/i18n/routing.js +17 -0
- package/dist/source/lib/design/modal-inert.d.ts +6 -0
- package/dist/source/lib/design/modal-inert.js +73 -0
- package/dist/source/lib/utils.d.ts +5 -0
- package/dist/source/lib/utils.js +8 -0
- package/dist/tokens.ts +217 -0
- package/docs/components/README.md +21 -0
- package/docs/components/avatar.md +47 -0
- package/docs/components/badge.md +29 -0
- package/docs/components/button.md +39 -0
- package/docs/components/card.md +32 -0
- package/docs/components/checkbox.md +35 -0
- package/docs/components/common.md +31 -0
- package/docs/components/composition.md +68 -0
- package/docs/components/dialog.md +41 -0
- package/docs/components/dropdown-menu.md +38 -0
- package/docs/components/input.md +32 -0
- package/docs/components/select.md +39 -0
- package/docs/components/sonner.md +37 -0
- package/docs/components/switch.md +33 -0
- package/docs/components/tabs.md +40 -0
- package/docs/components/textarea.md +35 -0
- package/docs/design/component-demand.md +30 -0
- package/docs/design/public-ui-final-verification.md +96 -0
- package/docs/design/public-ui-release-validation.md +86 -0
- package/docs/design/public-ui-stage3-verification.md +98 -0
- package/docs/design/public-ui-stage4-verification.md +129 -0
- package/docs/design/public-ui-support.md +42 -0
- package/docs/design/v2-migration.md +229 -0
- package/docs/package-release.md +108 -0
- package/licenses/Lato-OFL.txt +93 -0
- package/licenses/Noto-Sans-JP-OFL.txt +93 -0
- package/licenses/Nunito-Sans-OFL.txt +93 -0
- package/licenses/Pretendard-OFL.txt +94 -0
- package/licenses/React-MIT.txt +21 -0
- package/licenses/Storybook-MIT.txt +21 -0
- package/licenses/popper-MIT.txt +25 -0
- package/licenses/react-remove-scroll-bar-MIT.txt +21 -0
- package/licenses/store2-MIT.txt +22 -0
- package/licenses/toggle-selection-MIT.txt +21 -0
- package/package.json +184 -34
- package/src/styles/components.css +276 -0
- package/src/styles/globals.css +18 -0
- package/src/styles/theme.css +185 -98
- package/messages/en.json +0 -221
- package/messages/ja.json +0 -221
- package/messages/ko.json +0 -221
- package/src/app/globals.css +0 -32
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
5
|
+
import { Logo } from "./logo.js";
|
|
6
|
+
import { Badge } from "./ui/badge.js";
|
|
7
|
+
import Image from "next/image";
|
|
8
|
+
const PROJECTS = [
|
|
9
|
+
{
|
|
10
|
+
key: "cc",
|
|
11
|
+
href: "/cc",
|
|
12
|
+
accent: "oklch(0.704 0.140 181)",
|
|
13
|
+
icon: "/images/coral.png",
|
|
14
|
+
status: "active"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
key: "pkm",
|
|
18
|
+
href: "/pkm",
|
|
19
|
+
accent: "oklch(0.702 0.183 293)",
|
|
20
|
+
icon: "/images/jellyfish.png",
|
|
21
|
+
status: "coming"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
key: "naeilUi",
|
|
25
|
+
href: "/design",
|
|
26
|
+
accent: "oklch(0.623 0.214 259)",
|
|
27
|
+
icon: "/images/whale.png",
|
|
28
|
+
status: "active"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
key: "sa",
|
|
32
|
+
href: "/sa",
|
|
33
|
+
accent: "oklch(0.723 0.219 149)",
|
|
34
|
+
icon: "/images/fish.png",
|
|
35
|
+
status: "active"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
key: "babyAgent",
|
|
39
|
+
href: "/baby-agent",
|
|
40
|
+
accent: "oklch(0.769 0.188 70.08)",
|
|
41
|
+
icon: "/images/turtle.png",
|
|
42
|
+
status: "coming"
|
|
43
|
+
}
|
|
44
|
+
];
|
|
45
|
+
function Nav({
|
|
46
|
+
Link,
|
|
47
|
+
usePathname,
|
|
48
|
+
brandHref = "/",
|
|
49
|
+
brandExternal = false,
|
|
50
|
+
brandSlot,
|
|
51
|
+
projectsExternal = false,
|
|
52
|
+
externalBaseUrl = "https://naeil.dev",
|
|
53
|
+
currentProjectKey,
|
|
54
|
+
currentProjectHref,
|
|
55
|
+
subNav,
|
|
56
|
+
authSlot,
|
|
57
|
+
showProjects = true,
|
|
58
|
+
showBlog = true,
|
|
59
|
+
toolbarSlot
|
|
60
|
+
}) {
|
|
61
|
+
const t = useTranslations("nav");
|
|
62
|
+
const pt = useTranslations("projects");
|
|
63
|
+
const pathname = usePathname();
|
|
64
|
+
const [scrolled, setScrolled] = useState(false);
|
|
65
|
+
const [mobileOpen, setMobileOpen] = useState(false);
|
|
66
|
+
const [projectsOpen, setProjectsOpen] = useState(false);
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
const onScroll = () => setScrolled(window.scrollY > 16);
|
|
69
|
+
window.addEventListener("scroll", onScroll, { passive: true });
|
|
70
|
+
return () => window.removeEventListener("scroll", onScroll);
|
|
71
|
+
}, []);
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
setMobileOpen(false);
|
|
74
|
+
setProjectsOpen(false);
|
|
75
|
+
}, [pathname]);
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
document.body.style.overflow = mobileOpen ? "hidden" : "";
|
|
78
|
+
return () => {
|
|
79
|
+
document.body.style.overflow = "";
|
|
80
|
+
};
|
|
81
|
+
}, [mobileOpen]);
|
|
82
|
+
const linkClass = (href) => {
|
|
83
|
+
const isActive = pathname === href;
|
|
84
|
+
return [
|
|
85
|
+
"text-sm font-medium transition-colors",
|
|
86
|
+
isActive ? "text-foreground" : "text-muted-foreground hover:text-foreground"
|
|
87
|
+
].join(" ");
|
|
88
|
+
};
|
|
89
|
+
const isProjectActive = pathname.startsWith("/projects") || pathname.startsWith("/cc") || pathname.startsWith("/pkm") || pathname.startsWith("/sa") || pathname.startsWith("/design");
|
|
90
|
+
function getProjectLink(project) {
|
|
91
|
+
if (currentProjectKey && project.key === currentProjectKey) {
|
|
92
|
+
return { href: currentProjectHref || "/", external: false };
|
|
93
|
+
}
|
|
94
|
+
if (projectsExternal) {
|
|
95
|
+
return { href: `${externalBaseUrl}${project.href}`, external: true };
|
|
96
|
+
}
|
|
97
|
+
return { href: project.href, external: false };
|
|
98
|
+
}
|
|
99
|
+
const brandContent = brandSlot != null ? brandSlot : /* @__PURE__ */ jsx(Logo, { variant: "horizontal", size: 28, className: "block" });
|
|
100
|
+
const brandElement = brandExternal ? /* @__PURE__ */ jsx("a", { href: brandHref, children: brandContent }) : /* @__PURE__ */ jsx(Link, { href: brandHref, children: brandContent });
|
|
101
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
102
|
+
/* @__PURE__ */ jsx(
|
|
103
|
+
"nav",
|
|
104
|
+
{
|
|
105
|
+
className: [
|
|
106
|
+
"fixed top-0 z-50 w-full transition-[background-color,border-color] duration-300",
|
|
107
|
+
scrolled || mobileOpen ? "border-b border-border/40 bg-background/80 backdrop-blur-md" : "border-b border-transparent bg-transparent"
|
|
108
|
+
].join(" "),
|
|
109
|
+
children: /* @__PURE__ */ jsxs("div", { className: "mx-auto flex h-[58px] max-w-7xl items-center px-6", children: [
|
|
110
|
+
/* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center md:w-[200px]", children: brandElement }),
|
|
111
|
+
/* @__PURE__ */ jsxs("div", { className: "hidden flex-1 items-center gap-6 md:flex", children: [
|
|
112
|
+
showProjects && /* @__PURE__ */ jsxs("div", { className: "group relative", children: [
|
|
113
|
+
/* @__PURE__ */ jsxs(
|
|
114
|
+
"button",
|
|
115
|
+
{
|
|
116
|
+
className: [
|
|
117
|
+
"text-sm font-medium transition-colors",
|
|
118
|
+
isProjectActive ? "text-foreground" : "text-muted-foreground hover:text-foreground"
|
|
119
|
+
].join(" "),
|
|
120
|
+
children: [
|
|
121
|
+
t("projects"),
|
|
122
|
+
/* @__PURE__ */ jsx(
|
|
123
|
+
"svg",
|
|
124
|
+
{
|
|
125
|
+
width: "10",
|
|
126
|
+
height: "10",
|
|
127
|
+
viewBox: "0 0 24 24",
|
|
128
|
+
fill: "none",
|
|
129
|
+
stroke: "currentColor",
|
|
130
|
+
strokeWidth: "2",
|
|
131
|
+
strokeLinecap: "round",
|
|
132
|
+
strokeLinejoin: "round",
|
|
133
|
+
className: "ml-1 inline-block transition-transform group-hover:rotate-180",
|
|
134
|
+
children: /* @__PURE__ */ jsx("path", { d: "M6 9l6 6 6-6" })
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
),
|
|
140
|
+
/* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute left-0 top-full pt-3 opacity-0 transition-opacity duration-150 group-hover:pointer-events-auto group-hover:opacity-100", children: /* @__PURE__ */ jsx("div", { className: "border-border/40 bg-background/95 w-[520px] rounded-xl border p-4 shadow-xl backdrop-blur-md", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-1", children: PROJECTS.map((project) => {
|
|
141
|
+
const { href, external } = getProjectLink(project);
|
|
142
|
+
const inner = /* @__PURE__ */ jsxs("div", { className: "hover:bg-muted/50 flex items-start gap-3.5 rounded-lg px-3 py-3 transition-colors", children: [
|
|
143
|
+
/* @__PURE__ */ jsx(
|
|
144
|
+
"div",
|
|
145
|
+
{
|
|
146
|
+
className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg border",
|
|
147
|
+
style: {
|
|
148
|
+
borderColor: `color-mix(in oklch, ${project.accent} 30%, transparent)`,
|
|
149
|
+
backgroundColor: `color-mix(in oklch, ${project.accent} 8%, transparent)`
|
|
150
|
+
},
|
|
151
|
+
children: /* @__PURE__ */ jsx(
|
|
152
|
+
Image,
|
|
153
|
+
{
|
|
154
|
+
src: project.icon,
|
|
155
|
+
alt: "",
|
|
156
|
+
width: 24,
|
|
157
|
+
height: 24,
|
|
158
|
+
className: "object-contain"
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
),
|
|
163
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 pt-0.5", children: [
|
|
164
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
165
|
+
/* @__PURE__ */ jsx("span", { className: "text-foreground text-sm font-medium", children: pt(`${project.key}.name`) }),
|
|
166
|
+
project.status === "coming" && /* @__PURE__ */ jsx(
|
|
167
|
+
Badge,
|
|
168
|
+
{
|
|
169
|
+
variant: "outline",
|
|
170
|
+
className: "text-muted-foreground px-1 py-0 text-[9px]",
|
|
171
|
+
children: pt("status.coming")
|
|
172
|
+
}
|
|
173
|
+
)
|
|
174
|
+
] }),
|
|
175
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-0.5 text-xs leading-snug", children: pt(`${project.key}.description`) })
|
|
176
|
+
] })
|
|
177
|
+
] });
|
|
178
|
+
if (external) {
|
|
179
|
+
return /* @__PURE__ */ jsx("a", { href, children: inner }, project.key);
|
|
180
|
+
}
|
|
181
|
+
return /* @__PURE__ */ jsx(Link, { href, children: inner }, project.key);
|
|
182
|
+
}) }) }) })
|
|
183
|
+
] }),
|
|
184
|
+
showBlog && /* @__PURE__ */ jsx(Fragment, { children: projectsExternal ? /* @__PURE__ */ jsx(
|
|
185
|
+
"a",
|
|
186
|
+
{
|
|
187
|
+
href: `${externalBaseUrl}/blog`,
|
|
188
|
+
className: "text-sm font-medium text-muted-foreground transition-colors hover:text-foreground",
|
|
189
|
+
children: t("blog")
|
|
190
|
+
}
|
|
191
|
+
) : /* @__PURE__ */ jsx(Link, { href: "/blog", className: linkClass("/blog"), children: t("blog") }) }),
|
|
192
|
+
subNav && subNav.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
193
|
+
/* @__PURE__ */ jsx("div", { className: "h-4 w-px bg-border/40" }),
|
|
194
|
+
subNav.map((item) => /* @__PURE__ */ jsx(
|
|
195
|
+
Link,
|
|
196
|
+
{
|
|
197
|
+
href: item.href,
|
|
198
|
+
className: linkClass(item.href),
|
|
199
|
+
children: item.label
|
|
200
|
+
},
|
|
201
|
+
item.href
|
|
202
|
+
))
|
|
203
|
+
] })
|
|
204
|
+
] }),
|
|
205
|
+
/* @__PURE__ */ jsxs("div", { className: "hidden items-center gap-3 md:flex", children: [
|
|
206
|
+
authSlot,
|
|
207
|
+
authSlot && toolbarSlot && /* @__PURE__ */ jsx("div", { className: "h-4 w-px bg-border/40" }),
|
|
208
|
+
toolbarSlot && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-4", children: toolbarSlot })
|
|
209
|
+
] }),
|
|
210
|
+
/* @__PURE__ */ jsx(
|
|
211
|
+
"button",
|
|
212
|
+
{
|
|
213
|
+
className: "text-muted-foreground hover:text-foreground ml-auto transition-colors md:hidden",
|
|
214
|
+
onClick: () => setMobileOpen(!mobileOpen),
|
|
215
|
+
"aria-label": "Menu",
|
|
216
|
+
children: mobileOpen ? /* @__PURE__ */ jsx(CloseIcon, {}) : /* @__PURE__ */ jsx(MenuIcon, {})
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
] })
|
|
220
|
+
}
|
|
221
|
+
),
|
|
222
|
+
mobileOpen && /* @__PURE__ */ jsx("div", { className: "bg-background/95 fixed inset-0 z-40 overflow-y-auto pt-[58px] backdrop-blur-md md:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col px-6 py-6", children: [
|
|
223
|
+
showProjects && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
224
|
+
/* @__PURE__ */ jsxs(
|
|
225
|
+
"button",
|
|
226
|
+
{
|
|
227
|
+
className: "text-foreground flex items-center justify-between py-3 text-base font-medium",
|
|
228
|
+
onClick: () => setProjectsOpen(!projectsOpen),
|
|
229
|
+
children: [
|
|
230
|
+
t("projects"),
|
|
231
|
+
/* @__PURE__ */ jsx(
|
|
232
|
+
"svg",
|
|
233
|
+
{
|
|
234
|
+
width: "14",
|
|
235
|
+
height: "14",
|
|
236
|
+
viewBox: "0 0 24 24",
|
|
237
|
+
fill: "none",
|
|
238
|
+
stroke: "currentColor",
|
|
239
|
+
strokeWidth: "2",
|
|
240
|
+
strokeLinecap: "round",
|
|
241
|
+
strokeLinejoin: "round",
|
|
242
|
+
className: [
|
|
243
|
+
"transition-transform duration-200",
|
|
244
|
+
projectsOpen ? "rotate-180" : ""
|
|
245
|
+
].join(" "),
|
|
246
|
+
children: /* @__PURE__ */ jsx("path", { d: "M6 9l6 6 6-6" })
|
|
247
|
+
}
|
|
248
|
+
)
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
),
|
|
252
|
+
projectsOpen && /* @__PURE__ */ jsx("div", { className: "mb-2 flex flex-col gap-1 pl-1", children: PROJECTS.map((project) => {
|
|
253
|
+
const { href, external } = getProjectLink(project);
|
|
254
|
+
const inner = /* @__PURE__ */ jsxs("div", { className: "hover:bg-muted/50 flex items-center gap-3 rounded-lg px-3 py-3 transition-colors", children: [
|
|
255
|
+
/* @__PURE__ */ jsx(
|
|
256
|
+
"div",
|
|
257
|
+
{
|
|
258
|
+
className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border",
|
|
259
|
+
style: {
|
|
260
|
+
borderColor: `color-mix(in oklch, ${project.accent} 30%, transparent)`,
|
|
261
|
+
backgroundColor: `color-mix(in oklch, ${project.accent} 8%, transparent)`
|
|
262
|
+
},
|
|
263
|
+
children: /* @__PURE__ */ jsx(
|
|
264
|
+
Image,
|
|
265
|
+
{
|
|
266
|
+
src: project.icon,
|
|
267
|
+
alt: "",
|
|
268
|
+
width: 20,
|
|
269
|
+
height: 20,
|
|
270
|
+
className: "object-contain"
|
|
271
|
+
}
|
|
272
|
+
)
|
|
273
|
+
}
|
|
274
|
+
),
|
|
275
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
276
|
+
/* @__PURE__ */ jsx("span", { className: "text-foreground text-sm font-medium", children: pt(`${project.key}.name`) }),
|
|
277
|
+
project.status === "coming" && /* @__PURE__ */ jsx(
|
|
278
|
+
Badge,
|
|
279
|
+
{
|
|
280
|
+
variant: "outline",
|
|
281
|
+
className: "text-muted-foreground ml-2 px-1 py-0 text-[9px]",
|
|
282
|
+
children: pt("status.coming")
|
|
283
|
+
}
|
|
284
|
+
)
|
|
285
|
+
] })
|
|
286
|
+
] });
|
|
287
|
+
if (external) {
|
|
288
|
+
return /* @__PURE__ */ jsx(
|
|
289
|
+
"a",
|
|
290
|
+
{
|
|
291
|
+
href,
|
|
292
|
+
onClick: () => setMobileOpen(false),
|
|
293
|
+
children: inner
|
|
294
|
+
},
|
|
295
|
+
project.key
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
return /* @__PURE__ */ jsx(
|
|
299
|
+
Link,
|
|
300
|
+
{
|
|
301
|
+
href,
|
|
302
|
+
onClick: () => setMobileOpen(false),
|
|
303
|
+
children: inner
|
|
304
|
+
},
|
|
305
|
+
project.key
|
|
306
|
+
);
|
|
307
|
+
}) })
|
|
308
|
+
] }),
|
|
309
|
+
showBlog && /* @__PURE__ */ jsx(Fragment, { children: projectsExternal ? /* @__PURE__ */ jsx(
|
|
310
|
+
"a",
|
|
311
|
+
{
|
|
312
|
+
href: `${externalBaseUrl}/blog`,
|
|
313
|
+
className: "text-foreground border-border/40 border-t py-3 text-base font-medium",
|
|
314
|
+
onClick: () => setMobileOpen(false),
|
|
315
|
+
children: t("blog")
|
|
316
|
+
}
|
|
317
|
+
) : /* @__PURE__ */ jsx(
|
|
318
|
+
Link,
|
|
319
|
+
{
|
|
320
|
+
href: "/blog",
|
|
321
|
+
className: "text-foreground border-border/40 border-t py-3 text-base font-medium",
|
|
322
|
+
onClick: () => setMobileOpen(false),
|
|
323
|
+
children: t("blog")
|
|
324
|
+
}
|
|
325
|
+
) }),
|
|
326
|
+
subNav && subNav.length > 0 && /* @__PURE__ */ jsx("div", { className: "border-border/40 border-t", children: subNav.map((item) => /* @__PURE__ */ jsx(
|
|
327
|
+
Link,
|
|
328
|
+
{
|
|
329
|
+
href: item.href,
|
|
330
|
+
className: "text-foreground block py-3 text-base font-medium",
|
|
331
|
+
onClick: () => setMobileOpen(false),
|
|
332
|
+
children: item.label
|
|
333
|
+
},
|
|
334
|
+
item.href
|
|
335
|
+
)) }),
|
|
336
|
+
authSlot && /* @__PURE__ */ jsx("div", { className: "border-border/40 border-t pt-4", children: authSlot }),
|
|
337
|
+
toolbarSlot && /* @__PURE__ */ jsx("div", { className: "border-border/40 flex items-center gap-4 border-t pt-4 mt-2", children: toolbarSlot })
|
|
338
|
+
] }) })
|
|
339
|
+
] });
|
|
340
|
+
}
|
|
341
|
+
function MenuIcon() {
|
|
342
|
+
return /* @__PURE__ */ jsx(
|
|
343
|
+
"svg",
|
|
344
|
+
{
|
|
345
|
+
width: "22",
|
|
346
|
+
height: "22",
|
|
347
|
+
viewBox: "0 0 24 24",
|
|
348
|
+
fill: "none",
|
|
349
|
+
stroke: "currentColor",
|
|
350
|
+
strokeWidth: "1.5",
|
|
351
|
+
strokeLinecap: "round",
|
|
352
|
+
strokeLinejoin: "round",
|
|
353
|
+
children: /* @__PURE__ */ jsx("path", { d: "M4 6h16M4 12h16M4 18h16" })
|
|
354
|
+
}
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
function CloseIcon() {
|
|
358
|
+
return /* @__PURE__ */ jsx(
|
|
359
|
+
"svg",
|
|
360
|
+
{
|
|
361
|
+
width: "22",
|
|
362
|
+
height: "22",
|
|
363
|
+
viewBox: "0 0 24 24",
|
|
364
|
+
fill: "none",
|
|
365
|
+
stroke: "currentColor",
|
|
366
|
+
strokeWidth: "1.5",
|
|
367
|
+
strokeLinecap: "round",
|
|
368
|
+
strokeLinejoin: "round",
|
|
369
|
+
children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
|
|
370
|
+
}
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
export {
|
|
374
|
+
Nav
|
|
375
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ThemeProvider as ThemeProvider$1 } from 'next-themes';
|
|
3
|
+
|
|
4
|
+
declare function ThemeProvider({ children, ...props }: React.ComponentProps<typeof ThemeProvider$1>): react_jsx_runtime.JSX.Element;
|
|
5
|
+
|
|
6
|
+
export { ThemeProvider };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
4
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
5
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __spreadValues = (a, b) => {
|
|
10
|
+
for (var prop in b || (b = {}))
|
|
11
|
+
if (__hasOwnProp.call(b, prop))
|
|
12
|
+
__defNormalProp(a, prop, b[prop]);
|
|
13
|
+
if (__getOwnPropSymbols)
|
|
14
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
+
if (__propIsEnum.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
}
|
|
18
|
+
return a;
|
|
19
|
+
};
|
|
20
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
|
+
var __objRest = (source, exclude) => {
|
|
22
|
+
var target = {};
|
|
23
|
+
for (var prop in source)
|
|
24
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
25
|
+
target[prop] = source[prop];
|
|
26
|
+
if (source != null && __getOwnPropSymbols)
|
|
27
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
28
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
29
|
+
target[prop] = source[prop];
|
|
30
|
+
}
|
|
31
|
+
return target;
|
|
32
|
+
};
|
|
33
|
+
import { jsx } from "react/jsx-runtime";
|
|
34
|
+
import { ThemeProvider as NextThemesProvider } from "next-themes";
|
|
35
|
+
function ThemeProvider(_a) {
|
|
36
|
+
var _b = _a, {
|
|
37
|
+
children
|
|
38
|
+
} = _b, props = __objRest(_b, [
|
|
39
|
+
"children"
|
|
40
|
+
]);
|
|
41
|
+
return /* @__PURE__ */ jsx(NextThemesProvider, __spreadProps(__spreadValues({}, props), { children }));
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
ThemeProvider
|
|
45
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useTheme } from "next-themes";
|
|
4
|
+
import { useSyncExternalStore } from "react";
|
|
5
|
+
const emptySubscribe = () => () => {
|
|
6
|
+
};
|
|
7
|
+
function useIsMounted() {
|
|
8
|
+
return useSyncExternalStore(
|
|
9
|
+
emptySubscribe,
|
|
10
|
+
() => true,
|
|
11
|
+
() => false
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
function ThemeToggleIcon() {
|
|
15
|
+
const { resolvedTheme, setTheme } = useTheme();
|
|
16
|
+
const mounted = useIsMounted();
|
|
17
|
+
if (!mounted) {
|
|
18
|
+
return /* @__PURE__ */ jsx("div", { className: "h-4 w-4" });
|
|
19
|
+
}
|
|
20
|
+
const isDark = resolvedTheme === "dark";
|
|
21
|
+
return /* @__PURE__ */ jsx(
|
|
22
|
+
"button",
|
|
23
|
+
{
|
|
24
|
+
onClick: () => setTheme(isDark ? "light" : "dark"),
|
|
25
|
+
className: "ui-control ui-focus inline-flex w-11 items-center justify-center text-muted-foreground hover:text-foreground",
|
|
26
|
+
"aria-label": isDark ? "Switch to light mode" : "Switch to dark mode",
|
|
27
|
+
children: isDark ? /* @__PURE__ */ jsxs(
|
|
28
|
+
"svg",
|
|
29
|
+
{
|
|
30
|
+
width: "16",
|
|
31
|
+
height: "16",
|
|
32
|
+
viewBox: "0 0 24 24",
|
|
33
|
+
fill: "none",
|
|
34
|
+
stroke: "currentColor",
|
|
35
|
+
strokeWidth: "1.5",
|
|
36
|
+
strokeLinecap: "round",
|
|
37
|
+
strokeLinejoin: "round",
|
|
38
|
+
children: [
|
|
39
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "5" }),
|
|
40
|
+
/* @__PURE__ */ jsx("path", { d: "M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" })
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
) : /* @__PURE__ */ jsx(
|
|
44
|
+
"svg",
|
|
45
|
+
{
|
|
46
|
+
width: "16",
|
|
47
|
+
height: "16",
|
|
48
|
+
viewBox: "0 0 24 24",
|
|
49
|
+
fill: "none",
|
|
50
|
+
stroke: "currentColor",
|
|
51
|
+
strokeWidth: "1.5",
|
|
52
|
+
strokeLinecap: "round",
|
|
53
|
+
strokeLinejoin: "round",
|
|
54
|
+
children: /* @__PURE__ */ jsx("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" })
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
ThemeToggleIcon
|
|
62
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useTheme } from "next-themes";
|
|
4
|
+
import { useSyncExternalStore } from "react";
|
|
5
|
+
import { Button } from "./ui/button.js";
|
|
6
|
+
const emptySubscribe = () => () => {
|
|
7
|
+
};
|
|
8
|
+
function useIsMounted() {
|
|
9
|
+
return useSyncExternalStore(
|
|
10
|
+
emptySubscribe,
|
|
11
|
+
() => true,
|
|
12
|
+
() => false
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
function ThemeToggle() {
|
|
16
|
+
const { resolvedTheme, setTheme } = useTheme();
|
|
17
|
+
const mounted = useIsMounted();
|
|
18
|
+
if (!mounted) {
|
|
19
|
+
return /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", className: "w-24", children: "\u2026" });
|
|
20
|
+
}
|
|
21
|
+
return /* @__PURE__ */ jsx(
|
|
22
|
+
Button,
|
|
23
|
+
{
|
|
24
|
+
variant: "outline",
|
|
25
|
+
size: "sm",
|
|
26
|
+
className: "w-24",
|
|
27
|
+
onClick: () => setTheme(resolvedTheme === "dark" ? "light" : "dark"),
|
|
28
|
+
children: resolvedTheme === "dark" ? "\u2600\uFE0F Light" : "\u{1F319} Dark"
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
export {
|
|
33
|
+
ThemeToggle
|
|
34
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
|
|
4
|
+
type HeadingProps = react.HTMLAttributes<HTMLHeadingElement> & {
|
|
5
|
+
children: react.ReactNode;
|
|
6
|
+
};
|
|
7
|
+
declare const pageTitleClass = "text-foreground text-3xl font-semibold leading-tight";
|
|
8
|
+
declare const sectionTitleClass = "text-foreground text-xl font-semibold";
|
|
9
|
+
declare function PageTitle({ className, children, ...props }: HeadingProps): react_jsx_runtime.JSX.Element;
|
|
10
|
+
declare function SectionTitle({ className, children, ...props }: HeadingProps): react_jsx_runtime.JSX.Element;
|
|
11
|
+
|
|
12
|
+
export { PageTitle, SectionTitle, pageTitleClass, sectionTitleClass };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __objRest = (source, exclude) => {
|
|
21
|
+
var target = {};
|
|
22
|
+
for (var prop in source)
|
|
23
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
24
|
+
target[prop] = source[prop];
|
|
25
|
+
if (source != null && __getOwnPropSymbols)
|
|
26
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
27
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
28
|
+
target[prop] = source[prop];
|
|
29
|
+
}
|
|
30
|
+
return target;
|
|
31
|
+
};
|
|
32
|
+
import { jsx } from "react/jsx-runtime";
|
|
33
|
+
import { cn } from "../lib/utils.js";
|
|
34
|
+
const pageTitleClass = "text-foreground text-3xl font-semibold leading-tight";
|
|
35
|
+
const sectionTitleClass = "text-foreground text-xl font-semibold";
|
|
36
|
+
function PageTitle(_a) {
|
|
37
|
+
var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
|
|
38
|
+
return /* @__PURE__ */ jsx("h1", __spreadProps(__spreadValues({ className: cn(pageTitleClass, className) }, props), { children }));
|
|
39
|
+
}
|
|
40
|
+
function SectionTitle(_c) {
|
|
41
|
+
var _d = _c, { className, children } = _d, props = __objRest(_d, ["className", "children"]);
|
|
42
|
+
return /* @__PURE__ */ jsx("h2", __spreadProps(__spreadValues({ className: cn(sectionTitleClass, className) }, props), { children }));
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
PageTitle,
|
|
46
|
+
SectionTitle,
|
|
47
|
+
pageTitleClass,
|
|
48
|
+
sectionTitleClass
|
|
49
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { Avatar as Avatar$1 } from 'radix-ui';
|
|
4
|
+
|
|
5
|
+
declare function Avatar({ className, size, ...props }: react.ComponentProps<typeof Avatar$1.Root> & {
|
|
6
|
+
size?: "default" | "sm" | "lg";
|
|
7
|
+
}): react_jsx_runtime.JSX.Element;
|
|
8
|
+
declare function AvatarImage({ className, ...props }: react.ComponentProps<typeof Avatar$1.Image>): react_jsx_runtime.JSX.Element;
|
|
9
|
+
declare function AvatarFallback({ className, ...props }: react.ComponentProps<typeof Avatar$1.Fallback>): react_jsx_runtime.JSX.Element;
|
|
10
|
+
declare function AvatarBadge({ className, ...props }: react.ComponentProps<"span">): react_jsx_runtime.JSX.Element;
|
|
11
|
+
declare function AvatarGroup({ className, ...props }: react.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
12
|
+
declare function AvatarGroupCount({ className, ...props }: react.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
13
|
+
|
|
14
|
+
export { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage };
|