@coffic/cosy-ui 0.8.21 → 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 (35) hide show
  1. package/dist/app.css +1 -1
  2. package/dist/src/assets/iconData.ts +5 -1
  3. package/dist/src-astro/banner/Banner.astro +55 -3
  4. package/dist/src-astro/banner/index.ts +1 -52
  5. package/dist/src-astro/button/Button.astro +40 -1
  6. package/dist/src-astro/code-container/ButtonCodeToggle.astro +55 -0
  7. package/dist/src-astro/code-container/ButtonCopyCode.astro +74 -0
  8. package/dist/src-astro/code-container/CodeContainer.astro +14 -289
  9. package/dist/src-astro/code-container/CodePanel.astro +14 -0
  10. package/dist/src-astro/code-container/CodeToolbar.astro +100 -0
  11. package/dist/src-astro/code-container/Description.astro +17 -0
  12. package/dist/src-astro/code-container/Preview.astro +93 -0
  13. package/dist/src-astro/footer/Footer.astro +23 -20
  14. package/dist/src-astro/footer/FooterSection.astro +7 -9
  15. package/dist/src-astro/grid/index.ts +1 -9
  16. package/dist/src-astro/heading/index.ts +1 -9
  17. package/dist/src-astro/hero/Hero.astro +72 -8
  18. package/dist/src-astro/icons/CodeIcon.astro +22 -0
  19. package/dist/src-astro/icons/index.ts +2 -1
  20. package/dist/src-astro/language-switcher/LanguageSwitcher.astro +6 -2
  21. package/dist/src-astro/link/Link.astro +50 -3
  22. package/package.json +1 -1
  23. package/dist/src-astro/banner/BannerAllAnimations.astro +0 -10
  24. package/dist/src-astro/banner/BannerBasic.astro +0 -5
  25. package/dist/src-astro/banner/BannerCustomStyle.astro +0 -8
  26. package/dist/src-astro/banner/BannerDanger.astro +0 -5
  27. package/dist/src-astro/banner/BannerFadeIn.astro +0 -5
  28. package/dist/src-astro/banner/BannerInfo.astro +0 -5
  29. package/dist/src-astro/banner/BannerPrimary.astro +0 -5
  30. package/dist/src-astro/banner/BannerSecondary.astro +0 -5
  31. package/dist/src-astro/banner/BannerSlideUp.astro +0 -5
  32. package/dist/src-astro/banner/BannerSuccess.astro +0 -5
  33. package/dist/src-astro/banner/BannerWarning.astro +0 -5
  34. package/dist/src-astro/grid/GridBasic.astro +0 -21
  35. package/dist/src-astro/heading/HeadingBasic.astro +0 -10
@@ -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>
@@ -172,6 +172,7 @@ import {
172
172
  LanguageUtil,
173
173
  type IFooterProps,
174
174
  createTextGetter,
175
+ Link,
175
176
  } from '../../index-astro';
176
177
  import FooterSection from './FooterSection.astro';
177
178
  import '../../style.ts';
@@ -242,9 +243,7 @@ const debugClasses = debug
242
243
  ]}>
243
244
  {/* 品牌区域 */}
244
245
  <aside class:list={['cosy:max-w-xs cosy:text-center', debugClasses.aside]}>
245
- <a
246
- href={homeLink}
247
- class="cosy:flex cosy:items-center cosy:gap-2 cosy:mb-4 cosy:no-underline">
246
+ <Link href={homeLink} align="center" noUnderline block class="cosy:mb-4">
248
247
  {
249
248
  logo && (
250
249
  <img
@@ -260,21 +259,25 @@ const debugClasses = debug
260
259
  <h2 class="cosy:font-bold cosy:text-xl">{siteName}</h2>
261
260
  <p class="cosy:text-base-content/70">{slogan}</p>
262
261
  </div>
263
- </a>
262
+ </Link>
264
263
 
265
264
  {/* 社交媒体链接 */}
266
265
  {
267
266
  processedSocialLinks.length > 0 && (
268
267
  <div class="cosy:flex cosy:justify-center cosy:gap-2 cosy:mt-4">
269
268
  {processedSocialLinks.map((link) => (
270
- <a
269
+ <Link
271
270
  href={link.url}
272
- class="cosy:btn cosy:btn-circle cosy:btn-ghost cosy:btn-sm"
273
- target="_blank"
271
+ btn
272
+ circle
273
+ ghost
274
+ size="sm"
275
+ color="primary"
276
+ external
274
277
  rel="noopener noreferrer"
275
278
  aria-label={link.name}>
276
279
  <SocialIcon platform={link.platform} />
277
- </a>
280
+ </Link>
278
281
  ))}
279
282
  </div>
280
283
  )
@@ -307,10 +310,10 @@ const debugClasses = debug
307
310
  <FooterSection
308
311
  title={t('about')}
309
312
  links={[
310
- { name: t('aboutUs'), href: aboutLink },
311
- { name: t('team'), href: teamLink },
312
- { name: t('careers'), href: careersLink },
313
- { name: t('contactUs'), href: contactLink },
313
+ { name: t('aboutUs'), href: aboutLink ?? '' },
314
+ { name: t('team'), href: teamLink ?? '' },
315
+ { name: t('careers'), href: careersLink ?? '' },
316
+ { name: t('contactUs'), href: contactLink ?? '' },
314
317
  ].filter((link) => link.href)}
315
318
  />
316
319
  )
@@ -328,11 +331,11 @@ const debugClasses = debug
328
331
  <FooterSection
329
332
  title={t('resources')}
330
333
  links={[
331
- { name: t('news'), href: newsLink },
332
- { name: t('blog'), href: blogLink },
333
- { name: t('faq'), href: faqLink },
334
- { name: t('history'), href: historyLink },
335
- { name: t('techStack'), href: techStackLink },
334
+ { name: t('news'), href: newsLink ?? '' },
335
+ { name: t('blog'), href: blogLink ?? '' },
336
+ { name: t('faq'), href: faqLink ?? '' },
337
+ { name: t('history'), href: historyLink ?? '' },
338
+ { name: t('techStack'), href: techStackLink ?? '' },
336
339
  ].filter((link) => link.href)}
337
340
  />
338
341
  )
@@ -344,8 +347,8 @@ const debugClasses = debug
344
347
  <FooterSection
345
348
  title={t('legal')}
346
349
  links={[
347
- { name: t('terms'), href: termsLink },
348
- { name: t('privacy'), href: privacyLink },
350
+ { name: t('terms'), href: termsLink ?? '' },
351
+ { name: t('privacy'), href: privacyLink ?? '' },
349
352
  ].filter((link) => link.href)}
350
353
  />
351
354
  )
@@ -366,7 +369,7 @@ const debugClasses = debug
366
369
  {/* 底部版权信息 */}
367
370
  <div
368
371
  class:list={[
369
- 'cosy:footer cosy:footer-center cosy:p-4 cosy:bg-base-300 cosy:text-base-content',
372
+ 'cosy:footer cosy:footer-center cosy:p-4 cosy:bg-base-300',
370
373
  debugClasses.footer,
371
374
  ]}>
372
375
  <aside
@@ -6,10 +6,7 @@
6
6
  * FooterSection 组件用于在页脚中显示一组链接,通常用于导航、产品列表等。
7
7
  */
8
8
 
9
- interface Link {
10
- name: string;
11
- href?: string;
12
- }
9
+ import { Link, type IProduct } from '../../index-astro';
13
10
 
14
11
  interface Props {
15
12
  /**
@@ -20,7 +17,7 @@ interface Props {
20
17
  /**
21
18
  * 链接列表
22
19
  */
23
- links: Link[];
20
+ links: IProduct[];
24
21
  }
25
22
 
26
23
  const { title, links } = Astro.props;
@@ -33,12 +30,13 @@ const { title, links } = Astro.props;
33
30
  links.map((link) => (
34
31
  <li class="cosy:list-none">
35
32
  {link.href ? (
36
- <a
33
+ <Link
37
34
  href={link.href}
38
- class="cosy:link cosy:link-hover cosy:no-underline cosy:hover:no-underline"
39
- >
35
+ size="sm"
36
+ target={link.external ? '_blank' : '_self'}
37
+ variant="text">
40
38
  {link.name}
41
- </a>
39
+ </Link>
42
40
  ) : (
43
41
  <span class="cosy:opacity-50">{link.name}</span>
44
42
  )}
@@ -1,11 +1,3 @@
1
1
  import Grid from './Grid.astro';
2
- import GridBasic from './GridBasic.astro';
3
- import BasicSourceCode from './GridBasic.astro?raw';
4
- import { extractSimpleExample } from '../../src/utils/component';
5
2
 
6
- export { Grid, GridBasic };
7
-
8
- // 导出示例源代码
9
- export const GridExampleCodes = {
10
- Basic: extractSimpleExample(BasicSourceCode, 'Grid'),
11
- };
3
+ export { Grid };
@@ -1,11 +1,3 @@
1
1
  import Heading from './Heading.astro';
2
- import HeadingBasic from './HeadingBasic.astro';
3
- import BasicSourceCode from './HeadingBasic.astro?raw';
4
- import { extractSimpleExample } from '../../src/utils/component';
5
2
 
6
- export { Heading, HeadingBasic };
7
-
8
- // 导出示例源代码
9
- export const HeadingExampleCodes = {
10
- Basic: extractSimpleExample(BasicSourceCode, 'Heading'),
11
- };
3
+ export { Heading };
@@ -143,7 +143,7 @@
143
143
  * @prop {string} links[].text - 链接按钮的文本
144
144
  * @prop {string} links[].href - 链接按钮的目标地址
145
145
  * @prop {string} links[].variant - 链接按钮的变体,可选值:"primary", "secondary", "accent", "info", "success", "warning", "error"
146
- * @prop {string} [background="gradient"] - 背景样式,可选值:"gradient", "plain"
146
+ * @prop {string} [background="gradient"] - 背景样式,可选值:"gradient", "plain", "gradient-primary", "gradient-secondary", "gradient-accent", "gradient-success", "gradient-warning", "gradient-info", "gradient-sky", "gradient-sunset", "gradient-forest", "gradient-ocean", "gradient-mountain", "gradient-flower", "gradient-watermelon", "gradient-lemon", "gradient-grape", "gradient-blueberry", "gradient-mango", "gradient-kiwi", "gradient-pitaya", "gradient-banana"
147
147
  * @prop {string} [align="center"] - 内容对齐方式,可选值:"center", "left", "right"
148
148
  * @prop {string} [imagePosition="right"] - 图片位置,可选值:"right", "left", "top", "bottom"
149
149
  * @prop {string} [backgroundImage] - 背景图片的URL
@@ -176,7 +176,29 @@ interface Props {
176
176
  alt: string;
177
177
  };
178
178
  links: Link[];
179
- background?: 'gradient' | 'plain';
179
+ background?:
180
+ | 'gradient'
181
+ | 'plain'
182
+ | 'gradient-primary'
183
+ | 'gradient-secondary'
184
+ | 'gradient-accent'
185
+ | 'gradient-success'
186
+ | 'gradient-warning'
187
+ | 'gradient-info'
188
+ | 'gradient-sky'
189
+ | 'gradient-sunset'
190
+ | 'gradient-forest'
191
+ | 'gradient-ocean'
192
+ | 'gradient-mountain'
193
+ | 'gradient-flower'
194
+ | 'gradient-watermelon'
195
+ | 'gradient-lemon'
196
+ | 'gradient-grape'
197
+ | 'gradient-blueberry'
198
+ | 'gradient-mango'
199
+ | 'gradient-kiwi'
200
+ | 'gradient-pitaya'
201
+ | 'gradient-banana';
180
202
  align?: 'center' | 'left' | 'right';
181
203
  imagePosition?: 'right' | 'left' | 'top' | 'bottom';
182
204
  backgroundImage?: string;
@@ -200,6 +222,49 @@ const {
200
222
  // 确保不透明度在0-1之间
201
223
  const safeOpacity = Math.max(0, Math.min(1, overlayOpacity));
202
224
 
225
+ // 渐变色背景映射
226
+ const gradientBgClassMap = {
227
+ gradient: 'cosy:bg-gradient-to-br cosy:from-primary/10 cosy:to-secondary/20',
228
+ 'gradient-primary':
229
+ 'cosy:bg-gradient-to-br cosy:from-primary-400 cosy:to-primary-700',
230
+ 'gradient-secondary':
231
+ 'cosy:bg-gradient-to-br cosy:from-secondary-400 cosy:to-secondary-700',
232
+ 'gradient-accent':
233
+ 'cosy:bg-gradient-to-br cosy:from-accent-400 cosy:to-accent-700',
234
+ 'gradient-success':
235
+ 'cosy:bg-gradient-to-br cosy:from-success-400 cosy:to-success-700',
236
+ 'gradient-warning':
237
+ 'cosy:bg-gradient-to-br cosy:from-warning-400 cosy:to-warning-700',
238
+ 'gradient-info': 'cosy:bg-gradient-to-br cosy:from-info-400 cosy:to-info-700',
239
+ 'gradient-sky': 'cosy:bg-gradient-to-br cosy:from-sky-400 cosy:to-indigo-500',
240
+ 'gradient-sunset':
241
+ 'cosy:bg-gradient-to-br cosy:from-orange-400 cosy:via-pink-500 cosy:to-red-500',
242
+ 'gradient-forest':
243
+ 'cosy:bg-gradient-to-br cosy:from-green-700 cosy:to-lime-300',
244
+ 'gradient-ocean':
245
+ 'cosy:bg-gradient-to-br cosy:from-cyan-400 cosy:to-blue-700',
246
+ 'gradient-mountain':
247
+ 'cosy:bg-gradient-to-br cosy:from-gray-400 cosy:to-blue-900',
248
+ 'gradient-flower':
249
+ 'cosy:bg-gradient-to-br cosy:from-pink-300 cosy:via-purple-400 cosy:to-fuchsia-500',
250
+ 'gradient-watermelon':
251
+ 'cosy:bg-gradient-to-br cosy:from-green-300 cosy:via-pink-400 cosy:to-red-500',
252
+ 'gradient-lemon':
253
+ 'cosy:bg-gradient-to-br cosy:from-yellow-200 cosy:via-yellow-400 cosy:to-yellow-600',
254
+ 'gradient-grape':
255
+ 'cosy:bg-gradient-to-br cosy:from-purple-400 cosy:via-indigo-500 cosy:to-purple-700',
256
+ 'gradient-blueberry':
257
+ 'cosy:bg-gradient-to-br cosy:from-blue-400 cosy:via-blue-600 cosy:to-indigo-700',
258
+ 'gradient-mango':
259
+ 'cosy:bg-gradient-to-br cosy:from-yellow-300 cosy:via-orange-400 cosy:to-orange-600',
260
+ 'gradient-kiwi':
261
+ 'cosy:bg-gradient-to-br cosy:from-lime-200 cosy:via-green-400 cosy:to-green-700',
262
+ 'gradient-pitaya':
263
+ 'cosy:bg-gradient-to-br cosy:from-pink-200 cosy:via-fuchsia-400 cosy:to-lime-300',
264
+ 'gradient-banana':
265
+ 'cosy:bg-gradient-to-br cosy:from-yellow-100 cosy:via-yellow-300 cosy:to-yellow-500',
266
+ };
267
+
203
268
  // 确定容器类
204
269
  const containerClasses = [
205
270
  'cosy:hero',
@@ -207,8 +272,9 @@ const containerClasses = [
207
272
  'cosy:w-full',
208
273
  'cosy:relative',
209
274
  backgroundImage ? 'cosy:bg-cover cosy:bg-center' : '',
210
- !backgroundImage && background === 'gradient'
211
- ? 'cosy:bg-gradient-to-br cosy:from-primary/10 cosy:to-secondary/20'
275
+ !backgroundImage && background.startsWith('gradient')
276
+ ? gradientBgClassMap[background as keyof typeof gradientBgClassMap] ||
277
+ gradientBgClassMap['gradient']
212
278
  : '',
213
279
  !backgroundImage && background === 'plain' ? 'cosy:bg-base-100' : '',
214
280
  ].join(' ');
@@ -330,7 +396,7 @@ const contentOrder = {
330
396
 
331
397
  <div
332
398
  class={containerClasses}
333
- style={backgroundImage ? `background-image: url(${backgroundImage})` : ''}
399
+ style={backgroundImage ? `background-image: url(${backgroundImage})` : {}}
334
400
  ignore-heading>
335
401
  {
336
402
  backgroundImage && backgroundOverlay !== 'none' && (
@@ -354,9 +420,7 @@ const contentOrder = {
354
420
  (align === 'left' ? 'cosy:text-left cosy:items-start' : '') +
355
421
  (align === 'right' ? 'cosy:text-right cosy:items-end' : '')}>
356
422
  <h2 class={titleClasses}>{title}</h2>
357
- <p class={descriptionClasses}>
358
- {description}
359
- </p>
423
+ <p class={descriptionClasses}>{description}</p>
360
424
 
361
425
  {
362
426
  Astro.slots.has('app') && (
@@ -0,0 +1,22 @@
1
+ ---
2
+ // @component CodeIcon
3
+ // @description 代码相关的图标,用于表示代码块、开发等场景
4
+ import AstroIcon from './AstroIcon.astro';
5
+
6
+ interface Props {
7
+ /** 图标的大小 @default "24px" */
8
+ size?: string;
9
+ /** 图标的颜色 @default "currentColor" */
10
+ color?: string;
11
+ /** 自定义类名 */
12
+ class?: string;
13
+ }
14
+
15
+ const {
16
+ size = '24px',
17
+ color = 'currentColor',
18
+ class: className = '',
19
+ } = Astro.props;
20
+ ---
21
+
22
+ <AstroIcon name="code" size={size} stroke={color} class={className} />
@@ -17,6 +17,8 @@ export { default as CheckCircle } from './CheckCircle.astro';
17
17
  export { default as CheckIcon } from './CheckIcon.astro';
18
18
  export { default as ClipboardIcon } from './ClipboardIcon.astro';
19
19
  export { default as CloseIcon } from './CloseIcon.astro';
20
+ export { default as CodeIcon } from './CodeIcon.astro';
21
+ export { default as DeleteIcon } from './DeleteIcon.astro';
20
22
  export { default as ErrorIcon } from './ErrorIcon.astro';
21
23
  export { default as GithubIcon } from './GithubIcon.astro';
22
24
  export { default as InfoCircle } from './InfoCircle.astro';
@@ -36,7 +38,6 @@ export { default as StarIcon } from './StarIcon.astro';
36
38
  export { default as HeartIcon } from './HeartIcon.astro';
37
39
  export { default as SaveIcon } from './SaveIcon.astro';
38
40
  export { default as EditIcon } from './EditIcon.astro';
39
- export { default as DeleteIcon } from './DeleteIcon.astro';
40
41
  export { default as ToolsIcon } from './ToolsIcon.astro';
41
42
  export { default as WalletIcon } from './WalletIcon.astro';
42
43
  export { default as ReportIcon } from './ReportIcon.astro';
@@ -32,16 +32,20 @@ import '../../style.ts';
32
32
 
33
33
  interface Props {
34
34
  languages: string[];
35
+ /**
36
+ * 自定义类名
37
+ */
38
+ class?: string;
35
39
  }
36
40
 
37
- const { languages = ['zh-cn', 'en'] } = Astro.props;
41
+ const { languages = ['zh-cn', 'en'], class: className = '' } = Astro.props;
38
42
 
39
43
  const currentLocale = Astro.currentLocale;
40
44
  const currentLanguageName = LanguageUtil.getLanguageName(currentLocale);
41
45
  ---
42
46
 
43
47
  <!-- 语言切换按钮 -->
44
- <div class="cosy:dropdown cosy:dropdown-end">
48
+ <div class={`cosy:dropdown cosy:dropdown-end ${className}`}>
45
49
  <div tabindex="0" role="button" class:list={['cosy:btn cosy:btn-ghost']}>
46
50
  <span class="cosy:mr-1">{currentLanguageName}</span>
47
51
  <ChevronDownIcon size="16px" class="cosy:w-4 cosy:h-4" />
@@ -85,6 +85,21 @@ interface Props extends HTMLAttributes<'a'> {
85
85
  size?: LinkSize;
86
86
  debug?: boolean;
87
87
  centerText?: boolean;
88
+ btn?: boolean;
89
+ circle?: boolean;
90
+ ghost?: boolean;
91
+ noUnderline?: boolean;
92
+ rounded?: boolean;
93
+ fullWidth?: boolean;
94
+ color?:
95
+ | 'primary'
96
+ | 'secondary'
97
+ | 'accent'
98
+ | 'info'
99
+ | 'success'
100
+ | 'warning'
101
+ | 'error';
102
+ align?: 'left' | 'center' | 'right';
88
103
  }
89
104
 
90
105
  const {
@@ -98,13 +113,21 @@ const {
98
113
  'class:list': classList,
99
114
  debug = false,
100
115
  centerText = false,
116
+ btn = false,
117
+ circle = false,
118
+ ghost = false,
119
+ noUnderline = true,
120
+ rounded = false,
121
+ fullWidth = false,
122
+ color,
123
+ align,
101
124
  ...rest
102
125
  } = Astro.props;
103
126
 
104
127
  // 构建类名
105
128
  const classes = [
106
129
  // 基础链接样式
107
- 'cosy:items-center cosy:cursor-pointer cosy:no-underline cosy:transition-all cosy:duration-200',
130
+ 'cosy:items-center cosy:cursor-pointer cosy:transition-all cosy:duration-200',
108
131
 
109
132
  // 显示方式
110
133
  block ? 'cosy:flex cosy:w-full' : 'cosy:inline-flex',
@@ -113,7 +136,7 @@ const classes = [
113
136
  variant === 'primary' && 'cosy:text-primary cosy:hover:text-primary-focus',
114
137
  variant === 'secondary' &&
115
138
  'cosy:text-secondary cosy:hover:text-secondary-focus',
116
- variant === 'text' && 'cosy:text-neutral cosy:hover:text-neutral-focus',
139
+ variant === 'text',
117
140
  variant === 'cta' &&
118
141
  'cosy:text-accent cosy:hover:text-accent-focus cosy:font-medium',
119
142
  variant === 'ghost' &&
@@ -136,11 +159,35 @@ const classes = [
136
159
  animation === 'hover-scale' &&
137
160
  'cosy:hover:scale-105 cosy:transition-transform',
138
161
 
162
+ // 新增:按钮风格
163
+ btn && 'cosy:btn',
164
+ btn && size === 'sm' && 'cosy:btn-sm',
165
+ btn && size === 'lg' && 'cosy:btn-lg',
166
+ btn && ghost && 'cosy:btn-ghost',
167
+ btn && color && `cosy:btn-${color}`,
168
+ btn && fullWidth && 'cosy:btn-block',
169
+ btn && circle && 'cosy:btn-circle',
170
+ btn && rounded && 'cosy:rounded-full',
171
+
172
+ // 非按钮风格下的圆角
173
+ !btn && rounded && 'cosy:rounded',
174
+
175
+ // 非按钮风格下的无下划线
176
+ !btn && noUnderline && 'cosy:no-underline cosy:hover:no-underline',
177
+
178
+ // 宽度100%
179
+ fullWidth && !btn && 'cosy:w-full',
180
+
181
+ // 对齐
182
+ align === 'center' && 'cosy:justify-center cosy:text-center',
183
+ align === 'right' && 'cosy:justify-end cosy:text-right',
184
+ align === 'left' && 'cosy:justify-start cosy:text-left',
185
+
139
186
  // 自定义类名
140
187
  className,
141
188
  ];
142
189
 
143
- // 文本居中样式
190
+ // 文本居中样式(兼容旧用法)
144
191
  if (centerText) {
145
192
  classes.push('cosy:justify-center cosy:text-center');
146
193
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffic/cosy-ui",
3
- "version": "0.8.21",
3
+ "version": "0.8.22",
4
4
  "description": "An astro component library",
5
5
  "author": {
6
6
  "name": "nookery",
@@ -1,10 +0,0 @@
1
- ---
2
- import { Banner } from '../../index-astro';
3
- ---
4
-
5
- <div class="flex flex-col gap-4">
6
- <Banner animation="none">这是一个没有动画的横幅</Banner>
7
- <Banner animation="fade">这是一个只有淡入动画的横幅</Banner>
8
- <Banner animation="slide">这是一个只有上滑动画的横幅</Banner>
9
- <Banner animation="both">这是一个同时有淡入和上滑动画的横幅</Banner>
10
- </div>