@coffic/cosy-ui 0.4.3 → 0.4.5

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.
@@ -57,7 +57,8 @@
57
57
  import '../../app.css';
58
58
  import Link from '../base/Link.astro';
59
59
  import Image from '../base/Image.astro';
60
- import type { HeaderProps } from '@/types/header';
60
+ import type { HeaderProps } from '../../index';
61
+ import Logo from '../../assets/logo.png';
61
62
 
62
63
  interface Props extends HeaderProps {}
63
64
 
@@ -69,7 +70,7 @@ const {
69
70
  { code: 'zh-cn', name: '中文' },
70
71
  { code: 'en', name: 'English' },
71
72
  ],
72
- logo,
73
+ logo = Logo,
73
74
  logoHref = '/',
74
75
  navItems = [],
75
76
  sticky = true,
@@ -26,7 +26,6 @@ import { isPathMatch } from '../../utils/path';
26
26
  import Modal from '../display/Modal.astro';
27
27
  import SidebarNav from './SidebarNav.astro';
28
28
  import MenuIcon from '../icons/MenuIcon.astro';
29
-
30
29
  import type { SidebarProps } from '../../types/sidebar';
31
30
 
32
31
  export interface Props extends SidebarProps{}
@@ -127,7 +127,7 @@ const baseClasses = [
127
127
  'cosy:mx-auto',
128
128
  'cosy:dark:prose-invert', // 暗黑模式支持,
129
129
  'cosy:m-0',
130
- 'cosy:p-0',
130
+ 'cosy:pb-96',
131
131
  widthClasses,
132
132
  className,
133
133
  ];
package/dist/index.ts CHANGED
@@ -29,11 +29,9 @@ export { default as Blog } from './components/data-display/Blog.astro';
29
29
  export { default as Footer } from './components/layouts/Footer.astro';
30
30
  export { default as Header } from './components/layouts/Header.astro';
31
31
  export { default as AppLayout } from './components/layouts/AppLayout.astro';
32
- export { default as DefaultLayout } from './components/layouts/DefaultLayout.astro';
33
32
  export { default as Stack } from './components/layouts/Stack.astro';
34
33
  export { default as Grid } from './components/layouts/Grid.astro';
35
34
  export { default as BaseLayout } from './components/layouts/BaseLayout.astro';
36
- export { default as LandingLayout } from './components/layouts/LandingLayout.astro';
37
35
  export { default as DashboardLayout } from './components/layouts/DashboardLayout.astro';
38
36
  export { default as Flex } from './components/layouts/Flex.astro';
39
37
 
@@ -78,5 +76,10 @@ export * from './utils/url';
78
76
  export * from './utils/language';
79
77
 
80
78
  // Types
81
- export type { SidebarSection } from './types/sidebar';
79
+ export * from './types/sidebar';
80
+ export * from './types/main';
81
+ export * from './types/article';
82
+ export * from './types/layout';
83
+ export * from './types/header';
84
+ export * from './types/meta';
82
85
  export type { ImageProvider, ImageOptions } from './utils/image';
@@ -30,7 +30,7 @@ export interface HeaderProps {
30
30
  /**
31
31
  * Logo图片元数据
32
32
  */
33
- logo: ImageMetadata;
33
+ logo?: ImageMetadata;
34
34
 
35
35
  /**
36
36
  * Logo 链接地址
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffic/cosy-ui",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "An astro component library",
5
5
  "author": {
6
6
  "name": "nookery",
@@ -1,170 +0,0 @@
1
- ---
2
- /**
3
- * DefaultLayout组件
4
- *
5
- * 包含常用页面结构的默认布局,包括简单的页眉和页脚
6
- *
7
- * @example
8
- * ```astro
9
- * ---
10
- * import DefaultLayout from '../layouts/DefaultLayout.astro';
11
- * ---
12
- *
13
- * <DefaultLayout title="页面标题" description="页面描述">
14
- * <h1>页面内容</h1>
15
- * <p>这是页面的主要内容</p>
16
- * </DefaultLayout>
17
- * ```
18
- */
19
-
20
- import BaseLayout from './BaseLayout.astro';
21
- import Link from '../base/Link.astro';
22
-
23
- // 导入样式
24
- import '../../app.css';
25
-
26
- export interface NavLink {
27
- href: string;
28
- label: string;
29
- }
30
-
31
- export interface Props {
32
- /**
33
- * 页面标题
34
- */
35
- title: string;
36
-
37
- /**
38
- * 页面描述
39
- */
40
- description?: string;
41
-
42
- /**
43
- * 页面关键词
44
- */
45
- keywords?: string;
46
-
47
- /**
48
- * 是否显示页眉
49
- * @default true
50
- */
51
- showHeader?: boolean;
52
-
53
- /**
54
- * 是否显示页脚
55
- * @default true
56
- */
57
- showFooter?: boolean;
58
-
59
- /**
60
- * 网站名称
61
- * @default "网站名称"
62
- */
63
- siteName?: string;
64
-
65
- /**
66
- * 导航链接
67
- */
68
- navLinks?: NavLink[];
69
-
70
- /**
71
- * 页面容器类名
72
- */
73
- containerClass?: string;
74
-
75
- /**
76
- * 自定义头部内容
77
- */
78
- head?: astroHTML.JSX.Element;
79
-
80
- /**
81
- * 页面类名
82
- */
83
- class?: string;
84
-
85
- /**
86
- * 类名列表
87
- */
88
- 'class:list'?: any;
89
- }
90
-
91
- const {
92
- title,
93
- description,
94
- keywords,
95
- showHeader = true,
96
- showFooter = true,
97
- siteName = "网站名称",
98
- navLinks = [
99
- { href: "/", label: "首页" },
100
- { href: "/about", label: "关于" },
101
- { href: "/contact", label: "联系我们" }
102
- ],
103
- containerClass = "container mx-auto px-4 py-8",
104
- head,
105
- class: className,
106
- 'class:list': classList,
107
- ...rest
108
- } = Astro.props;
109
-
110
- const year = new Date().getFullYear();
111
- ---
112
-
113
- <BaseLayout
114
- title={title}
115
- description={description}
116
- keywords={keywords}
117
- head={head}
118
- class={className}
119
- {...rest}
120
- >
121
- {showHeader && (
122
- <header class="site-header">
123
- <div class="container px-4 py-4">
124
- <div class="header-content">
125
- <div class="logo">
126
- <a href="/" class="site-name">{siteName}</a>
127
- </div>
128
-
129
- <nav class="main-nav">
130
- <ul class="nav-list">
131
- {navLinks.map((link: NavLink) => (
132
- <li class="nav-item">
133
- <Link href={link.href} variant="text">{link.label}</Link>
134
- </li>
135
- ))}
136
- </ul>
137
- </nav>
138
- </div>
139
- </div>
140
- </header>
141
- )}
142
-
143
- <main class={containerClass}>
144
- <slot />
145
- </main>
146
-
147
- {showFooter && (
148
- <footer class="site-footer">
149
- <div class="container px-4 py-8">
150
- <div class="footer-content">
151
- <div class="footer-info">
152
- <p class="copyright">&copy; {year} {siteName}. 保留所有权利。</p>
153
- </div>
154
-
155
- <nav class="footer-nav">
156
- <ul class="nav-list">
157
- {navLinks.map((link: NavLink) => (
158
- <li class="nav-item">
159
- <Link href={link.href} variant="text" size="sm">{link.label}</Link>
160
- </li>
161
- ))}
162
- </ul>
163
- </nav>
164
- </div>
165
- </div>
166
- </footer>
167
- )}
168
-
169
- <slot name="after-footer" />
170
- </BaseLayout>
@@ -1,388 +0,0 @@
1
- ---
2
- /**
3
- * LandingLayout组件
4
- *
5
- * 适用于落地页的布局,包含页眉、页脚和多个区块
6
- *
7
- * @example
8
- * ```astro
9
- * ---
10
- * import LandingLayout from '../layouts/LandingLayout.astro';
11
- * ---
12
- *
13
- * <LandingLayout
14
- * title="产品名称 - 简短的产品描述"
15
- * description="详细的产品描述,包含关键词"
16
- * >
17
- * <div slot="hero">
18
- * <h1>产品标题</h1>
19
- * <p>产品简介</p>
20
- * <button>立即开始</button>
21
- * </div>
22
- *
23
- * <section>
24
- * <h2>产品特点</h2>
25
- * <p>详细介绍产品特点...</p>
26
- * </section>
27
- * </LandingLayout>
28
- * ```
29
- */
30
-
31
- import BaseLayout from './BaseLayout.astro';
32
-
33
- // 导入样式
34
- import '../../app.css';
35
-
36
- export interface NavItem {
37
- href: string;
38
- label: string;
39
- isButton?: boolean;
40
- }
41
-
42
- export interface FooterLink {
43
- href: string;
44
- label: string;
45
- }
46
-
47
- export interface FooterSection {
48
- title: string;
49
- links: FooterLink[];
50
- }
51
-
52
- export interface SocialLink {
53
- href: string;
54
- icon: string;
55
- label: string;
56
- }
57
-
58
- export interface Props {
59
- /**
60
- * 页面标题
61
- */
62
- title: string;
63
-
64
- /**
65
- * 页面描述
66
- */
67
- description?: string;
68
-
69
- /**
70
- * 页面关键词
71
- */
72
- keywords?: string;
73
-
74
- /**
75
- * 品牌名称
76
- * @default "品牌名称"
77
- */
78
- brandName?: string;
79
-
80
- /**
81
- * 品牌Logo URL
82
- */
83
- logoUrl?: string;
84
-
85
- /**
86
- * 导航链接
87
- */
88
- navItems?: NavItem[];
89
-
90
- /**
91
- * 页脚链接分组
92
- */
93
- footerSections?: FooterSection[];
94
-
95
- /**
96
- * 社交媒体链接
97
- */
98
- socialLinks?: SocialLink[];
99
-
100
- /**
101
- * 版权信息
102
- */
103
- copyright?: string;
104
-
105
- /**
106
- * 自定义头部内容
107
- */
108
- head?: astroHTML.JSX.Element;
109
-
110
- /**
111
- * 页面类名
112
- */
113
- class?: string;
114
-
115
- /**
116
- * 类名列表
117
- */
118
- 'class:list'?: any;
119
- }
120
-
121
- const {
122
- title,
123
- description,
124
- keywords,
125
- brandName = "品牌名称",
126
- logoUrl,
127
- navItems = [
128
- { href: "/", label: "首页" },
129
- { href: "/features", label: "特性" },
130
- { href: "/pricing", label: "价格" },
131
- { href: "/about", label: "关于我们" },
132
- { href: "/contact", label: "联系我们" },
133
- { href: "/signup", label: "注册", isButton: true }
134
- ],
135
- footerSections = [
136
- {
137
- title: "产品",
138
- links: [
139
- { href: "/features", label: "特性" },
140
- { href: "/pricing", label: "价格" },
141
- { href: "/docs", label: "文档" },
142
- { href: "/releases", label: "更新日志" }
143
- ]
144
- },
145
- {
146
- title: "公司",
147
- links: [
148
- { href: "/about", label: "关于我们" },
149
- { href: "/team", label: "团队" },
150
- { href: "/careers", label: "招聘" },
151
- { href: "/contact", label: "联系我们" }
152
- ]
153
- },
154
- {
155
- title: "资源",
156
- links: [
157
- { href: "/blog", label: "博客" },
158
- { href: "/community", label: "社区" },
159
- { href: "/support", label: "支持" }
160
- ]
161
- },
162
- {
163
- title: "法律",
164
- links: [
165
- { href: "/privacy", label: "隐私政策" },
166
- { href: "/terms", label: "服务条款" }
167
- ]
168
- }
169
- ],
170
- socialLinks = [
171
- { href: "https://twitter.com", icon: "twitter", label: "Twitter" },
172
- { href: "https://github.com", icon: "github", label: "GitHub" },
173
- { href: "https://linkedin.com", icon: "linkedin", label: "LinkedIn" }
174
- ],
175
- copyright = `© ${new Date().getFullYear()} ${brandName}. 保留所有权利。`,
176
- head,
177
- class: className,
178
- 'class:list': classList,
179
- ...rest
180
- } = Astro.props;
181
-
182
- // 社交媒体图标映射
183
- const socialIconMap: Record<string, string> = {
184
- twitter: "🐦",
185
- github: "🐙",
186
- linkedin: "🔗",
187
- facebook: "👤",
188
- instagram: "📷",
189
- youtube: "📺",
190
- discord: "💬",
191
- slack: "🔶",
192
- wechat: "💬",
193
- weibo: "微"
194
- };
195
- ---
196
-
197
- <BaseLayout
198
- title={title}
199
- description={description}
200
- keywords={keywords}
201
- head={head}
202
- class="landing-layout"
203
- {...rest}
204
- >
205
- <!-- 页眉 -->
206
- <header class="site-header">
207
- <div class="container">
208
- <div class="header-content">
209
- <div class="brand">
210
- <a href="/" class="brand-link">
211
- {logoUrl ? (
212
- <img src={logoUrl} alt={brandName} class="brand-logo" />
213
- ) : (
214
- <span class="brand-name">{brandName}</span>
215
- )}
216
- </a>
217
- </div>
218
-
219
- <nav class="main-nav">
220
- <ul class="nav-list">
221
- {navItems.map((item: NavItem) => (
222
- <li class="nav-item">
223
- {item.isButton ? (
224
- <a href={item.href} class="btn btn-primary btn-sm">{item.label}</a>
225
- ) : (
226
- <a href={item.href} class="nav-link">{item.label}</a>
227
- )}
228
- </li>
229
- ))}
230
- </ul>
231
- </nav>
232
-
233
- <button class="mobile-menu-button" aria-label="菜单" id="mobile-menu-toggle">
234
- <span class="menu-icon">☰</span>
235
- </button>
236
- </div>
237
- </div>
238
- </header>
239
-
240
- <!-- 移动端导航菜单 -->
241
- <div class="mobile-menu" id="mobile-menu">
242
- <div class="mobile-menu-container">
243
- <div class="mobile-menu-header">
244
- <div class="brand">
245
- {logoUrl ? (
246
- <img src={logoUrl} alt={brandName} class="brand-logo" />
247
- ) : (
248
- <span class="brand-name">{brandName}</span>
249
- )}
250
- </div>
251
- <button class="close-menu-button" aria-label="关闭菜单" id="close-mobile-menu">
252
- <span class="close-icon">✕</span>
253
- </button>
254
- </div>
255
-
256
- <nav class="mobile-nav">
257
- <ul class="mobile-nav-list">
258
- {navItems.map((item: NavItem) => (
259
- <li class="mobile-nav-item">
260
- <a href={item.href} class="mobile-nav-link">
261
- {item.label}
262
- </a>
263
- </li>
264
- ))}
265
- </ul>
266
- </nav>
267
- </div>
268
- </div>
269
-
270
- <!-- 英雄区块 -->
271
- <section class="hero-section">
272
- <div class="container">
273
- <slot name="hero" />
274
- </div>
275
- </section>
276
-
277
- <!-- 主要内容 -->
278
- <main class="main-content">
279
- <slot />
280
- </main>
281
-
282
- <!-- 页脚 -->
283
- <footer class="site-footer">
284
- <div class="container">
285
- <div class="footer-content">
286
- <div class="footer-brand">
287
- <div class="brand">
288
- {logoUrl ? (
289
- <img src={logoUrl} alt={brandName} class="brand-logo" />
290
- ) : (
291
- <span class="brand-name">{brandName}</span>
292
- )}
293
- </div>
294
- <p class="brand-tagline">
295
- <slot name="footer-tagline">简短的品牌标语或描述</slot>
296
- </p>
297
-
298
- <div class="social-links">
299
- {socialLinks.map((link: SocialLink) => (
300
- <a href={link.href} class="social-link" aria-label={link.label} target="_blank" rel="noopener noreferrer">
301
- <span class="social-icon">{socialIconMap[link.icon] || "🔗"}</span>
302
- </a>
303
- ))}
304
- </div>
305
- </div>
306
-
307
- <div class="footer-links">
308
- {footerSections.map((section: FooterSection) => (
309
- <div class="footer-section">
310
- <h3 class="footer-title">{section.title}</h3>
311
- <ul class="footer-list">
312
- {section.links.map((link: FooterLink) => (
313
- <li class="footer-item">
314
- <a href={link.href} class="footer-link">{link.label}</a>
315
- </li>
316
- ))}
317
- </ul>
318
- </div>
319
- ))}
320
- </div>
321
- </div>
322
-
323
- <div class="footer-bottom">
324
- <p class="copyright">{copyright}</p>
325
- <slot name="footer-extra" />
326
- </div>
327
- </div>
328
- </footer>
329
- </BaseLayout>
330
-
331
- <script>
332
- // 移动端菜单功能
333
- document.addEventListener('DOMContentLoaded', () => {
334
- const mobileMenuToggle = document.getElementById('mobile-menu-toggle');
335
- const closeMobileMenu = document.getElementById('close-mobile-menu');
336
- const mobileMenu = document.getElementById('mobile-menu');
337
- const mobileNavLinks = document.querySelectorAll('.mobile-nav-link');
338
-
339
- if (mobileMenuToggle && mobileMenu) {
340
- mobileMenuToggle.addEventListener('click', () => {
341
- mobileMenu.classList.add('active');
342
- document.body.style.overflow = 'hidden';
343
- });
344
- }
345
-
346
- if (closeMobileMenu && mobileMenu) {
347
- closeMobileMenu.addEventListener('click', () => {
348
- mobileMenu.classList.remove('active');
349
- document.body.style.overflow = '';
350
- });
351
- }
352
-
353
- // 点击导航链接后关闭菜单
354
- mobileNavLinks.forEach(link => {
355
- link.addEventListener('click', () => {
356
- if (mobileMenu) {
357
- mobileMenu.classList.remove('active');
358
- document.body.style.overflow = '';
359
- }
360
- });
361
- });
362
-
363
- // 页眉滚动效果
364
- const header = document.querySelector('.site-header');
365
- let lastScrollTop = 0;
366
-
367
- window.addEventListener('scroll', () => {
368
- const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
369
-
370
- if (header) {
371
- if (scrollTop > 100) {
372
- header.classList.add('scrolled');
373
-
374
- if (scrollTop > lastScrollTop) {
375
- header.classList.add('hidden');
376
- } else {
377
- header.classList.remove('hidden');
378
- }
379
- } else {
380
- header.classList.remove('scrolled');
381
- header.classList.remove('hidden');
382
- }
383
- }
384
-
385
- lastScrollTop = scrollTop;
386
- });
387
- });
388
- </script>