@coffic/cosy-ui 0.8.12 → 0.8.16

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 (179) hide show
  1. package/README.md +31 -0
  2. package/dist/app.css +1 -1
  3. package/dist/index-astro.ts +18 -10
  4. package/dist/index-vue.ts +2 -2
  5. package/dist/{vue → src}/utils/language.ts +1 -1
  6. package/dist/src/utils/link.ts +250 -0
  7. package/dist/{vue → src}/utils/path.ts +1 -1
  8. package/dist/src-astro/article/index.ts +1 -1
  9. package/dist/src-astro/assets/iconData.ts +5 -0
  10. package/dist/src-astro/banner/index.ts +1 -1
  11. package/dist/src-astro/code-container/CodeContainer.astro +6 -91
  12. package/dist/src-astro/confirm-dialog/ConfirmDialog.astro +119 -0
  13. package/dist/src-astro/confirm-dialog/index.ts +2 -0
  14. package/dist/src-astro/confirm-dialog/types.ts +47 -0
  15. package/dist/src-astro/cosy.ts +1 -1
  16. package/dist/src-astro/database/index.ts +3 -0
  17. package/dist/src-astro/entities/BlogDoc.ts +1 -1
  18. package/dist/src-astro/entities/CourseDoc.ts +1 -1
  19. package/dist/src-astro/entities/ExperimentDoc.ts +1 -1
  20. package/dist/src-astro/entities/LessonDoc.ts +1 -1
  21. package/dist/src-astro/entities/MetaDoc.ts +1 -1
  22. package/dist/src-astro/entities/Tag.ts +1 -1
  23. package/dist/src-astro/errors/403.astro +1 -1
  24. package/dist/src-astro/errors/404.astro +1 -1
  25. package/dist/src-astro/errors/500.astro +1 -1
  26. package/dist/src-astro/errors/503.astro +1 -1
  27. package/dist/src-astro/flex/index.ts +1 -1
  28. package/dist/src-astro/footer/Footer.astro +1 -1
  29. package/dist/src-astro/grid/index.ts +1 -1
  30. package/dist/src-astro/heading/index.ts +1 -1
  31. package/dist/src-astro/icons/LogOut.astro +28 -0
  32. package/dist/src-astro/icons/index.ts +1 -0
  33. package/dist/src-astro/image/index.ts +1 -1
  34. package/dist/src-astro/language-switcher/index.ts +1 -1
  35. package/dist/src-astro/layout-basic/index.ts +1 -1
  36. package/dist/src-astro/layout-dashboard/DashboardLayout.astro +76 -1
  37. package/dist/src-astro/layout-dashboard/tools.ts +158 -0
  38. package/dist/src-astro/layout-dashboard/types.ts +1 -154
  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/buttons-vue → src-vue/buttons}/Button.vue +14 -19
  72. package/dist/{vue/icons-vue → src-vue/icons}/VueIcon.vue +3 -13
  73. package/dist/src-vue/utils/link.ts +250 -0
  74. package/package.json +1 -1
  75. package/dist/src-astro/utils/link.ts +0 -250
  76. package/dist/vue/utils/link.ts +0 -250
  77. /package/dist/{vue → src}/utils/component.ts +0 -0
  78. /package/dist/{vue → src}/utils/i18n.ts +0 -0
  79. /package/dist/{vue → src}/utils/image.ts +0 -0
  80. /package/dist/{vue → src}/utils/lang_entry.ts +0 -0
  81. /package/dist/{vue → src}/utils/lang_package.ts +0 -0
  82. /package/dist/{vue → src}/utils/logger.ts +0 -0
  83. /package/dist/{vue → src}/utils/social.ts +0 -0
  84. /package/dist/{vue → src}/utils/theme.ts +0 -0
  85. /package/dist/{vue → src}/utils/url.ts +0 -0
  86. /package/dist/{vue → src-vue}/SmartLink.vue +0 -0
  87. /package/dist/{vue → src-vue}/TagList.vue +0 -0
  88. /package/dist/{vue → src-vue}/alert-dialog-vue/AlertDialog.vue +0 -0
  89. /package/dist/{vue → src-vue}/alert-dialog-vue/Basic.vue +0 -0
  90. /package/dist/{vue → src-vue}/alert-dialog-vue/Multilang.vue +0 -0
  91. /package/dist/{vue → src-vue}/alert-dialog-vue/index.ts +0 -0
  92. /package/dist/{vue → src-vue}/banner-box-vue/BannerBox.vue +0 -0
  93. /package/dist/{vue → src-vue}/banner-box-vue/DownloadButton.vue +0 -0
  94. /package/dist/{vue → src-vue}/banner-box-vue/ExampleBasic.vue +0 -0
  95. /package/dist/{vue → src-vue}/banner-box-vue/ExampleCustomBg.vue +0 -0
  96. /package/dist/{vue → src-vue}/banner-box-vue/ExampleDisplayModeAlways.vue +0 -0
  97. /package/dist/{vue → src-vue}/banner-box-vue/ExampleDisplayModeHover.vue +0 -0
  98. /package/dist/{vue → src-vue}/banner-box-vue/ExampleDisplayModeNever.vue +0 -0
  99. /package/dist/{vue → src-vue}/banner-box-vue/ExampleImageExport.vue +0 -0
  100. /package/dist/{vue → src-vue}/banner-box-vue/ExampleSizePreset.vue +0 -0
  101. /package/dist/{vue → src-vue}/banner-box-vue/FeatureCard.vue +0 -0
  102. /package/dist/{vue → src-vue}/banner-box-vue/SmartBanner.vue +0 -0
  103. /package/dist/{vue → src-vue}/banner-box-vue/bgStyles.ts +0 -0
  104. /package/dist/{vue → src-vue}/banner-box-vue/index.ts +0 -0
  105. /package/dist/{vue → src-vue}/banner-box-vue/sizePresets.ts +0 -0
  106. /package/dist/{vue → src-vue}/blog-vue/Basic.vue +0 -0
  107. /package/dist/{vue → src-vue}/blog-vue/BlogList.vue +0 -0
  108. /package/dist/{vue → src-vue}/blog-vue/Empty.vue +0 -0
  109. /package/dist/{vue → src-vue}/blog-vue/EmptyEnglish.vue +0 -0
  110. /package/dist/{vue → src-vue}/blog-vue/English.vue +0 -0
  111. /package/dist/{vue → src-vue}/blog-vue/index.ts +0 -0
  112. /package/dist/{vue/buttons-vue → src-vue/buttons}/ButtonBasic.vue +0 -0
  113. /package/dist/{vue/buttons-vue → src-vue/buttons}/ButtonFeature.vue +0 -0
  114. /package/dist/{vue/buttons-vue → src-vue/buttons}/ButtonFeatureBasic.vue +0 -0
  115. /package/dist/{vue/buttons-vue → src-vue/buttons}/ButtonFeatureWithTips.vue +0 -0
  116. /package/dist/{vue/buttons-vue → src-vue/buttons}/ButtonLink.vue +0 -0
  117. /package/dist/{vue/buttons-vue → src-vue/buttons}/ButtonSizes.vue +0 -0
  118. /package/dist/{vue/buttons-vue → src-vue/buttons}/ButtonVariants.vue +0 -0
  119. /package/dist/{vue/buttons-vue → src-vue/buttons}/ButtonWithIcons.vue +0 -0
  120. /package/dist/{vue/buttons-vue → src-vue/buttons}/index.ts +0 -0
  121. /package/dist/{vue → src-vue}/confirm-dialog-vue/Basic.vue +0 -0
  122. /package/dist/{vue → src-vue}/confirm-dialog-vue/ConfirmDialog.vue +0 -0
  123. /package/dist/{vue → src-vue}/confirm-dialog-vue/CustomButtons.vue +0 -0
  124. /package/dist/{vue → src-vue}/confirm-dialog-vue/index.ts +0 -0
  125. /package/dist/{vue → src-vue}/cosy.ts +0 -0
  126. /package/dist/{vue → src-vue}/counter-vue/VueCounter.vue +0 -0
  127. /package/dist/{vue → src-vue}/counter-vue/index.ts +0 -0
  128. /package/dist/{vue → src-vue}/iPhone-vue/Basic.vue +0 -0
  129. /package/dist/{vue → src-vue}/iPhone-vue/CustomBackground.vue +0 -0
  130. /package/dist/{vue → src-vue}/iPhone-vue/NoFrame.vue +0 -0
  131. /package/dist/{vue → src-vue}/iPhone-vue/WeatherApp.vue +0 -0
  132. /package/dist/{vue → src-vue}/iPhone-vue/assets/iPhone 14 Pro - Deep Purple - Landscape.png +0 -0
  133. /package/dist/{vue → src-vue}/iPhone-vue/assets/iPhone 14 Pro - Deep Purple - Portrait.png +0 -0
  134. /package/dist/{vue → src-vue}/iPhone-vue/assets/iPhone 14 Pro - Gold - Landscape.png +0 -0
  135. /package/dist/{vue → src-vue}/iPhone-vue/assets/iPhone 14 Pro - Gold - Portrait.png +0 -0
  136. /package/dist/{vue → src-vue}/iPhone-vue/assets/iPhone 14 Pro - Silver - Landscape.png +0 -0
  137. /package/dist/{vue → src-vue}/iPhone-vue/assets/iPhone 14 Pro - Silver - Portrait.png +0 -0
  138. /package/dist/{vue → src-vue}/iPhone-vue/assets/iPhone 14 Pro - Space Black - Landscape.png +0 -0
  139. /package/dist/{vue → src-vue}/iPhone-vue/assets/iPhone 14 Pro - Space Black - Portrait.png +0 -0
  140. /package/dist/{vue → src-vue}/iPhone-vue/iPhoneWindow.vue +0 -0
  141. /package/dist/{vue → src-vue}/iPhone-vue/index.ts +0 -0
  142. /package/dist/{vue/icons-vue → src-vue/icons}/AlertTriangleIcon.vue +0 -0
  143. /package/dist/{vue/icons-vue → src-vue/icons}/CalendarIcon.vue +0 -0
  144. /package/dist/{vue/icons-vue → src-vue/icons}/CheckCircleIcon.vue +0 -0
  145. /package/dist/{vue/icons-vue → src-vue/icons}/CheckIcon.vue +0 -0
  146. /package/dist/{vue/icons-vue → src-vue/icons}/ChevronDownIcon.vue +0 -0
  147. /package/dist/{vue/icons-vue → src-vue/icons}/ClipboardIcon.vue +0 -0
  148. /package/dist/{vue/icons-vue → src-vue/icons}/CloseIcon.vue +0 -0
  149. /package/dist/{vue/icons-vue → src-vue/icons}/InboxArchiveIcon.vue +0 -0
  150. /package/dist/{vue/icons-vue → src-vue/icons}/InfoCircleIcon.vue +0 -0
  151. /package/dist/{vue/icons-vue → src-vue/icons}/InfoIcon.vue +0 -0
  152. /package/dist/{vue/icons-vue → src-vue/icons}/LinkIcon.vue +0 -0
  153. /package/dist/{vue/icons-vue → src-vue/icons}/MenuIcon.vue +0 -0
  154. /package/dist/{vue/icons-vue → src-vue/icons}/SearchIcon.vue +0 -0
  155. /package/dist/{vue/icons-vue → src-vue/icons}/SettingsIcon.vue +0 -0
  156. /package/dist/{vue/icons-vue → src-vue/icons}/UserIcon.vue +0 -0
  157. /package/dist/{vue/icons-vue → src-vue/icons}/XCircleIcon.vue +0 -0
  158. /package/dist/{vue/icons-vue → src-vue/icons}/index.ts +0 -0
  159. /package/dist/{vue → src-vue}/list-vue/ListItem.vue +0 -0
  160. /package/dist/{vue → src-vue}/list-vue/index.ts +0 -0
  161. /package/dist/{vue → src-vue}/mac-window-vue/Basic.vue +0 -0
  162. /package/dist/{vue → src-vue}/mac-window-vue/CustomHeight.vue +0 -0
  163. /package/dist/{vue → src-vue}/mac-window-vue/MacWindow.vue +0 -0
  164. /package/dist/{vue → src-vue}/mac-window-vue/WithEvents.vue +0 -0
  165. /package/dist/{vue → src-vue}/mac-window-vue/WithSidebar.vue +0 -0
  166. /package/dist/{vue → src-vue}/mac-window-vue/WithTabs.vue +0 -0
  167. /package/dist/{vue → src-vue}/mac-window-vue/WithToolbar.vue +0 -0
  168. /package/dist/{vue → src-vue}/mac-window-vue/index.ts +0 -0
  169. /package/dist/{src-astro → src-vue}/utils/component.ts +0 -0
  170. /package/dist/{src-astro → src-vue}/utils/i18n.ts +0 -0
  171. /package/dist/{src-astro → src-vue}/utils/image.ts +0 -0
  172. /package/dist/{src-astro → src-vue}/utils/lang_entry.ts +0 -0
  173. /package/dist/{src-astro → src-vue}/utils/lang_package.ts +0 -0
  174. /package/dist/{src-astro → src-vue}/utils/language.ts +0 -0
  175. /package/dist/{src-astro → src-vue}/utils/logger.ts +0 -0
  176. /package/dist/{src-astro → src-vue}/utils/path.ts +0 -0
  177. /package/dist/{src-astro → src-vue}/utils/social.ts +0 -0
  178. /package/dist/{src-astro → src-vue}/utils/theme.ts +0 -0
  179. /package/dist/{src-astro → src-vue}/utils/url.ts +0 -0
@@ -24,12 +24,15 @@ export * from './src-astro/layout-basic';
24
24
  export * from './src-astro/layout-basic/BaseLayout.astro';
25
25
  export * from './src-astro/layout-dashboard';
26
26
  export * from './src-astro/link';
27
+ export * from './src-astro/login';
28
+ export * from './src-astro/logout';
27
29
  export * from './src-astro/main';
28
30
  export * from './src-astro/modal';
29
31
  export * from './src-astro/module';
30
32
  export * from './src-astro/nav-item';
31
33
  export * from './src-astro/nav-section';
32
34
  export * from './src-astro/products';
35
+ export * from './src-astro/register';
33
36
  export * from './src-astro/section';
34
37
  export * from './src-astro/sidebar';
35
38
  export * from './src-astro/sidebar-nav';
@@ -39,6 +42,8 @@ export * from './src-astro/team-member';
39
42
  export * from './src-astro/text';
40
43
  export * from './src-astro/theme-switcher';
41
44
  export * from './src-astro/toc';
45
+ export * from './src-astro/toast';
46
+ export * from './src-astro/confirm-dialog';
42
47
 
43
48
  // 类型定义 (按字母顺序)
44
49
  export * from './src-astro/types/article';
@@ -72,15 +77,18 @@ export * from './src-astro/database/LessonDB';
72
77
  export * from './src-astro/database/MetaDB';
73
78
 
74
79
  // 工具类型
75
- export type { ImageProvider, ImageOptions } from './src-astro/utils/image';
76
- export * from './src-astro/utils/image';
77
- export * from './src-astro/utils/i18n';
78
- export * from './src-astro/utils/path';
79
- export * from './src-astro/utils/url';
80
- export * from './src-astro/utils/language';
81
- export * from './src-astro/utils/lang_package';
82
- export * from './src-astro/utils/logger';
83
- export * from './src-astro/utils/link';
80
+ export type { ImageProvider, ImageOptions } from './src/utils/image';
81
+ export * from './src/utils/image';
82
+ export * from './src/utils/i18n';
83
+ export * from './src/utils/path';
84
+ export * from './src/utils/url';
85
+ export * from './src/utils/language';
86
+ export * from './src/utils/lang_package';
87
+ export * from './src/utils/logger';
88
+ export * from './src/utils/link';
84
89
 
85
90
  // 图标组件
86
- export * from './src-astro/icons';
91
+ export * from './src-astro/icons';
92
+
93
+ // 数据库
94
+ export * from './src-astro/database/index';
package/dist/index-vue.ts CHANGED
@@ -14,10 +14,10 @@ export * from './src-vue/counter-vue/index';
14
14
  export * from './src-vue/confirm-dialog-vue/index';
15
15
 
16
16
  // Buttons
17
- export * from './src-vue/buttons-vue/index';
17
+ export * from './src-vue/buttons/index';
18
18
 
19
19
  // Icons
20
- export * from './src-vue/icons-vue/index';
20
+ export * from './src-vue/icons/index';
21
21
 
22
22
  // List
23
23
  export * from './src-vue/list-vue/index';
@@ -1,6 +1,6 @@
1
1
  import { getRelativeLocaleUrl } from 'astro:i18n';
2
2
  import type { AstroGlobal } from 'astro';
3
- import { cosyLogger } from '../cosy';
3
+ import { cosyLogger } from '../../src-astro/cosy';
4
4
 
5
5
  // 默认语言
6
6
  export const DEFAULT_LANGUAGE = 'en';
@@ -0,0 +1,250 @@
1
+ import { cosyLogger } from '../../src-astro/cosy';
2
+
3
+ export class LinkUtil {
4
+ // 从 astro.config.ts 中获取基础路径
5
+ static getBaseUrl = (): string => {
6
+ return import.meta.env.BASE_URL;
7
+ };
8
+
9
+ // 生成带基础路径的完整 URL
10
+ static createUrl = (path: string): string => {
11
+ const baseUrl = LinkUtil.getBaseUrl();
12
+ // 如果路径以 '/' 开头,去除开头的 '/'
13
+ if (path.startsWith('/')) {
14
+ path = path.substring(1);
15
+ }
16
+
17
+ return `${baseUrl}${path}`;
18
+ };
19
+
20
+ /**
21
+ * 规范化语言代码
22
+ * @param lang - 语言代码
23
+ * @returns 规范化后的语言代码
24
+ */
25
+ static normalizeLanguage(lang: string): string {
26
+ const normalizedLang = lang.toLowerCase().replace('zh-CN', 'zh-cn');
27
+ if (normalizedLang.length == 0) {
28
+ console.error('lang is empty');
29
+ return 'en';
30
+ }
31
+ return normalizedLang;
32
+ }
33
+
34
+ static getHomeLink(lang: string): string {
35
+ return `${this.getBaseUrl}/${lang}`;
36
+ }
37
+
38
+ static getLessonsLink(lang: string): string {
39
+ return `/${lang}/lessons`;
40
+ }
41
+
42
+ static getExperimentsLink(lang: string): string {
43
+ return `/${lang}/experiments`;
44
+ }
45
+
46
+ static getExperimentLink(lang: string, experimentId: string): string {
47
+ if (experimentId.endsWith(lang)) {
48
+ return `/${lang}/experiments/${experimentId.replace(`${lang}`, '')}`;
49
+ } else {
50
+ const idWithoutLang = experimentId.replace(`${lang}/`, '');
51
+ return `/${lang}/experiments/${idWithoutLang}`;
52
+ }
53
+ }
54
+
55
+ static getCoursesLink(lang: string): string {
56
+ return `/${lang}/courses`;
57
+ }
58
+
59
+ static getBlogsLink(lang: string): string {
60
+ return `/${lang}/blogs`;
61
+ }
62
+
63
+ static getLessonLink(lang: string, lessonId: string): string {
64
+ if (lessonId.endsWith(lang)) {
65
+ return `${this.getBaseUrl()}${lang}/lessons/${lessonId.replace(`${lang}`, '')}`;
66
+ } else {
67
+ const idWithoutLang = lessonId.replace(`${lang}/`, '');
68
+ return `${this.getBaseUrl()}${lang}/lessons/${idWithoutLang}`;
69
+ }
70
+ }
71
+
72
+ static getTagLink(lang: string, tagName: string): string {
73
+ return `/${lang}/blogs/tag/${tagName}`;
74
+ }
75
+
76
+ static getBlogLink(blogId: string, lang: string): string {
77
+ const debug = false;
78
+ const blogIdWithoutLang = blogId.replace(`${lang}/`, '');
79
+
80
+ if (debug) {
81
+ cosyLogger.info(`获取博客文档链接,博客文档ID: ${blogId}`);
82
+ }
83
+
84
+ return `/${lang}/blogs/${blogIdWithoutLang}`;
85
+ }
86
+
87
+ static getCourseLink(courseId: string): string {
88
+ const debug = false;
89
+ const lang = courseId.split('/')[0];
90
+ const courseIdWithoutLang = courseId.replace(`${lang}/`, '');
91
+
92
+ if (debug) {
93
+ cosyLogger.info(`获取课程文档链接,课程文档ID: ${courseId}`);
94
+ }
95
+
96
+ return LinkUtil.createUrl(`/${lang}/courses/${courseIdWithoutLang}`);
97
+ }
98
+
99
+ static getMetaLink(lang: string, slug: string): string {
100
+ return `/${this.normalizeLanguage(lang)}/meta/${slug}`;
101
+ }
102
+
103
+ static getSigninLink(lang: string): string {
104
+ return `/${this.normalizeLanguage(lang)}/signin`;
105
+ }
106
+
107
+ static getAuthCallbackCookieLink(lang: string): string {
108
+ return `/${this.normalizeLanguage(lang)}/auth/callback_cookie`;
109
+ }
110
+
111
+ static getAuthCallbackTokenLink(lang: string): string {
112
+ return `/${this.normalizeLanguage(lang)}/auth/callback_token`;
113
+ }
114
+
115
+ static getAuthAccountLink(lang: string): string {
116
+ return `/${this.normalizeLanguage(lang)}/auth/account`;
117
+ }
118
+
119
+ static getDashboardUrl(lang: string): string {
120
+ return `/${this.normalizeLanguage(lang)}/auth/dashboard`;
121
+ }
122
+
123
+ static getAuthErrorLink(lang: string): string {
124
+ return `/${this.normalizeLanguage(lang)}/auth/error`;
125
+ }
126
+
127
+ static getPrivacyLink(lang: string): string {
128
+ return this.getMetaLink(lang, 'privacy');
129
+ }
130
+
131
+ static getTermsLink(lang: string): string {
132
+ return this.getMetaLink(lang, 'terms');
133
+ }
134
+
135
+ static getAboutLink(lang: string): string {
136
+ return this.getMetaLink(lang, 'about');
137
+ }
138
+
139
+ /**
140
+ * 根据ID生成链接
141
+ *
142
+ * 该函数根据文档ID生成对应的链接路径。
143
+ *
144
+ * @param {string} id - 文档ID, 例如 'courses/zh-cn/supervisor/index.md'
145
+ * @returns {string} 返回生成的链接路径
146
+ * @example
147
+ * // 例如:
148
+ * // id=courses/zh-cn/supervisor/index.md,则返回/zh-cn/courses/supervisor
149
+ * // id=courses/en/supervisor/index.md,则返回/en/courses/supervisor
150
+ */
151
+ static getLink(id: string): string {
152
+ const category = id.split('/')[0];
153
+ const lang = id.split('/')[1];
154
+ const path = id.split('/').slice(2).join('/');
155
+
156
+ const link = `/${lang}/${category}/${path}`;
157
+ return link.replace(/\/+/g, '/');
158
+ }
159
+
160
+ /**
161
+ * 根据分类生成顶级链接
162
+ *
163
+ * @param {string} category - 分类名称
164
+ * @param {string} lang - 语言代码,例如 'zh-cn', 'en'
165
+ * @returns {string} 返回生成的顶级链接路径
166
+ * @example
167
+ * // 例如:
168
+ * // category=courses, lang=zh-cn,则返回/zh-cn/courses
169
+ * // category=courses, lang=en,则返回/en/courses
170
+ */
171
+ static getTopLevelLink(category: string, lang: string): string {
172
+ return `/${lang}/${category}`;
173
+ }
174
+
175
+ /**
176
+ * 处理首页重定向
177
+ * @param locale - 语言代码
178
+ * @returns 规范化的语言代码
179
+ */
180
+ static homeRedirect(locale: string): string {
181
+ return locale || 'en';
182
+ }
183
+
184
+ /**
185
+ * 检查是否为首页路径
186
+ * @param pathname - 路径
187
+ * @returns 是否为首页
188
+ */
189
+ static isHomePath(pathname: string): boolean {
190
+ return pathname === '/' || pathname === '';
191
+ }
192
+
193
+ static isHomeLink(path: string, lang: string): boolean {
194
+ return path === `/${lang}` || path === `/${lang}/`;
195
+ }
196
+
197
+ static isLessonsLink(path: string, lang: string): boolean {
198
+ return (
199
+ path === `/${lang}/lessons` ||
200
+ path === `/${lang}/lessons/` ||
201
+ path.startsWith(`/${lang}/lessons/`)
202
+ );
203
+ }
204
+
205
+ static isExperimentsLink(path: string, lang: string): boolean {
206
+ return (
207
+ path === `/${lang}/experiments` ||
208
+ path === `/${lang}/experiments/` ||
209
+ path.startsWith(`/${lang}/experiments/`)
210
+ );
211
+ }
212
+
213
+ static isCoursesLink(path: string, lang: string): boolean {
214
+ return (
215
+ path === `/${lang}/courses` ||
216
+ path === `/${lang}/courses/` ||
217
+ path.startsWith(`/${lang}/courses/`)
218
+ );
219
+ }
220
+
221
+ static isBlogsLink(path: string, lang: string): boolean {
222
+ return (
223
+ path === `/${lang}/blogs` ||
224
+ path === `/${lang}/blogs/` ||
225
+ path.startsWith(`/${lang}/blogs/`)
226
+ );
227
+ }
228
+
229
+ static getOAuthSuccessLink(currentOrigin: string): string {
230
+ return `${currentOrigin}/api/callback_success`;
231
+ }
232
+
233
+ static getOAuthErrorLink(currentOrigin: string): string {
234
+ return `${currentOrigin}/api/callback_error`;
235
+ }
236
+
237
+ static getLoginLink(currentOrigin: string): string {
238
+ return `${currentOrigin}/api/login`;
239
+ }
240
+
241
+ static getActiveLink(currentLink: string, links: string[]): string {
242
+ let activeLink = '';
243
+ for (const link of links) {
244
+ if (currentLink.startsWith(link) && link.length > activeLink.length) {
245
+ activeLink = link;
246
+ }
247
+ }
248
+ return activeLink;
249
+ }
250
+ }
@@ -1,4 +1,4 @@
1
- import { cosyLogger } from '../cosy';
1
+ import { cosyLogger } from '../../src-astro/cosy';
2
2
 
3
3
  /**
4
4
  * 判断当前路径是否匹配目标路径
@@ -1,7 +1,7 @@
1
1
  import Article from './Article.astro';
2
2
  import ArticleBasic from './ArticleBasic.astro';
3
3
  import BasicSourceCode from './ArticleBasic.astro?raw';
4
- import { extractSimpleExample } from '../utils/component';
4
+ import { extractSimpleExample } from '../../src/utils/component';
5
5
 
6
6
  export { Article, ArticleBasic };
7
7
 
@@ -200,6 +200,11 @@ export const iconData: Record<string, IconData> = {
200
200
  path: 'M17 9V7a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2m2 4h10a2 2 0 002-2v-6a2 2 0 00-2-2H9a2 2 0 00-2 2v6a2 2 0 002 2zm7-5a2 2 0 11-4 0 2 2 0 014 0z',
201
201
  },
202
202
 
203
+ // 退出登录图标
204
+ logOut: {
205
+ path: 'M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4m7 14l5-5-5-5m5 5H9',
206
+ },
207
+
203
208
  // 报告图标
204
209
  report: {
205
210
  path: 'M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z',
@@ -21,7 +21,7 @@ import CustomStyleSourceCode from './BannerCustomStyle.astro?raw';
21
21
  import FadeInSourceCode from './BannerFadeIn.astro?raw';
22
22
  import SlideUpSourceCode from './BannerSlideUp.astro?raw';
23
23
  import AllAnimationsSourceCode from './BannerAllAnimations.astro?raw';
24
- import { extractSimpleExample } from '../utils/component';
24
+ import { extractSimpleExample } from '../../src/utils/component';
25
25
 
26
26
  export {
27
27
  Banner,
@@ -4,13 +4,12 @@
4
4
  *
5
5
  * @description
6
6
  * 用于展示代码示例的容器组件,提供样式隔离功能防止内外样式相互影响。
7
- * 支持两种隔离模式:样式重置模式和iframe完全隔离模式。
7
+ * 支持样式重置模式。
8
8
  * 使用时只需在默认slot中传入内容,并为每个示例设置对应的id (tab-1, tab-2等)
9
9
  *
10
10
  * @features
11
11
  * - 样式隔离:防止外部样式影响内部组件展示
12
12
  * - 样式重置:重置内部样式,避免样式冲突
13
- * - iframe模式:完全隔离的预览环境
14
13
  * - 代码预览切换:支持预览和代码视图切换
15
14
  * - 多标签页:支持多个示例的标签页展示
16
15
  *
@@ -26,13 +25,6 @@
26
25
  * </div>
27
26
  * </CodeContainer>
28
27
  *
29
- * <!-- 使用iframe完全隔离 -->
30
- * <CodeContainer codes={[code]} useIframe={true}>
31
- * <div id="tab-1">
32
- * <SomeComponent />
33
- * </div>
34
- * </CodeContainer>
35
- *
36
28
  * <!-- 禁用样式重置 -->
37
29
  * <CodeContainer codes={[code]} resetStyles={false}>
38
30
  * <div id="tab-1">
@@ -58,11 +50,6 @@ interface Props {
58
50
  * 每个示例对应的源代码
59
51
  */
60
52
  codes: string[];
61
- /**
62
- * 是否使用iframe隔离内容
63
- * @default false
64
- */
65
- useIframe?: boolean;
66
53
  /**
67
54
  * 是否重置内部样式
68
55
  * @default true
@@ -74,7 +61,6 @@ const {
74
61
  titles = [],
75
62
  descriptions = [],
76
63
  codes,
77
- useIframe = false,
78
64
  resetStyles = true,
79
65
  } = Astro.props;
80
66
  ---
@@ -132,22 +118,11 @@ const {
132
118
 
133
119
  <div class="cosy:relative cosy:p-4 cosy:bg-gradient-to-br cosy:from-red-100 cosy:to-green-300 cosy:rounded-b">
134
120
  <div class="cosy:block cosy:code-example-panel" data-panel="preview">
135
- {useIframe ? (
136
- <div class="cosy:w-full cosy:min-h-64 cosy:bg-white cosy:rounded cosy:border">
137
- <iframe
138
- class="cosy:w-full cosy:min-h-64 cosy:border-none cosy:rounded"
139
- data-preview-frame={`tab-${index + 1}`}
140
- sandbox="allow-scripts allow-same-origin"
141
- title={`示例预览 ${index + 1}`}
142
- />
143
- </div>
144
- ) : (
145
- <div
146
- class={`cosy:code-preview-area ${resetStyles ? 'cosy:reset-styles' : ''}`}
147
- data-preview-area={`tab-${index + 1}`}>
148
- <slot />
149
- </div>
150
- )}
121
+ <div
122
+ class={`cosy:code-preview-area ${resetStyles ? 'cosy:reset-styles' : ''}`}
123
+ data-preview-area={`tab-${index + 1}`}>
124
+ <slot />
125
+ </div>
151
126
  </div>
152
127
 
153
128
  <div class="cosy:hidden cosy:code-example-panel" data-panel="code">
@@ -228,13 +203,6 @@ const {
228
203
  margin-bottom: 0.25em;
229
204
  }
230
205
 
231
- /* iframe 隔离样式 */
232
- [data-role='code-container'] iframe[data-preview-frame] {
233
- background: white;
234
- border: 1px solid #e5e7eb;
235
- border-radius: 0.375rem;
236
- }
237
-
238
206
  /* 防止内部组件的样式泄漏到外部 */
239
207
  [data-role='code-container'] .cosy\:code-preview-area {
240
208
  position: relative;
@@ -255,62 +223,9 @@ const {
255
223
  </style>
256
224
 
257
225
  <script>
258
- function initializeIframePreviews() {
259
- const iframes = document.querySelectorAll('[data-preview-frame]');
260
-
261
- iframes.forEach((iframe) => {
262
- const container = iframe.closest('[data-role="code-container"]');
263
- if (!container) return;
264
-
265
- const frameId = iframe.getAttribute('data-preview-frame');
266
- const contentElement = container.querySelector(`#${frameId}`);
267
-
268
- if (contentElement) {
269
- // 创建独立的HTML文档内容
270
- const iframeElement = iframe as HTMLIFrameElement;
271
- const iframeDoc =
272
- iframeElement.contentDocument ||
273
- iframeElement.contentWindow?.document;
274
- if (iframeDoc) {
275
- const htmlContent = `
276
- <!DOCTYPE html>
277
- <html>
278
- <head>
279
- <meta charset="UTF-8">
280
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
281
- <title>示例预览</title>
282
- <style>
283
- /* 基础样式重置 */
284
- * { margin: 0; padding: 0; box-sizing: border-box; }
285
- body {
286
- font-family: system-ui, -apple-system, sans-serif;
287
- padding: 1rem;
288
- background: white;
289
- color: #374151;
290
- line-height: 1.5;
291
- }
292
- </style>
293
- </head>
294
- <body>
295
- ${contentElement.innerHTML}
296
- </body>
297
- </html>
298
- `;
299
-
300
- iframeDoc.open();
301
- iframeDoc.write(htmlContent);
302
- iframeDoc.close();
303
- }
304
- }
305
- });
306
- }
307
-
308
226
  function initializeCodeContainer() {
309
227
  console.log('CodeContainer: 初始化代码容器');
310
228
 
311
- // 初始化 iframe 预览
312
- initializeIframePreviews();
313
-
314
229
  // 示例切换功能
315
230
  const exampleTabs = document.querySelectorAll(
316
231
  '[role="tab"][data-tab^="tab-"]'
@@ -0,0 +1,119 @@
1
+ ---
2
+ /**
3
+ * @component ConfirmDialog
4
+ *
5
+ * @description
6
+ * ConfirmDialog 组件用于显示确认对话框,支持自定义标题、消息内容和按钮文本。
7
+ * 它会覆盖在页面内容上方,并提供一个聚焦的交互环境。
8
+ *
9
+ * @design
10
+ * 设计理念:
11
+ * 1. 聚焦交互 - 通过遮罩层和动画效果引导用户注意力
12
+ * 2. 灵活布局 - 支持标题、内容和操作按钮的自定义
13
+ * 3. 可访问性 - 支持键盘导航和屏幕阅读器
14
+ * 4. 响应式设计 - 在不同屏幕尺寸下保持良好的用户体验
15
+ *
16
+ * @usage
17
+ * 基本用法:
18
+ * ```astro
19
+ * <ConfirmDialog
20
+ * id="delete-confirm"
21
+ * title="确认删除"
22
+ * message="您确定要删除这个项目吗?此操作无法撤销。"
23
+ * />
24
+ *
25
+ * <!-- 触发按钮 -->
26
+ * <button data-confirm-dialog-target="delete-confirm">删除</button>
27
+ * ```
28
+ *
29
+ * 自定义按钮文本:
30
+ * ```astro
31
+ * <ConfirmDialog
32
+ * id="save-confirm"
33
+ * title="保存更改"
34
+ * message="您确定要保存这些更改吗?"
35
+ * confirmText="保存"
36
+ * cancelText="取消"
37
+ * />
38
+ * ```
39
+ */
40
+
41
+ import '../../style.ts';
42
+ import type { ConfirmDialogProps } from './types';
43
+ import { getConfirmDialogStyle } from './types';
44
+
45
+ const {
46
+ id,
47
+ title = '确认操作',
48
+ message,
49
+ cancelText = '取消',
50
+ confirmText = '确认',
51
+ class: className = '',
52
+ } = Astro.props as ConfirmDialogProps;
53
+
54
+ const style = getConfirmDialogStyle();
55
+ ---
56
+
57
+ <dialog id={id} class:list={['cosy:modal', 'cosy:modal-middle', className]}>
58
+ <div
59
+ class:list={[
60
+ 'cosy:modal-box',
61
+ 'cosy:p-6',
62
+ 'cosy:max-w-sm',
63
+ 'cosy:rounded-lg',
64
+ 'cosy:shadow-lg',
65
+ style.bg,
66
+ ]}>
67
+ {
68
+ title && (
69
+ <h3 class:list={['cosy:text-lg', 'cosy:font-medium', style.text]}>
70
+ {title}
71
+ </h3>
72
+ )
73
+ }
74
+ <p class:list={['cosy:py-4', style.text]}>{message}</p>
75
+
76
+ <div class:list={['cosy:modal-action', 'cosy:gap-2']}>
77
+ <form method="dialog" class="cosy:flex cosy:gap-2">
78
+ <button class:list={[style.cancelBtn]}>{cancelText}</button>
79
+ <button
80
+ class:list={[style.confirmBtn]}
81
+ onclick={`window.handleConfirmDialog?.('${id}')`}
82
+ type="submit">{confirmText}</button
83
+ >
84
+ </form>
85
+ </div>
86
+ </div>
87
+
88
+ <form method="dialog" class="cosy:modal-backdrop">
89
+ <button>关闭</button>
90
+ </form>
91
+ </dialog>
92
+
93
+ <script is:inline define:vars={{ id }}>
94
+ // 为了方便使用,我们提供一些辅助方法
95
+ document.addEventListener('DOMContentLoaded', () => {
96
+ const dialog = document.getElementById(id);
97
+ if (!dialog) return;
98
+
99
+ // 为所有触发这个确认框的按钮添加点击事件
100
+ document
101
+ .querySelectorAll(`[data-confirm-dialog-target="${id}"]`)
102
+ .forEach((trigger) => {
103
+ trigger.addEventListener('click', () => {
104
+ dialog.showModal();
105
+ });
106
+ });
107
+
108
+ // 全局处理确认事件的方法
109
+ if (!window.handleConfirmDialog) {
110
+ window.handleConfirmDialog = (dialogId) => {
111
+ // 触发自定义事件
112
+ const event = new CustomEvent('confirm-dialog-confirm', {
113
+ detail: { dialogId },
114
+ });
115
+ document.dispatchEvent(event);
116
+ };
117
+ }
118
+ });
119
+ </script>
@@ -0,0 +1,2 @@
1
+ export { default as ConfirmDialog } from './ConfirmDialog.astro';
2
+ export type { ConfirmDialogProps } from './types';
@@ -0,0 +1,47 @@
1
+ export interface ConfirmDialogProps {
2
+ /**
3
+ * 对话框的唯一标识符
4
+ */
5
+ id: string;
6
+
7
+ /**
8
+ * 对话框标题
9
+ */
10
+ title?: string;
11
+
12
+ /**
13
+ * 对话框消息内容
14
+ */
15
+ message: string;
16
+
17
+ /**
18
+ * 取消按钮文本
19
+ */
20
+ cancelText?: string;
21
+
22
+ /**
23
+ * 确认按钮文本
24
+ */
25
+ confirmText?: string;
26
+
27
+ /**
28
+ * 自定义类名
29
+ */
30
+ class?: string;
31
+ }
32
+
33
+ export interface ConfirmDialogStyle {
34
+ bg: string;
35
+ border: string;
36
+ text: string;
37
+ confirmBtn: string;
38
+ cancelBtn: string;
39
+ }
40
+
41
+ export const getConfirmDialogStyle = (): ConfirmDialogStyle => ({
42
+ bg: 'cosy:bg-base-100',
43
+ border: 'cosy:border-base-300',
44
+ text: 'cosy:text-base-content',
45
+ confirmBtn: 'cosy:btn cosy:btn-primary',
46
+ cancelBtn: 'cosy:btn cosy:btn-ghost',
47
+ });