@coffic/cosy-ui 0.8.11 → 0.8.13

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 (82) hide show
  1. package/dist/app.css +1 -1
  2. package/dist/index-astro.ts +18 -10
  3. package/dist/{src-astro → src}/utils/language.ts +1 -1
  4. package/dist/src/utils/link.ts +250 -0
  5. package/dist/{src-astro → src}/utils/path.ts +1 -1
  6. package/dist/src-astro/article/index.ts +1 -1
  7. package/dist/src-astro/assets/iconData.ts +5 -0
  8. package/dist/src-astro/banner/index.ts +1 -1
  9. package/dist/src-astro/code-container/CodeContainer.astro +6 -91
  10. package/dist/src-astro/confirm-dialog/ConfirmDialog.astro +119 -0
  11. package/dist/src-astro/confirm-dialog/index.ts +2 -0
  12. package/dist/src-astro/confirm-dialog/types.ts +47 -0
  13. package/dist/src-astro/cosy.ts +1 -1
  14. package/dist/src-astro/database/index.ts +3 -0
  15. package/dist/src-astro/entities/BlogDoc.ts +1 -1
  16. package/dist/src-astro/entities/CourseDoc.ts +1 -1
  17. package/dist/src-astro/entities/ExperimentDoc.ts +1 -1
  18. package/dist/src-astro/entities/LessonDoc.ts +1 -1
  19. package/dist/src-astro/entities/MetaDoc.ts +1 -1
  20. package/dist/src-astro/entities/Tag.ts +1 -1
  21. package/dist/src-astro/errors/403.astro +1 -1
  22. package/dist/src-astro/errors/404.astro +1 -1
  23. package/dist/src-astro/errors/500.astro +1 -1
  24. package/dist/src-astro/errors/503.astro +1 -1
  25. package/dist/src-astro/flex/index.ts +1 -1
  26. package/dist/src-astro/footer/Footer.astro +1 -1
  27. package/dist/src-astro/grid/index.ts +1 -1
  28. package/dist/src-astro/heading/index.ts +1 -1
  29. package/dist/src-astro/icons/LogOut.astro +28 -0
  30. package/dist/src-astro/icons/index.ts +1 -0
  31. package/dist/src-astro/image/index.ts +1 -1
  32. package/dist/src-astro/language-switcher/index.ts +1 -1
  33. package/dist/src-astro/layout-basic/index.ts +1 -1
  34. package/dist/src-astro/layout-dashboard/DashboardLayout.astro +156 -23
  35. package/dist/src-astro/layout-dashboard/DashboardSidebar.astro +76 -63
  36. package/dist/src-astro/layout-dashboard/DashboardTopNavbar.astro +47 -15
  37. package/dist/src-astro/layout-dashboard/tools.ts +158 -0
  38. package/dist/src-astro/layout-dashboard/types.ts +37 -184
  39. package/dist/src-astro/link/index.ts +1 -1
  40. package/dist/src-astro/login/Login.astro +251 -0
  41. package/dist/src-astro/login/index.ts +2 -0
  42. package/dist/src-astro/logout/Logout.astro +117 -0
  43. package/dist/src-astro/logout/index.ts +2 -0
  44. package/dist/src-astro/module/index.ts +1 -1
  45. package/dist/src-astro/nav-item/NavItems.astro +1 -1
  46. package/dist/src-astro/nav-item/index.ts +1 -1
  47. package/dist/src-astro/nav-section/index.ts +1 -1
  48. package/dist/src-astro/register/Register.astro +289 -0
  49. package/dist/src-astro/register/index.ts +2 -0
  50. package/dist/src-astro/sidebar/Sidebar.astro +1 -1
  51. package/dist/src-astro/sidebar/index.ts +1 -1
  52. package/dist/src-astro/sidebar-nav/SidebarNav.astro +1 -1
  53. package/dist/src-astro/sidebar-nav/index.ts +1 -1
  54. package/dist/src-astro/speak/index.ts +1 -1
  55. package/dist/src-astro/stack/index.ts +1 -1
  56. package/dist/src-astro/team-member/TeamMemberBasic.astro +1 -1
  57. package/dist/src-astro/team-member/TeamMemberCustomStyle.astro +1 -1
  58. package/dist/src-astro/team-member/TeamMemberGroup.astro +1 -1
  59. package/dist/src-astro/team-member/TeamMemberWithSocial.astro +1 -1
  60. package/dist/src-astro/team-member/index.ts +1 -1
  61. package/dist/src-astro/text/index.ts +1 -1
  62. package/dist/src-astro/theme-switcher/ThemeSwitcher.astro +1 -1
  63. package/dist/src-astro/theme-switcher/index.ts +1 -1
  64. package/dist/src-astro/toast/Toast.astro +114 -0
  65. package/dist/src-astro/toast/ToastContainer.astro +249 -0
  66. package/dist/src-astro/toast/index.ts +4 -0
  67. package/dist/src-astro/toast/types.ts +78 -0
  68. package/dist/src-astro/toc/TableOfContents.astro +2 -2
  69. package/dist/src-astro/toc/index.ts +1 -1
  70. package/dist/src-astro/types/nav.ts +26 -1
  71. package/dist/vue/utils/link.ts +238 -238
  72. package/package.json +1 -1
  73. package/dist/src-astro/utils/link.ts +0 -250
  74. /package/dist/{src-astro → src}/utils/component.ts +0 -0
  75. /package/dist/{src-astro → src}/utils/i18n.ts +0 -0
  76. /package/dist/{src-astro → src}/utils/image.ts +0 -0
  77. /package/dist/{src-astro → src}/utils/lang_entry.ts +0 -0
  78. /package/dist/{src-astro → src}/utils/lang_package.ts +0 -0
  79. /package/dist/{src-astro → src}/utils/logger.ts +0 -0
  80. /package/dist/{src-astro → src}/utils/social.ts +0 -0
  81. /package/dist/{src-astro → src}/utils/theme.ts +0 -0
  82. /package/dist/{src-astro → src}/utils/url.ts +0 -0
@@ -1,5 +1,5 @@
1
1
  import type { BlogEntry } from '../database/BlogDB';
2
- import { LinkUtil } from '../utils/link';
2
+ import { LinkUtil } from '../../src/utils/link';
3
3
  import Tag from './Tag';
4
4
  import { BaseDoc } from './BaseDoc';
5
5
  import { COLLECTION_BLOG } from '../database/BlogDB';
@@ -2,7 +2,7 @@ import { cosyLogger } from '../cosy';
2
2
  import { SidebarItemEntity } from './SidebarItem';
3
3
  import type { CourseEntry } from '../database/CourseDB';
4
4
  import { courseDB } from '../database/CourseDB';
5
- import { LinkUtil } from '../utils/link';
5
+ import { LinkUtil } from '../../src/utils/link';
6
6
  import { COLLECTION_COURSE } from '../database/CourseDB';
7
7
  import { BaseDoc } from './BaseDoc';
8
8
 
@@ -2,7 +2,7 @@ import type { ExperimentEntry } from '../database/ExperimentDB';
2
2
  import { experimentDB } from '../database/ExperimentDB';
3
3
  import { cosyLogger } from '../cosy';
4
4
  import { SidebarItemEntity } from './SidebarItem';
5
- import { LinkUtil } from '../utils/link';
5
+ import { LinkUtil } from '../../src/utils/link';
6
6
  import { COLLECTION_EXPERIMENT } from '../database/ExperimentDB';
7
7
  import { BaseDoc } from './BaseDoc';
8
8
  import type { IHeadingType } from '../types/heading';
@@ -2,7 +2,7 @@ import type { LessonEntry } from '../database/LessonDB';
2
2
  import { lessonDB } from '../database/LessonDB';
3
3
  import { cosyLogger } from '../cosy';
4
4
  import { SidebarItemEntity } from './SidebarItem';
5
- import { LinkUtil } from '../utils/link';
5
+ import { LinkUtil } from '../../src/utils/link';
6
6
  import { COLLECTION_LESSON } from '../database/LessonDB';
7
7
  import { BaseDoc } from './BaseDoc';
8
8
  import type { IHeadingType } from '../types/heading';
@@ -1,6 +1,6 @@
1
1
  import { SidebarItemEntity } from './SidebarItem';
2
2
  import type { MetaEntry } from '../database/MetaDB';
3
- import { LinkUtil } from '../utils/link';
3
+ import { LinkUtil } from '../../src/utils/link';
4
4
  import { BaseDoc } from './BaseDoc';
5
5
  import { metaDB } from '../database/MetaDB';
6
6
  import { COLLECTION_META } from '../database/MetaDB';
@@ -1,7 +1,7 @@
1
1
  import { blogDB } from '../database/BlogDB';
2
2
  import { SidebarItemEntity } from './SidebarItem';
3
3
  import { type ITagStaticPath } from '../types/static-path';
4
- import { LinkUtil } from '../utils/link';
4
+ import { LinkUtil } from '../../src/utils/link';
5
5
 
6
6
  export class Tag {
7
7
  name: string;
@@ -35,7 +35,7 @@
35
35
  */
36
36
 
37
37
  import '../../style.ts';
38
- import { LinkUtil } from '../utils/link.ts';
38
+ import { LinkUtil } from '../../src/utils/link.ts';
39
39
 
40
40
  const baseUrl = LinkUtil.getBaseUrl();
41
41
  const path = Astro.url.pathname;
@@ -36,7 +36,7 @@
36
36
  */
37
37
 
38
38
  import '../../style.ts';
39
- import { LinkUtil } from '../utils/link.ts';
39
+ import { LinkUtil } from '../../src/utils/link.ts';
40
40
 
41
41
  const baseUrl = LinkUtil.getBaseUrl();
42
42
  const path = Astro.url.pathname;
@@ -35,7 +35,7 @@
35
35
  */
36
36
 
37
37
  import '../../style.ts';
38
- import { LinkUtil } from '../utils/link.ts';
38
+ import { LinkUtil } from '../../src/utils/link.ts';
39
39
 
40
40
  const baseUrl = LinkUtil.getBaseUrl();
41
41
  const path = Astro.url.pathname;
@@ -40,7 +40,7 @@
40
40
  */
41
41
 
42
42
  import '../../style.ts';
43
- import { LinkUtil } from '../utils/link.ts';
43
+ import { LinkUtil } from '../../src/utils/link.ts';
44
44
 
45
45
  const baseUrl = LinkUtil.getBaseUrl();
46
46
  const path = Astro.url.pathname;
@@ -1,7 +1,7 @@
1
1
  import Flex from './Flex.astro';
2
2
  import FlexBasic from './FlexBasic.astro';
3
3
  import BasicSourceCode from './FlexBasic.astro?raw';
4
- import { extractSimpleExample } from '../utils/component';
4
+ import { extractSimpleExample } from '../../src/utils/component';
5
5
 
6
6
  export { Flex, FlexBasic };
7
7
 
@@ -145,7 +145,7 @@
145
145
  * - 社交媒体图标包含屏幕阅读器专用的文本说明
146
146
  */
147
147
 
148
- import { processSocialLink } from '../utils/social.ts';
148
+ import { processSocialLink } from '../../src/utils/social.ts';
149
149
  import {
150
150
  SocialIcon,
151
151
  LanguageUtil,
@@ -1,7 +1,7 @@
1
1
  import Grid from './Grid.astro';
2
2
  import GridBasic from './GridBasic.astro';
3
3
  import BasicSourceCode from './GridBasic.astro?raw';
4
- import { extractSimpleExample } from '../utils/component';
4
+ import { extractSimpleExample } from '../../src/utils/component';
5
5
 
6
6
  export { Grid, GridBasic };
7
7
 
@@ -1,7 +1,7 @@
1
1
  import Heading from './Heading.astro';
2
2
  import HeadingBasic from './HeadingBasic.astro';
3
3
  import BasicSourceCode from './HeadingBasic.astro?raw';
4
- import { extractSimpleExample } from '../utils/component';
4
+ import { extractSimpleExample } from '../../src/utils/component';
5
5
 
6
6
  export { Heading, HeadingBasic };
7
7
 
@@ -0,0 +1,28 @@
1
+ ---
2
+ import AstroIcon from './AstroIcon.astro';
3
+
4
+ interface Props {
5
+ /**
6
+ * 图标的大小
7
+ * @default "24px"
8
+ */
9
+ size?: string;
10
+ /**
11
+ * 图标的颜色
12
+ * @default "currentColor"
13
+ */
14
+ color?: string;
15
+ /**
16
+ * 自定义类名
17
+ */
18
+ class?: string;
19
+ }
20
+
21
+ const {
22
+ size = '24px',
23
+ color = 'currentColor',
24
+ class: className = '',
25
+ } = Astro.props;
26
+ ---
27
+
28
+ <AstroIcon name="logOut" size={size} stroke={color} class={className} />
@@ -43,4 +43,5 @@ export { default as ReportIcon } from './ReportIcon.astro';
43
43
  export { default as SecurityIcon } from './SecurityIcon.astro';
44
44
  export { default as UploadIcon } from './UploadIcon.astro';
45
45
  export { default as DownloadIcon } from './DownloadIcon.astro';
46
+ export { default as LogOut } from './LogOut.astro';
46
47
 
@@ -5,7 +5,7 @@ import ImageLoading from './ImageLoading.astro';
5
5
  import BasicSourceCode from './ImageBasic.astro?raw';
6
6
  import EffectsSourceCode from './ImageEffects.astro?raw';
7
7
  import LoadingSourceCode from './ImageLoading.astro?raw';
8
- import { extractSimpleExample } from '../utils/component';
8
+ import { extractSimpleExample } from '../../src/utils/component';
9
9
 
10
10
  export { Image, ImageBasic, ImageEffects, ImageLoading };
11
11
 
@@ -1,7 +1,7 @@
1
1
  import LanguageSwitcher from './LanguageSwitcher.astro';
2
2
  import LanguageSwitcherBasic from './LanguageSwitcherBasic.astro';
3
3
  import BasicSourceCode from './LanguageSwitcherBasic.astro?raw';
4
- import { extractSimpleExample } from '../utils/component';
4
+ import { extractSimpleExample } from '../../src/utils/component';
5
5
 
6
6
  export { LanguageSwitcher, LanguageSwitcherBasic };
7
7
 
@@ -1,7 +1,7 @@
1
1
  import BaseLayout from './BaseLayout.astro';
2
2
  import BaseLayoutBasic from './BaseLayoutBasic.astro';
3
3
  import BasicSourceCode from './BaseLayoutBasic.astro?raw';
4
- import { extractSimpleExample } from '../utils/component';
4
+ import { extractSimpleExample } from '../../src/utils/component';
5
5
 
6
6
  export { BaseLayout, BaseLayoutBasic };
7
7
 
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * @description
6
6
  * DashboardLayout 组件适用于管理后台的布局,包含侧边栏导航和顶部导航栏。
7
- * 提供了完整的管理界面框架,包括响应式设计和暗色主题支持。
7
+ * 提供了完整的管理界面框架,包括响应式设计、暗色主题支持和内置 Toast 通知系统。
8
8
  *
9
9
  * @design
10
10
  * 设计理念:
@@ -12,8 +12,10 @@
12
12
  * 2. 响应式布局 - 在不同设备上提供良好的用户体验
13
13
  * 3. 可定制性 - 支持自定义导航项、系统名称和用户信息
14
14
  * 4. 状态保持 - 记住用户的侧边栏折叠状态
15
+ * 5. 统一通知 - 内置 Toast 系统,提供一致的消息提示体验
15
16
  *
16
17
  * @usage
18
+ * 基本用法:
17
19
  * ```astro
18
20
  * ---
19
21
  * import { DashboardLayout } from '@coffic/cosy-ui';
@@ -24,12 +26,19 @@
24
26
  * { href: "/dashboard/settings", text: "系统设置" }, // 自动匹配 settings 图标
25
27
  * { href: "/dashboard/reports", icon: "chart", text: "报表" } // 手动指定图标
26
28
  * ];
29
+ *
30
+ * const userMenuItems = [
31
+ * { href: "/profile", text: "个人资料" }, // 自动匹配 user 图标
32
+ * { href: "/settings", text: "设置" }, // 自动匹配 settings 图标
33
+ * { href: "/logout", text: "退出登录" } // 自动匹配 logout 图标
34
+ * ];
27
35
  * ---
28
36
  *
29
37
  * <DashboardLayout
30
38
  * title="管理后台"
31
39
  * navItems={navItems}
32
40
  * userName="管理员"
41
+ * userMenuItems={userMenuItems}
33
42
  * sidebarSize="lg"
34
43
  * >
35
44
  * <h1>仪表盘内容</h1>
@@ -37,6 +46,91 @@
37
46
  * </DashboardLayout>
38
47
  * ```
39
48
  *
49
+ * 带有底部自定义内容的用法:
50
+ * ```astro
51
+ * <DashboardLayout
52
+ * title="管理后台"
53
+ * navItems={navItems}
54
+ * userName="管理员"
55
+ * >
56
+ * <h1>仪表盘内容</h1>
57
+ * <p>这是仪表盘的主要内容</p>
58
+ *
59
+ * <div slot="sidebar-footer" class="p-4">
60
+ * <div class="flex items-center gap-3">
61
+ * <div class="avatar">
62
+ * <div class="w-10 rounded-full">
63
+ * <img src="/avatar.jpg" alt="用户头像" />
64
+ * </div>
65
+ * </div>
66
+ * <div>
67
+ * <div class="font-semibold">张三</div>
68
+ * <div class="text-sm opacity-70">产品经理</div>
69
+ * </div>
70
+ * </div>
71
+ * </div>
72
+ * </DashboardLayout>
73
+ * ```
74
+ *
75
+ * 带有主内容区域背景的用法:
76
+ * ```astro
77
+ * <DashboardLayout
78
+ * title="管理后台"
79
+ * navItems={navItems}
80
+ * userName="管理员"
81
+ * mainBackgroundTheme="gradient-cool"
82
+ * >
83
+ * <h1>仪表盘内容</h1>
84
+ * <p>这是带有背景的主要内容</p>
85
+ *
86
+ * <script>
87
+ * // 在页面中使用 toast
88
+ * function handleAction() {
89
+ * // 简单用法
90
+ * showToast('操作成功!');
91
+ *
92
+ * // 带选项的用法
93
+ * showToast({
94
+ * message: '数据保存成功',
95
+ * type: 'success',
96
+ * duration: 2000
97
+ * });
98
+ * }
99
+ * </script>
100
+ * </DashboardLayout>
101
+ * ```
102
+ *
103
+ * Toast 使用示例:
104
+ * ```javascript
105
+ * // 成功消息
106
+ * showToast({
107
+ * message: '保存成功!',
108
+ * type: 'success'
109
+ * });
110
+ *
111
+ * // 错误消息
112
+ * showToast({
113
+ * message: '网络连接失败',
114
+ * type: 'error',
115
+ * duration: 5000
116
+ * });
117
+ *
118
+ * // 警告消息
119
+ * showToast({
120
+ * message: '请注意数据安全',
121
+ * type: 'warning'
122
+ * });
123
+ *
124
+ * // 信息消息
125
+ * showToast({
126
+ * message: '系统将在 5 分钟后维护',
127
+ * type: 'info'
128
+ * });
129
+ *
130
+ * // 简化用法
131
+ * showToast('这是一条简单的消息');
132
+ * ```
133
+ *
40
134
  * @props
41
135
  * - title: string - 页面标题
42
136
  * - description?: string - 页面描述
@@ -44,28 +138,33 @@
44
138
  * - navItems: NavItem[] - 导航项目
45
139
  * - userName?: string - 用户名
46
140
  * - userAvatar?: string - 用户头像
141
+ * - userMenuItems?: UserMenuItem[] - 用户菜单项,默认包含个人资料、设置、退出登录,图标会自动匹配
47
142
  * - sidebarCollapsed?: boolean - 是否折叠侧边栏,默认为false
48
143
  * - sidebarSize?: 'sm' | 'md' | 'lg' | 'xl' - 侧边栏尺寸,默认为"md"
49
144
  * - sidebarTheme?: SidebarTheme - 侧边栏主题,默认为"default"
50
- * - contentTheme?: ContentTheme - 内容区域主题,默认为"card"
145
+ * - mainBackgroundTheme?: MainBackgroundTheme - 主内容区域背景主题,默认为"transparent"
51
146
  * - head?: astroHTML.JSX.Element - 自定义头部内容
52
147
  * - class?: string - 页面类名
53
148
  * - class:list?: any - 类名列表
149
+ * - debug?: boolean - 调试模式,默认为false
54
150
  *
55
151
  * @slots
56
152
  * - default - 主要内容区域
153
+ * - sidebar-footer - 侧边栏底部自定义内容,可用于展示用户信息、版权信息等
57
154
  */
58
155
 
59
156
  import { BaseLayout } from '../../index-astro';
60
157
  import DashboardSidebar from './DashboardSidebar.astro';
61
158
  import DashboardTopNavbar from './DashboardTopNavbar.astro';
159
+ import { ToastContainer, ConfirmDialog } from '../../index-astro';
62
160
  import '../../style.ts';
63
161
  import {
64
162
  type NavItem,
65
163
  type SidebarSize,
66
164
  type SidebarTheme,
67
- type ContentTheme,
68
- getContentTheme,
165
+ type MainBackgroundTheme,
166
+ type UserMenuItem,
167
+ getMainBackgroundTheme,
69
168
  } from './types';
70
169
 
71
170
  export interface Props {
@@ -100,6 +199,11 @@ export interface Props {
100
199
  */
101
200
  userAvatar?: string;
102
201
 
202
+ /**
203
+ * 用户菜单项
204
+ */
205
+ userMenuItems?: UserMenuItem[];
206
+
103
207
  /**
104
208
  * 是否折叠侧边栏
105
209
  * @default false
@@ -119,10 +223,10 @@ export interface Props {
119
223
  sidebarTheme?: SidebarTheme;
120
224
 
121
225
  /**
122
- * 内容区域主题
123
- * @default "card"
226
+ * 主内容区域背景主题
227
+ * @default "transparent"
124
228
  */
125
- contentTheme?: ContentTheme;
229
+ mainBackgroundTheme?: MainBackgroundTheme;
126
230
 
127
231
  /**
128
232
  * 自定义头部内容
@@ -138,6 +242,24 @@ export interface Props {
138
242
  * 类名列表
139
243
  */
140
244
  'class:list'?: any;
245
+
246
+ /**
247
+ * 是否启用 Toast 功能
248
+ * @default true
249
+ */
250
+ enableToast?: boolean;
251
+
252
+ /**
253
+ * 是否启用确认对话框功能
254
+ * @default true
255
+ */
256
+ enableConfirmDialog?: boolean;
257
+
258
+ /**
259
+ * 调试模式
260
+ * @default false
261
+ */
262
+ debug?: boolean;
141
263
  }
142
264
 
143
265
  const {
@@ -147,18 +269,22 @@ const {
147
269
  navItems,
148
270
  userName,
149
271
  userAvatar,
272
+ userMenuItems,
150
273
  sidebarCollapsed = false,
151
274
  sidebarSize = 'md',
152
275
  sidebarTheme = 'default',
153
- contentTheme = 'card',
276
+ mainBackgroundTheme = 'transparent',
277
+ enableToast = true,
278
+ enableConfirmDialog = true,
154
279
  head,
155
280
  class: className,
156
281
  'class:list': classList,
282
+ debug = false,
157
283
  ...rest
158
284
  } = Astro.props;
159
285
 
160
286
  const currentPath = Astro.url.pathname;
161
- const contentStyles = getContentTheme(contentTheme);
287
+ const mainBackgroundStyles = getMainBackgroundTheme(mainBackgroundTheme);
162
288
  ---
163
289
 
164
290
  <BaseLayout
@@ -168,6 +294,7 @@ const contentStyles = getContentTheme(contentTheme);
168
294
  keywords=""
169
295
  author=""
170
296
  robots=""
297
+ debug={debug}
171
298
  class:list={['cosy:min-h-screen cosy:bg-base-200', className, classList]}
172
299
  {...rest}>
173
300
  <div class:list={['cosy:drawer', { 'cosy:drawer-open': !sidebarCollapsed }]}>
@@ -184,8 +311,9 @@ const contentStyles = getContentTheme(contentTheme);
184
311
  navItems={navItems}
185
312
  currentPath={currentPath}
186
313
  size={sidebarSize}
187
- theme={sidebarTheme}
188
- />
314
+ theme={sidebarTheme}>
315
+ <slot name="sidebar-footer" slot="footer" />
316
+ </DashboardSidebar>
189
317
  </div>
190
318
 
191
319
  <!-- 主内容区 -->
@@ -195,24 +323,29 @@ const contentStyles = getContentTheme(contentTheme);
195
323
  title={title}
196
324
  userName={userName}
197
325
  userAvatar={userAvatar}
326
+ userMenuItems={userMenuItems}
198
327
  />
199
328
 
200
329
  <!-- 页面内容 -->
201
- <main class="cosy:flex-1 cosy:p-4 cosy:lg:p-6">
202
- {
203
- contentStyles.container ? (
204
- <div class={`${contentStyles.container} ${contentStyles.shadow}`}>
205
- <div class="cosy:card-body">
206
- <slot />
207
- </div>
208
- </div>
209
- ) : (
210
- <slot />
211
- )
212
- }
330
+ <main
331
+ class:list={['cosy:flex-1 cosy:p-4 cosy:lg:p-6', mainBackgroundStyles]}>
332
+ <slot />
213
333
  </main>
214
334
  </div>
215
335
  </div>
336
+
337
+ <!-- Toast 容器 -->
338
+ {enableToast && <ToastContainer />}
339
+
340
+ {
341
+ enableConfirmDialog && (
342
+ <ConfirmDialog
343
+ id="dashboard-confirm"
344
+ title="确认操作"
345
+ message="您确定要执行此操作吗?"
346
+ />
347
+ )
348
+ }
216
349
  </BaseLayout>
217
350
 
218
351
  <script>
@@ -29,6 +29,9 @@
29
29
  * - currentPath?: string - 当前路径,用于高亮当前页面
30
30
  * - size?: 'sm' | 'md' | 'lg' | 'xl' - 侧边栏尺寸,默认为"md"
31
31
  * - theme?: SidebarTheme - 侧边栏主题,默认为"default"
32
+ *
33
+ * @slots
34
+ * - footer - 侧边栏底部自定义内容,可用于展示用户信息等
32
35
  */
33
36
 
34
37
  import '../../style.ts';
@@ -86,7 +89,7 @@ const themeStyles = getSidebarTheme(theme);
86
89
  <aside
87
90
  class:list={[
88
91
  getSidebarWidth(size),
89
- 'cosy:min-h-full',
92
+ 'cosy:min-h-full cosy:flex cosy:flex-col',
90
93
  themeStyles.bg,
91
94
  themeStyles.textColor,
92
95
  ]}>
@@ -113,69 +116,79 @@ const themeStyles = getSidebarTheme(theme);
113
116
  </div>
114
117
 
115
118
  <!-- 导航菜单 -->
116
- <ul
117
- class="cosy:menu cosy:p-4 cosy:space-y-1 cosy:list-none cosy:no-underline">
118
- {
119
- navItems.map((item: NavItem) => {
120
- const isActive =
121
- currentPath === item.href ||
122
- (item.items &&
123
- item.items.some(
124
- (subitem: NavItem) => currentPath === subitem.href
125
- ));
126
-
127
- return (
128
- <li>
129
- <a
130
- href={item.href}
131
- class:list={['cosy:no-underline', { active: isActive }]}>
132
- <AstroIcon
133
- name={getNavItemIcon(item)}
134
- size="16px"
135
- stroke="currentColor"
136
- />
137
- <span>{item.text}</span>
138
- {item.badge && (
139
- <span class="cosy:badge cosy:badge-primary cosy:badge-sm">
140
- {item.badge}
141
- </span>
119
+ <div class="cosy:flex-1 cosy:overflow-y-auto">
120
+ <ul
121
+ class="cosy:menu cosy:p-4 cosy:space-y-1 cosy:list-none cosy:no-underline">
122
+ {
123
+ navItems.map((item: NavItem) => {
124
+ const isActive =
125
+ currentPath === item.href ||
126
+ (item.items &&
127
+ item.items.some(
128
+ (subitem: NavItem) => currentPath === subitem.href
129
+ ));
130
+
131
+ return (
132
+ <li>
133
+ <a
134
+ href={item.href}
135
+ class:list={[
136
+ 'cosy:no-underline',
137
+ { 'cosy:menu-active': isActive },
138
+ ]}>
139
+ <AstroIcon
140
+ name={getNavItemIcon(item)}
141
+ size="16px"
142
+ stroke="currentColor"
143
+ />
144
+ <span>{item.text}</span>
145
+ {item.badge && (
146
+ <span class="cosy:badge cosy:badge-primary cosy:badge-sm">
147
+ {item.badge}
148
+ </span>
149
+ )}
150
+ </a>
151
+
152
+ {item.items && (
153
+ <ul class="cosy:ml-4 cosy:list-none cosy:no-underline">
154
+ {item.items.map((subitem: NavItem) => {
155
+ const isSubActive = currentPath === subitem.href;
156
+ return (
157
+ <li>
158
+ <a
159
+ href={subitem.href}
160
+ class:list={[
161
+ 'cosy:text-sm cosy:no-underline',
162
+ { 'cosy:menu-active': isSubActive },
163
+ ]}>
164
+ <AstroIcon
165
+ name={getNavItemIcon(subitem)}
166
+ size="14px"
167
+ stroke="currentColor"
168
+ />
169
+ <span>{subitem.text}</span>
170
+ {subitem.badge && (
171
+ <span class="cosy:badge cosy:badge-primary cosy:badge-xs">
172
+ {subitem.badge}
173
+ </span>
174
+ )}
175
+ </a>
176
+ </li>
177
+ );
178
+ })}
179
+ </ul>
142
180
  )}
143
- </a>
144
-
145
- {item.items && (
146
- <ul class="cosy:ml-4 cosy:list-none cosy:no-underline">
147
- {item.items.map((subitem: NavItem) => {
148
- const isSubActive = currentPath === subitem.href;
149
- return (
150
- <li>
151
- <a
152
- href={subitem.href}
153
- class:list={[
154
- 'cosy:text-sm cosy:no-underline',
155
- { active: isSubActive },
156
- ]}>
157
- <AstroIcon
158
- name={getNavItemIcon(subitem)}
159
- size="14px"
160
- stroke="currentColor"
161
- />
162
- <span>{subitem.text}</span>
163
- {subitem.badge && (
164
- <span class="cosy:badge cosy:badge-primary cosy:badge-xs">
165
- {subitem.badge}
166
- </span>
167
- )}
168
- </a>
169
- </li>
170
- );
171
- })}
172
- </ul>
173
- )}
174
- </li>
175
- );
176
- })
177
- }
178
- </ul>
181
+ </li>
182
+ );
183
+ })
184
+ }
185
+ </ul>
186
+ </div>
187
+
188
+ <!-- 侧边栏底部自定义内容 -->
189
+ <div class:list={['cosy:mt-auto cosy:border-t', themeStyles.borderColor]}>
190
+ <slot name="footer" />
191
+ </div>
179
192
  </aside>
180
193
 
181
194
  <script>