@naeil/ui 0.6.0 → 0.7.2

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 (42) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +15 -10
  3. package/contracts/naeil-chrome.v1.json +12 -0
  4. package/dist/{chunk-VL7FS4QM.js → chunk-7JBLPGZ4.js} +4 -343
  5. package/dist/chunk-HSTDPY56.js +74 -0
  6. package/dist/chunk-MGCCKOGU.js +385 -0
  7. package/dist/{chunk-CE73AEJZ.js → chunk-QQQQZEPV.js} +249 -3
  8. package/dist/components/index.d.ts +2 -2
  9. package/dist/components/index.js +10 -8
  10. package/dist/components/naeil-footer.d.ts +16 -0
  11. package/dist/components/naeil-footer.js +76 -0
  12. package/dist/components/naeil-header.d.ts +23 -5
  13. package/dist/components/naeil-header.js +5 -2
  14. package/dist/components/ui/index.d.ts +2 -2
  15. package/dist/components/ui/index.js +6 -6
  16. package/dist/lib/ui-release.d.ts +1 -0
  17. package/dist/lib/ui-release.js +1 -0
  18. package/dist/naeil-header-content-BvISJ4RV.d.ts +4 -0
  19. package/dist/{navigation-CL10a6Eb.d.ts → navigation-CgPeL9tF.d.ts} +1 -1
  20. package/dist/{site-footer-B67meCDv.d.ts → site-footer-vXDa_6yr.d.ts} +4 -2
  21. package/dist/source/components/naeil-footer.d.ts +16 -0
  22. package/dist/source/components/naeil-footer.js +95 -0
  23. package/dist/source/components/naeil-header-account.d.ts +26 -0
  24. package/dist/source/components/naeil-header-account.js +67 -0
  25. package/dist/source/components/naeil-header-content.d.ts +1 -25
  26. package/dist/source/components/naeil-header-content.js +0 -28
  27. package/dist/source/components/naeil-header.d.ts +2 -1
  28. package/dist/source/components/naeil-header.js +6 -1
  29. package/dist/source/components/ui/site-footer.d.ts +4 -2
  30. package/dist/source/components/ui/site-footer.js +6 -2
  31. package/dist/source/lib/ui-release.d.ts +6 -0
  32. package/dist/source/lib/ui-release.js +4 -0
  33. package/docs/components/README.md +4 -3
  34. package/docs/components/application-layout.md +48 -15
  35. package/docs/components/naeil-footer.md +20 -0
  36. package/docs/components/naeil-header.md +25 -7
  37. package/docs/components/navigation.md +3 -1
  38. package/docs/design/v2-migration.md +11 -10
  39. package/docs/package-release.md +33 -12
  40. package/package.json +16 -4
  41. package/src/styles/components.css +35 -0
  42. package/dist/chunk-QSTGUEEI.js +0 -323
@@ -0,0 +1,16 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { S as SiteFooterProps } from '../site-footer-vXDa_6yr.js';
3
+ import { N as NaeilHeaderLocale } from '../naeil-header-content-BvISJ4RV.js';
4
+ import 'react';
5
+ import '../navigation-CgPeL9tF.js';
6
+
7
+ type NaeilFooterLocale = NaeilHeaderLocale;
8
+ interface NaeilFooterProps extends Omit<SiteFooterProps, "brand" | "description" | "groups"> {
9
+ locale: NaeilFooterLocale;
10
+ /** Only localize/route canonical paths; default destinations use the official origin. */
11
+ resolveHref?: (path: string) => string;
12
+ }
13
+ /** Canonical content in full/compact density. Product legal/status copy belongs in meta. */
14
+ declare function NaeilFooter({ locale, resolveHref, variant, Link, onNavigate, ...props }: NaeilFooterProps): react_jsx_runtime.JSX.Element;
15
+
16
+ export { NaeilFooter, type NaeilFooterLocale, type NaeilFooterProps };
@@ -0,0 +1,76 @@
1
+ "use client";
2
+ "use client";
3
+ import {
4
+ Logo,
5
+ uiRelease
6
+ } from "../chunk-7JBLPGZ4.js";
7
+ import {
8
+ SiteFooter
9
+ } from "../chunk-HSTDPY56.js";
10
+ import {
11
+ __objRest,
12
+ __spreadProps,
13
+ __spreadValues
14
+ } from "../chunk-JBTDRVZ7.js";
15
+
16
+ // src/components/naeil-footer.tsx
17
+ import { jsx } from "react/jsx-runtime";
18
+ var content = {
19
+ en: { navigation: "Navigation", projects: "Projects", blog: "Blog", social: "Social" },
20
+ ko: { navigation: "\uB124\uBE44\uAC8C\uC774\uC158", projects: "\uD504\uB85C\uC81D\uD2B8", blog: "\uBE14\uB85C\uADF8", social: "\uC18C\uC15C" },
21
+ ja: { navigation: "\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3", projects: "\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8", blog: "\u30D6\u30ED\u30B0", social: "\u30BD\u30FC\u30B7\u30E3\u30EB" }
22
+ };
23
+ var NativeLink = (props) => /* @__PURE__ */ jsx("a", __spreadValues({}, props));
24
+ function NaeilFooter(_a) {
25
+ var _b = _a, {
26
+ locale,
27
+ resolveHref = (path) => `https://naeil.dev/${locale}${path === "/" ? "" : path}`,
28
+ variant = "full",
29
+ Link = NativeLink,
30
+ onNavigate
31
+ } = _b, props = __objRest(_b, [
32
+ "locale",
33
+ "resolveHref",
34
+ "variant",
35
+ "Link",
36
+ "onNavigate"
37
+ ]);
38
+ const copy = content[locale];
39
+ const home = { id: "brand", label: ".naeil", href: resolveHref("/") };
40
+ return /* @__PURE__ */ jsx(
41
+ SiteFooter,
42
+ __spreadProps(__spreadValues({}, props), {
43
+ variant,
44
+ Link,
45
+ onNavigate,
46
+ "data-naeil-footer": true,
47
+ "data-naeil-ui-version": uiRelease.version,
48
+ "data-naeil-ui-contract": uiRelease.contractVersion,
49
+ brand: /* @__PURE__ */ jsx(
50
+ Link,
51
+ {
52
+ href: home.href,
53
+ "aria-label": ".naeil",
54
+ "data-footer-brand": true,
55
+ className: "ui-focus inline-flex min-h-11 items-center",
56
+ onClick: (event) => onNavigate == null ? void 0 : onNavigate(event, home),
57
+ children: /* @__PURE__ */ jsx(Logo, { variant: "footer", size: 20, label: null })
58
+ }
59
+ ),
60
+ description: variant === "full" ? "Tomorrow starts here." : void 0,
61
+ groups: [
62
+ { id: "navigation", label: copy.navigation, links: [
63
+ { id: "projects", label: copy.projects, href: resolveHref("/projects") },
64
+ { id: "blog", label: copy.blog, href: resolveHref("/blog") }
65
+ ] },
66
+ { id: "social", label: copy.social, links: [
67
+ // All canonical destinations use the consumer Link, including this absolute URL.
68
+ { id: "github", label: "GitHub", href: "https://github.com/naeil-dev", target: "_blank" }
69
+ ] }
70
+ ]
71
+ })
72
+ );
73
+ }
74
+ export {
75
+ NaeilFooter
76
+ };
@@ -1,9 +1,27 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { a as NavigationProps, b as NavigationLinkProps, N as NavigationLink, c as NavigationLinkComponent } from '../navigation-CL10a6Eb.js';
3
+ import { b as NavigationLinkComponent, a as NavigationProps, c as NavigationLinkProps, N as NavigationLink } from '../navigation-CgPeL9tF.js';
4
+ import { N as NaeilHeaderLocale } from '../naeil-header-content-BvISJ4RV.js';
4
5
 
5
- declare const headerLocales: readonly ["en", "ko", "ja"];
6
- type NaeilHeaderLocale = (typeof headerLocales)[number];
6
+ type NaeilHeaderAccount = {
7
+ status: "signed-out";
8
+ loginHref: string;
9
+ } | {
10
+ status: "signed-in";
11
+ /** Consumer starts its guarded session action and owns failures/navigation. */
12
+ onLogout: () => void;
13
+ busy?: boolean;
14
+ displayName?: string;
15
+ email?: string;
16
+ };
17
+ interface NaeilHeaderAccountControlProps {
18
+ locale: NaeilHeaderLocale;
19
+ account: NaeilHeaderAccount;
20
+ /** The same route/save adapter used by the rest of the application header. */
21
+ Link?: NavigationLinkComponent;
22
+ }
23
+ /** Shared account presentation only: never reads sessions or calls an auth API. */
24
+ declare function NaeilHeaderAccountControl({ locale, account, Link }: NaeilHeaderAccountControlProps): react_jsx_runtime.JSX.Element;
7
25
 
8
26
  interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "toolbar" | "mobileToolbar" | "labels"> {
9
27
  locale: NaeilHeaderLocale;
@@ -14,7 +32,7 @@ interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "to
14
32
  brandLinkProps?: Omit<NavigationLinkProps, "href" | "children">;
15
33
  /** Omit when the application does not support changing its UI language. */
16
34
  onLocaleChange?: (locale: NaeilHeaderLocale) => void;
17
- /** Application-owned authentication; this module has no site session/backend. */
35
+ /** Use NaeilHeaderAccountControl for canonical UI; the app owns auth state/I/O. */
18
36
  authSlot?: ReactNode;
19
37
  labels?: NavigationProps["labels"];
20
38
  projects?: NavigationLink[];
@@ -51,4 +69,4 @@ declare function NaeilHeaderLocaleControl({ locale, onLocaleChange }: {
51
69
  /** One complete, opt-in branded composition shared by naeil.dev and applications. */
52
70
  declare function NaeilHeader({ locale, resolveHref, brandHref, brandSlot, brandLinkProps, brandLinkComponent, onLocaleChange, authSlot, toolbarSlot, projects, projectsExternal, translations, showProjects, showBlog, subNav, currentProjectKey, currentProjectHref, labels, Link, currentHref, onNavigate, className, containerClassName, ...props }: NaeilHeaderProps): react_jsx_runtime.JSX.Element;
53
71
 
54
- export { NaeilHeader, type NaeilHeaderLocale, NaeilHeaderLocaleControl, type NaeilHeaderProps, NaeilHeaderThemeControl };
72
+ export { NaeilHeader, type NaeilHeaderAccount, NaeilHeaderAccountControl, type NaeilHeaderAccountControlProps, NaeilHeaderLocale, NaeilHeaderLocaleControl, type NaeilHeaderProps, NaeilHeaderThemeControl };
@@ -2,13 +2,16 @@
2
2
  "use client";
3
3
  import {
4
4
  NaeilHeader,
5
+ NaeilHeaderAccountControl,
5
6
  NaeilHeaderLocaleControl,
6
7
  NaeilHeaderThemeControl
7
- } from "../chunk-VL7FS4QM.js";
8
- import "../chunk-CE73AEJZ.js";
8
+ } from "../chunk-MGCCKOGU.js";
9
+ import "../chunk-7JBLPGZ4.js";
10
+ import "../chunk-QQQQZEPV.js";
9
11
  import "../chunk-JBTDRVZ7.js";
10
12
  export {
11
13
  NaeilHeader,
14
+ NaeilHeaderAccountControl,
12
15
  NaeilHeaderLocaleControl,
13
16
  NaeilHeaderThemeControl
14
17
  };
@@ -4,8 +4,8 @@ import { Avatar as Avatar$1, Dialog as Dialog$1, DropdownMenu as DropdownMenu$1,
4
4
  import * as class_variance_authority_types from 'class-variance-authority/types';
5
5
  import { VariantProps } from 'class-variance-authority';
6
6
  import { ToasterProps } from 'sonner';
7
- export { d as Navigation, e as NavigationGroup, f as NavigationItem, N as NavigationLink, c as NavigationLinkComponent, b as NavigationLinkProps, a as NavigationProps } from '../../navigation-CL10a6Eb.js';
8
- export { a as SiteFooter, S as SiteFooterProps } from '../../site-footer-B67meCDv.js';
7
+ export { d as Navigation, e as NavigationGroup, f as NavigationItem, N as NavigationLink, b as NavigationLinkComponent, c as NavigationLinkProps, a as NavigationProps } from '../../navigation-CgPeL9tF.js';
8
+ export { a as SiteFooter, S as SiteFooterProps } from '../../site-footer-vXDa_6yr.js';
9
9
 
10
10
  declare function Avatar({ className, size, ...props }: React.ComponentProps<typeof Avatar$1.Root> & {
11
11
  size?: "default" | "sm" | "lg";
@@ -1,5 +1,10 @@
1
1
  "use client";
2
2
  import {
3
+ SiteFooter
4
+ } from "../../chunk-HSTDPY56.js";
5
+ import {
6
+ Badge,
7
+ Button,
3
8
  DropdownMenu,
4
9
  DropdownMenuCheckboxItem,
5
10
  DropdownMenuContent,
@@ -15,11 +20,6 @@ import {
15
20
  DropdownMenuSubContent,
16
21
  DropdownMenuSubTrigger,
17
22
  DropdownMenuTrigger,
18
- SiteFooter
19
- } from "../../chunk-QSTGUEEI.js";
20
- import {
21
- Badge,
22
- Button,
23
23
  Navigation,
24
24
  Select,
25
25
  SelectContent,
@@ -33,7 +33,7 @@ import {
33
33
  SelectValue,
34
34
  badgeVariants,
35
35
  buttonVariants
36
- } from "../../chunk-CE73AEJZ.js";
36
+ } from "../../chunk-QQQQZEPV.js";
37
37
  import {
38
38
  __objRest,
39
39
  __spreadProps,
@@ -0,0 +1 @@
1
+ export declare const uiRelease: Readonly<{version: "0.7.2"; contractVersion: "1"}>;
@@ -0,0 +1 @@
1
+ export const uiRelease = Object.freeze({"version":"0.7.2","contractVersion":"1"});
@@ -0,0 +1,4 @@
1
+ declare const headerLocales: readonly ["en", "ko", "ja"];
2
+ type NaeilHeaderLocale = (typeof headerLocales)[number];
3
+
4
+ export type { NaeilHeaderLocale as N };
@@ -45,4 +45,4 @@ interface NavigationProps extends Omit<React.ComponentPropsWithoutRef<"header">,
45
45
  }
46
46
  declare function Navigation({ brand, items, labels, Link, currentHref, toolbar, mobileToolbar, mobileFooter, containerClassName, onNavigate, className, ...props }: NavigationProps): react_jsx_runtime.JSX.Element;
47
47
 
48
- export { type NavigationLink as N, type NavigationProps as a, type NavigationLinkProps as b, type NavigationLinkComponent as c, Navigation as d, type NavigationGroup as e, type NavigationItem as f };
48
+ export { type NavigationLink as N, type NavigationProps as a, type NavigationLinkComponent as b, type NavigationLinkProps as c, Navigation as d, type NavigationGroup as e, type NavigationItem as f };
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
- import { N as NavigationLink, c as NavigationLinkComponent } from './navigation-CL10a6Eb.js';
3
+ import { N as NavigationLink, b as NavigationLinkComponent, a as NavigationProps } from './navigation-CgPeL9tF.js';
4
4
 
5
5
  interface SiteFooterProps extends React.ComponentPropsWithoutRef<"footer"> {
6
6
  brand?: React.ReactNode;
@@ -14,8 +14,10 @@ interface SiteFooterProps extends React.ComponentPropsWithoutRef<"footer"> {
14
14
  meta?: React.ReactNode;
15
15
  containerClassName?: string;
16
16
  variant?: "full" | "compact";
17
+ /** Called for every group link, including native external anchors. Preserve modified clicks. */
18
+ onNavigate?: NavigationProps["onNavigate"];
17
19
  }
18
20
  /** Product content and translations belong to the consumer, including legal copy. */
19
- declare function SiteFooter({ brand, description, groups, Link, meta, children, containerClassName, className, variant, ...props }: SiteFooterProps): react_jsx_runtime.JSX.Element;
21
+ declare function SiteFooter({ brand, description, groups, Link, meta, children, containerClassName, className, variant, onNavigate, ...props }: SiteFooterProps): react_jsx_runtime.JSX.Element;
20
22
 
21
23
  export { type SiteFooterProps as S, SiteFooter as a };
@@ -0,0 +1,16 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { SiteFooterProps } from './ui/site-footer.js';
3
+ import { NaeilHeaderLocale } from './naeil-header-content.js';
4
+ import 'react';
5
+ import './ui/navigation.js';
6
+
7
+ type NaeilFooterLocale = NaeilHeaderLocale;
8
+ interface NaeilFooterProps extends Omit<SiteFooterProps, "brand" | "description" | "groups"> {
9
+ locale: NaeilFooterLocale;
10
+ /** Only localize/route canonical paths; default destinations use the official origin. */
11
+ resolveHref?: (path: string) => string;
12
+ }
13
+ /** Canonical content in full/compact density. Product legal/status copy belongs in meta. */
14
+ declare function NaeilFooter({ locale, resolveHref, variant, Link, onNavigate, ...props }: NaeilFooterProps): react_jsx_runtime.JSX.Element;
15
+
16
+ export { NaeilFooter, type NaeilFooterLocale, type NaeilFooterProps };
@@ -0,0 +1,95 @@
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 { Logo } from "./logo.js";
35
+ import { SiteFooter } from "./ui/site-footer.js";
36
+ import { uiRelease } from "../lib/ui-release.js";
37
+ const content = {
38
+ en: { navigation: "Navigation", projects: "Projects", blog: "Blog", social: "Social" },
39
+ ko: { navigation: "\uB124\uBE44\uAC8C\uC774\uC158", projects: "\uD504\uB85C\uC81D\uD2B8", blog: "\uBE14\uB85C\uADF8", social: "\uC18C\uC15C" },
40
+ ja: { navigation: "\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3", projects: "\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8", blog: "\u30D6\u30ED\u30B0", social: "\u30BD\u30FC\u30B7\u30E3\u30EB" }
41
+ };
42
+ const NativeLink = (props) => /* @__PURE__ */ jsx("a", __spreadValues({}, props));
43
+ function NaeilFooter(_a) {
44
+ var _b = _a, {
45
+ locale,
46
+ resolveHref = (path) => `https://naeil.dev/${locale}${path === "/" ? "" : path}`,
47
+ variant = "full",
48
+ Link = NativeLink,
49
+ onNavigate
50
+ } = _b, props = __objRest(_b, [
51
+ "locale",
52
+ "resolveHref",
53
+ "variant",
54
+ "Link",
55
+ "onNavigate"
56
+ ]);
57
+ const copy = content[locale];
58
+ const home = { id: "brand", label: ".naeil", href: resolveHref("/") };
59
+ return /* @__PURE__ */ jsx(
60
+ SiteFooter,
61
+ __spreadProps(__spreadValues({}, props), {
62
+ variant,
63
+ Link,
64
+ onNavigate,
65
+ "data-naeil-footer": true,
66
+ "data-naeil-ui-version": uiRelease.version,
67
+ "data-naeil-ui-contract": uiRelease.contractVersion,
68
+ brand: /* @__PURE__ */ jsx(
69
+ Link,
70
+ {
71
+ href: home.href,
72
+ "aria-label": ".naeil",
73
+ "data-footer-brand": true,
74
+ className: "ui-focus inline-flex min-h-11 items-center",
75
+ onClick: (event) => onNavigate == null ? void 0 : onNavigate(event, home),
76
+ children: /* @__PURE__ */ jsx(Logo, { variant: "footer", size: 20, label: null })
77
+ }
78
+ ),
79
+ description: variant === "full" ? "Tomorrow starts here." : void 0,
80
+ groups: [
81
+ { id: "navigation", label: copy.navigation, links: [
82
+ { id: "projects", label: copy.projects, href: resolveHref("/projects") },
83
+ { id: "blog", label: copy.blog, href: resolveHref("/blog") }
84
+ ] },
85
+ { id: "social", label: copy.social, links: [
86
+ // All canonical destinations use the consumer Link, including this absolute URL.
87
+ { id: "github", label: "GitHub", href: "https://github.com/naeil-dev", target: "_blank" }
88
+ ] }
89
+ ]
90
+ })
91
+ );
92
+ }
93
+ export {
94
+ NaeilFooter
95
+ };
@@ -0,0 +1,26 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { NavigationLinkComponent } from './ui/navigation.js';
3
+ import { NaeilHeaderLocale } from './naeil-header-content.js';
4
+ import 'react';
5
+
6
+ type NaeilHeaderAccount = {
7
+ status: "signed-out";
8
+ loginHref: string;
9
+ } | {
10
+ status: "signed-in";
11
+ /** Consumer starts its guarded session action and owns failures/navigation. */
12
+ onLogout: () => void;
13
+ busy?: boolean;
14
+ displayName?: string;
15
+ email?: string;
16
+ };
17
+ interface NaeilHeaderAccountControlProps {
18
+ locale: NaeilHeaderLocale;
19
+ account: NaeilHeaderAccount;
20
+ /** The same route/save adapter used by the rest of the application header. */
21
+ Link?: NavigationLinkComponent;
22
+ }
23
+ /** Shared account presentation only: never reads sessions or calls an auth API. */
24
+ declare function NaeilHeaderAccountControl({ locale, account, Link }: NaeilHeaderAccountControlProps): react_jsx_runtime.JSX.Element;
25
+
26
+ export { type NaeilHeaderAccount, NaeilHeaderAccountControl, type NaeilHeaderAccountControlProps };
@@ -0,0 +1,67 @@
1
+ "use client";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
6
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
+ var __spreadValues = (a, b) => {
8
+ for (var prop in b || (b = {}))
9
+ if (__hasOwnProp.call(b, prop))
10
+ __defNormalProp(a, prop, b[prop]);
11
+ if (__getOwnPropSymbols)
12
+ for (var prop of __getOwnPropSymbols(b)) {
13
+ if (__propIsEnum.call(b, prop))
14
+ __defNormalProp(a, prop, b[prop]);
15
+ }
16
+ return a;
17
+ };
18
+ import { jsx, jsxs } from "react/jsx-runtime";
19
+ import { UserRound } from "lucide-react";
20
+ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuItem } from "./ui/dropdown-menu.js";
21
+ const labels = {
22
+ en: { menu: "Account menu", account: "Account", login: "Log in", logout: "Log out", busy: "Logging out\u2026" },
23
+ 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" },
24
+ 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" }
25
+ };
26
+ const NativeLink = (props) => /* @__PURE__ */ jsx("a", __spreadValues({}, props));
27
+ function NaeilHeaderAccountControl({ locale, account, Link = NativeLink }) {
28
+ const text = labels[locale];
29
+ if (account.status === "signed-out") {
30
+ 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 });
31
+ }
32
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
33
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
34
+ "button",
35
+ {
36
+ type: "button",
37
+ className: "ui-focus naeil-header-account-trigger",
38
+ "data-naeil-account-trigger": true,
39
+ "data-naeil-account-state": "signed-in",
40
+ "aria-label": text.menu,
41
+ "aria-busy": account.busy || void 0,
42
+ children: /* @__PURE__ */ jsx("span", { className: "naeil-header-account-avatar", "aria-hidden": "true", children: /* @__PURE__ */ jsx(UserRound, {}) })
43
+ }
44
+ ) }),
45
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-56 max-w-[calc(100vw-2rem)]", "data-naeil-account-menu": true, children: [
46
+ /* @__PURE__ */ jsxs(DropdownMenuLabel, { className: "flex min-w-0 flex-col font-normal", children: [
47
+ /* @__PURE__ */ jsx("span", { className: "truncate text-base font-medium", children: account.displayName || text.account }),
48
+ account.email && /* @__PURE__ */ jsx("span", { className: "truncate text-sm text-muted-foreground", children: account.email })
49
+ ] }),
50
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
51
+ /* @__PURE__ */ jsx(
52
+ DropdownMenuItem,
53
+ {
54
+ className: "min-h-11",
55
+ disabled: account.busy,
56
+ onSelect: () => {
57
+ if (!account.busy) account.onLogout();
58
+ },
59
+ children: account.busy ? text.busy : text.logout
60
+ }
61
+ )
62
+ ] })
63
+ ] });
64
+ }
65
+ export {
66
+ NaeilHeaderAccountControl
67
+ };
@@ -6,35 +6,11 @@ declare const headerLocaleNames: {
6
6
  readonly ja: "日本語";
7
7
  };
8
8
  declare const headerProjects: readonly [{
9
- readonly key: "cc";
10
- readonly href: "/cc";
11
- readonly accent: "oklch(0.704 0.140 181)";
12
- readonly icon: "coral";
13
- readonly status: "active";
14
- }, {
15
- readonly key: "pkm";
16
- readonly href: "/pkm";
17
- readonly accent: "oklch(0.702 0.183 293)";
18
- readonly icon: "jellyfish";
19
- readonly status: "coming";
20
- }, {
21
9
  readonly key: "naeilUi";
22
10
  readonly href: "/design";
23
11
  readonly accent: "oklch(0.623 0.214 259)";
24
12
  readonly icon: "whale";
25
- readonly status: "active";
26
- }, {
27
- readonly key: "sa";
28
- readonly href: "/sa";
29
- readonly accent: "oklch(0.723 0.219 149)";
30
- readonly icon: "fish";
31
- readonly status: "active";
32
- }, {
33
- readonly key: "babyAgent";
34
- readonly href: "/baby-agent";
35
- readonly accent: "oklch(0.769 0.188 70.08)";
36
- readonly icon: "turtle";
37
- readonly status: "coming";
13
+ readonly status: "active" | "coming";
38
14
  }];
39
15
  declare const headerContent: {
40
16
  readonly en: {
@@ -1,40 +1,12 @@
1
1
  const headerLocales = ["en", "ko", "ja"];
2
2
  const headerLocaleNames = { en: "English", ko: "\uD55C\uAD6D\uC5B4", ja: "\u65E5\u672C\u8A9E" };
3
3
  const headerProjects = [
4
- {
5
- "key": "cc",
6
- "href": "/cc",
7
- "accent": "oklch(0.704 0.140 181)",
8
- "icon": "coral",
9
- "status": "active"
10
- },
11
- {
12
- "key": "pkm",
13
- "href": "/pkm",
14
- "accent": "oklch(0.702 0.183 293)",
15
- "icon": "jellyfish",
16
- "status": "coming"
17
- },
18
4
  {
19
5
  "key": "naeilUi",
20
6
  "href": "/design",
21
7
  "accent": "oklch(0.623 0.214 259)",
22
8
  "icon": "whale",
23
9
  "status": "active"
24
- },
25
- {
26
- "key": "sa",
27
- "href": "/sa",
28
- "accent": "oklch(0.723 0.219 149)",
29
- "icon": "fish",
30
- "status": "active"
31
- },
32
- {
33
- "key": "babyAgent",
34
- "href": "/baby-agent",
35
- "accent": "oklch(0.769 0.188 70.08)",
36
- "icon": "turtle",
37
- "status": "coming"
38
10
  }
39
11
  ];
40
12
  const headerContent = {
@@ -2,6 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
  import { NavigationProps, NavigationLinkProps, NavigationLink, NavigationLinkComponent } from './ui/navigation.js';
4
4
  import { NaeilHeaderLocale } from './naeil-header-content.js';
5
+ export { NaeilHeaderAccount, NaeilHeaderAccountControl, NaeilHeaderAccountControlProps } from './naeil-header-account.js';
5
6
 
6
7
  interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "toolbar" | "mobileToolbar" | "labels"> {
7
8
  locale: NaeilHeaderLocale;
@@ -12,7 +13,7 @@ interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "to
12
13
  brandLinkProps?: Omit<NavigationLinkProps, "href" | "children">;
13
14
  /** Omit when the application does not support changing its UI language. */
14
15
  onLocaleChange?: (locale: NaeilHeaderLocale) => void;
15
- /** Application-owned authentication; this module has no site session/backend. */
16
+ /** Use NaeilHeaderAccountControl for canonical UI; the app owns auth state/I/O. */
16
17
  authSlot?: ReactNode;
17
18
  labels?: NavigationProps["labels"];
18
19
  projects?: NavigationLink[];
@@ -40,7 +40,9 @@ import { Button } from "./ui/button.js";
40
40
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select.js";
41
41
  import { Navigation } from "./ui/navigation.js";
42
42
  import { cn } from "../lib/utils.js";
43
+ import { uiRelease } from "../lib/ui-release.js";
43
44
  import { headerContent, headerLocales, headerLocaleNames, headerProjects } from "./naeil-header-content.js";
45
+ import { NaeilHeaderAccountControl } from "./naeil-header-account.js";
44
46
  const subscribe = () => () => {
45
47
  };
46
48
  function NaeilHeaderThemeControl({ locale }) {
@@ -159,6 +161,8 @@ function NaeilHeader(_a) {
159
161
  __spreadProps(__spreadValues({}, props), {
160
162
  "data-global-header": true,
161
163
  "data-naeil-header": true,
164
+ "data-naeil-ui-version": uiRelease.version,
165
+ "data-naeil-ui-contract": uiRelease.contractVersion,
162
166
  Link,
163
167
  currentHref,
164
168
  onNavigate,
@@ -177,7 +181,7 @@ function NaeilHeader(_a) {
177
181
  })
178
182
  ),
179
183
  items: [
180
- ...showProjects ? [{ id: "projects", label: (_b2 = translations == null ? void 0 : translations.projects) != null ? _b2 : content.nav.projects, items: projectLinks, columns: 2 }] : [],
184
+ ...showProjects ? [{ id: "projects", label: (_b2 = translations == null ? void 0 : translations.projects) != null ? _b2 : content.nav.projects, items: projectLinks, columns: projectLinks.length > 1 ? 2 : 1 }] : [],
181
185
  ...showBlog ? [{ id: "blog", label: (_c = translations == null ? void 0 : translations.blog) != null ? _c : content.nav.blog, href: resolveHref("/blog"), external: projectsExternal }] : [],
182
186
  ...(subNav != null ? subNav : []).map((item) => __spreadProps(__spreadValues({}, item), { id: item.href }))
183
187
  ],
@@ -191,6 +195,7 @@ function NaeilHeader(_a) {
191
195
  }
192
196
  export {
193
197
  NaeilHeader,
198
+ NaeilHeaderAccountControl,
194
199
  NaeilHeaderLocaleControl,
195
200
  NaeilHeaderThemeControl
196
201
  };
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
- import { NavigationLink, NavigationLinkComponent } from './navigation.js';
3
+ import { NavigationLink, NavigationLinkComponent, NavigationProps } from './navigation.js';
4
4
 
5
5
  interface SiteFooterProps extends react.ComponentPropsWithoutRef<"footer"> {
6
6
  brand?: react.ReactNode;
@@ -14,8 +14,10 @@ interface SiteFooterProps extends react.ComponentPropsWithoutRef<"footer"> {
14
14
  meta?: react.ReactNode;
15
15
  containerClassName?: string;
16
16
  variant?: "full" | "compact";
17
+ /** Called for every group link, including native external anchors. Preserve modified clicks. */
18
+ onNavigate?: NavigationProps["onNavigate"];
17
19
  }
18
20
  /** Product content and translations belong to the consumer, including legal copy. */
19
- declare function SiteFooter({ brand, description, groups, Link, meta, children, containerClassName, className, variant, ...props }: SiteFooterProps): react_jsx_runtime.JSX.Element;
21
+ declare function SiteFooter({ brand, description, groups, Link, meta, children, containerClassName, className, variant, onNavigate, ...props }: SiteFooterProps): react_jsx_runtime.JSX.Element;
20
22
 
21
23
  export { SiteFooter, type SiteFooterProps };
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  var __defProp = Object.defineProperty;
2
3
  var __defProps = Object.defineProperties;
3
4
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
@@ -41,7 +42,8 @@ function SiteFooter(_a) {
41
42
  children,
42
43
  containerClassName,
43
44
  className,
44
- variant = "full"
45
+ variant = "full",
46
+ onNavigate
45
47
  } = _b, props = __objRest(_b, [
46
48
  "brand",
47
49
  "description",
@@ -51,7 +53,8 @@ function SiteFooter(_a) {
51
53
  "children",
52
54
  "containerClassName",
53
55
  "className",
54
- "variant"
56
+ "variant",
57
+ "onNavigate"
55
58
  ]);
56
59
  return /* @__PURE__ */ jsx(
57
60
  "footer",
@@ -77,6 +80,7 @@ function SiteFooter(_a) {
77
80
  target: item.target,
78
81
  rel: item.target === "_blank" ? "noopener noreferrer" : void 0,
79
82
  className: "ui-site-footer-link ui-focus",
83
+ onClick: (event) => onNavigate == null ? void 0 : onNavigate(event, item),
80
84
  children: item.label
81
85
  },
82
86
  item.id
@@ -0,0 +1,6 @@
1
+ declare const uiRelease: {
2
+ readonly version: "0.7.2";
3
+ readonly contractVersion: "1";
4
+ };
5
+
6
+ export { uiRelease };
@@ -0,0 +1,4 @@
1
+ const uiRelease = { version: "0.7.2", contractVersion: "1" };
2
+ export {
3
+ uiRelease
4
+ };