czon 0.7.5 → 0.7.6

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.
@@ -7,10 +7,16 @@ exports.CZONHeader = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const DarkModeSwitch_1 = require("./DarkModeSwitch");
9
9
  const LanguageSwitch_1 = require("./LanguageSwitch");
10
+ const NavLinks_1 = require("./NavLinks");
10
11
  const CZONHeader = props => {
12
+ const navLinks = props.ctx.site.options.site?.navLinks;
13
+ const hasNavLinks = navLinks && navLinks.length > 0;
11
14
  return (react_1.default.createElement("header", { className: "czon-header py-4 border-b flex justify-between items-center px-6" },
12
- react_1.default.createElement("h1", { className: "text-2xl font-bold" },
13
- react_1.default.createElement("a", { href: "index.html" }, props.ctx.site.options.site?.title ?? 'CZON')),
15
+ react_1.default.createElement("div", { className: "flex items-center gap-4" },
16
+ hasNavLinks && react_1.default.createElement(NavLinks_1.NavLinksMobile, { navLinks: navLinks }),
17
+ react_1.default.createElement("h1", { className: "text-2xl font-bold" },
18
+ react_1.default.createElement("a", { href: "index.html" }, props.ctx.site.options.site?.title ?? 'CZON')),
19
+ hasNavLinks && react_1.default.createElement(NavLinks_1.NavLinksDesktop, { navLinks: navLinks })),
14
20
  react_1.default.createElement("div", { className: "flex items-center gap-4" },
15
21
  react_1.default.createElement(DarkModeSwitch_1.DarkModeSwitch, null),
16
22
  props.lang && react_1.default.createElement(LanguageSwitch_1.LanguageSwitch, { ctx: props.ctx, lang: props.lang, file: props.file }))));
@@ -0,0 +1,282 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.NavLinksDesktop = exports.NavLinksMobile = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const mobileStyle = `
9
+ /* Mobile hamburger menu styles */
10
+ .nav-links-mobile {
11
+ display: block;
12
+ }
13
+
14
+ @media (min-width: 768px) {
15
+ .nav-links-mobile {
16
+ display: none;
17
+ }
18
+ }
19
+
20
+ .nav-links-mobile-trigger {
21
+ display: flex;
22
+ align-items: center;
23
+ justify-content: center;
24
+ width: 2.5rem;
25
+ height: 2.5rem;
26
+ border-radius: 0.375rem;
27
+ background: var(--bg-secondary);
28
+ border: 1px solid var(--border-color);
29
+ color: var(--text-primary);
30
+ cursor: pointer;
31
+ transition: all 0.2s ease;
32
+ }
33
+
34
+ .nav-links-mobile-trigger:hover {
35
+ background: var(--ls-bg-hover);
36
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
37
+ }
38
+
39
+ /* Hamburger icon animation */
40
+ .nav-links-hamburger {
41
+ width: 1.25rem;
42
+ height: 1.25rem;
43
+ position: relative;
44
+ display: flex;
45
+ flex-direction: column;
46
+ justify-content: center;
47
+ gap: 4px;
48
+ }
49
+
50
+ .nav-links-hamburger span {
51
+ display: block;
52
+ width: 100%;
53
+ height: 2px;
54
+ background: currentColor;
55
+ border-radius: 1px;
56
+ transition: all 0.3s ease;
57
+ }
58
+
59
+ #nav-links-toggle:checked ~ .nav-links-mobile-trigger .nav-links-hamburger span:nth-child(1) {
60
+ transform: translateY(6px) rotate(45deg);
61
+ }
62
+
63
+ #nav-links-toggle:checked ~ .nav-links-mobile-trigger .nav-links-hamburger span:nth-child(2) {
64
+ opacity: 0;
65
+ }
66
+
67
+ #nav-links-toggle:checked ~ .nav-links-mobile-trigger .nav-links-hamburger span:nth-child(3) {
68
+ transform: translateY(-6px) rotate(-45deg);
69
+ }
70
+
71
+ /* Mobile dropdown */
72
+ .nav-links-dropdown {
73
+ position: fixed;
74
+ top: 4rem;
75
+ left: 0;
76
+ right: 0;
77
+ background: var(--bg-secondary);
78
+ border-bottom: 1px solid var(--border-color);
79
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
80
+ z-index: 100;
81
+ max-height: 0;
82
+ overflow: hidden;
83
+ opacity: 0;
84
+ transition: max-height 0.3s ease, opacity 0.3s ease;
85
+ }
86
+
87
+ #nav-links-toggle:checked ~ .nav-links-dropdown {
88
+ max-height: 80vh;
89
+ opacity: 1;
90
+ overflow-y: auto;
91
+ }
92
+
93
+ .nav-links-dropdown-list {
94
+ display: flex;
95
+ flex-direction: column;
96
+ padding: 0.5rem;
97
+ }
98
+
99
+ .nav-link-mobile-item {
100
+ display: block;
101
+ padding: 0.75rem 1rem;
102
+ font-size: 1rem;
103
+ font-weight: 500;
104
+ color: var(--text-secondary);
105
+ text-decoration: none;
106
+ border-radius: 0.375rem;
107
+ transition: all 0.15s ease;
108
+ }
109
+
110
+ .nav-link-mobile-item:hover {
111
+ background: var(--ls-bg-hover);
112
+ color: var(--text-primary);
113
+ }
114
+ `;
115
+ const desktopStyle = `
116
+ /* Desktop nav styles */
117
+ .nav-links-desktop {
118
+ display: none;
119
+ }
120
+
121
+ @media (min-width: 768px) {
122
+ .nav-links-desktop {
123
+ display: flex;
124
+ max-width: 40vw;
125
+ overflow: hidden;
126
+ }
127
+ }
128
+
129
+ .nav-links-desktop-list {
130
+ display: flex;
131
+ gap: 0.5rem;
132
+ overflow: hidden;
133
+ }
134
+
135
+ .nav-link-item {
136
+ white-space: nowrap;
137
+ padding: 0.5rem 0.75rem;
138
+ border-radius: 0.375rem;
139
+ font-size: 0.875rem;
140
+ font-weight: 500;
141
+ color: var(--text-secondary);
142
+ text-decoration: none;
143
+ transition: all 0.15s ease;
144
+ flex-shrink: 0;
145
+ }
146
+
147
+ .nav-link-item:hover {
148
+ background: var(--ls-bg-hover);
149
+ color: var(--text-primary);
150
+ }
151
+
152
+ /* Desktop overflow menu */
153
+ .nav-links-more-container {
154
+ position: relative;
155
+ }
156
+
157
+ .nav-links-more-trigger {
158
+ display: flex;
159
+ align-items: center;
160
+ gap: 0.25rem;
161
+ padding: 0.5rem 0.75rem;
162
+ border-radius: 0.375rem;
163
+ font-size: 0.875rem;
164
+ font-weight: 500;
165
+ color: var(--text-secondary);
166
+ background: transparent;
167
+ border: none;
168
+ cursor: pointer;
169
+ transition: all 0.15s ease;
170
+ }
171
+
172
+ .nav-links-more-trigger:hover {
173
+ background: var(--ls-bg-hover);
174
+ color: var(--text-primary);
175
+ }
176
+
177
+ .nav-links-more-icon {
178
+ width: 1rem;
179
+ height: 1rem;
180
+ transition: transform 0.2s ease;
181
+ }
182
+
183
+ #nav-links-more-toggle:checked ~ .nav-links-more-trigger .nav-links-more-icon {
184
+ transform: rotate(180deg);
185
+ }
186
+
187
+ .nav-links-more-dropdown {
188
+ position: absolute;
189
+ top: 100%;
190
+ left: 0;
191
+ margin-top: 0.25rem;
192
+ min-width: 12rem;
193
+ background: var(--bg-secondary);
194
+ border: 1px solid var(--border-color);
195
+ border-radius: 0.5rem;
196
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
197
+ z-index: 50;
198
+ opacity: 0;
199
+ visibility: hidden;
200
+ transform: translateY(-10px);
201
+ transition: opacity 0.2s ease, visibility 0.2s ease, transform 0.2s ease;
202
+ }
203
+
204
+ #nav-links-more-toggle:checked ~ .nav-links-more-dropdown {
205
+ opacity: 1;
206
+ visibility: visible;
207
+ transform: translateY(0);
208
+ }
209
+
210
+ .nav-links-more-list {
211
+ display: flex;
212
+ flex-direction: column;
213
+ padding: 0.5rem;
214
+ }
215
+
216
+ .nav-link-more-item {
217
+ display: block;
218
+ padding: 0.5rem 0.75rem;
219
+ font-size: 0.875rem;
220
+ font-weight: 500;
221
+ color: var(--text-secondary);
222
+ text-decoration: none;
223
+ border-radius: 0.375rem;
224
+ transition: all 0.15s ease;
225
+ }
226
+
227
+ .nav-link-more-item:hover {
228
+ background: var(--ls-bg-hover);
229
+ color: var(--text-primary);
230
+ }
231
+ `;
232
+ /**
233
+ * 移动端汉堡菜单导航组件
234
+ * 仅在移动端显示(< 768px)
235
+ */
236
+ const NavLinksMobile = ({ navLinks }) => {
237
+ if (!navLinks || navLinks.length === 0) {
238
+ return null;
239
+ }
240
+ return (react_1.default.createElement("nav", { className: "nav-links-mobile", "aria-label": "Mobile navigation" },
241
+ react_1.default.createElement("style", null, mobileStyle),
242
+ react_1.default.createElement("input", { id: "nav-links-toggle", type: "checkbox", className: "hidden", "aria-hidden": "true" }),
243
+ react_1.default.createElement("label", { htmlFor: "nav-links-toggle", className: "nav-links-mobile-trigger", "aria-label": "Toggle navigation menu", "aria-haspopup": "true", "aria-expanded": "false" },
244
+ react_1.default.createElement("div", { className: "nav-links-hamburger" },
245
+ react_1.default.createElement("span", null),
246
+ react_1.default.createElement("span", null),
247
+ react_1.default.createElement("span", null))),
248
+ react_1.default.createElement("div", { className: "nav-links-dropdown", role: "menu", "aria-label": "Navigation links" },
249
+ react_1.default.createElement("div", { className: "nav-links-dropdown-list" }, navLinks.map((link, index) => (react_1.default.createElement("a", { key: index, href: link.href, className: "nav-link-mobile-item", role: "menuitem" }, link.title)))))));
250
+ };
251
+ exports.NavLinksMobile = NavLinksMobile;
252
+ /**
253
+ * 计算在 40% 宽度内可以显示的链接数量
254
+ * 由于是 SSG,这里使用固定值,假设每个链接平均宽度约 100px
255
+ * 在 40vw 下大约可以显示 4-6 个链接
256
+ */
257
+ const MAX_VISIBLE_LINKS = 5;
258
+ /**
259
+ * 桌面端导航组件
260
+ * 仅在桌面端显示(>= 768px),最大宽度 40vw
261
+ */
262
+ const NavLinksDesktop = ({ navLinks }) => {
263
+ if (!navLinks || navLinks.length === 0) {
264
+ return null;
265
+ }
266
+ const visibleLinks = navLinks.slice(0, MAX_VISIBLE_LINKS);
267
+ const overflowLinks = navLinks.slice(MAX_VISIBLE_LINKS);
268
+ const hasOverflow = overflowLinks.length > 0;
269
+ return (react_1.default.createElement("nav", { className: "nav-links-desktop", "aria-label": "Main navigation" },
270
+ react_1.default.createElement("style", null, desktopStyle),
271
+ react_1.default.createElement("div", { className: "nav-links-desktop-list" }, visibleLinks.map((link, index) => (react_1.default.createElement("a", { key: index, href: link.href, className: "nav-link-item" }, link.title)))),
272
+ hasOverflow && (react_1.default.createElement("div", { className: "nav-links-more-container" },
273
+ react_1.default.createElement("input", { id: "nav-links-more-toggle", type: "checkbox", className: "hidden", "aria-hidden": "true" }),
274
+ react_1.default.createElement("label", { htmlFor: "nav-links-more-toggle", className: "nav-links-more-trigger", "aria-label": "More navigation links", "aria-haspopup": "true", "aria-expanded": "false" },
275
+ react_1.default.createElement("span", null, "More"),
276
+ react_1.default.createElement("svg", { className: "nav-links-more-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true" },
277
+ react_1.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }))),
278
+ react_1.default.createElement("div", { className: "nav-links-more-dropdown", role: "menu", "aria-label": "Additional navigation links" },
279
+ react_1.default.createElement("div", { className: "nav-links-more-list" }, overflowLinks.map((link, index) => (react_1.default.createElement("a", { key: index, href: link.href, className: "nav-link-more-item", role: "menuitem" }, link.title)))))))));
280
+ };
281
+ exports.NavLinksDesktop = NavLinksDesktop;
282
+ //# sourceMappingURL=NavLinks.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "czon",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "description": "CZON - AI enhanced Markdown content engine",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",