@naeil/ui 0.4.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.
- package/CHANGELOG.md +11 -1
- package/DESIGN.md +19 -0
- package/README.md +16 -9
- package/THIRD_PARTY_NOTICES.md +4 -0
- package/dist/chunk-CE73AEJZ.js +667 -0
- package/dist/{chunk-QKVN6Q6C.js → chunk-QSTGUEEI.js} +60 -175
- package/dist/chunk-S64H3OYQ.js +1512 -0
- package/dist/components/index.d.ts +19 -5
- package/dist/components/index.js +135 -1618
- package/dist/components/naeil-header.d.ts +54 -0
- package/dist/components/naeil-header.js +14 -0
- package/dist/components/ui/index.d.ts +2 -0
- package/dist/components/ui/index.js +40 -179
- package/dist/navigation-CL10a6Eb.d.ts +48 -0
- package/dist/site-footer-B67meCDv.d.ts +21 -0
- package/dist/source/components/footer.d.ts +13 -4
- package/dist/source/components/footer.js +75 -71
- package/dist/source/components/index.d.ts +5 -3
- package/dist/source/components/locale-switcher.js +1 -1
- package/dist/source/components/naeil-header-content.d.ts +171 -0
- package/dist/source/components/naeil-header-content.js +176 -0
- package/dist/source/components/naeil-header.d.ts +52 -0
- package/dist/source/components/naeil-header.js +196 -0
- package/dist/source/components/nav.d.ts +10 -2
- package/dist/source/components/nav.js +51 -347
- package/dist/source/components/ui/index.d.ts +2 -0
- package/dist/source/components/ui/index.js +4 -0
- package/dist/source/components/ui/navigation.d.ts +48 -0
- package/dist/source/components/ui/navigation.js +347 -0
- package/dist/source/components/ui/site-footer.d.ts +21 -0
- package/dist/source/components/ui/site-footer.js +93 -0
- package/docs/components/README.md +6 -1
- package/docs/components/common.md +1 -1
- package/docs/components/naeil-header.md +50 -0
- package/docs/components/navigation.md +59 -0
- package/docs/design/public-ui-support.md +14 -1
- package/docs/design/v2-migration.md +46 -12
- package/docs/package-release.md +36 -14
- package/package.json +13 -1
- package/src/styles/components.css +292 -0
- package/src/styles/theme.css +4 -0
|
@@ -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
|
|
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, {}),
|
|
@@ -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 };
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
const headerLocales = ["en", "ko", "ja"];
|
|
2
|
+
const headerLocaleNames = { en: "English", ko: "\uD55C\uAD6D\uC5B4", ja: "\u65E5\u672C\u8A9E" };
|
|
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
|
+
{
|
|
19
|
+
"key": "naeilUi",
|
|
20
|
+
"href": "/design",
|
|
21
|
+
"accent": "oklch(0.623 0.214 259)",
|
|
22
|
+
"icon": "whale",
|
|
23
|
+
"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
|
+
}
|
|
39
|
+
];
|
|
40
|
+
const headerContent = {
|
|
41
|
+
"en": {
|
|
42
|
+
"nav": {
|
|
43
|
+
"home": "Home",
|
|
44
|
+
"projects": "Projects",
|
|
45
|
+
"blog": "Blog",
|
|
46
|
+
"navigation": "Main navigation",
|
|
47
|
+
"menu": "Menu",
|
|
48
|
+
"closeMenu": "Close menu"
|
|
49
|
+
},
|
|
50
|
+
"theme": {
|
|
51
|
+
"switchToLight": "Switch to light theme",
|
|
52
|
+
"switchToDark": "Switch to dark theme"
|
|
53
|
+
},
|
|
54
|
+
"locale": {
|
|
55
|
+
"switchLabel": "Language"
|
|
56
|
+
},
|
|
57
|
+
"projects": {
|
|
58
|
+
"cc": {
|
|
59
|
+
"name": "Content Collector",
|
|
60
|
+
"description": "Automated content collection from RSS, YouTube, Reddit + AI summarization"
|
|
61
|
+
},
|
|
62
|
+
"pkm": {
|
|
63
|
+
"name": "PKM",
|
|
64
|
+
"description": "Personal knowledge management \u2014 document parsing, embeddings, semantic search"
|
|
65
|
+
},
|
|
66
|
+
"naeilUi": {
|
|
67
|
+
"name": "naeil-ui",
|
|
68
|
+
"description": "Minimal design system \u2014 OKLCH tokens, Tailwind v4, shadcn"
|
|
69
|
+
},
|
|
70
|
+
"sa": {
|
|
71
|
+
"name": "Sustainability Analyzer",
|
|
72
|
+
"description": "AI-powered ESG report analysis \u2014 PDF parsing, qualitative assessment, comparison tables"
|
|
73
|
+
},
|
|
74
|
+
"babyAgent": {
|
|
75
|
+
"name": "Baby Agent",
|
|
76
|
+
"description": "Parenting AI agent \u2014 LINE-based Q&A, records, reminders"
|
|
77
|
+
},
|
|
78
|
+
"status": {
|
|
79
|
+
"active": "Active",
|
|
80
|
+
"coming": "Coming Soon"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"ko": {
|
|
85
|
+
"nav": {
|
|
86
|
+
"home": "\uD648",
|
|
87
|
+
"projects": "\uD504\uB85C\uC81D\uD2B8",
|
|
88
|
+
"blog": "\uBE14\uB85C\uADF8",
|
|
89
|
+
"navigation": "\uC8FC\uC694 \uBA54\uB274",
|
|
90
|
+
"menu": "\uBA54\uB274",
|
|
91
|
+
"closeMenu": "\uBA54\uB274 \uB2EB\uAE30"
|
|
92
|
+
},
|
|
93
|
+
"theme": {
|
|
94
|
+
"switchToLight": "\uBC1D\uC740 \uD14C\uB9C8\uB85C \uC804\uD658",
|
|
95
|
+
"switchToDark": "\uC5B4\uB450\uC6B4 \uD14C\uB9C8\uB85C \uC804\uD658"
|
|
96
|
+
},
|
|
97
|
+
"locale": {
|
|
98
|
+
"switchLabel": "\uC5B8\uC5B4"
|
|
99
|
+
},
|
|
100
|
+
"projects": {
|
|
101
|
+
"cc": {
|
|
102
|
+
"name": "Content Collector",
|
|
103
|
+
"description": "RSS, YouTube, Reddit \uC790\uB3D9 \uC218\uC9D1 + AI \uC694\uC57D"
|
|
104
|
+
},
|
|
105
|
+
"pkm": {
|
|
106
|
+
"name": "PKM",
|
|
107
|
+
"description": "\uAC1C\uC778 \uC9C0\uC2DD \uAD00\uB9AC \u2014 \uBB38\uC11C \uD30C\uC2F1, \uC784\uBCA0\uB529, \uC2DC\uB9E8\uD2F1 \uAC80\uC0C9"
|
|
108
|
+
},
|
|
109
|
+
"naeilUi": {
|
|
110
|
+
"name": "naeil-ui",
|
|
111
|
+
"description": "\uBBF8\uB2C8\uBA40 \uB514\uC790\uC778 \uC2DC\uC2A4\uD15C \u2014 OKLCH \uD1A0\uD070, Tailwind v4, shadcn"
|
|
112
|
+
},
|
|
113
|
+
"sa": {
|
|
114
|
+
"name": "Sustainability Analyzer",
|
|
115
|
+
"description": "ESG \uB9AC\uD3EC\uD2B8 AI \uBD84\uC11D \u2014 PDF \uD30C\uC2F1, \uC815\uC131\uD3C9\uAC00, \uBE44\uAD50\uD45C \uC790\uB3D9 \uC0DD\uC131"
|
|
116
|
+
},
|
|
117
|
+
"babyAgent": {
|
|
118
|
+
"name": "Baby Agent",
|
|
119
|
+
"description": "\uC721\uC544 AI \uC5D0\uC774\uC804\uD2B8 \u2014 LINE \uAE30\uBC18 Q&A, \uAE30\uB85D, \uB9AC\uB9C8\uC778\uB354"
|
|
120
|
+
},
|
|
121
|
+
"status": {
|
|
122
|
+
"active": "\uD65C\uC131",
|
|
123
|
+
"coming": "\uC900\uBE44 \uC911"
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"ja": {
|
|
128
|
+
"nav": {
|
|
129
|
+
"home": "\u30DB\u30FC\u30E0",
|
|
130
|
+
"projects": "\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8",
|
|
131
|
+
"blog": "\u30D6\u30ED\u30B0",
|
|
132
|
+
"navigation": "\u30E1\u30A4\u30F3\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3",
|
|
133
|
+
"menu": "\u30E1\u30CB\u30E5\u30FC",
|
|
134
|
+
"closeMenu": "\u30E1\u30CB\u30E5\u30FC\u3092\u9589\u3058\u308B"
|
|
135
|
+
},
|
|
136
|
+
"theme": {
|
|
137
|
+
"switchToLight": "\u30E9\u30A4\u30C8\u30C6\u30FC\u30DE\u306B\u5207\u308A\u66FF\u3048\u308B",
|
|
138
|
+
"switchToDark": "\u30C0\u30FC\u30AF\u30C6\u30FC\u30DE\u306B\u5207\u308A\u66FF\u3048\u308B"
|
|
139
|
+
},
|
|
140
|
+
"locale": {
|
|
141
|
+
"switchLabel": "\u8A00\u8A9E"
|
|
142
|
+
},
|
|
143
|
+
"projects": {
|
|
144
|
+
"cc": {
|
|
145
|
+
"name": "Content Collector",
|
|
146
|
+
"description": "RSS\u3001YouTube\u3001Reddit\u306E\u81EA\u52D5\u53CE\u96C6 + AI\u8981\u7D04"
|
|
147
|
+
},
|
|
148
|
+
"pkm": {
|
|
149
|
+
"name": "PKM",
|
|
150
|
+
"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"
|
|
151
|
+
},
|
|
152
|
+
"naeilUi": {
|
|
153
|
+
"name": "naeil-ui",
|
|
154
|
+
"description": "\u30DF\u30CB\u30DE\u30EB\u30C7\u30B6\u30A4\u30F3\u30B7\u30B9\u30C6\u30E0 \u2014 OKLCH\u30C8\u30FC\u30AF\u30F3\u3001Tailwind v4\u3001shadcn"
|
|
155
|
+
},
|
|
156
|
+
"sa": {
|
|
157
|
+
"name": "Sustainability Analyzer",
|
|
158
|
+
"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"
|
|
159
|
+
},
|
|
160
|
+
"babyAgent": {
|
|
161
|
+
"name": "Baby Agent",
|
|
162
|
+
"description": "\u80B2\u5150AI\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8 \u2014 LINE Q&A\u3001\u8A18\u9332\u3001\u30EA\u30DE\u30A4\u30F3\u30C0\u30FC"
|
|
163
|
+
},
|
|
164
|
+
"status": {
|
|
165
|
+
"active": "\u30A2\u30AF\u30C6\u30A3\u30D6",
|
|
166
|
+
"coming": "\u6E96\u5099\u4E2D"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
export {
|
|
172
|
+
headerContent,
|
|
173
|
+
headerLocaleNames,
|
|
174
|
+
headerLocales,
|
|
175
|
+
headerProjects
|
|
176
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { NavigationProps, NavigationLinkProps, NavigationLink, NavigationLinkComponent } from './ui/navigation.js';
|
|
4
|
+
import { NaeilHeaderLocale } from './naeil-header-content.js';
|
|
5
|
+
|
|
6
|
+
interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "toolbar" | "mobileToolbar" | "labels"> {
|
|
7
|
+
locale: NaeilHeaderLocale;
|
|
8
|
+
/** Resolve canonical unlocalized paths. Defaults to the official localized site. */
|
|
9
|
+
resolveHref?: (path: string) => string;
|
|
10
|
+
brandHref?: string;
|
|
11
|
+
brandSlot?: ReactNode;
|
|
12
|
+
brandLinkProps?: Omit<NavigationLinkProps, "href" | "children">;
|
|
13
|
+
/** Omit when the application does not support changing its UI language. */
|
|
14
|
+
onLocaleChange?: (locale: NaeilHeaderLocale) => void;
|
|
15
|
+
/** Application-owned authentication; this module has no site session/backend. */
|
|
16
|
+
authSlot?: ReactNode;
|
|
17
|
+
labels?: NavigationProps["labels"];
|
|
18
|
+
projects?: NavigationLink[];
|
|
19
|
+
/** Legacy remote-catalog mode: generated noncurrent project/blog links use native anchors. */
|
|
20
|
+
projectsExternal?: boolean;
|
|
21
|
+
/** Legacy next-intl copy overrides; catalog/artwork/layout remain shared. */
|
|
22
|
+
translations?: {
|
|
23
|
+
projects: string;
|
|
24
|
+
blog: string;
|
|
25
|
+
project: (key: string) => string;
|
|
26
|
+
};
|
|
27
|
+
showProjects?: boolean;
|
|
28
|
+
showBlog?: boolean;
|
|
29
|
+
subNav?: Array<{
|
|
30
|
+
label: string;
|
|
31
|
+
href: string;
|
|
32
|
+
}>;
|
|
33
|
+
currentProjectKey?: string;
|
|
34
|
+
currentProjectHref?: string;
|
|
35
|
+
/** Compatibility escape hatch replacing the default theme/locale/auth toolbar. */
|
|
36
|
+
toolbarSlot?: ReactNode;
|
|
37
|
+
/** Compatibility escape hatch for the legacy native external brand link. */
|
|
38
|
+
brandLinkComponent?: NavigationLinkComponent;
|
|
39
|
+
}
|
|
40
|
+
/** The actual header theme control; reads only the consumer's theme provider. */
|
|
41
|
+
declare function NaeilHeaderThemeControl({ locale }: {
|
|
42
|
+
locale: NaeilHeaderLocale;
|
|
43
|
+
}): react_jsx_runtime.JSX.Element;
|
|
44
|
+
/** Shared rendering used by the whole header and legacy site control adapters. */
|
|
45
|
+
declare function NaeilHeaderLocaleControl({ locale, onLocaleChange }: {
|
|
46
|
+
locale: NaeilHeaderLocale;
|
|
47
|
+
onLocaleChange: (locale: NaeilHeaderLocale) => void;
|
|
48
|
+
}): react_jsx_runtime.JSX.Element;
|
|
49
|
+
/** One complete, opt-in branded composition shared by naeil.dev and applications. */
|
|
50
|
+
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;
|
|
51
|
+
|
|
52
|
+
export { NaeilHeader, NaeilHeaderLocale, NaeilHeaderLocaleControl, type NaeilHeaderProps, NaeilHeaderThemeControl };
|
|
@@ -0,0 +1,196 @@
|
|
|
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 { useSyncExternalStore } from "react";
|
|
35
|
+
import { useTheme } from "next-themes";
|
|
36
|
+
import { Moon, Sun } from "lucide-react";
|
|
37
|
+
import { Logo } from "./logo.js";
|
|
38
|
+
import { Badge } from "./ui/badge.js";
|
|
39
|
+
import { Button } from "./ui/button.js";
|
|
40
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select.js";
|
|
41
|
+
import { Navigation } from "./ui/navigation.js";
|
|
42
|
+
import { cn } from "../lib/utils.js";
|
|
43
|
+
import { headerContent, headerLocales, headerLocaleNames, headerProjects } from "./naeil-header-content.js";
|
|
44
|
+
const subscribe = () => () => {
|
|
45
|
+
};
|
|
46
|
+
function NaeilHeaderThemeControl({ locale }) {
|
|
47
|
+
const { resolvedTheme, setTheme } = useTheme();
|
|
48
|
+
const mounted = useSyncExternalStore(subscribe, () => true, () => false);
|
|
49
|
+
const dark = mounted && resolvedTheme === "dark";
|
|
50
|
+
return /* @__PURE__ */ jsx(
|
|
51
|
+
Button,
|
|
52
|
+
{
|
|
53
|
+
variant: "ghost",
|
|
54
|
+
size: "icon",
|
|
55
|
+
className: "size-11 shrink-0",
|
|
56
|
+
disabled: !mounted,
|
|
57
|
+
"aria-label": headerContent[locale].theme[dark ? "switchToLight" : "switchToDark"],
|
|
58
|
+
onClick: () => setTheme(dark ? "light" : "dark"),
|
|
59
|
+
children: dark ? /* @__PURE__ */ jsx(Sun, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Moon, { "aria-hidden": "true" })
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
function NaeilHeaderLocaleControl({ locale, onLocaleChange }) {
|
|
64
|
+
return /* @__PURE__ */ jsxs(Select, { value: locale, onValueChange: (value) => onLocaleChange(value), children: [
|
|
65
|
+
/* @__PURE__ */ jsx(
|
|
66
|
+
SelectTrigger,
|
|
67
|
+
{
|
|
68
|
+
className: "h-11 w-auto min-w-20 border-transparent bg-transparent px-2",
|
|
69
|
+
"aria-label": headerContent[locale].locale.switchLabel,
|
|
70
|
+
children: /* @__PURE__ */ jsx(SelectValue, { children: locale.toUpperCase() })
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
/* @__PURE__ */ jsx(SelectContent, { align: "end", children: headerLocales.map((value) => /* @__PURE__ */ jsx(SelectItem, { value, className: "min-h-11", lang: value, children: headerLocaleNames[value] }, value)) })
|
|
74
|
+
] });
|
|
75
|
+
}
|
|
76
|
+
const NativeLink = (props) => /* @__PURE__ */ jsx("a", __spreadValues({}, props));
|
|
77
|
+
function NaeilHeader(_a) {
|
|
78
|
+
var _b = _a, {
|
|
79
|
+
locale,
|
|
80
|
+
resolveHref = (path) => `https://naeil.dev/${locale}${path === "/" ? "" : path}`,
|
|
81
|
+
brandHref,
|
|
82
|
+
brandSlot,
|
|
83
|
+
brandLinkProps,
|
|
84
|
+
brandLinkComponent,
|
|
85
|
+
onLocaleChange,
|
|
86
|
+
authSlot,
|
|
87
|
+
toolbarSlot,
|
|
88
|
+
projects,
|
|
89
|
+
projectsExternal = false,
|
|
90
|
+
translations,
|
|
91
|
+
showProjects = true,
|
|
92
|
+
showBlog = true,
|
|
93
|
+
subNav,
|
|
94
|
+
currentProjectKey,
|
|
95
|
+
currentProjectHref,
|
|
96
|
+
labels,
|
|
97
|
+
Link = NativeLink,
|
|
98
|
+
currentHref,
|
|
99
|
+
onNavigate,
|
|
100
|
+
className,
|
|
101
|
+
containerClassName
|
|
102
|
+
} = _b, props = __objRest(_b, [
|
|
103
|
+
"locale",
|
|
104
|
+
"resolveHref",
|
|
105
|
+
"brandHref",
|
|
106
|
+
"brandSlot",
|
|
107
|
+
"brandLinkProps",
|
|
108
|
+
"brandLinkComponent",
|
|
109
|
+
"onLocaleChange",
|
|
110
|
+
"authSlot",
|
|
111
|
+
"toolbarSlot",
|
|
112
|
+
"projects",
|
|
113
|
+
"projectsExternal",
|
|
114
|
+
"translations",
|
|
115
|
+
"showProjects",
|
|
116
|
+
"showBlog",
|
|
117
|
+
"subNav",
|
|
118
|
+
"currentProjectKey",
|
|
119
|
+
"currentProjectHref",
|
|
120
|
+
"labels",
|
|
121
|
+
"Link",
|
|
122
|
+
"currentHref",
|
|
123
|
+
"onNavigate",
|
|
124
|
+
"className",
|
|
125
|
+
"containerClassName"
|
|
126
|
+
]);
|
|
127
|
+
var _b2, _c;
|
|
128
|
+
const content = headerContent[locale];
|
|
129
|
+
const projectLinks = !showProjects ? [] : projects != null ? projects : headerProjects.map((project) => {
|
|
130
|
+
var _a3, _b3, _c2;
|
|
131
|
+
const current = project.key === currentProjectKey;
|
|
132
|
+
return {
|
|
133
|
+
id: project.key,
|
|
134
|
+
label: (_a3 = translations == null ? void 0 : translations.project(`${project.key}.name`)) != null ? _a3 : content.projects[project.key].name,
|
|
135
|
+
description: (_b3 = translations == null ? void 0 : translations.project(`${project.key}.description`)) != null ? _b3 : content.projects[project.key].description,
|
|
136
|
+
href: current ? currentProjectHref || "/" : resolveHref(project.href),
|
|
137
|
+
external: !current && projectsExternal,
|
|
138
|
+
active: current || currentHref === project.href || (currentHref == null ? void 0 : currentHref.startsWith(`${project.href}/`)) || currentHref === resolveHref(project.href),
|
|
139
|
+
icon: /* @__PURE__ */ jsx("span", { className: "naeil-header-project-icon", style: {
|
|
140
|
+
borderColor: `color-mix(in oklch, ${project.accent} 30%, transparent)`,
|
|
141
|
+
backgroundColor: `color-mix(in oklch, ${project.accent} 8%, transparent)`
|
|
142
|
+
}, children: /* @__PURE__ */ jsx("img", { src: `https://naeil.dev/images/${project.icon}.png`, alt: "", width: 24, height: 24 }) }),
|
|
143
|
+
badge: project.status === "coming" ? /* @__PURE__ */ jsx(Badge, { variant: "outline", children: (_c2 = translations == null ? void 0 : translations.project("status.coming")) != null ? _c2 : content.projects.status.coming }) : void 0
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
const brandDestination = brandHref != null ? brandHref : resolveHref("/");
|
|
147
|
+
const BrandLink = brandLinkComponent != null ? brandLinkComponent : Link;
|
|
148
|
+
const _a2 = brandLinkProps != null ? brandLinkProps : {}, { onClick: onBrandClick } = _a2, brandProps = __objRest(_a2, ["onClick"]);
|
|
149
|
+
const toolbar = /* @__PURE__ */ jsx("div", { "data-app-toolbar": true, className: "naeil-header-controls", children: toolbarSlot !== void 0 ? toolbarSlot : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
150
|
+
/* @__PURE__ */ jsx(NaeilHeaderThemeControl, { locale }),
|
|
151
|
+
onLocaleChange && /* @__PURE__ */ jsx(NaeilHeaderLocaleControl, { locale, onLocaleChange }),
|
|
152
|
+
authSlot && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
153
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "naeil-header-separator" }),
|
|
154
|
+
authSlot
|
|
155
|
+
] })
|
|
156
|
+
] }) });
|
|
157
|
+
return /* @__PURE__ */ jsx(
|
|
158
|
+
Navigation,
|
|
159
|
+
__spreadProps(__spreadValues({}, props), {
|
|
160
|
+
"data-global-header": true,
|
|
161
|
+
"data-naeil-header": true,
|
|
162
|
+
Link,
|
|
163
|
+
currentHref,
|
|
164
|
+
onNavigate,
|
|
165
|
+
brand: /* @__PURE__ */ jsx(
|
|
166
|
+
BrandLink,
|
|
167
|
+
__spreadProps(__spreadValues({
|
|
168
|
+
href: brandDestination,
|
|
169
|
+
"data-app-brand": true,
|
|
170
|
+
"aria-label": brandSlot == null ? ".naeil" : void 0
|
|
171
|
+
}, brandProps), {
|
|
172
|
+
onClick: (event) => {
|
|
173
|
+
onBrandClick == null ? void 0 : onBrandClick(event);
|
|
174
|
+
onNavigate == null ? void 0 : onNavigate(event, { id: "brand", href: brandDestination, label: ".naeil" });
|
|
175
|
+
},
|
|
176
|
+
children: brandSlot != null ? brandSlot : /* @__PURE__ */ jsx(Logo, { variant: "horizontal", size: 28, className: "block", label: null })
|
|
177
|
+
})
|
|
178
|
+
),
|
|
179
|
+
items: [
|
|
180
|
+
...showProjects ? [{ id: "projects", label: (_b2 = translations == null ? void 0 : translations.projects) != null ? _b2 : content.nav.projects, items: projectLinks, columns: 2 }] : [],
|
|
181
|
+
...showBlog ? [{ id: "blog", label: (_c = translations == null ? void 0 : translations.blog) != null ? _c : content.nav.blog, href: resolveHref("/blog"), external: projectsExternal }] : [],
|
|
182
|
+
...(subNav != null ? subNav : []).map((item) => __spreadProps(__spreadValues({}, item), { id: item.href }))
|
|
183
|
+
],
|
|
184
|
+
labels: labels != null ? labels : { navigation: content.nav.navigation, menu: content.nav.menu, close: content.nav.closeMenu },
|
|
185
|
+
toolbar,
|
|
186
|
+
mobileToolbar: toolbar,
|
|
187
|
+
className: cn("naeil-header fixed top-0 w-full", className),
|
|
188
|
+
containerClassName: cn("naeil-header-frame max-w-7xl", containerClassName)
|
|
189
|
+
})
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
export {
|
|
193
|
+
NaeilHeader,
|
|
194
|
+
NaeilHeaderLocaleControl,
|
|
195
|
+
NaeilHeaderThemeControl
|
|
196
|
+
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { NavigationLink, NavigationProps } from './ui/navigation.js';
|
|
3
|
+
import 'react';
|
|
2
4
|
|
|
3
5
|
interface NavProps {
|
|
4
6
|
/** Internal Link component (from consumer's next-intl routing) */
|
|
@@ -33,7 +35,13 @@ interface NavProps {
|
|
|
33
35
|
showBlog?: boolean;
|
|
34
36
|
/** Right-side toolbar (theme toggle, locale switcher, etc.) */
|
|
35
37
|
toolbarSlot?: React.ReactNode;
|
|
38
|
+
/** Replace the legacy naeil project inventory with application-owned links. */
|
|
39
|
+
projects?: NavigationLink[];
|
|
40
|
+
className?: string;
|
|
41
|
+
containerClassName?: string;
|
|
42
|
+
labels?: NavigationProps["labels"];
|
|
36
43
|
}
|
|
37
|
-
|
|
44
|
+
/** Legacy Next/next-intl adapter; the complete branded composition lives in NaeilHeader. */
|
|
45
|
+
declare function Nav({ Link, usePathname, brandHref, brandExternal, brandSlot, projectsExternal, externalBaseUrl, currentProjectKey, currentProjectHref, subNav, authSlot, showProjects, showBlog, toolbarSlot, projects, className, containerClassName, labels, }: NavProps): react_jsx_runtime.JSX.Element;
|
|
38
46
|
|
|
39
|
-
export { Nav };
|
|
47
|
+
export { Nav, type NavProps };
|