@coffic/cosy-ui 0.8.20 → 0.8.22

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 (45) hide show
  1. package/dist/app.css +1 -1
  2. package/dist/src/assets/iconData.ts +10 -0
  3. package/dist/src/utils/i18n.ts +52 -50
  4. package/dist/src-astro/banner/Banner.astro +55 -3
  5. package/dist/src-astro/banner/index.ts +1 -52
  6. package/dist/src-astro/button/Button.astro +41 -2
  7. package/dist/src-astro/code-container/ButtonCodeToggle.astro +55 -0
  8. package/dist/src-astro/code-container/ButtonCopyCode.astro +74 -0
  9. package/dist/src-astro/code-container/CodeContainer.astro +14 -289
  10. package/dist/src-astro/code-container/CodePanel.astro +14 -0
  11. package/dist/src-astro/code-container/CodeToolbar.astro +100 -0
  12. package/dist/src-astro/code-container/Description.astro +17 -0
  13. package/dist/src-astro/code-container/Preview.astro +93 -0
  14. package/dist/src-astro/footer/Footer.astro +52 -20
  15. package/dist/src-astro/footer/FooterSection.astro +7 -9
  16. package/dist/src-astro/grid/index.ts +1 -9
  17. package/dist/src-astro/heading/index.ts +1 -9
  18. package/dist/src-astro/hero/Hero.astro +78 -9
  19. package/dist/src-astro/icons/AppStoreIcon.astro +37 -0
  20. package/dist/src-astro/icons/AstroIcon.astro +8 -1
  21. package/dist/src-astro/icons/CodeIcon.astro +22 -0
  22. package/dist/src-astro/icons/WebsiteIcon.astro +31 -0
  23. package/dist/src-astro/icons/index.ts +4 -2
  24. package/dist/src-astro/language-switcher/LanguageSwitcher.astro +6 -2
  25. package/dist/src-astro/link/Link.astro +50 -3
  26. package/dist/src-astro/nav-item/index.ts +1 -9
  27. package/dist/src-astro/products/ProductCard.astro +68 -32
  28. package/dist/src-astro/types/footer.ts +130 -125
  29. package/dist/src-vue/iPhone/iPhoneWindow.vue +2 -6
  30. package/dist/src-vue/utils/i18n.ts +52 -50
  31. package/package.json +1 -1
  32. package/dist/src-astro/banner/BannerAllAnimations.astro +0 -10
  33. package/dist/src-astro/banner/BannerBasic.astro +0 -5
  34. package/dist/src-astro/banner/BannerCustomStyle.astro +0 -8
  35. package/dist/src-astro/banner/BannerDanger.astro +0 -5
  36. package/dist/src-astro/banner/BannerFadeIn.astro +0 -5
  37. package/dist/src-astro/banner/BannerInfo.astro +0 -5
  38. package/dist/src-astro/banner/BannerPrimary.astro +0 -5
  39. package/dist/src-astro/banner/BannerSecondary.astro +0 -5
  40. package/dist/src-astro/banner/BannerSlideUp.astro +0 -5
  41. package/dist/src-astro/banner/BannerSuccess.astro +0 -5
  42. package/dist/src-astro/banner/BannerWarning.astro +0 -5
  43. package/dist/src-astro/grid/GridBasic.astro +0 -21
  44. package/dist/src-astro/heading/HeadingBasic.astro +0 -10
  45. package/dist/src-astro/nav-item/NavItemsBasic.astro +0 -30
@@ -34,7 +34,10 @@
34
34
  * ```
35
35
  */
36
36
 
37
- import { ClipboardIcon, CheckIcon, InfoIcon } from '../../index-astro';
37
+ import CodeToolbar from './CodeToolbar.astro';
38
+ import Description from './Description.astro';
39
+ import Preview from './Preview.astro';
40
+ import CodePanel from './CodePanel.astro';
38
41
  import '../../style.ts';
39
42
 
40
43
  interface Props {
@@ -66,318 +69,40 @@ const {
66
69
  ---
67
70
 
68
71
  <div data-role="code-container" class="cosy:mb-8 cosy:card" ignore-heading>
69
- <!-- 工具栏 -->
70
- <div
71
- class="cosy:flex cosy:justify-between cosy:items-center cosy:bg-base-200 cosy:px-4 cosy:rounded-t">
72
- <!-- 标签 -->
73
- <div class="cosy:flex cosy:items-center cosy:gap-4">
74
- <div role="tablist" class="cosy:tabs cosy:tabs-box">
75
- {
76
- codes.map((_, index) => (
77
- <button
78
- role="tab"
79
- class={`cosy:tab ${index === 0 ? 'cosy:tab-active' : ''}`}
80
- data-tab={`tab-${index + 1}`}>
81
- {titles[index] || `示例 ${index + 1}`}
82
- </button>
83
- ))
84
- }
85
- </div>
86
- </div>
87
-
88
- <!-- 工具按钮 -->
89
- <div class="cosy:flex cosy:items-center cosy:gap-2">
90
- <button
91
- role="switch"
92
- class="cosy:btn cosy:btn-ghost cosy:btn-sm"
93
- aria-checked="false"
94
- aria-label="切换代码/预览"
95
- data-toggle="code">
96
- <span class="cosy:code-icon"><InfoIcon /></span>
97
- </button>
98
- <button
99
- class="cosy:gap-2 cosy:btn cosy:btn-ghost cosy:btn-sm"
100
- aria-label="复制代码">
101
- <span class="cosy:copy-icon"><ClipboardIcon /></span>
102
- <span class="cosy:hidden cosy:check-icon"><CheckIcon /></span>
103
- </button>
104
- </div>
105
- </div>
72
+ <CodeToolbar
73
+ titles={titles.length ? titles : codes.map((_, i) => `示例 ${i + 1}`)}
74
+ activeTab={0}
75
+ isCodeView={false}
76
+ code={codes[0]}
77
+ />
106
78
 
107
79
  {
108
80
  codes.map((code, index) => (
109
81
  <div
110
82
  class={`cosy:example-container ${index === 0 ? 'cosy:block' : 'cosy:hidden'}`}
111
83
  data-example={`tab-${index + 1}`}>
112
- {/* 描述 */}
113
- {descriptions[index] && (
114
- <p
115
- class="cosy:px-6 cosy:py-2 cosy:text-sm not-prose
116
- cosy:bg-gradient-to-b cosy:from-blue-100/50 cosy:to-blue-100/90
117
- cosy:dark:from-blue-900/20 cosy:dark:to-blue-900/20">
118
- {descriptions[index]}
119
- </p>
120
- )}
84
+ <Description text={descriptions[index]} />
121
85
 
122
86
  <div class="cosy:relative cosy:p-4 cosy:bg-gradient-to-br cosy:from-red-100 cosy:to-green-300 cosy:dark:from-red-900/20 cosy:dark:to-green-900/20 cosy:rounded-b">
123
- <div class="cosy:block cosy:code-example-panel" data-panel="preview">
87
+ <Preview>
124
88
  <div
125
89
  class={`cosy:code-preview-area ${resetStyles ? 'cosy:reset-styles' : ''}`}
126
90
  data-preview-area={`tab-${index + 1}`}>
127
91
  <slot />
128
92
  </div>
129
- </div>
93
+ </Preview>
130
94
 
131
- <div class="cosy:hidden cosy:code-example-panel" data-panel="code">
132
- <pre class="cosy:overflow-x-auto" style="margin:0">
133
- <code class="cosy:language-astro">{code}</code>
134
- </pre>
135
- </div>
95
+ <CodePanel code={code} />
136
96
  </div>
137
97
  </div>
138
98
  ))
139
99
  }
140
100
  </div>
141
101
 
142
- <!-- 样式隔离和重置 -->
143
- <style>
144
- /* 预览区域样式重置,防止外部样式影响内部组件 */
145
- [data-role='code-container'] .cosy\:reset-styles {
146
- /* 重置所有可能影响布局的样式 */
147
- all: initial;
148
- font-family: inherit;
149
- color: inherit;
150
- line-height: 1.5;
151
-
152
- /* 恢复必要的基础样式 */
153
- display: block;
154
- box-sizing: border-box;
155
-
156
- /* 隔离样式作用域 */
157
- isolation: isolate;
158
- contain: layout style;
159
- }
160
-
161
- /* 重置内部所有元素的样式 */
162
- [data-role='code-container'] .cosy\:reset-styles * {
163
- all: unset;
164
- display: revert;
165
- box-sizing: border-box;
166
- }
167
-
168
- /* 恢复必要的文本样式 */
169
- [data-role='code-container'] .cosy\:reset-styles {
170
- font-family:
171
- system-ui,
172
- -apple-system,
173
- BlinkMacSystemFont,
174
- 'Segoe UI',
175
- Roboto,
176
- 'Helvetica Neue',
177
- Arial,
178
- sans-serif;
179
- font-size: 14px;
180
- line-height: 1.5;
181
- color: #374151;
182
- }
183
-
184
- /* 恢复基本的HTML元素样式 */
185
- [data-role='code-container'] .cosy\:reset-styles h1,
186
- [data-role='code-container'] .cosy\:reset-styles h2,
187
- [data-role='code-container'] .cosy\:reset-styles h3,
188
- [data-role='code-container'] .cosy\:reset-styles h4,
189
- [data-role='code-container'] .cosy\:reset-styles h5,
190
- [data-role='code-container'] .cosy\:reset-styles h6 {
191
- font-weight: bold;
192
- margin-bottom: 0.5em;
193
- }
194
-
195
- [data-role='code-container'] .cosy\:reset-styles p {
196
- margin-bottom: 1em;
197
- }
198
-
199
- [data-role='code-container'] .cosy\:reset-styles ul,
200
- [data-role='code-container'] .cosy\:reset-styles ol {
201
- padding-left: 1.5em;
202
- margin-bottom: 1em;
203
- }
204
-
205
- [data-role='code-container'] .cosy\:reset-styles li {
206
- margin-bottom: 0.25em;
207
- }
208
-
209
- /* 防止内部组件的样式泄漏到外部 */
210
- [data-role='code-container'] .cosy\:code-preview-area {
211
- position: relative;
212
- z-index: 0;
213
- }
214
-
215
- /* 确保预览区域的样式隔离 */
216
- [data-role='code-container'] .cosy\:code-preview-area::before {
217
- content: '';
218
- position: absolute;
219
- top: -1px;
220
- left: -1px;
221
- right: -1px;
222
- bottom: -1px;
223
- pointer-events: none;
224
- z-index: -1;
225
- }
226
- </style>
227
-
228
102
  <script>
229
103
  function initializeCodeContainer() {
230
104
  console.log('CodeContainer: 初始化代码容器');
231
105
 
232
- // 示例切换功能
233
- const exampleTabs = document.querySelectorAll(
234
- '[role="tab"][data-tab^="tab-"]'
235
- );
236
- exampleTabs.forEach((tab) => {
237
- tab.addEventListener('click', () => {
238
- console.log('CodeContainer: 切换示例', tab.getAttribute('data-tab'));
239
- const container = tab.closest('[data-role="code-container"]');
240
- if (!container) return;
241
-
242
- // 更新标签状态
243
- container
244
- .querySelectorAll('[role="tab"][data-tab^="tab-"]')
245
- .forEach((t) => {
246
- t.classList.remove('cosy:tab-active');
247
- });
248
- tab.classList.add('cosy:tab-active');
249
-
250
- // 获取当前标签对应的内容 id
251
- const targetId = tab.getAttribute('data-tab');
252
- if (!targetId) return;
253
-
254
- // 切换示例容器
255
- container
256
- .querySelectorAll('.cosy\\:example-container')
257
- .forEach((example) => {
258
- if (example.getAttribute('data-example') === targetId) {
259
- example.classList.remove('cosy:hidden');
260
- example.classList.add('cosy:block');
261
- } else {
262
- example.classList.add('cosy:hidden');
263
- example.classList.remove('cosy:block');
264
- }
265
- });
266
-
267
- // 更新对应内容的可见性
268
- const allContent = container.querySelectorAll('[id^="tab-"]');
269
- allContent.forEach((content) => {
270
- if (content.id === targetId) {
271
- content.classList.remove('cosy:hidden');
272
- content.classList.add('cosy:block');
273
- } else {
274
- content.classList.add('cosy:hidden');
275
- content.classList.remove('cosy:block');
276
- }
277
- });
278
- });
279
- });
280
-
281
- // 代码开关功能
282
- const codeToggles = document.querySelectorAll('[data-toggle="code"]');
283
- codeToggles.forEach((toggle) => {
284
- toggle.addEventListener('click', () => {
285
- console.log('code toggle clicked', toggle);
286
- const container = toggle.closest('[data-role="code-container"]');
287
- if (!container) {
288
- console.error('CodeContainer: 无法找到父容器');
289
- return;
290
- }
291
-
292
- // 切换开关状态
293
- const isChecked = toggle.getAttribute('aria-checked') === 'true';
294
- console.log('代码按钮 isChecked:', isChecked);
295
- toggle.setAttribute('aria-checked', !isChecked ? 'true' : 'false');
296
- toggle.classList.toggle('cosy:btn-primary', !isChecked);
297
- toggle.classList.toggle('cosy:btn-ghost', isChecked);
298
-
299
- // 找到当前显示的示例
300
- const activeExample = container.querySelector(
301
- '.cosy\\:example-container:not(.cosy\\:hidden)'
302
- );
303
- if (!activeExample) {
304
- console.error('CodeContainer: 无法找到活动示例');
305
- return;
306
- }
307
-
308
- // 切换面板
309
- activeExample
310
- .querySelectorAll('.cosy\\:code-example-panel')
311
- .forEach((panel) => {
312
- if (panel.getAttribute('data-panel') === 'code') {
313
- console.log(
314
- '处理代码面板的展示/隐藏,此时的isChecked:',
315
- isChecked
316
- );
317
- panel.classList.toggle('cosy:hidden', isChecked);
318
- panel.classList.toggle('cosy:block', !isChecked);
319
- } else {
320
- console.log(
321
- '处理预览面板的展示/隐藏,此时的isChecked:',
322
- isChecked
323
- );
324
- panel.classList.toggle('cosy:hidden', !isChecked);
325
- panel.classList.toggle('cosy:block', isChecked);
326
- }
327
- });
328
- });
329
- });
330
-
331
- // 复制代码功能
332
- const copyButtons = document.querySelectorAll('[aria-label="复制代码"]');
333
- copyButtons.forEach((button) => {
334
- button.addEventListener('click', () => {
335
- const container = button.closest('[data-role="code-container"]');
336
- if (!container) return;
337
-
338
- // 确保代码面板是显示的
339
- const codeToggle = container.querySelector('[data-toggle="code"]');
340
- if (codeToggle?.getAttribute('aria-checked') !== 'true') {
341
- (codeToggle as HTMLElement)?.click();
342
- }
343
-
344
- // 找到当前显示的示例
345
- const activeExample = container.querySelector(
346
- '.cosy\\:example-container:not(.cosy\\:hidden)'
347
- );
348
- if (!activeExample) return;
349
-
350
- const codePanel = activeExample.querySelector('[data-panel="code"]');
351
- if (!codePanel) return;
352
-
353
- const codeElement = codePanel.querySelector('code');
354
- if (!codeElement) return;
355
-
356
- const code = codeElement.textContent || '';
357
-
358
- // 复制到剪贴板
359
- navigator.clipboard.writeText(code).then(() => {
360
- button.classList.add('cosy:btn-success');
361
- button
362
- .querySelector('.cosy\\:copy-icon')
363
- ?.classList.add('cosy:hidden');
364
- button
365
- .querySelector('.cosy\\:check-icon')
366
- ?.classList.remove('cosy:hidden');
367
-
368
- setTimeout(() => {
369
- button.classList.remove('cosy:btn-success');
370
- button
371
- .querySelector('.cosy\\:copy-icon')
372
- ?.classList.remove('cosy:hidden');
373
- button
374
- .querySelector('.cosy\\:check-icon')
375
- ?.classList.add('cosy:hidden');
376
- }, 3000);
377
- });
378
- });
379
- });
380
-
381
106
  // 初始化时隐藏除第一个以外的所有内容
382
107
  document
383
108
  .querySelectorAll('[data-role="code-container"]')
@@ -0,0 +1,14 @@
1
+ ---
2
+ interface Props {
3
+ code: string;
4
+ }
5
+ const { code = '' } = Astro.props;
6
+ ---
7
+
8
+ <div class="cosy:hidden cosy:code-example-panel" data-panel="code">
9
+ <pre
10
+ class="cosy:overflow-x-auto"
11
+ style="margin:0">
12
+ <code class="cosy:language-astro">{code}</code>
13
+ </pre>
14
+ </div>
@@ -0,0 +1,100 @@
1
+ ---
2
+ import CodeToggleButton from './ButtonCodeToggle.astro';
3
+ import CopyCodeButton from './ButtonCopyCode.astro';
4
+
5
+ interface Props {
6
+ titles: string[];
7
+ activeTab: number;
8
+ isCodeView: boolean;
9
+ code: string;
10
+ }
11
+
12
+ const {
13
+ titles = [],
14
+ activeTab = 0,
15
+ isCodeView = false,
16
+ code = '',
17
+ } = Astro.props;
18
+ ---
19
+
20
+ <div
21
+ class="cosy:flex cosy:justify-between cosy:items-center cosy:bg-base-200 cosy:px-4 cosy:rounded-t">
22
+ <!-- 标签 -->
23
+ <div class="cosy:flex cosy:items-center cosy:gap-4">
24
+ <div role="tablist" class="cosy:tabs cosy:tabs-box">
25
+ {
26
+ titles.map((title: string, index: number) => (
27
+ <button
28
+ role="tab"
29
+ class={`cosy:tab ${index === activeTab ? 'cosy:tab-active' : ''}`}
30
+ data-tab={`tab-${index + 1}`}>
31
+ {title || `示例 ${index + 1}`}
32
+ </button>
33
+ ))
34
+ }
35
+ </div>
36
+ </div>
37
+ <!-- 工具按钮 -->
38
+ <div class="cosy:flex cosy:items-center cosy:gap-2">
39
+ <CodeToggleButton isCodeView={isCodeView} />
40
+ <CopyCodeButton code={code} />
41
+ </div>
42
+ </div>
43
+
44
+ <script>
45
+ function initializeTab() {
46
+ console.log('CodeContainer: 初始化标签切换按钮');
47
+
48
+ const exampleTabs = document.querySelectorAll(
49
+ '[role="tab"][data-tab^="tab-"]'
50
+ );
51
+ exampleTabs.forEach((tab) => {
52
+ tab.addEventListener('click', () => {
53
+ console.log('CodeContainer: 切换示例', tab.getAttribute('data-tab'));
54
+ const container = tab.closest('[data-role="code-container"]');
55
+ if (!container) return;
56
+
57
+ // 更新标签状态
58
+ container
59
+ .querySelectorAll('[role="tab"][data-tab^="tab-"]')
60
+ .forEach((t) => {
61
+ t.classList.remove('cosy:tab-active');
62
+ });
63
+ tab.classList.add('cosy:tab-active');
64
+
65
+ // 获取当前标签对应的内容 id
66
+ const targetId = tab.getAttribute('data-tab');
67
+ if (!targetId) return;
68
+
69
+ // 切换示例容器
70
+ container
71
+ .querySelectorAll('.cosy\\:example-container')
72
+ .forEach((example) => {
73
+ if (example.getAttribute('data-example') === targetId) {
74
+ example.classList.remove('cosy:hidden');
75
+ example.classList.add('cosy:block');
76
+ } else {
77
+ example.classList.add('cosy:hidden');
78
+ example.classList.remove('cosy:block');
79
+ }
80
+ });
81
+
82
+ // 更新对应内容的可见性
83
+ const allContent = container.querySelectorAll('[id^="tab-"]');
84
+ allContent.forEach((content) => {
85
+ if (content.id === targetId) {
86
+ content.classList.remove('cosy:hidden');
87
+ content.classList.add('cosy:block');
88
+ } else {
89
+ content.classList.add('cosy:hidden');
90
+ content.classList.remove('cosy:block');
91
+ }
92
+ });
93
+ });
94
+ });
95
+ }
96
+
97
+ document.addEventListener('astro:page-load', () => {
98
+ initializeTab();
99
+ });
100
+ </script>
@@ -0,0 +1,17 @@
1
+ ---
2
+ interface Props {
3
+ text: string;
4
+ }
5
+ const { text = '' } = Astro.props;
6
+ ---
7
+
8
+ {
9
+ text && (
10
+ <p
11
+ class="cosy:px-6 cosy:py-2 cosy:text-sm not-prose
12
+ cosy:bg-gradient-to-b cosy:from-blue-100/50 cosy:to-blue-100/90
13
+ cosy:dark:from-blue-900/20 cosy:dark:to-blue-900/20">
14
+ {text}
15
+ </p>
16
+ )
17
+ }
@@ -0,0 +1,93 @@
1
+ ---
2
+ // 预览组件,渲染slot内容
3
+ ---
4
+
5
+ <div class="cosy:code-example-panel cosy:block" data-panel="preview">
6
+ <slot />
7
+ </div>
8
+
9
+ <!-- 样式隔离和重置 -->
10
+ <style>
11
+ /* 预览区域样式重置,防止外部样式影响内部组件 */
12
+ [data-role='code-container'] .cosy\:reset-styles {
13
+ /* 重置所有可能影响布局的样式 */
14
+ all: initial;
15
+ font-family: inherit;
16
+ color: inherit;
17
+ line-height: 1.5;
18
+
19
+ /* 恢复必要的基础样式 */
20
+ display: block;
21
+ box-sizing: border-box;
22
+
23
+ /* 隔离样式作用域 */
24
+ isolation: isolate;
25
+ contain: layout style;
26
+ }
27
+
28
+ /* 重置内部所有元素的样式 */
29
+ [data-role='code-container'] .cosy\:reset-styles * {
30
+ all: unset;
31
+ display: revert;
32
+ box-sizing: border-box;
33
+ }
34
+
35
+ /* 恢复必要的文本样式 */
36
+ [data-role='code-container'] .cosy\:reset-styles {
37
+ font-family:
38
+ system-ui,
39
+ -apple-system,
40
+ BlinkMacSystemFont,
41
+ 'Segoe UI',
42
+ Roboto,
43
+ 'Helvetica Neue',
44
+ Arial,
45
+ sans-serif;
46
+ font-size: 14px;
47
+ line-height: 1.5;
48
+ color: #374151;
49
+ }
50
+
51
+ /* 恢复基本的HTML元素样式 */
52
+ [data-role='code-container'] .cosy\:reset-styles h1,
53
+ [data-role='code-container'] .cosy\:reset-styles h2,
54
+ [data-role='code-container'] .cosy\:reset-styles h3,
55
+ [data-role='code-container'] .cosy\:reset-styles h4,
56
+ [data-role='code-container'] .cosy\:reset-styles h5,
57
+ [data-role='code-container'] .cosy\:reset-styles h6 {
58
+ font-weight: bold;
59
+ margin-bottom: 0.5em;
60
+ }
61
+
62
+ [data-role='code-container'] .cosy\:reset-styles p {
63
+ margin-bottom: 1em;
64
+ }
65
+
66
+ [data-role='code-container'] .cosy\:reset-styles ul,
67
+ [data-role='code-container'] .cosy\:reset-styles ol {
68
+ padding-left: 1.5em;
69
+ margin-bottom: 1em;
70
+ }
71
+
72
+ [data-role='code-container'] .cosy\:reset-styles li {
73
+ margin-bottom: 0.25em;
74
+ }
75
+
76
+ /* 防止内部组件的样式泄漏到外部 */
77
+ [data-role='code-container'] .cosy\:code-preview-area {
78
+ position: relative;
79
+ z-index: 0;
80
+ }
81
+
82
+ /* 确保预览区域的样式隔离 */
83
+ [data-role='code-container'] .cosy\:code-preview-area::before {
84
+ content: '';
85
+ position: absolute;
86
+ top: -1px;
87
+ left: -1px;
88
+ right: -1px;
89
+ bottom: -1px;
90
+ pointer-events: none;
91
+ z-index: -1;
92
+ }
93
+ </style>