@coffic/cosy-ui 0.9.40 → 0.9.41

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 (30) hide show
  1. package/dist/app.css +1 -1
  2. package/dist/index-astro.ts +18 -13
  3. package/dist/src-astro/avatar/Avatar.astro +118 -0
  4. package/dist/src-astro/avatar/index.ts +2 -0
  5. package/dist/src-astro/avatar/types.ts +29 -0
  6. package/dist/src-astro/contact/Contact.astro +155 -172
  7. package/dist/src-astro/container/Container.astro +16 -0
  8. package/dist/src-astro/features/FeatureCard.astro +63 -0
  9. package/dist/src-astro/features/FeatureShowcase.astro +164 -0
  10. package/dist/src-astro/features/index.ts +3 -0
  11. package/dist/src-astro/heading/Heading.astro +56 -8
  12. package/dist/src-astro/icons/AppStoreIcon.astro +1 -1
  13. package/dist/src-astro/mac-window/MacWindow.astro +9 -4
  14. package/dist/src-astro/products/ProductShowcase.astro +159 -0
  15. package/dist/src-astro/products/ProductShowcaseItem.astro +216 -0
  16. package/dist/src-astro/products/index.ts +4 -0
  17. package/dist/src-astro/review/Review.astro +159 -0
  18. package/dist/src-astro/review/Reviews.astro +162 -0
  19. package/dist/src-astro/review/index.ts +3 -0
  20. package/dist/src-astro/review/types.ts +127 -0
  21. package/dist/src-astro/stats-display/StatsDisplay.astro +201 -0
  22. package/dist/src-astro/stats-display/index.ts +10 -0
  23. package/dist/src-astro/stats-display/types.ts +79 -0
  24. package/dist/src-astro/text/Text.astro +4 -1
  25. package/dist/src-vue/container/Container.vue +64 -62
  26. package/dist/src-vue/container/types.ts +3 -3
  27. package/dist/src-vue/heading/Heading.vue +64 -10
  28. package/dist/src-vue/heading/types.ts +9 -0
  29. package/dist/src-vue/mac-window/MacWindow.vue +164 -212
  30. package/package.json +1 -1
@@ -0,0 +1,201 @@
1
+ ---
2
+ /**
3
+ * @component StatsDisplay
4
+ *
5
+ * @description
6
+ * StatsDisplay 组件用于展示统计数据,采用极简设计风格。
7
+ * 适合在首页、关于我们页面或产品介绍页面中展示关键数据指标。
8
+ * 支持多种布局模式和自定义样式。
9
+ *
10
+ * StatsDisplay component for showcasing statistical data with minimalist design.
11
+ * Perfect for displaying key metrics on homepages, about pages, or product introduction pages.
12
+ * Supports multiple layout modes and custom styling options.
13
+ *
14
+ * @design
15
+ * 设计理念 / Design Principles:
16
+ * 1. 极简美学 - 大数字、细字重、简洁布局 / Minimalist Aesthetics - Large numbers, thin font weights, clean layouts
17
+ * 2. 视觉层次 - 通过字体大小和颜色建立清晰层次 / Visual Hierarchy - Clear hierarchy through font sizes and colors
18
+ * 3. 响应式设计 - 自适应不同屏幕尺寸 / Responsive Design - Adapts to different screen sizes
19
+ * 4. 可定制性 - 支持多种样式和布局选项 / Customizability - Multiple styling and layout options
20
+ *
21
+ * @usage
22
+ * 基本用法 / Basic Usage:
23
+ * ```astro
24
+ * <StatsDisplay
25
+ * stats={[
26
+ * { value: "10+", label: "年经验" },
27
+ * { value: "500+", label: "客户" },
28
+ * { value: "1000+", label: "项目" }
29
+ * ]}
30
+ * />
31
+ * ```
32
+ *
33
+ * 自定义样式 / Custom Styling:
34
+ * ```astro
35
+ * <StatsDisplay
36
+ * stats={[
37
+ * { value: "10M+", label: "用户", color: "blue" },
38
+ * { value: "20+", label: "奖项", color: "success" }
39
+ * ]}
40
+ * valueSize="4xl"
41
+ * valueColor="primary"
42
+ * labelColor="gray"
43
+ * />
44
+ * ```
45
+ *
46
+ * 预设颜色使用 / Using Preset Colors:
47
+ * ```astro
48
+ * <StatsDisplay
49
+ * stats={[
50
+ * { value: "99%", label: "满意度", color: "success" },
51
+ * { value: "24/7", label: "支持", color: "info" }
52
+ * ]}
53
+ * valueColor="primary"
54
+ * labelColor="secondary"
55
+ * />
56
+ * ```
57
+ *
58
+ * 紧凑模式 / Compact Mode:
59
+ * ```astro
60
+ * <StatsDisplay
61
+ * stats={stats}
62
+ * compact
63
+ * columns={2}
64
+ * />
65
+ * ```
66
+ *
67
+ * @props
68
+ * @param {Array<{value: string, label: string, color?: string|PresetColor}>} stats - 统计数据数组 / Statistical data array
69
+ * @param {string} [class] - 自定义CSS类 / Custom CSS class
70
+ * @param {boolean} [compact] - 是否使用紧凑模式 / Whether to use compact mode
71
+ * @param {number} [columns] - 列数(响应式)/ Number of columns (responsive)
72
+ * @param {string} [valueSize] - 数值字体大小 / Font size for values
73
+ * @param {string|PresetColor} [valueColor] - 数值颜色(支持预设颜色)/ Color for values (supports preset colors)
74
+ * @param {string|PresetColor} [labelColor] - 标签颜色(支持预设颜色)/ Color for labels (supports preset colors)
75
+ * @param {string} [valueWeight] - 数值字重 / Font weight for values
76
+ * @param {string} [labelWeight] - 标签字重 / Font weight for labels
77
+ * @param {string} [gap] - 项目间距 / Spacing between items
78
+ * @param {string} [align] - 对齐方式 / Alignment option
79
+ *
80
+ * @presetColors
81
+ * 预设颜色选项 / Preset color options:
82
+ * - primary: 主色调 (#3b82f6)
83
+ * - secondary: 次要色调 (#6b7280)
84
+ * - success: 成功色 (#10b981)
85
+ * - warning: 警告色 (#f59e0b)
86
+ * - error: 错误色 (#ef4444)
87
+ * - info: 信息色 (#06b6d4)
88
+ * - blue: 蓝色 (#3b82f6)
89
+ * - green: 绿色 (#10b981)
90
+ * - yellow: 黄色 (#f59e0b)
91
+ * - red: 红色 (#ef4444)
92
+ * - purple: 紫色 (#8b5cf6)
93
+ * - pink: 粉色 (#ec4899)
94
+ * - indigo: 靛蓝 (#6366f1)
95
+ * - gray: 灰色 (#6b7280)
96
+ */
97
+
98
+ import '../../style.ts';
99
+ import Text from '../text/Text.astro';
100
+ import type { PresetColor, StatItem } from './types';
101
+
102
+ // 预设颜色映射 / Preset color mapping
103
+ const PRESET_COLORS: Record<PresetColor, string> = {
104
+ primary: '#3b82f6',
105
+ secondary: '#6b7280',
106
+ success: '#10b981',
107
+ warning: '#f59e0b',
108
+ error: '#ef4444',
109
+ info: '#06b6d4',
110
+ blue: '#3b82f6',
111
+ green: '#10b981',
112
+ yellow: '#f59e0b',
113
+ red: '#ef4444',
114
+ purple: '#8b5cf6',
115
+ pink: '#ec4899',
116
+ indigo: '#6366f1',
117
+ gray: '#6b7280',
118
+ };
119
+
120
+ // 颜色解析函数 / Color resolution function
121
+ const resolveColor = (
122
+ color: string | PresetColor | undefined,
123
+ defaultColor: string
124
+ ): string => {
125
+ if (!color) return defaultColor;
126
+ return PRESET_COLORS[color as PresetColor] || color;
127
+ };
128
+
129
+ const {
130
+ stats = [],
131
+ class: className = '',
132
+ compact = false,
133
+ columns = 4,
134
+ valueSize = '3xl',
135
+ valueColor = 'primary',
136
+ labelColor = 'gray',
137
+ valueWeight = 'thin',
138
+ labelWeight = 'light',
139
+ gap = 'lg',
140
+ align = 'center',
141
+ } = Astro.props;
142
+
143
+ // 构建容器样式类
144
+ const containerClasses = [
145
+ 'cosy:grid',
146
+ `cosy:grid-cols-${columns}`,
147
+ `cosy:gap-${gap}`,
148
+ `cosy:text-${align}`,
149
+ compact ? 'cosy:gap-md' : '',
150
+ className,
151
+ ]
152
+ .filter(Boolean)
153
+ .join(' ');
154
+
155
+ // 构建数值样式
156
+ const getValueStyle = (item: StatItem) => {
157
+ return [
158
+ `cosy:text-${valueSize}`,
159
+ `cosy:font-${valueWeight}`,
160
+ 'cosy:mb-2',
161
+ 'cosy:leading-none',
162
+ ].join(' ');
163
+ };
164
+
165
+ // 构建标签样式
166
+ const getLabelStyle = () =>
167
+ [`cosy:text-${labelWeight}`, 'cosy:leading-relaxed'].join(' ');
168
+
169
+ // 获取数值颜色样式
170
+ const getValueColorStyle = (item: StatItem): string => {
171
+ const customColor = item.color
172
+ ? resolveColor(item.color, '#3b82f6')
173
+ : resolveColor(valueColor, '#3b82f6');
174
+ return `color: ${customColor};`;
175
+ };
176
+
177
+ // 获取标签颜色样式
178
+ const getLabelColorStyle = (item: StatItem): string => {
179
+ // 如果单个项目有自定义颜色,优先使用项目颜色
180
+ // 否则使用全局 labelColor 设置
181
+ const customColor = item.color
182
+ ? resolveColor(item.color, '#6b7280')
183
+ : resolveColor(labelColor, '#6b7280');
184
+ return `color: ${customColor};`;
185
+ };
186
+ ---
187
+
188
+ <div class={containerClasses}>
189
+ {
190
+ stats.map((stat: StatItem) => (
191
+ <div class="cosy:flex cosy:flex-col cosy:items-center">
192
+ <div class={getValueStyle(stat)} style={getValueColorStyle(stat)}>
193
+ {stat.value}
194
+ </div>
195
+ <Text class={getLabelStyle()} style={getLabelColorStyle(stat)}>
196
+ {stat.label}
197
+ </Text>
198
+ </div>
199
+ ))
200
+ }
201
+ </div>
@@ -0,0 +1,10 @@
1
+ export { default as StatsDisplay } from './StatsDisplay.astro';
2
+ export type {
3
+ StatsDisplayProps,
4
+ StatItem,
5
+ PresetColor,
6
+ FontSize,
7
+ FontWeight,
8
+ Spacing,
9
+ Alignment
10
+ } from './types';
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @fileoverview StatsDisplay 组件类型定义
3
+ * Type definitions for StatsDisplay component
4
+ */
5
+
6
+ /** 预设颜色类型 / Preset color types */
7
+ export type PresetColor =
8
+ | 'primary'
9
+ | 'secondary'
10
+ | 'success'
11
+ | 'warning'
12
+ | 'error'
13
+ | 'info'
14
+ | 'blue'
15
+ | 'green'
16
+ | 'yellow'
17
+ | 'red'
18
+ | 'purple'
19
+ | 'pink'
20
+ | 'indigo'
21
+ | 'gray';
22
+
23
+ /** 字体大小类型 / Font size types */
24
+ export type FontSize =
25
+ | 'xs'
26
+ | 'sm'
27
+ | 'base'
28
+ | 'lg'
29
+ | 'xl'
30
+ | '2xl'
31
+ | '3xl'
32
+ | '4xl'
33
+ | '5xl'
34
+ | '6xl';
35
+
36
+ /** 字重类型 / Font weight types */
37
+ export type FontWeight = 'thin' | 'light' | 'normal' | 'medium' | 'semibold' | 'bold';
38
+
39
+ /** 间距类型 / Spacing types */
40
+ export type Spacing = 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl';
41
+
42
+ /** 对齐方式类型 / Alignment types */
43
+ export type Alignment = 'left' | 'center' | 'right';
44
+
45
+ /** 统计项接口 / Stat item interface */
46
+ export interface StatItem {
47
+ /** 数值 / Numeric value */
48
+ value: string;
49
+ /** 标签 / Description label */
50
+ label: string;
51
+ /** 自定义颜色(可选)/ Custom color (optional) */
52
+ color?: string | PresetColor;
53
+ }
54
+
55
+ /** StatsDisplay 组件属性接口 / StatsDisplay component props interface */
56
+ export interface StatsDisplayProps {
57
+ /** 统计数据数组 / Statistical data array */
58
+ stats: StatItem[];
59
+ /** 自定义CSS类 / Custom CSS class */
60
+ class?: string;
61
+ /** 是否使用紧凑模式 / Whether to use compact mode */
62
+ compact?: boolean;
63
+ /** 列数(响应式)/ Number of columns (responsive) */
64
+ columns?: number;
65
+ /** 数值字体大小 / Font size for values */
66
+ valueSize?: FontSize;
67
+ /** 数值颜色 / Color for values */
68
+ valueColor?: string | PresetColor;
69
+ /** 标签颜色 / Color for labels */
70
+ labelColor?: string | PresetColor;
71
+ /** 数值字重 / Font weight for values */
72
+ valueWeight?: FontWeight;
73
+ /** 标签字重 / Font weight for labels */
74
+ labelWeight?: FontWeight;
75
+ /** 项目间距 / Spacing between items */
76
+ gap?: Spacing;
77
+ /** 对齐方式 / Alignment option */
78
+ align?: Alignment;
79
+ }
@@ -86,6 +86,7 @@
86
86
  * @prop {boolean} [underline=false] - 是否添加下划线
87
87
  * @prop {boolean} [truncate=false] - 是否截断文本并显示省略号
88
88
  * @prop {string} [class] - 自定义 CSS 类名
89
+ * @prop {string} [style] - 自定义内联样式
89
90
  *
90
91
  * @slots
91
92
  * @slot default - 文本内容
@@ -107,6 +108,7 @@ export interface Props {
107
108
  underline?: boolean;
108
109
  truncate?: boolean;
109
110
  class?: string;
111
+ style?: string;
110
112
  }
111
113
 
112
114
  const {
@@ -119,6 +121,7 @@ const {
119
121
  underline = false,
120
122
  truncate = false,
121
123
  class: className = '',
124
+ style = '',
122
125
  } = Astro.props;
123
126
 
124
127
  // 根据大小设置样式
@@ -169,7 +172,7 @@ const truncateClass = truncate ? 'cosy:truncate' : '';
169
172
  const combinedClass = `text ${sizeClass} ${weightClass} ${colorClass} ${alignClass} ${italicClass} ${underlineClass} ${truncateClass} ${className}`;
170
173
  ---
171
174
 
172
- <Element class={combinedClass}>
175
+ <Element class={combinedClass} style={style}>
173
176
  <slot />
174
177
  </Element>
175
178
 
@@ -20,98 +20,100 @@ import { allBackgroundClasses } from './backgrounds';
20
20
  * @props {string} [background] - 预设的语义化背景色,使用 Tailwind v4 语法(如 bg-primary/50)
21
21
  */
22
22
 
23
- interface Props extends IContainerProps { }
23
+ interface Props extends IContainerProps {}
24
24
 
25
25
  const props = withDefaults(defineProps<Props>(), {
26
- size: 'md',
27
- padding: 'md',
28
- centered: true,
29
- border: false,
30
- gap: 'none',
31
- rounded: 'none',
32
- class: '',
26
+ padding: 'md',
27
+ centered: true,
28
+ border: false,
29
+ gap: 'none',
30
+ rounded: 'none',
31
+ class: '',
33
32
  });
34
33
 
35
34
  // 静态类名映射
36
35
  const sizeClasses = {
37
- xs: 'cosy:max-w-xs',
38
- sm: 'cosy:max-w-sm',
39
- md: 'cosy:max-w-2xl',
40
- lg: 'cosy:max-w-4xl',
41
- xl: 'cosy:max-w-6xl',
42
- full: 'cosy:w-full',
36
+ none: '',
37
+ xs: 'cosy:max-w-xs',
38
+ sm: 'cosy:max-w-sm',
39
+ md: 'cosy:max-w-2xl',
40
+ lg: 'cosy:max-w-4xl',
41
+ xl: 'cosy:max-w-6xl',
42
+ full: 'cosy:w-full',
43
43
  } as const;
44
44
 
45
45
  const paddingClasses = {
46
- none: 'cosy:p-0',
47
- sm: 'cosy:p-2',
48
- md: 'cosy:p-4',
49
- lg: 'cosy:p-6',
50
- xl: 'cosy:p-8',
46
+ none: 'cosy:p-0',
47
+ sm: 'cosy:p-2',
48
+ md: 'cosy:p-4',
49
+ lg: 'cosy:p-6',
50
+ xl: 'cosy:p-8',
51
51
  } as const;
52
52
 
53
53
  const roundedClasses = {
54
- none: '',
55
- sm: 'cosy:rounded-sm',
56
- md: 'cosy:rounded-md',
57
- lg: 'cosy:rounded-lg',
58
- xl: 'cosy:rounded-xl',
59
- full: 'cosy:rounded-full',
54
+ none: '',
55
+ sm: 'cosy:rounded-sm',
56
+ md: 'cosy:rounded-md',
57
+ lg: 'cosy:rounded-lg',
58
+ xl: 'cosy:rounded-xl',
59
+ full: 'cosy:rounded-full',
60
60
  } as const;
61
61
 
62
62
  const flexClasses = {
63
- row: 'cosy:flex cosy:flex-row',
64
- col: 'cosy:flex cosy:flex-col',
65
- 'row-reverse': 'cosy:flex cosy:flex-row-reverse',
66
- 'col-reverse': 'cosy:flex cosy:flex-col-reverse',
63
+ row: 'cosy:flex cosy:flex-row',
64
+ col: 'cosy:flex cosy:flex-col',
65
+ 'row-reverse': 'cosy:flex cosy:flex-row-reverse',
66
+ 'col-reverse': 'cosy:flex cosy:flex-col-reverse',
67
67
  } as const;
68
68
 
69
69
  const gapClasses = {
70
- none: 'cosy:gap-0',
71
- xs: 'cosy:gap-1',
72
- sm: 'cosy:gap-2',
73
- md: 'cosy:gap-4',
74
- lg: 'cosy:gap-6',
75
- xl: 'cosy:gap-8',
70
+ none: 'cosy:gap-0',
71
+ xs: 'cosy:gap-1',
72
+ sm: 'cosy:gap-2',
73
+ md: 'cosy:gap-4',
74
+ lg: 'cosy:gap-6',
75
+ xl: 'cosy:gap-8',
76
76
  } as const;
77
77
 
78
78
  const itemsClasses = {
79
- start: 'cosy:items-start',
80
- end: 'cosy:items-end',
81
- center: 'cosy:items-center',
82
- baseline: 'cosy:items-baseline',
83
- stretch: 'cosy:items-stretch',
79
+ start: 'cosy:items-start',
80
+ end: 'cosy:items-end',
81
+ center: 'cosy:items-center',
82
+ baseline: 'cosy:items-baseline',
83
+ stretch: 'cosy:items-stretch',
84
84
  } as const;
85
85
 
86
86
  const justifyClasses = {
87
- start: 'cosy:justify-start',
88
- end: 'cosy:justify-end',
89
- center: 'cosy:justify-center',
90
- between: 'cosy:justify-between',
91
- around: 'cosy:justify-around',
92
- evenly: 'cosy:justify-evenly',
87
+ start: 'cosy:justify-start',
88
+ end: 'cosy:justify-end',
89
+ center: 'cosy:justify-center',
90
+ between: 'cosy:justify-between',
91
+ around: 'cosy:justify-around',
92
+ evenly: 'cosy:justify-evenly',
93
93
  } as const;
94
94
 
95
95
  // 构建CSS类名
96
+ const resolvedSize = computed(() => props.width ?? 'md');
97
+
96
98
  const containerClasses = computed(() => [
97
- 'cosy:w-full',
98
- props.centered ? 'cosy:mx-auto' : '',
99
- sizeClasses[props.size],
100
- paddingClasses[props.padding],
101
- roundedClasses[props.rounded],
102
- props.border ? 'cosy:border' : '',
103
- props.flex ? flexClasses[props.flex] : '',
104
- props.flex ? gapClasses[props.gap] : '',
105
- props.items && props.flex ? itemsClasses[props.items] : '',
106
- props.justify && props.flex ? justifyClasses[props.justify] : '',
107
- // 处理背景色 - 使用预定义的完整类名
108
- props.background ? allBackgroundClasses[props.background] : '',
109
- props.class,
99
+ 'cosy:w-full',
100
+ props.centered ? 'cosy:mx-auto' : '',
101
+ sizeClasses[resolvedSize.value],
102
+ paddingClasses[props.padding],
103
+ roundedClasses[props.rounded],
104
+ props.border ? 'cosy:border' : '',
105
+ props.flex ? flexClasses[props.flex] : '',
106
+ props.flex ? gapClasses[props.gap] : '',
107
+ props.items && props.flex ? itemsClasses[props.items] : '',
108
+ props.justify && props.flex ? justifyClasses[props.justify] : '',
109
+ // 处理背景色 - 使用预定义的完整类名
110
+ props.background ? allBackgroundClasses[props.background] : '',
111
+ props.class,
110
112
  ]);
111
113
  </script>
112
114
 
113
115
  <template>
114
- <section :class="containerClasses" container>
115
- <slot />
116
- </section>
116
+ <section :class="containerClasses" container>
117
+ <slot />
118
+ </section>
117
119
  </template>
@@ -49,10 +49,10 @@ export interface IContainerProps {
49
49
  padding?: 'none' | 'sm' | 'md' | 'lg' | 'xl';
50
50
 
51
51
  /**
52
- * 容器尺寸
53
- * @default "md"
52
+ * (推荐)容器宽度(与 Astro 版本保持一致)
53
+ * size 等价;如同时传入,优先使用 width
54
54
  */
55
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
55
+ width?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
56
56
 
57
57
  /**
58
58
  * 圆角大小
@@ -23,11 +23,13 @@ import type { IHeadingProps } from './types';
23
23
  * 1. 层次清晰 - 通过不同级别的标题建立内容的视觉层次结构
24
24
  * 2. 一致性 - 确保整个应用中标题样式的一致性
25
25
  * 3. 可定制性 - 支持多种配置选项,适应不同场景需求
26
- * 4. 无障碍性 - 遵循语义化HTML标准,确保屏幕阅读器可以正确解析内容结构
27
- * 5. 链接支持 - 标题可以作为链接使用,提供更好的导航体验
26
+ * 4. 字体控制 - 提供精细的字体粗细控制,满足不同设计需求
27
+ * 5. 无障碍性 - 遵循语义化HTML标准,确保屏幕阅读器可以正确解析内容结构
28
+ * 6. 链接支持 - 标题可以作为链接使用,提供更好的导航体验
28
29
  *
29
30
  * 视觉特点:
30
31
  * - 字体大小和粗细随级别变化
32
+ * - 支持自定义字体粗细(thin 到 black 共8个级别)
31
33
  * - 可选的下划线或底部边框
32
34
  * - 可定制的颜色和间距
33
35
  * - 响应式设计,在不同屏幕尺寸下保持良好的可读性
@@ -76,6 +78,18 @@ import type { IHeadingProps } from './types';
76
78
  * <Heading :level="3" background="primary" color="white">主要背景色标题</Heading>
77
79
  * ```
78
80
  *
81
+ * 字体粗细支持:
82
+ * ```vue
83
+ * <Heading :level="2" weight="thin">细体标题</Heading>
84
+ * <Heading :level="2" weight="light">轻体标题</Heading>
85
+ * <Heading :level="2" weight="normal">正常标题</Heading>
86
+ * <Heading :level="2" weight="medium">中等标题</Heading>
87
+ * <Heading :level="2" weight="semibold">半粗体标题</Heading>
88
+ * <Heading :level="2" weight="bold">粗体标题</Heading>
89
+ * <Heading :level="2" weight="extrabold">特粗体标题</Heading>
90
+ * <Heading :level="2" weight="black">超粗体标题</Heading>
91
+ * ```
92
+ *
79
93
  * @props
80
94
  * @prop {'left'|'center'|'right'} [align='left'] - 文本对齐方式
81
95
  * @prop {boolean} [anchor=false] - 是否显示锚点链接图标
@@ -89,6 +103,7 @@ import type { IHeadingProps } from './types';
89
103
  * @prop {'none'|'sm'|'md'|'lg'|'xl'} [margin='md'] - 上下外边距大小
90
104
  * @prop {'none'|'sm'|'md'|'lg'|'xl'} [padding='none'] - 内边距大小(仅在设置背景色时生效)
91
105
  * @prop {boolean} [underline=false] - 是否显示下划线
106
+ * @prop {'thin'|'light'|'normal'|'medium'|'semibold'|'bold'|'extrabold'|'black'} [weight] - 字体粗细,不指定时根据标题级别使用默认粗细(h1: bold, h2-h3: semibold, h4-h6: medium)
92
107
  *
93
108
  * @slots
94
109
  * @slot default - 标题内容
@@ -115,21 +130,60 @@ const props = withDefaults(defineProps<Props>(), {
115
130
  margin: 'md',
116
131
  padding: 'none',
117
132
  underline: false,
133
+ weight: undefined,
118
134
  });
119
135
 
120
- // 根据级别和颜色设置样式
121
- const headingClass = computed(() => {
136
+ // 字体粗细映射
137
+ const weightClassMap = {
138
+ thin: 'cosy:font-thin',
139
+ light: 'cosy:font-light',
140
+ normal: 'cosy:font-normal',
141
+ medium: 'cosy:font-medium',
142
+ semibold: 'cosy:font-semibold',
143
+ bold: 'cosy:font-bold',
144
+ extrabold: 'cosy:font-extrabold',
145
+ black: 'cosy:font-black',
146
+ };
147
+
148
+ // 根据级别设置基础样式(不包含字体粗细)
149
+ const baseHeadingClass = computed(() => {
122
150
  const levelMap = {
123
- 1: 'cosy:text-4xl cosy:font-bold',
124
- 2: 'cosy:text-3xl cosy:font-semibold',
125
- 3: 'cosy:text-2xl cosy:font-semibold',
126
- 4: 'cosy:text-xl cosy:font-medium',
127
- 5: 'cosy:text-lg cosy:font-medium',
128
- 6: 'cosy:text-base cosy:font-medium',
151
+ 1: 'cosy:text-4xl',
152
+ 2: 'cosy:text-3xl',
153
+ 3: 'cosy:text-2xl',
154
+ 4: 'cosy:text-xl',
155
+ 5: 'cosy:text-lg',
156
+ 6: 'cosy:text-base',
129
157
  };
130
158
  return levelMap[props.level as keyof typeof levelMap] || levelMap[2];
131
159
  });
132
160
 
161
+ // 默认字体粗细(当未指定 weight 时使用)
162
+ const defaultWeightClass = computed(() => {
163
+ const defaultMap = {
164
+ 1: 'cosy:font-bold',
165
+ 2: 'cosy:font-semibold',
166
+ 3: 'cosy:font-semibold',
167
+ 4: 'cosy:font-medium',
168
+ 5: 'cosy:font-medium',
169
+ 6: 'cosy:font-medium',
170
+ };
171
+ return defaultMap[props.level as keyof typeof defaultMap] || defaultMap[2];
172
+ });
173
+
174
+ // 字体粗细样式
175
+ const weightClass = computed(() => {
176
+ if (props.weight && props.weight in weightClassMap) {
177
+ return weightClassMap[props.weight as keyof typeof weightClassMap];
178
+ }
179
+ return defaultWeightClass.value;
180
+ });
181
+
182
+ // 组合标题样式类
183
+ const headingClass = computed(() => {
184
+ return `${baseHeadingClass.value} ${weightClass.value}`;
185
+ });
186
+
133
187
  const colorClass = computed(() => {
134
188
  const colorMap = {
135
189
  default: '',
@@ -22,5 +22,14 @@ export interface IHeadingProps {
22
22
  margin?: 'none' | 'sm' | 'md' | 'lg' | 'xl';
23
23
  padding?: 'none' | 'sm' | 'md' | 'lg' | 'xl';
24
24
  underline?: boolean;
25
+ weight?:
26
+ | 'thin'
27
+ | 'light'
28
+ | 'normal'
29
+ | 'medium'
30
+ | 'semibold'
31
+ | 'bold'
32
+ | 'extrabold'
33
+ | 'black';
25
34
  }
26
35