@naeil/ui 0.6.0 → 0.7.1

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 (38) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/contracts/naeil-chrome.v1.json +12 -0
  3. package/dist/chunk-HSTDPY56.js +74 -0
  4. package/dist/chunk-OLKTEYLS.js +413 -0
  5. package/dist/{chunk-CE73AEJZ.js → chunk-QQQQZEPV.js} +249 -3
  6. package/dist/{chunk-VL7FS4QM.js → chunk-VWIUN35X.js} +4 -343
  7. package/dist/components/index.d.ts +2 -2
  8. package/dist/components/index.js +10 -8
  9. package/dist/components/naeil-footer.d.ts +16 -0
  10. package/dist/components/naeil-footer.js +76 -0
  11. package/dist/components/naeil-header.d.ts +23 -5
  12. package/dist/components/naeil-header.js +5 -2
  13. package/dist/components/ui/index.d.ts +2 -2
  14. package/dist/components/ui/index.js +6 -6
  15. package/dist/lib/ui-release.d.ts +1 -0
  16. package/dist/lib/ui-release.js +1 -0
  17. package/dist/naeil-header-content-BvISJ4RV.d.ts +4 -0
  18. package/dist/{navigation-CL10a6Eb.d.ts → navigation-CgPeL9tF.d.ts} +1 -1
  19. package/dist/{site-footer-B67meCDv.d.ts → site-footer-vXDa_6yr.d.ts} +4 -2
  20. package/dist/source/components/naeil-footer.d.ts +16 -0
  21. package/dist/source/components/naeil-footer.js +95 -0
  22. package/dist/source/components/naeil-header-account.d.ts +26 -0
  23. package/dist/source/components/naeil-header-account.js +67 -0
  24. package/dist/source/components/naeil-header.d.ts +2 -1
  25. package/dist/source/components/naeil-header.js +5 -0
  26. package/dist/source/components/ui/site-footer.d.ts +4 -2
  27. package/dist/source/components/ui/site-footer.js +6 -2
  28. package/dist/source/lib/ui-release.d.ts +6 -0
  29. package/dist/source/lib/ui-release.js +4 -0
  30. package/docs/components/README.md +2 -1
  31. package/docs/components/application-layout.md +8 -7
  32. package/docs/components/naeil-footer.md +20 -0
  33. package/docs/components/naeil-header.md +21 -5
  34. package/docs/components/navigation.md +3 -1
  35. package/docs/package-release.md +3 -1
  36. package/package.json +16 -4
  37. package/src/styles/components.css +35 -0
  38. package/dist/chunk-QSTGUEEI.js +0 -323
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.1 — account presentation correction (candidate)
4
+
5
+ - Add canonical `NaeilHeaderAccountControl` for shared login/account/logout presentation while consumers retain session and save guards.
6
+ - Preserve existing header slots and imports; include authenticated menu/busy/failure coverage and packed consumer checks.
7
+
8
+ ## 0.7.0 — unpublished candidate
9
+
10
+ - Add React-only canonical NaeilFooter with full/compact content, localized destinations and save-navigation adapters. Preserve generic and Next Footer overrides.
11
+ - Add SiteFooter onNavigate for every group link including native external anchors.
12
+ - Add package/chrome-contract identity, independent rendered release references and fail-closed service rollout verification.
13
+ - Keep approved 1600px/clamp frame and purpose-specific content widths unchanged.
14
+
15
+
3
16
  ## 0.6.0 — shared application frame (2026-10-16)
4
17
 
5
18
  - Align Navigation, SiteFooter, NaeilHeader and preserved Nav/Footer adapters with a shared 1600px maximum outer frame and responsive `clamp(16px, 2.4vw, 40px)` gutters. Add `ui-app-frame` for main composition; retain explicit classes and product token overrides.
@@ -0,0 +1,12 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "contractVersion": "1",
4
+ "authority": "DESIGN.md: approved 2026-10-16 frame; shared-ui-rollout spec: canonical footer and guard",
5
+ "frame": { "maxWidth": 1600, "gutterMin": 16, "gutterVw": 2.4, "gutterMax": 40 },
6
+ "header": { "height": 65, "brandHeight": 28, "desktopBrandReservation": 160 },
7
+ "footer": { "variants": ["full", "compact"], "brandHeight": 20, "requiredPaths": ["/", "/projects", "/blog"], "github": "https://github.com/naeil-dev" },
8
+ "viewports": [390, 768, 1440, 1920],
9
+ "themes": ["light", "dark"],
10
+ "locales": ["en", "ko", "ja"],
11
+ "tolerancePx": 1
12
+ }
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ import {
3
+ __objRest,
4
+ __spreadProps,
5
+ __spreadValues,
6
+ cn
7
+ } from "./chunk-JBTDRVZ7.js";
8
+
9
+ // src/components/ui/site-footer.tsx
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ function SiteFooter(_a) {
12
+ var _b = _a, {
13
+ brand,
14
+ description,
15
+ groups = [],
16
+ Link,
17
+ meta,
18
+ children,
19
+ containerClassName,
20
+ className,
21
+ variant = "full",
22
+ onNavigate
23
+ } = _b, props = __objRest(_b, [
24
+ "brand",
25
+ "description",
26
+ "groups",
27
+ "Link",
28
+ "meta",
29
+ "children",
30
+ "containerClassName",
31
+ "className",
32
+ "variant",
33
+ "onNavigate"
34
+ ]);
35
+ return /* @__PURE__ */ jsx(
36
+ "footer",
37
+ __spreadProps(__spreadValues({
38
+ "data-slot": "site-footer",
39
+ "data-variant": variant,
40
+ className: cn("ui-site-footer", className)
41
+ }, props), {
42
+ children: /* @__PURE__ */ jsxs("div", { className: cn("ui-site-footer-frame", containerClassName), children: [
43
+ /* @__PURE__ */ jsxs("div", { className: "ui-site-footer-brand", children: [
44
+ brand,
45
+ description && /* @__PURE__ */ jsx("div", { className: "ui-site-footer-description", children: description }),
46
+ children
47
+ ] }),
48
+ groups.map((group) => /* @__PURE__ */ jsxs("nav", { "aria-label": group.label, children: [
49
+ /* @__PURE__ */ jsx("h2", { className: "ui-site-footer-label", children: group.label }),
50
+ group.links.map((item) => {
51
+ const Component = !item.external && Link ? Link : "a";
52
+ return /* @__PURE__ */ jsx(
53
+ Component,
54
+ {
55
+ href: item.href,
56
+ target: item.target,
57
+ rel: item.target === "_blank" ? "noopener noreferrer" : void 0,
58
+ className: "ui-site-footer-link ui-focus",
59
+ onClick: (event) => onNavigate == null ? void 0 : onNavigate(event, item),
60
+ children: item.label
61
+ },
62
+ item.id
63
+ );
64
+ })
65
+ ] }, group.id)),
66
+ meta && /* @__PURE__ */ jsx("div", { className: "ui-site-footer-meta", children: meta })
67
+ ] })
68
+ })
69
+ );
70
+ }
71
+
72
+ export {
73
+ SiteFooter
74
+ };
@@ -0,0 +1,413 @@
1
+ "use client";
2
+ import {
3
+ Logo,
4
+ uiRelease
5
+ } from "./chunk-VWIUN35X.js";
6
+ import {
7
+ Badge,
8
+ Button,
9
+ DropdownMenu,
10
+ DropdownMenuContent,
11
+ DropdownMenuItem,
12
+ DropdownMenuLabel,
13
+ DropdownMenuSeparator,
14
+ DropdownMenuTrigger,
15
+ Navigation,
16
+ Select,
17
+ SelectContent,
18
+ SelectItem,
19
+ SelectTrigger,
20
+ SelectValue
21
+ } from "./chunk-QQQQZEPV.js";
22
+ import {
23
+ __objRest,
24
+ __spreadProps,
25
+ __spreadValues,
26
+ cn
27
+ } from "./chunk-JBTDRVZ7.js";
28
+
29
+ // src/components/naeil-header.tsx
30
+ import { useSyncExternalStore } from "react";
31
+ import { useTheme } from "next-themes";
32
+ import { Moon, Sun } from "lucide-react";
33
+
34
+ // src/components/naeil-header-content.ts
35
+ var headerLocales = ["en", "ko", "ja"];
36
+ var headerLocaleNames = { en: "English", ko: "\uD55C\uAD6D\uC5B4", ja: "\u65E5\u672C\u8A9E" };
37
+ var headerProjects = [
38
+ {
39
+ "key": "cc",
40
+ "href": "/cc",
41
+ "accent": "oklch(0.704 0.140 181)",
42
+ "icon": "coral",
43
+ "status": "active"
44
+ },
45
+ {
46
+ "key": "pkm",
47
+ "href": "/pkm",
48
+ "accent": "oklch(0.702 0.183 293)",
49
+ "icon": "jellyfish",
50
+ "status": "coming"
51
+ },
52
+ {
53
+ "key": "naeilUi",
54
+ "href": "/design",
55
+ "accent": "oklch(0.623 0.214 259)",
56
+ "icon": "whale",
57
+ "status": "active"
58
+ },
59
+ {
60
+ "key": "sa",
61
+ "href": "/sa",
62
+ "accent": "oklch(0.723 0.219 149)",
63
+ "icon": "fish",
64
+ "status": "active"
65
+ },
66
+ {
67
+ "key": "babyAgent",
68
+ "href": "/baby-agent",
69
+ "accent": "oklch(0.769 0.188 70.08)",
70
+ "icon": "turtle",
71
+ "status": "coming"
72
+ }
73
+ ];
74
+ var headerContent = {
75
+ "en": {
76
+ "nav": {
77
+ "home": "Home",
78
+ "projects": "Projects",
79
+ "blog": "Blog",
80
+ "navigation": "Main navigation",
81
+ "menu": "Menu",
82
+ "closeMenu": "Close menu"
83
+ },
84
+ "theme": {
85
+ "switchToLight": "Switch to light theme",
86
+ "switchToDark": "Switch to dark theme"
87
+ },
88
+ "locale": {
89
+ "switchLabel": "Language"
90
+ },
91
+ "projects": {
92
+ "cc": {
93
+ "name": "Content Collector",
94
+ "description": "Automated content collection from RSS, YouTube, Reddit + AI summarization"
95
+ },
96
+ "pkm": {
97
+ "name": "PKM",
98
+ "description": "Personal knowledge management \u2014 document parsing, embeddings, semantic search"
99
+ },
100
+ "naeilUi": {
101
+ "name": "naeil-ui",
102
+ "description": "Minimal design system \u2014 OKLCH tokens, Tailwind v4, shadcn"
103
+ },
104
+ "sa": {
105
+ "name": "Sustainability Analyzer",
106
+ "description": "AI-powered ESG report analysis \u2014 PDF parsing, qualitative assessment, comparison tables"
107
+ },
108
+ "babyAgent": {
109
+ "name": "Baby Agent",
110
+ "description": "Parenting AI agent \u2014 LINE-based Q&A, records, reminders"
111
+ },
112
+ "status": {
113
+ "active": "Active",
114
+ "coming": "Coming Soon"
115
+ }
116
+ }
117
+ },
118
+ "ko": {
119
+ "nav": {
120
+ "home": "\uD648",
121
+ "projects": "\uD504\uB85C\uC81D\uD2B8",
122
+ "blog": "\uBE14\uB85C\uADF8",
123
+ "navigation": "\uC8FC\uC694 \uBA54\uB274",
124
+ "menu": "\uBA54\uB274",
125
+ "closeMenu": "\uBA54\uB274 \uB2EB\uAE30"
126
+ },
127
+ "theme": {
128
+ "switchToLight": "\uBC1D\uC740 \uD14C\uB9C8\uB85C \uC804\uD658",
129
+ "switchToDark": "\uC5B4\uB450\uC6B4 \uD14C\uB9C8\uB85C \uC804\uD658"
130
+ },
131
+ "locale": {
132
+ "switchLabel": "\uC5B8\uC5B4"
133
+ },
134
+ "projects": {
135
+ "cc": {
136
+ "name": "Content Collector",
137
+ "description": "RSS, YouTube, Reddit \uC790\uB3D9 \uC218\uC9D1 + AI \uC694\uC57D"
138
+ },
139
+ "pkm": {
140
+ "name": "PKM",
141
+ "description": "\uAC1C\uC778 \uC9C0\uC2DD \uAD00\uB9AC \u2014 \uBB38\uC11C \uD30C\uC2F1, \uC784\uBCA0\uB529, \uC2DC\uB9E8\uD2F1 \uAC80\uC0C9"
142
+ },
143
+ "naeilUi": {
144
+ "name": "naeil-ui",
145
+ "description": "\uBBF8\uB2C8\uBA40 \uB514\uC790\uC778 \uC2DC\uC2A4\uD15C \u2014 OKLCH \uD1A0\uD070, Tailwind v4, shadcn"
146
+ },
147
+ "sa": {
148
+ "name": "Sustainability Analyzer",
149
+ "description": "ESG \uB9AC\uD3EC\uD2B8 AI \uBD84\uC11D \u2014 PDF \uD30C\uC2F1, \uC815\uC131\uD3C9\uAC00, \uBE44\uAD50\uD45C \uC790\uB3D9 \uC0DD\uC131"
150
+ },
151
+ "babyAgent": {
152
+ "name": "Baby Agent",
153
+ "description": "\uC721\uC544 AI \uC5D0\uC774\uC804\uD2B8 \u2014 LINE \uAE30\uBC18 Q&A, \uAE30\uB85D, \uB9AC\uB9C8\uC778\uB354"
154
+ },
155
+ "status": {
156
+ "active": "\uD65C\uC131",
157
+ "coming": "\uC900\uBE44 \uC911"
158
+ }
159
+ }
160
+ },
161
+ "ja": {
162
+ "nav": {
163
+ "home": "\u30DB\u30FC\u30E0",
164
+ "projects": "\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8",
165
+ "blog": "\u30D6\u30ED\u30B0",
166
+ "navigation": "\u30E1\u30A4\u30F3\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3",
167
+ "menu": "\u30E1\u30CB\u30E5\u30FC",
168
+ "closeMenu": "\u30E1\u30CB\u30E5\u30FC\u3092\u9589\u3058\u308B"
169
+ },
170
+ "theme": {
171
+ "switchToLight": "\u30E9\u30A4\u30C8\u30C6\u30FC\u30DE\u306B\u5207\u308A\u66FF\u3048\u308B",
172
+ "switchToDark": "\u30C0\u30FC\u30AF\u30C6\u30FC\u30DE\u306B\u5207\u308A\u66FF\u3048\u308B"
173
+ },
174
+ "locale": {
175
+ "switchLabel": "\u8A00\u8A9E"
176
+ },
177
+ "projects": {
178
+ "cc": {
179
+ "name": "Content Collector",
180
+ "description": "RSS\u3001YouTube\u3001Reddit\u306E\u81EA\u52D5\u53CE\u96C6 + AI\u8981\u7D04"
181
+ },
182
+ "pkm": {
183
+ "name": "PKM",
184
+ "description": "\u500B\u4EBA\u30CA\u30EC\u30C3\u30B8\u7BA1\u7406 \u2014 \u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u89E3\u6790\u3001\u57CB\u3081\u8FBC\u307F\u3001\u30BB\u30DE\u30F3\u30C6\u30A3\u30C3\u30AF\u691C\u7D22"
185
+ },
186
+ "naeilUi": {
187
+ "name": "naeil-ui",
188
+ "description": "\u30DF\u30CB\u30DE\u30EB\u30C7\u30B6\u30A4\u30F3\u30B7\u30B9\u30C6\u30E0 \u2014 OKLCH\u30C8\u30FC\u30AF\u30F3\u3001Tailwind v4\u3001shadcn"
189
+ },
190
+ "sa": {
191
+ "name": "Sustainability Analyzer",
192
+ "description": "ESG\u30EC\u30DD\u30FC\u30C8AI\u5206\u6790 \u2014 PDF\u89E3\u6790\u3001\u5B9A\u6027\u8A55\u4FA1\u3001\u6BD4\u8F03\u8868\u306E\u81EA\u52D5\u751F\u6210"
193
+ },
194
+ "babyAgent": {
195
+ "name": "Baby Agent",
196
+ "description": "\u80B2\u5150AI\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8 \u2014 LINE Q&A\u3001\u8A18\u9332\u3001\u30EA\u30DE\u30A4\u30F3\u30C0\u30FC"
197
+ },
198
+ "status": {
199
+ "active": "\u30A2\u30AF\u30C6\u30A3\u30D6",
200
+ "coming": "\u6E96\u5099\u4E2D"
201
+ }
202
+ }
203
+ }
204
+ };
205
+
206
+ // src/components/naeil-header-account.tsx
207
+ import { UserRound } from "lucide-react";
208
+ import { jsx, jsxs } from "react/jsx-runtime";
209
+ var labels = {
210
+ en: { menu: "Account menu", account: "Account", login: "Log in", logout: "Log out", busy: "Logging out\u2026" },
211
+ ko: { menu: "\uACC4\uC815 \uBA54\uB274", account: "\uACC4\uC815", login: "\uB85C\uADF8\uC778", logout: "\uB85C\uADF8\uC544\uC6C3", busy: "\uB85C\uADF8\uC544\uC6C3 \uC911\u2026" },
212
+ ja: { menu: "\u30A2\u30AB\u30A6\u30F3\u30C8\u30E1\u30CB\u30E5\u30FC", account: "\u30A2\u30AB\u30A6\u30F3\u30C8", login: "\u30ED\u30B0\u30A4\u30F3", logout: "\u30ED\u30B0\u30A2\u30A6\u30C8", busy: "\u30ED\u30B0\u30A2\u30A6\u30C8\u4E2D\u2026" }
213
+ };
214
+ var NativeLink = (props) => /* @__PURE__ */ jsx("a", __spreadValues({}, props));
215
+ function NaeilHeaderAccountControl({ locale, account, Link = NativeLink }) {
216
+ const text = labels[locale];
217
+ if (account.status === "signed-out") {
218
+ return /* @__PURE__ */ jsx(Link, { href: account.loginHref, className: "ui-navigation-link ui-focus naeil-header-login", "data-naeil-account-state": "signed-out", children: text.login });
219
+ }
220
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
221
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
222
+ "button",
223
+ {
224
+ type: "button",
225
+ className: "ui-focus naeil-header-account-trigger",
226
+ "data-naeil-account-trigger": true,
227
+ "data-naeil-account-state": "signed-in",
228
+ "aria-label": text.menu,
229
+ "aria-busy": account.busy || void 0,
230
+ children: /* @__PURE__ */ jsx("span", { className: "naeil-header-account-avatar", "aria-hidden": "true", children: /* @__PURE__ */ jsx(UserRound, {}) })
231
+ }
232
+ ) }),
233
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-56 max-w-[calc(100vw-2rem)]", "data-naeil-account-menu": true, children: [
234
+ /* @__PURE__ */ jsxs(DropdownMenuLabel, { className: "flex min-w-0 flex-col font-normal", children: [
235
+ /* @__PURE__ */ jsx("span", { className: "truncate text-base font-medium", children: account.displayName || text.account }),
236
+ account.email && /* @__PURE__ */ jsx("span", { className: "truncate text-sm text-muted-foreground", children: account.email })
237
+ ] }),
238
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
239
+ /* @__PURE__ */ jsx(
240
+ DropdownMenuItem,
241
+ {
242
+ className: "min-h-11",
243
+ disabled: account.busy,
244
+ onSelect: () => {
245
+ if (!account.busy) account.onLogout();
246
+ },
247
+ children: account.busy ? text.busy : text.logout
248
+ }
249
+ )
250
+ ] })
251
+ ] });
252
+ }
253
+
254
+ // src/components/naeil-header.tsx
255
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
256
+ var subscribe = () => () => {
257
+ };
258
+ function NaeilHeaderThemeControl({ locale }) {
259
+ const { resolvedTheme, setTheme } = useTheme();
260
+ const mounted = useSyncExternalStore(subscribe, () => true, () => false);
261
+ const dark = mounted && resolvedTheme === "dark";
262
+ return /* @__PURE__ */ jsx2(
263
+ Button,
264
+ {
265
+ variant: "ghost",
266
+ size: "icon",
267
+ className: "size-11 shrink-0",
268
+ disabled: !mounted,
269
+ "aria-label": headerContent[locale].theme[dark ? "switchToLight" : "switchToDark"],
270
+ onClick: () => setTheme(dark ? "light" : "dark"),
271
+ children: dark ? /* @__PURE__ */ jsx2(Sun, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx2(Moon, { "aria-hidden": "true" })
272
+ }
273
+ );
274
+ }
275
+ function NaeilHeaderLocaleControl({ locale, onLocaleChange }) {
276
+ return /* @__PURE__ */ jsxs2(Select, { value: locale, onValueChange: (value) => onLocaleChange(value), children: [
277
+ /* @__PURE__ */ jsx2(
278
+ SelectTrigger,
279
+ {
280
+ className: "h-11 w-auto min-w-20 border-transparent bg-transparent px-2",
281
+ "aria-label": headerContent[locale].locale.switchLabel,
282
+ children: /* @__PURE__ */ jsx2(SelectValue, { children: locale.toUpperCase() })
283
+ }
284
+ ),
285
+ /* @__PURE__ */ jsx2(SelectContent, { align: "end", children: headerLocales.map((value) => /* @__PURE__ */ jsx2(SelectItem, { value, className: "min-h-11", lang: value, children: headerLocaleNames[value] }, value)) })
286
+ ] });
287
+ }
288
+ var NativeLink2 = (props) => /* @__PURE__ */ jsx2("a", __spreadValues({}, props));
289
+ function NaeilHeader(_a) {
290
+ var _b = _a, {
291
+ locale,
292
+ resolveHref = (path) => `https://naeil.dev/${locale}${path === "/" ? "" : path}`,
293
+ brandHref,
294
+ brandSlot,
295
+ brandLinkProps,
296
+ brandLinkComponent,
297
+ onLocaleChange,
298
+ authSlot,
299
+ toolbarSlot,
300
+ projects,
301
+ projectsExternal = false,
302
+ translations,
303
+ showProjects = true,
304
+ showBlog = true,
305
+ subNav,
306
+ currentProjectKey,
307
+ currentProjectHref,
308
+ labels: labels2,
309
+ Link = NativeLink2,
310
+ currentHref,
311
+ onNavigate,
312
+ className,
313
+ containerClassName
314
+ } = _b, props = __objRest(_b, [
315
+ "locale",
316
+ "resolveHref",
317
+ "brandHref",
318
+ "brandSlot",
319
+ "brandLinkProps",
320
+ "brandLinkComponent",
321
+ "onLocaleChange",
322
+ "authSlot",
323
+ "toolbarSlot",
324
+ "projects",
325
+ "projectsExternal",
326
+ "translations",
327
+ "showProjects",
328
+ "showBlog",
329
+ "subNav",
330
+ "currentProjectKey",
331
+ "currentProjectHref",
332
+ "labels",
333
+ "Link",
334
+ "currentHref",
335
+ "onNavigate",
336
+ "className",
337
+ "containerClassName"
338
+ ]);
339
+ var _b2, _c;
340
+ const content = headerContent[locale];
341
+ const projectLinks = !showProjects ? [] : projects != null ? projects : headerProjects.map((project) => {
342
+ var _a3, _b3, _c2;
343
+ const current = project.key === currentProjectKey;
344
+ return {
345
+ id: project.key,
346
+ label: (_a3 = translations == null ? void 0 : translations.project(`${project.key}.name`)) != null ? _a3 : content.projects[project.key].name,
347
+ description: (_b3 = translations == null ? void 0 : translations.project(`${project.key}.description`)) != null ? _b3 : content.projects[project.key].description,
348
+ href: current ? currentProjectHref || "/" : resolveHref(project.href),
349
+ external: !current && projectsExternal,
350
+ active: current || currentHref === project.href || (currentHref == null ? void 0 : currentHref.startsWith(`${project.href}/`)) || currentHref === resolveHref(project.href),
351
+ icon: /* @__PURE__ */ jsx2("span", { className: "naeil-header-project-icon", style: {
352
+ borderColor: `color-mix(in oklch, ${project.accent} 30%, transparent)`,
353
+ backgroundColor: `color-mix(in oklch, ${project.accent} 8%, transparent)`
354
+ }, children: /* @__PURE__ */ jsx2("img", { src: `https://naeil.dev/images/${project.icon}.png`, alt: "", width: 24, height: 24 }) }),
355
+ badge: project.status === "coming" ? /* @__PURE__ */ jsx2(Badge, { variant: "outline", children: (_c2 = translations == null ? void 0 : translations.project("status.coming")) != null ? _c2 : content.projects.status.coming }) : void 0
356
+ };
357
+ });
358
+ const brandDestination = brandHref != null ? brandHref : resolveHref("/");
359
+ const BrandLink = brandLinkComponent != null ? brandLinkComponent : Link;
360
+ const _a2 = brandLinkProps != null ? brandLinkProps : {}, { onClick: onBrandClick } = _a2, brandProps = __objRest(_a2, ["onClick"]);
361
+ const toolbar = /* @__PURE__ */ jsx2("div", { "data-app-toolbar": true, className: "naeil-header-controls", children: toolbarSlot !== void 0 ? toolbarSlot : /* @__PURE__ */ jsxs2(Fragment, { children: [
362
+ /* @__PURE__ */ jsx2(NaeilHeaderThemeControl, { locale }),
363
+ onLocaleChange && /* @__PURE__ */ jsx2(NaeilHeaderLocaleControl, { locale, onLocaleChange }),
364
+ authSlot && /* @__PURE__ */ jsxs2(Fragment, { children: [
365
+ /* @__PURE__ */ jsx2("div", { "aria-hidden": "true", className: "naeil-header-separator" }),
366
+ authSlot
367
+ ] })
368
+ ] }) });
369
+ return /* @__PURE__ */ jsx2(
370
+ Navigation,
371
+ __spreadProps(__spreadValues({}, props), {
372
+ "data-global-header": true,
373
+ "data-naeil-header": true,
374
+ "data-naeil-ui-version": uiRelease.version,
375
+ "data-naeil-ui-contract": uiRelease.contractVersion,
376
+ Link,
377
+ currentHref,
378
+ onNavigate,
379
+ brand: /* @__PURE__ */ jsx2(
380
+ BrandLink,
381
+ __spreadProps(__spreadValues({
382
+ href: brandDestination,
383
+ "data-app-brand": true,
384
+ "aria-label": brandSlot == null ? ".naeil" : void 0
385
+ }, brandProps), {
386
+ onClick: (event) => {
387
+ onBrandClick == null ? void 0 : onBrandClick(event);
388
+ onNavigate == null ? void 0 : onNavigate(event, { id: "brand", href: brandDestination, label: ".naeil" });
389
+ },
390
+ children: brandSlot != null ? brandSlot : /* @__PURE__ */ jsx2(Logo, { variant: "horizontal", size: 28, className: "block", label: null })
391
+ })
392
+ ),
393
+ items: [
394
+ ...showProjects ? [{ id: "projects", label: (_b2 = translations == null ? void 0 : translations.projects) != null ? _b2 : content.nav.projects, items: projectLinks, columns: 2 }] : [],
395
+ ...showBlog ? [{ id: "blog", label: (_c = translations == null ? void 0 : translations.blog) != null ? _c : content.nav.blog, href: resolveHref("/blog"), external: projectsExternal }] : [],
396
+ ...(subNav != null ? subNav : []).map((item) => __spreadProps(__spreadValues({}, item), { id: item.href }))
397
+ ],
398
+ labels: labels2 != null ? labels2 : { navigation: content.nav.navigation, menu: content.nav.menu, close: content.nav.closeMenu },
399
+ toolbar,
400
+ mobileToolbar: toolbar,
401
+ className: cn("naeil-header fixed top-0 w-full", className),
402
+ containerClassName: cn("naeil-header-frame", containerClassName)
403
+ })
404
+ );
405
+ }
406
+
407
+ export {
408
+ headerLocales,
409
+ NaeilHeaderAccountControl,
410
+ NaeilHeaderThemeControl,
411
+ NaeilHeaderLocaleControl,
412
+ NaeilHeader
413
+ };