@coffic/cosy-ui 0.9.24 → 0.9.25
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/dist/app.css +1 -1
- package/dist/index-astro.ts +0 -1
- package/dist/src/assets/iconData.ts +5 -0
- package/dist/src/utils/link.ts +1 -1
- package/dist/src/utils/theme.ts +99 -96
- package/dist/src-astro/article/Article.astro +1 -0
- package/dist/src-astro/container/Container.astro +9 -0
- package/dist/src-astro/footer/Footer.astro +16 -19
- package/dist/src-astro/footer/FooterCopyright.astro +8 -17
- package/dist/src-astro/footer/FooterICP.astro +18 -0
- package/dist/src-astro/footer/index.ts +1 -0
- package/dist/src-astro/footer/types.ts +27 -0
- package/dist/src-astro/header/Header.astro +53 -54
- package/dist/src-astro/header/HeaderCenter.astro +59 -0
- package/dist/src-astro/header/HeaderEnd.astro +90 -0
- package/dist/src-astro/header/HeaderStart.astro +78 -0
- package/dist/src-astro/header/MobileNav.astro +44 -0
- package/dist/src-astro/header/NavItems.astro +82 -0
- package/dist/src-astro/header/index.ts +6 -0
- package/dist/src-astro/icons/GlobeIcon.astro +28 -0
- package/dist/src-astro/icons/index.ts +1 -0
- package/dist/src-astro/language-switcher/LanguageSwitcher.astro +5 -2
- package/dist/src-astro/layout-app/AppHeader.astro +95 -0
- package/dist/src-astro/layout-app/AppLayout.astro +18 -26
- package/dist/src-astro/modal/Modal.astro +29 -4
- package/dist/src-astro/sidebar/DesktopSidebar.astro +123 -0
- package/dist/src-astro/sidebar/MobileSidebar.astro +91 -0
- package/dist/src-astro/sidebar/Sidebar.astro +45 -86
- package/dist/src-astro/sidebar/SidebarNav.astro +12 -3
- package/dist/src-astro/sidebar/index.ts +1 -2
- package/dist/src-astro/theme-switcher/ThemeItem.astro +43 -3
- package/dist/src-astro/theme-switcher/ThemeSwitcher.astro +6 -67
- package/dist/src-astro/theme-switcher/index.ts +1 -9
- package/dist/src-astro/types/footer.ts +5 -0
- package/dist/src-astro/types/header.ts +6 -0
- package/package.json +1 -1
- package/dist/src-astro/nav-item/NavItems.astro +0 -44
- package/dist/src-astro/nav-item/index.ts +0 -3
- package/dist/src-astro/sidebar/MobileNav.astro +0 -55
- package/dist/src-astro/theme-switcher/ThemeSwitcherBasic.astro +0 -7
package/dist/index-astro.ts
CHANGED
@@ -35,7 +35,6 @@ export * from './src-astro/logout';
|
|
35
35
|
export * from './src-astro/main';
|
36
36
|
export * from './src-astro/modal';
|
37
37
|
export * from './src-astro/module';
|
38
|
-
export * from './src-astro/nav-item';
|
39
38
|
export * from './src-astro/nav-section';
|
40
39
|
export * from './src-astro/placeholder';
|
41
40
|
export * from './src-astro/products';
|
@@ -239,4 +239,9 @@ export const iconData: Record<string, IconData> = {
|
|
239
239
|
website: {
|
240
240
|
path: 'M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z',
|
241
241
|
},
|
242
|
+
|
243
|
+
// 地球图标
|
244
|
+
globe: {
|
245
|
+
path: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.94-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z',
|
246
|
+
},
|
242
247
|
};
|
package/dist/src/utils/link.ts
CHANGED
package/dist/src/utils/theme.ts
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
interface ThemeManager {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
updateActiveTheme: (currentTheme: string) => void;
|
3
|
+
handleThemeClick: (this: HTMLElement) => void;
|
4
|
+
initialize: () => void;
|
5
|
+
setTheme: (theme: string) => void;
|
6
|
+
detectSystemTheme: () => string;
|
7
7
|
}
|
8
8
|
|
9
9
|
/**
|
@@ -14,109 +14,112 @@ interface ThemeManager {
|
|
14
14
|
* @returns ThemeManager 主题管理器对象
|
15
15
|
*/
|
16
16
|
export function createThemeManager(): ThemeManager {
|
17
|
-
|
18
|
-
|
17
|
+
const getThemeItems = () =>
|
18
|
+
document.querySelectorAll<HTMLElement>('[data-theme-id], .cosy\\:theme-item');
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
const updateActiveTheme = (currentTheme: string) => {
|
21
|
+
const themeItems = getThemeItems();
|
22
|
+
themeItems.forEach((item) => {
|
23
|
+
const themeId = item.getAttribute('data-theme-id');
|
24
|
+
const isActive = themeId === currentTheme;
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
// 设置元素的 data-active 属性
|
27
|
+
item.setAttribute('data-active', String(isActive));
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
29
|
+
// 更新 CheckIcon 显示状态
|
30
|
+
if (item.classList.contains('cosy:theme-item')) {
|
31
|
+
const checkmark = item.querySelector('.cosy\\:theme-check');
|
32
|
+
if (checkmark) {
|
33
|
+
if (isActive) {
|
34
|
+
checkmark.classList.remove('cosy:hidden');
|
35
|
+
item.classList.add('cosy:bg-base-200', 'cosy:font-medium');
|
36
|
+
} else {
|
37
|
+
checkmark.classList.add('cosy:hidden');
|
38
|
+
item.classList.remove('cosy:bg-base-200', 'cosy:font-medium');
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
});
|
43
|
+
};
|
36
44
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
45
|
+
function handleThemeClick(this: HTMLElement) {
|
46
|
+
const theme = this.getAttribute('data-theme-id');
|
47
|
+
if (theme) {
|
48
|
+
setTheme(theme);
|
49
|
+
}
|
42
50
|
}
|
43
|
-
}
|
44
51
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
/**
|
53
|
+
* 设置主题
|
54
|
+
*
|
55
|
+
* @param theme 主题ID
|
56
|
+
*/
|
57
|
+
const setTheme = (theme: string) => {
|
58
|
+
document.documentElement.setAttribute('data-theme', theme);
|
59
|
+
localStorage.setItem('theme', theme);
|
60
|
+
updateActiveTheme(theme);
|
61
|
+
};
|
55
62
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
/**
|
64
|
+
* 检测系统主题偏好(亮色/暗色)
|
65
|
+
*
|
66
|
+
* @returns 'dark' 或 'light'
|
67
|
+
*/
|
68
|
+
const detectSystemTheme = (): string => {
|
69
|
+
return window.matchMedia('(prefers-color-scheme: dark)').matches
|
70
|
+
? 'dark'
|
71
|
+
: 'light';
|
72
|
+
};
|
66
73
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
74
|
+
/**
|
75
|
+
* 初始化主题管理器
|
76
|
+
*
|
77
|
+
* 从本地存储中获取主题设置,如果没有则尝试使用系统主题,最后使用默认主题
|
78
|
+
*/
|
79
|
+
const initialize = () => {
|
80
|
+
// 从本地存储中获取主题
|
81
|
+
let savedTheme = localStorage.getItem('theme');
|
75
82
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
83
|
+
// 如果没有保存的主题,则尝试使用系统主题
|
84
|
+
if (!savedTheme) {
|
85
|
+
const systemTheme = detectSystemTheme();
|
86
|
+
if (systemTheme === 'dark') {
|
87
|
+
savedTheme = 'dark';
|
88
|
+
} else {
|
89
|
+
savedTheme = 'default'; // 默认使用默认主题
|
90
|
+
}
|
91
|
+
}
|
85
92
|
|
86
|
-
|
87
|
-
|
88
|
-
|
93
|
+
// 设置主题
|
94
|
+
document.documentElement.setAttribute('data-theme', savedTheme);
|
95
|
+
updateActiveTheme(savedTheme);
|
89
96
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
...Array.from(
|
95
|
-
document.querySelectorAll<HTMLElement>('.cosy\\:theme-item')
|
96
|
-
),
|
97
|
-
];
|
97
|
+
// 添加主题切换事件监听器
|
98
|
+
const themeItems = Array.from(
|
99
|
+
document.querySelectorAll<HTMLElement>('[data-theme-id]')
|
100
|
+
);
|
98
101
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
102
|
+
themeItems.forEach((item) => {
|
103
|
+
item.removeEventListener('click', handleThemeClick);
|
104
|
+
item.addEventListener('click', handleThemeClick);
|
105
|
+
});
|
103
106
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
107
|
+
// 监听系统主题变化
|
108
|
+
window
|
109
|
+
.matchMedia('(prefers-color-scheme: dark)')
|
110
|
+
.addEventListener('change', (e) => {
|
111
|
+
// 只有当用户没有手动设置过主题时,才跟随系统主题变化
|
112
|
+
if (!localStorage.getItem('theme')) {
|
113
|
+
setTheme(e.matches ? 'dark' : 'default');
|
114
|
+
}
|
115
|
+
});
|
116
|
+
};
|
114
117
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
118
|
+
return {
|
119
|
+
updateActiveTheme,
|
120
|
+
handleThemeClick,
|
121
|
+
initialize,
|
122
|
+
setTheme,
|
123
|
+
detectSystemTheme,
|
124
|
+
};
|
122
125
|
}
|
@@ -71,6 +71,15 @@
|
|
71
71
|
* <div>第二项</div>
|
72
72
|
* </Container>
|
73
73
|
* ```
|
74
|
+
*
|
75
|
+
* @props
|
76
|
+
* @prop {string} size - 容器尺寸
|
77
|
+
* @prop {string} padding - 内边距大小
|
78
|
+
* @prop {string} margin - 外边距大小
|
79
|
+
* @prop {boolean} centered - 是否居中显示
|
80
|
+
* @prop {boolean} border - 是否显示边框
|
81
|
+
* @prop {string} flex - flex布局方向
|
82
|
+
* @prop {string} gap - flex项目间距
|
74
83
|
*/
|
75
84
|
|
76
85
|
import type { HTMLAttributes } from 'astro/types';
|
@@ -139,6 +139,7 @@
|
|
139
139
|
* @prop {string} copyright - 版权信息
|
140
140
|
* @prop {string} inspirationalSlogan - 鼓舞人心的标语,显示在横幅中
|
141
141
|
* @prop {string} [icp] - ICP备案号(中国网站需要)
|
142
|
+
* @prop {string} [icpLink] - ICP备案链接(可选)
|
142
143
|
* @prop {Object} [logo] - 网站Logo对象,包含src和alt属性
|
143
144
|
* @prop {Array<Object>} [products=[]] - 产品链接数组,每个对象包含name、href和可选的external属性
|
144
145
|
* @prop {Array<Object>} [friendlyLinks=[]] - 友情链接数组,每个对象包含name、href和可选的external属性
|
@@ -173,10 +174,12 @@ import {
|
|
173
174
|
type IFooterProps,
|
174
175
|
createTextGetter,
|
175
176
|
Link,
|
177
|
+
Container,
|
176
178
|
} from '../../index-astro';
|
177
179
|
import FooterSection from './FooterSection.astro';
|
178
180
|
import '../../style.ts';
|
179
181
|
import FooterCopyright from './FooterCopyright.astro';
|
182
|
+
import FooterICP from './FooterICP.astro';
|
180
183
|
|
181
184
|
const {
|
182
185
|
siteName,
|
@@ -186,6 +189,7 @@ const {
|
|
186
189
|
copyright,
|
187
190
|
inspirationalSlogan,
|
188
191
|
icp,
|
192
|
+
icpLink,
|
189
193
|
logo,
|
190
194
|
products = [],
|
191
195
|
friendlyLinks = [],
|
@@ -234,7 +238,7 @@ const debugClasses = debug
|
|
234
238
|
|
235
239
|
<footer
|
236
240
|
class:list={[
|
237
|
-
'cosy:footer cosy:z-50 cosy:sm:footer-horizontal cosy:bg-base-200 cosy:text-base-content cosy:p-10',
|
241
|
+
'cosy:footer cosy:flex cosy:flex-col cosy:z-50 cosy:sm:footer-horizontal cosy:bg-base-200 cosy:text-base-content cosy:p-10',
|
238
242
|
debugClasses.footer,
|
239
243
|
]}>
|
240
244
|
<div
|
@@ -356,23 +360,16 @@ const debugClasses = debug
|
|
356
360
|
}
|
357
361
|
</div>
|
358
362
|
</div>
|
359
|
-
</footer>
|
360
363
|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
364
|
+
<div
|
365
|
+
class="cosy:flex cosy:flex-col cosy:items-center cosy:justify-center cosy:w-full cosy:opacity-70 cosy:lg:flex-row cosy:gap-4">
|
366
|
+
<FooterCopyright
|
367
|
+
company={company}
|
368
|
+
copyright={copyright}
|
369
|
+
currentYear={currentYear}
|
370
|
+
t={t}
|
371
|
+
/>
|
369
372
|
|
370
|
-
{
|
371
|
-
|
372
|
-
|
373
|
-
copyright={copyright}
|
374
|
-
icp={icp}
|
375
|
-
currentYear={currentYear}
|
376
|
-
t={t}
|
377
|
-
debugClasses={debugClasses}
|
378
|
-
/>
|
373
|
+
{icp && <FooterICP icp={icp} icpLink={icpLink} />}
|
374
|
+
</div>
|
375
|
+
</footer>
|
@@ -5,25 +5,16 @@
|
|
5
5
|
* @props
|
6
6
|
* @prop {string} company - 公司名称
|
7
7
|
* @prop {string} copyright - 版权信息
|
8
|
-
* @prop {string} icp - ICP备案号(可选)
|
9
8
|
* @prop {number} currentYear - 当前年份
|
10
9
|
* @prop {Function} t - 文本获取函数
|
11
|
-
* @prop {object} debugClasses - 调试样式类
|
12
10
|
*/
|
13
|
-
|
11
|
+
|
12
|
+
import '../../style.ts';
|
13
|
+
|
14
|
+
const { company, copyright, currentYear, t } = Astro.props;
|
14
15
|
---
|
15
16
|
|
16
|
-
<
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
]}>
|
21
|
-
<aside
|
22
|
-
class:list={['cosy:items-center cosy:grid-flow-col', debugClasses?.aside]}>
|
23
|
-
<p class="cosy:opacity-70 cosy:text-sm">
|
24
|
-
© {currentYear}
|
25
|
-
{company} - {copyright || (t && t('allRightsReserved'))}
|
26
|
-
</p>
|
27
|
-
{icp && <p class="cosy:opacity-70 cosy:ml-4 cosy:text-sm">{icp}</p>}
|
28
|
-
</aside>
|
29
|
-
</div>
|
17
|
+
<p class="cosy:text-sm cosy:text-center">
|
18
|
+
© {currentYear}
|
19
|
+
{company} - {copyright || (t && t('allRightsReserved'))}
|
20
|
+
</p>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
---
|
2
|
+
/**
|
3
|
+
* @component FooterICP
|
4
|
+
* @description 页脚ICP备案信息组件。
|
5
|
+
* @props
|
6
|
+
* @prop {string} icp - ICP备案号
|
7
|
+
* @prop {string} icpLink - ICP备案链接(可选,默认为工信部备案查询网站)
|
8
|
+
*/
|
9
|
+
|
10
|
+
import '../../style.ts';
|
11
|
+
import { Link } from '../../index-astro';
|
12
|
+
|
13
|
+
const { icp, icpLink = 'https://beian.miit.gov.cn/' } = Astro.props;
|
14
|
+
---
|
15
|
+
|
16
|
+
<Link href={icpLink} external variant="text" size="sm" noUnderline={true}>
|
17
|
+
{icp}
|
18
|
+
</Link>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
export interface FooterICPProps {
|
2
|
+
icp: string;
|
3
|
+
icpLink?: string;
|
4
|
+
debugClasses?: {
|
5
|
+
icp?: string;
|
6
|
+
};
|
7
|
+
}
|
8
|
+
|
9
|
+
export interface FooterCopyrightProps {
|
10
|
+
company: string;
|
11
|
+
copyright?: string;
|
12
|
+
currentYear: number;
|
13
|
+
t?: (key: string) => string;
|
14
|
+
debugClasses?: {
|
15
|
+
footer?: string;
|
16
|
+
aside?: string;
|
17
|
+
};
|
18
|
+
}
|
19
|
+
|
20
|
+
export interface FooterSectionProps {
|
21
|
+
title: string;
|
22
|
+
links: Array<{
|
23
|
+
name: string;
|
24
|
+
href?: string;
|
25
|
+
external?: boolean;
|
26
|
+
}>;
|
27
|
+
}
|
@@ -27,19 +27,26 @@
|
|
27
27
|
* <Header astroI18n={astroI18n} />
|
28
28
|
* ```
|
29
29
|
*
|
30
|
+
* 自定义导航项间距:
|
31
|
+
* ```astro
|
32
|
+
* <Header gap={4} />
|
33
|
+
* ```
|
34
|
+
*
|
30
35
|
* @props
|
31
36
|
* - astroI18n - 完整的 astro:i18n 模块(启用语言切换时需要)
|
37
|
+
* - gap - 导航项之间的间距,可选值:0, 1, 2, 3, 4, 6, 8, 10, 12,默认 2
|
32
38
|
*/
|
33
39
|
import {
|
34
|
-
LanguageSwitcher,
|
35
40
|
LinkUtil,
|
36
41
|
type IHeaderProps,
|
37
42
|
type INavItem,
|
38
|
-
|
39
|
-
ThemeSwitcher,
|
43
|
+
Modal,
|
40
44
|
} from '../../index-astro';
|
41
45
|
import Logo from '../../src/assets/logo-rounded.png';
|
42
|
-
import
|
46
|
+
import HeaderStart from './HeaderStart.astro';
|
47
|
+
import HeaderCenter from './HeaderCenter.astro';
|
48
|
+
import HeaderEnd from './HeaderEnd.astro';
|
49
|
+
import MobileNav from './MobileNav.astro';
|
43
50
|
|
44
51
|
export interface Props extends IHeaderProps {
|
45
52
|
debug?: boolean;
|
@@ -57,6 +64,7 @@ const {
|
|
57
64
|
paddingVertical = 'none',
|
58
65
|
navPosition = 'center',
|
59
66
|
showThemeSwitcher = true,
|
67
|
+
gap = 2,
|
60
68
|
astroI18n,
|
61
69
|
} = Astro.props;
|
62
70
|
|
@@ -121,7 +129,7 @@ const activeLink = LinkUtil.getActiveLink(
|
|
121
129
|
]}>
|
122
130
|
<div
|
123
131
|
class:list={[
|
124
|
-
'cosy:bg-
|
132
|
+
'cosy:bg-base-300/90 cosy:text-base-content cosy:flex cosy:flex-grow cosy:backdrop-blur not-prose cosy:shadow-md',
|
125
133
|
{
|
126
134
|
'cosy:rounded-none': rounded === 'none',
|
127
135
|
'cosy:rounded-sm': rounded === 'sm',
|
@@ -133,56 +141,47 @@ const activeLink = LinkUtil.getActiveLink(
|
|
133
141
|
headerHeightClass,
|
134
142
|
{ 'cosy:border cosy:border-dashed cosy:border-red-500': debug },
|
135
143
|
]}>
|
136
|
-
<
|
137
|
-
{
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
</div>
|
148
|
-
</div>
|
149
|
-
) : (
|
150
|
-
<LogoLink src={logo} href={logoHref} size={height} debug={debug} />
|
151
|
-
)
|
152
|
-
}
|
153
|
-
<slot name="navbar-start" />
|
154
|
-
</div>
|
155
|
-
|
156
|
-
<div class="cosy:hidden cosy:lg:flex cosy:navbar-center">
|
157
|
-
{
|
158
|
-
navPosition === 'center' && (
|
159
|
-
<NavItems
|
160
|
-
navItems={navItems}
|
161
|
-
activeLink={activeLink}
|
162
|
-
linkHeightClass={linkHeightClass}
|
163
|
-
/>
|
164
|
-
)
|
165
|
-
}
|
166
|
-
<slot name="navbar-center" />
|
167
|
-
</div>
|
168
|
-
|
169
|
-
<div class="cosy:navbar-end cosy:pr-1">
|
170
|
-
{
|
171
|
-
navPosition === 'end' && (
|
172
|
-
<div class="cosy:hidden cosy:lg:flex">
|
173
|
-
<NavItems
|
174
|
-
navItems={navItems}
|
175
|
-
activeLink={activeLink}
|
176
|
-
linkHeightClass={linkHeightClass}
|
177
|
-
/>
|
178
|
-
</div>
|
179
|
-
)
|
180
|
-
}
|
144
|
+
<HeaderStart
|
145
|
+
logo={logo}
|
146
|
+
logoHref={logoHref}
|
147
|
+
height={height}
|
148
|
+
navPosition={navPosition}
|
149
|
+
navItems={navItems}
|
150
|
+
activeLink={activeLink}
|
151
|
+
linkHeightClass={linkHeightClass}
|
152
|
+
debug={debug}>
|
153
|
+
<slot name="navbar-start" slot="navbar-start" />
|
154
|
+
</HeaderStart>
|
181
155
|
|
182
|
-
|
183
|
-
|
156
|
+
<HeaderCenter
|
157
|
+
navPosition={navPosition}
|
158
|
+
navItems={navItems}
|
159
|
+
activeLink={activeLink}
|
160
|
+
linkHeightClass={linkHeightClass}
|
161
|
+
gap={gap}
|
162
|
+
/>
|
184
163
|
|
185
|
-
|
186
|
-
|
164
|
+
<HeaderEnd
|
165
|
+
navPosition={navPosition}
|
166
|
+
navItems={navItems}
|
167
|
+
activeLink={activeLink}
|
168
|
+
linkHeightClass={linkHeightClass}
|
169
|
+
showThemeSwitcher={showThemeSwitcher}
|
170
|
+
isI18nEnabled={isI18nEnabled}
|
171
|
+
astroI18n={astroI18n}
|
172
|
+
/>
|
187
173
|
</div>
|
188
174
|
</header>
|
175
|
+
|
176
|
+
<!-- 移动端导航 Modal -->
|
177
|
+
{
|
178
|
+
navItems.length > 0 && (
|
179
|
+
<Modal id="mobile-nav" title="导航菜单">
|
180
|
+
<MobileNav
|
181
|
+
navItems={navItems}
|
182
|
+
activeLink={activeLink}
|
183
|
+
linkHeightClass={linkHeightClass}
|
184
|
+
/>
|
185
|
+
</Modal>
|
186
|
+
)
|
187
|
+
}
|
@@ -0,0 +1,59 @@
|
|
1
|
+
---
|
2
|
+
/**
|
3
|
+
* @component HeaderCenter
|
4
|
+
*
|
5
|
+
* @description
|
6
|
+
* HeaderCenter 组件负责渲染 Header 的中央区域,包括中央导航项。
|
7
|
+
* 这是一个内部组件,通常由 Header 组件使用。
|
8
|
+
*
|
9
|
+
* @usage
|
10
|
+
* ```astro
|
11
|
+
* <HeaderCenter
|
12
|
+
* navPosition={navPosition}
|
13
|
+
* navItems={navItems}
|
14
|
+
* activeLink={activeLink}
|
15
|
+
* linkHeightClass={linkHeightClass}
|
16
|
+
* gap={2}
|
17
|
+
* />
|
18
|
+
* ```
|
19
|
+
*
|
20
|
+
* @props
|
21
|
+
* - navPosition - 导航位置
|
22
|
+
* - navItems - 导航项数组
|
23
|
+
* - activeLink - 当前激活的链接
|
24
|
+
* - linkHeightClass - 链接高度类名
|
25
|
+
* - gap - 导航项之间的间距,可选值:0, 1, 2, 3, 4, 6, 8, 10, 12,默认 2
|
26
|
+
*/
|
27
|
+
import { type INavItem } from '../../index-astro';
|
28
|
+
import NavItems from './NavItems.astro';
|
29
|
+
|
30
|
+
export interface Props {
|
31
|
+
navPosition: string;
|
32
|
+
navItems: INavItem[];
|
33
|
+
activeLink: string;
|
34
|
+
linkHeightClass: string;
|
35
|
+
gap?: number;
|
36
|
+
}
|
37
|
+
|
38
|
+
const {
|
39
|
+
navPosition,
|
40
|
+
navItems,
|
41
|
+
activeLink,
|
42
|
+
linkHeightClass,
|
43
|
+
gap = 2,
|
44
|
+
} = Astro.props;
|
45
|
+
---
|
46
|
+
|
47
|
+
<div class="cosy:hidden cosy:lg:flex cosy:navbar-center">
|
48
|
+
{
|
49
|
+
navPosition === 'center' && (
|
50
|
+
<NavItems
|
51
|
+
navItems={navItems}
|
52
|
+
activeLink={activeLink}
|
53
|
+
linkHeightClass={linkHeightClass}
|
54
|
+
gap={gap}
|
55
|
+
/>
|
56
|
+
)
|
57
|
+
}
|
58
|
+
<slot name="navbar-center" />
|
59
|
+
</div>
|