@naeil/ui 0.3.0 → 0.5.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +22 -2
  2. package/DESIGN.md +27 -0
  3. package/README.md +16 -9
  4. package/THIRD_PARTY_NOTICES.md +6 -0
  5. package/dist/chunk-CE73AEJZ.js +667 -0
  6. package/dist/{chunk-QKVN6Q6C.js → chunk-QSTGUEEI.js} +60 -175
  7. package/dist/chunk-S64H3OYQ.js +1512 -0
  8. package/dist/components/index.d.ts +33 -10
  9. package/dist/components/index.js +101 -557
  10. package/dist/components/naeil-header.d.ts +54 -0
  11. package/dist/components/naeil-header.js +14 -0
  12. package/dist/components/ui/index.d.ts +3 -1
  13. package/dist/components/ui/index.js +40 -179
  14. package/dist/navigation-CL10a6Eb.d.ts +48 -0
  15. package/dist/site-footer-B67meCDv.d.ts +21 -0
  16. package/dist/source/components/brand-artwork.generated.d.ts +162 -0
  17. package/dist/source/components/brand-artwork.generated.js +1103 -0
  18. package/dist/source/components/footer.d.ts +13 -4
  19. package/dist/source/components/footer.js +74 -114
  20. package/dist/source/components/index.d.ts +6 -4
  21. package/dist/source/components/locale-switcher.js +1 -1
  22. package/dist/source/components/logo.d.ts +13 -4
  23. package/dist/source/components/logo.js +83 -44
  24. package/dist/source/components/naeil-header-content.d.ts +171 -0
  25. package/dist/source/components/naeil-header-content.js +176 -0
  26. package/dist/source/components/naeil-header.d.ts +52 -0
  27. package/dist/source/components/naeil-header.js +196 -0
  28. package/dist/source/components/nav.d.ts +12 -4
  29. package/dist/source/components/nav.js +51 -384
  30. package/dist/source/components/ui/index.d.ts +2 -0
  31. package/dist/source/components/ui/index.js +4 -0
  32. package/dist/source/components/ui/navigation.d.ts +48 -0
  33. package/dist/source/components/ui/navigation.js +347 -0
  34. package/dist/source/components/ui/site-footer.d.ts +21 -0
  35. package/dist/source/components/ui/site-footer.js +93 -0
  36. package/docs/components/README.md +6 -1
  37. package/docs/components/common.md +1 -1
  38. package/docs/components/naeil-header.md +50 -0
  39. package/docs/components/navigation.md +59 -0
  40. package/docs/design/public-ui-support.md +17 -2
  41. package/docs/design/v2-migration.md +75 -11
  42. package/docs/package-release.md +54 -13
  43. package/licenses/Lato-OFL.txt +93 -0
  44. package/package.json +18 -4
  45. package/src/styles/components.css +292 -0
  46. package/src/styles/theme.css +4 -0
@@ -1,15 +1,24 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { SiteFooterProps } from './ui/site-footer.js';
3
+ import 'react';
4
+ import './ui/navigation.js';
2
5
 
3
6
  interface FooterProps {
4
- /** Link component from consumer */
5
7
  Link?: React.ComponentType<{
6
8
  href: string;
7
9
  children: React.ReactNode;
8
10
  className?: string;
9
11
  }>;
10
- /** Whether links go to naeil.dev (external) or are internal. Default: false */
11
12
  linksExternal?: boolean;
13
+ brandSlot?: React.ReactNode;
14
+ description?: React.ReactNode;
15
+ groups?: SiteFooterProps["groups"];
16
+ socialSlot?: React.ReactNode;
17
+ meta?: React.ReactNode;
18
+ variant?: SiteFooterProps["variant"];
19
+ className?: string;
20
+ containerClassName?: string;
12
21
  }
13
- declare function Footer({ Link, linksExternal }: FooterProps): react_jsx_runtime.JSX.Element;
22
+ declare function Footer({ Link, linksExternal, brandSlot, description, groups, socialSlot, meta, variant, className, containerClassName, }: FooterProps): react_jsx_runtime.JSX.Element;
14
23
 
15
- export { Footer };
24
+ export { Footer, type FooterProps };
@@ -1,47 +1,87 @@
1
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));
2
21
  import { jsx, jsxs } from "react/jsx-runtime";
3
22
  import { useTranslations } from "next-intl";
4
- function NavLink({
5
- href,
6
- children,
23
+ import { Logo } from "./logo.js";
24
+ import { SiteFooter } from "./ui/site-footer.js";
25
+ import { cn } from "../lib/utils.js";
26
+ function Footer({
27
+ Link,
28
+ linksExternal = false,
29
+ brandSlot,
30
+ description,
31
+ groups,
32
+ socialSlot,
33
+ meta,
34
+ variant,
7
35
  className,
8
- linksExternal,
9
- Link
36
+ containerClassName
10
37
  }) {
11
- if (linksExternal) {
12
- return /* @__PURE__ */ jsx(
13
- "a",
14
- {
15
- href: `https://naeil.dev${href}`,
16
- target: "_blank",
17
- rel: "noopener noreferrer",
18
- className,
19
- children
20
- }
21
- );
22
- }
23
- if (Link) {
24
- return /* @__PURE__ */ jsx(Link, { href, className, children });
25
- }
26
- return /* @__PURE__ */ jsx("a", { href, className, children });
27
- }
28
- function Footer({ Link, linksExternal = false }) {
29
38
  const t = useTranslations("footer");
30
- return /* @__PURE__ */ jsx("footer", { className: "border-border/40 border-t", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto flex max-w-7xl flex-col gap-10 px-6 py-16 sm:flex-row sm:justify-between", children: [
31
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
32
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
33
- /* @__PURE__ */ jsx(Logo, { size: 20 }),
34
- /* @__PURE__ */ jsx("span", { className: "text-foreground text-sm font-semibold tracking-tight", children: ".naeil" })
35
- ] }),
36
- /* @__PURE__ */ jsx("p", { className: "text-muted-foreground max-w-[240px] text-sm leading-relaxed", children: t("tagline") }),
37
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
39
+ const destinations = [
40
+ { id: "projects", label: t("projects"), href: "/projects" },
41
+ { id: "blog", label: t("blog"), href: "/blog" }
42
+ ];
43
+ return /* @__PURE__ */ jsx(
44
+ SiteFooter,
45
+ {
46
+ Link,
47
+ className,
48
+ containerClassName: cn("max-w-7xl", containerClassName),
49
+ variant,
50
+ brand: brandSlot != null ? brandSlot : /* @__PURE__ */ jsx(Logo, { variant: "footer", size: 20, className: "block" }),
51
+ description: description === void 0 ? t("tagline") : description,
52
+ groups: groups != null ? groups : [
53
+ {
54
+ id: "navigation",
55
+ label: t("navigation"),
56
+ links: destinations.map((item) => __spreadProps(__spreadValues({}, item), {
57
+ href: linksExternal ? `https://naeil.dev${item.href}` : item.href,
58
+ external: linksExternal,
59
+ target: linksExternal ? "_blank" : void 0
60
+ }))
61
+ },
62
+ {
63
+ id: "social",
64
+ label: t("social"),
65
+ links: [
66
+ {
67
+ id: "github",
68
+ label: "GitHub",
69
+ href: "https://github.com/naeil-dev",
70
+ external: true,
71
+ target: "_blank"
72
+ }
73
+ ]
74
+ }
75
+ ],
76
+ meta,
77
+ children: socialSlot === void 0 ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
38
78
  /* @__PURE__ */ jsx(
39
79
  "a",
40
80
  {
41
81
  href: "https://github.com/naeil-dev",
42
82
  target: "_blank",
43
83
  rel: "noopener noreferrer",
44
- className: "text-muted-foreground hover:text-foreground transition-colors",
84
+ className: "ui-navigation-link ui-focus",
45
85
  "aria-label": "GitHub",
46
86
  children: /* @__PURE__ */ jsx(GitHubIcon, {})
47
87
  }
@@ -52,92 +92,12 @@ function Footer({ Link, linksExternal = false }) {
52
92
  href: "https://x.com",
53
93
  target: "_blank",
54
94
  rel: "noopener noreferrer",
55
- className: "text-muted-foreground hover:text-foreground transition-colors",
95
+ className: "ui-navigation-link ui-focus",
56
96
  "aria-label": "X",
57
97
  children: /* @__PURE__ */ jsx(XIcon, {})
58
98
  }
59
99
  )
60
- ] })
61
- ] }),
62
- /* @__PURE__ */ jsxs("div", { className: "flex gap-10 sm:gap-16", children: [
63
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
64
- /* @__PURE__ */ jsx("span", { className: "text-foreground text-xs font-medium uppercase tracking-wider", children: t("navigation") }),
65
- /* @__PURE__ */ jsx(
66
- NavLink,
67
- {
68
- href: "/projects",
69
- className: "text-muted-foreground hover:text-foreground text-sm transition-colors",
70
- linksExternal,
71
- Link,
72
- children: t("projects")
73
- }
74
- ),
75
- /* @__PURE__ */ jsx(
76
- NavLink,
77
- {
78
- href: "/blog",
79
- className: "text-muted-foreground hover:text-foreground text-sm transition-colors",
80
- linksExternal,
81
- Link,
82
- children: t("blog")
83
- }
84
- )
85
- ] }),
86
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
87
- /* @__PURE__ */ jsx("span", { className: "text-foreground text-xs font-medium uppercase tracking-wider", children: t("social") }),
88
- /* @__PURE__ */ jsx(
89
- "a",
90
- {
91
- href: "https://github.com/naeil-dev",
92
- target: "_blank",
93
- rel: "noopener noreferrer",
94
- className: "text-muted-foreground hover:text-foreground text-sm transition-colors",
95
- children: "GitHub \u2197"
96
- }
97
- )
98
- ] })
99
- ] })
100
- ] }) });
101
- }
102
- function Logo({ size = 20 }) {
103
- const id = `naeil-footer-logo-${size}`;
104
- return /* @__PURE__ */ jsxs(
105
- "svg",
106
- {
107
- width: size,
108
- height: size,
109
- viewBox: "0 0 24 24",
110
- fill: "none",
111
- "aria-label": "naeil",
112
- children: [
113
- /* @__PURE__ */ jsx(
114
- "path",
115
- {
116
- d: "M6 4 L6 16 L20 16",
117
- stroke: "currentColor",
118
- strokeWidth: "2",
119
- strokeLinecap: "square",
120
- strokeLinejoin: "miter"
121
- }
122
- ),
123
- /* @__PURE__ */ jsx(
124
- "circle",
125
- {
126
- cx: "15",
127
- cy: "16",
128
- r: "3.5",
129
- fill: `url(#${id}-grad)`,
130
- mask: `url(#${id})`
131
- }
132
- ),
133
- /* @__PURE__ */ jsxs("defs", { children: [
134
- /* @__PURE__ */ jsxs("linearGradient", { id: `${id}-grad`, x1: "15", y1: "12.5", x2: "15", y2: "16", children: [
135
- /* @__PURE__ */ jsx("stop", { stopColor: "#eab308" }),
136
- /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#dc2626" })
137
- ] }),
138
- /* @__PURE__ */ jsx("mask", { id, children: /* @__PURE__ */ jsx("rect", { x: "0", y: "0", width: "24", height: "16", fill: "white" }) })
139
- ] })
140
- ]
100
+ ] }) : socialSlot
141
101
  }
142
102
  );
143
103
  }
@@ -1,11 +1,13 @@
1
- export { Nav } from './nav.js';
2
- export { Footer } from './footer.js';
1
+ export { Nav, NavProps } from './nav.js';
2
+ export { Footer, FooterProps } from './footer.js';
3
3
  export { LocaleSwitcher } from './locale-switcher.js';
4
4
  export { ThemeToggle } from './theme-toggle.js';
5
5
  export { ThemeProvider } from './theme-provider.js';
6
6
  export { ThemeToggleIcon } from './theme-toggle-icon.js';
7
- export { Logo } from './logo.js';
7
+ export { Logo, LogoProps } from './logo.js';
8
8
  export { PageTitle, SectionTitle, pageTitleClass, sectionTitleClass } from './typography.js';
9
9
  import 'react/jsx-runtime';
10
- import 'next-themes';
10
+ import './ui/navigation.js';
11
11
  import 'react';
12
+ import './ui/site-footer.js';
13
+ import 'next-themes';
@@ -17,7 +17,7 @@ function LocaleSwitcher({
17
17
  /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
18
18
  "button",
19
19
  {
20
- className: "text-muted-foreground hover:text-foreground flex items-center gap-1.5 text-sm transition-colors focus:outline-none",
20
+ className: "ui-focus text-muted-foreground hover:text-foreground inline-flex min-h-11 min-w-11 items-center justify-center gap-1.5 rounded-md px-2 text-sm transition-colors",
21
21
  "aria-label": `Change language \u2014 current: ${(_a = current == null ? void 0 : current.short) != null ? _a : currentLocale}`,
22
22
  children: [
23
23
  /* @__PURE__ */ jsx(GlobeIcon, {}),
@@ -1,9 +1,18 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { SVGProps } from 'react';
2
3
 
3
- declare function Logo({ size, mono, className, }: {
4
+ interface LogoProps extends Omit<SVGProps<SVGSVGElement>, "children" | "width" | "height" | "viewBox"> {
5
+ /** Rendered height. Symbol stays square; lockups preserve their aspect ratio. */
4
6
  size?: number;
7
+ /** Legacy single-ink currentColor silhouette. Prefer tone="gray" for tonal detail. */
5
8
  mono?: boolean;
6
- className?: string;
7
- }): react_jsx_runtime.JSX.Element;
9
+ variant?: "symbol" | "horizontal" | "footer" | "stacked" | "wordmark";
10
+ tone?: "color" | "gray";
11
+ /** Auto follows the nearest .light/.dark or data-theme ancestor, then the OS. */
12
+ theme?: "auto" | "light" | "dark";
13
+ /** null marks a decorative logo; label the containing link instead. */
14
+ label?: string | null;
15
+ }
16
+ declare function Logo({ size, mono, variant, tone, theme, label, className, ...props }: LogoProps): react_jsx_runtime.JSX.Element;
8
17
 
9
- export { Logo };
18
+ export { Logo, type LogoProps };
@@ -1,50 +1,89 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
- function Logo({
3
- size = 20,
4
- mono = false,
5
- className
6
- }) {
7
- const id = `naeil-logo-${size}`;
8
- return /* @__PURE__ */ jsxs(
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 { Fragment, jsx, jsxs } from "react/jsx-runtime";
34
+ import { useId } from "react";
35
+ import { BrandArtwork, brandDimensions, brandVersion } from "./brand-artwork.generated.js";
36
+ const autoThemeCSS = `
37
+ :where(.light,[data-theme="light"]){--naeil-logo-light:inline;--naeil-logo-dark:none}
38
+ :where(.dark,[data-theme="dark"]){--naeil-logo-light:none;--naeil-logo-dark:inline}
39
+ @media(prefers-color-scheme:dark){[data-naeil-theme="auto"]{--naeil-logo-os-light:none;--naeil-logo-os-dark:inline}}
40
+ `;
41
+ function Logo(_a) {
42
+ var _b = _a, {
43
+ size = 20,
44
+ mono = false,
45
+ variant = "symbol",
46
+ tone = "color",
47
+ theme = "auto",
48
+ label = "naeil",
49
+ className
50
+ } = _b, props = __objRest(_b, [
51
+ "size",
52
+ "mono",
53
+ "variant",
54
+ "tone",
55
+ "theme",
56
+ "label",
57
+ "className"
58
+ ]);
59
+ const id = `naeil-${useId()}`;
60
+ const form = variant === "symbol" && size <= 48 ? "symbol-small" : variant;
61
+ const mode = mono ? "mono" : `${tone}${theme === "dark" ? "-dark" : ""}`;
62
+ const asset = `${form}-${mode}`;
63
+ const geometry = brandDimensions[asset];
64
+ const auto = !mono && theme === "auto";
65
+ return /* @__PURE__ */ jsx(
9
66
  "svg",
10
- {
11
- width: size,
67
+ __spreadProps(__spreadValues({
68
+ width: size * geometry.width / geometry.height,
12
69
  height: size,
13
- viewBox: "0 0 24 24",
70
+ viewBox: geometry.viewBox,
14
71
  fill: "none",
15
- "aria-label": "naeil",
16
- className,
17
- children: [
18
- /* @__PURE__ */ jsx(
19
- "path",
20
- {
21
- d: "M6 4 L6 16 L20 16",
22
- stroke: "currentColor",
23
- strokeWidth: "2",
24
- strokeLinecap: "square",
25
- strokeLinejoin: "miter"
26
- }
27
- ),
28
- mono ? /* @__PURE__ */ jsx("circle", { cx: "15", cy: "16", r: "3.5", fill: "currentColor", mask: `url(#${id})` }) : /* @__PURE__ */ jsx("circle", { cx: "15", cy: "16", r: "3.5", fill: `url(#${id}-grad)`, mask: `url(#${id})` }),
29
- /* @__PURE__ */ jsxs("defs", { children: [
30
- !mono && /* @__PURE__ */ jsxs(
31
- "linearGradient",
32
- {
33
- id: `${id}-grad`,
34
- x1: "15",
35
- y1: "12.5",
36
- x2: "15",
37
- y2: "16",
38
- children: [
39
- /* @__PURE__ */ jsx("stop", { stopColor: "#eab308" }),
40
- /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#dc2626" })
41
- ]
42
- }
43
- ),
44
- /* @__PURE__ */ jsx("mask", { id, children: /* @__PURE__ */ jsx("rect", { x: "0", y: "0", width: "24", height: "16", fill: "white" }) })
45
- ] })
46
- ]
47
- }
72
+ role: label === null ? void 0 : "img",
73
+ "aria-label": label != null ? label : void 0,
74
+ "aria-hidden": label === null ? true : void 0,
75
+ focusable: "false",
76
+ "data-naeil-brand": brandVersion,
77
+ "data-naeil-variant": variant,
78
+ "data-naeil-theme": auto ? "auto" : theme,
79
+ className
80
+ }, props), {
81
+ children: auto ? /* @__PURE__ */ jsxs(Fragment, { children: [
82
+ /* @__PURE__ */ jsx("style", { children: autoThemeCSS }),
83
+ /* @__PURE__ */ jsx("g", { "data-naeil-palette": "light", style: { display: "var(--naeil-logo-light, var(--naeil-logo-os-light, inline))" }, children: /* @__PURE__ */ jsx(BrandArtwork, { asset, id: `${id}-light` }) }),
84
+ /* @__PURE__ */ jsx("g", { "data-naeil-palette": "dark", style: { display: "var(--naeil-logo-dark, var(--naeil-logo-os-dark, none))" }, children: /* @__PURE__ */ jsx(BrandArtwork, { asset: `${form}-${tone}-dark`, id: `${id}-dark` }) })
85
+ ] }) : /* @__PURE__ */ jsx(BrandArtwork, { asset, id })
86
+ })
48
87
  );
49
88
  }
50
89
  export {
@@ -0,0 +1,171 @@
1
+ declare const headerLocales: readonly ["en", "ko", "ja"];
2
+ type NaeilHeaderLocale = (typeof headerLocales)[number];
3
+ declare const headerLocaleNames: {
4
+ readonly en: "English";
5
+ readonly ko: "한국어";
6
+ readonly ja: "日本語";
7
+ };
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
+ readonly key: "naeilUi";
22
+ readonly href: "/design";
23
+ readonly accent: "oklch(0.623 0.214 259)";
24
+ 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";
38
+ }];
39
+ declare const headerContent: {
40
+ readonly en: {
41
+ readonly nav: {
42
+ readonly home: "Home";
43
+ readonly projects: "Projects";
44
+ readonly blog: "Blog";
45
+ readonly navigation: "Main navigation";
46
+ readonly menu: "Menu";
47
+ readonly closeMenu: "Close menu";
48
+ };
49
+ readonly theme: {
50
+ readonly switchToLight: "Switch to light theme";
51
+ readonly switchToDark: "Switch to dark theme";
52
+ };
53
+ readonly locale: {
54
+ readonly switchLabel: "Language";
55
+ };
56
+ readonly projects: {
57
+ readonly cc: {
58
+ readonly name: "Content Collector";
59
+ readonly description: "Automated content collection from RSS, YouTube, Reddit + AI summarization";
60
+ };
61
+ readonly pkm: {
62
+ readonly name: "PKM";
63
+ readonly description: "Personal knowledge management — document parsing, embeddings, semantic search";
64
+ };
65
+ readonly naeilUi: {
66
+ readonly name: "naeil-ui";
67
+ readonly description: "Minimal design system — OKLCH tokens, Tailwind v4, shadcn";
68
+ };
69
+ readonly sa: {
70
+ readonly name: "Sustainability Analyzer";
71
+ readonly description: "AI-powered ESG report analysis — PDF parsing, qualitative assessment, comparison tables";
72
+ };
73
+ readonly babyAgent: {
74
+ readonly name: "Baby Agent";
75
+ readonly description: "Parenting AI agent — LINE-based Q&A, records, reminders";
76
+ };
77
+ readonly status: {
78
+ readonly active: "Active";
79
+ readonly coming: "Coming Soon";
80
+ };
81
+ };
82
+ };
83
+ readonly ko: {
84
+ readonly nav: {
85
+ readonly home: "홈";
86
+ readonly projects: "프로젝트";
87
+ readonly blog: "블로그";
88
+ readonly navigation: "주요 메뉴";
89
+ readonly menu: "메뉴";
90
+ readonly closeMenu: "메뉴 닫기";
91
+ };
92
+ readonly theme: {
93
+ readonly switchToLight: "밝은 테마로 전환";
94
+ readonly switchToDark: "어두운 테마로 전환";
95
+ };
96
+ readonly locale: {
97
+ readonly switchLabel: "언어";
98
+ };
99
+ readonly projects: {
100
+ readonly cc: {
101
+ readonly name: "Content Collector";
102
+ readonly description: "RSS, YouTube, Reddit 자동 수집 + AI 요약";
103
+ };
104
+ readonly pkm: {
105
+ readonly name: "PKM";
106
+ readonly description: "개인 지식 관리 — 문서 파싱, 임베딩, 시맨틱 검색";
107
+ };
108
+ readonly naeilUi: {
109
+ readonly name: "naeil-ui";
110
+ readonly description: "미니멀 디자인 시스템 — OKLCH 토큰, Tailwind v4, shadcn";
111
+ };
112
+ readonly sa: {
113
+ readonly name: "Sustainability Analyzer";
114
+ readonly description: "ESG 리포트 AI 분석 — PDF 파싱, 정성평가, 비교표 자동 생성";
115
+ };
116
+ readonly babyAgent: {
117
+ readonly name: "Baby Agent";
118
+ readonly description: "육아 AI 에이전트 — LINE 기반 Q&A, 기록, 리마인더";
119
+ };
120
+ readonly status: {
121
+ readonly active: "활성";
122
+ readonly coming: "준비 중";
123
+ };
124
+ };
125
+ };
126
+ readonly ja: {
127
+ readonly nav: {
128
+ readonly home: "ホーム";
129
+ readonly projects: "プロジェクト";
130
+ readonly blog: "ブログ";
131
+ readonly navigation: "メインナビゲーション";
132
+ readonly menu: "メニュー";
133
+ readonly closeMenu: "メニューを閉じる";
134
+ };
135
+ readonly theme: {
136
+ readonly switchToLight: "ライトテーマに切り替える";
137
+ readonly switchToDark: "ダークテーマに切り替える";
138
+ };
139
+ readonly locale: {
140
+ readonly switchLabel: "言語";
141
+ };
142
+ readonly projects: {
143
+ readonly cc: {
144
+ readonly name: "Content Collector";
145
+ readonly description: "RSS、YouTube、Redditの自動収集 + AI要約";
146
+ };
147
+ readonly pkm: {
148
+ readonly name: "PKM";
149
+ readonly description: "個人ナレッジ管理 — ドキュメント解析、埋め込み、セマンティック検索";
150
+ };
151
+ readonly naeilUi: {
152
+ readonly name: "naeil-ui";
153
+ readonly description: "ミニマルデザインシステム — OKLCHトークン、Tailwind v4、shadcn";
154
+ };
155
+ readonly sa: {
156
+ readonly name: "Sustainability Analyzer";
157
+ readonly description: "ESGレポートAI分析 — PDF解析、定性評価、比較表の自動生成";
158
+ };
159
+ readonly babyAgent: {
160
+ readonly name: "Baby Agent";
161
+ readonly description: "育児AIエージェント — LINE Q&A、記録、リマインダー";
162
+ };
163
+ readonly status: {
164
+ readonly active: "アクティブ";
165
+ readonly coming: "準備中";
166
+ };
167
+ };
168
+ };
169
+ };
170
+
171
+ export { type NaeilHeaderLocale, headerContent, headerLocaleNames, headerLocales, headerProjects };