@coffic/cosy-ui 0.9.10 → 0.9.11
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.
- package/dist/app.css +1 -1
- package/dist/index-astro.ts +2 -0
- package/dist/src-astro/card/Card.astro +10 -1
- package/dist/src-astro/card/index.ts +0 -16
- package/dist/src-astro/card-course/CardCourse.astro +83 -0
- package/dist/src-astro/card-course/CardCourseButton.astro +19 -0
- package/dist/src-astro/card-course/CardCourseContent.astro +29 -0
- package/dist/src-astro/card-course/CardCourseIcon.astro +20 -0
- package/dist/src-astro/card-course/config.ts +39 -0
- package/dist/src-astro/card-course/index.ts +3 -0
- package/dist/src-astro/card-course/types.ts +15 -0
- package/dist/src-astro/icons/SmartIcon.astro +195 -0
- package/dist/src-astro/icons/index.ts +3 -0
- package/dist/src-astro/smart-bg/SmartBg.astro +34 -0
- package/dist/src-astro/smart-bg/bg-util.ts +76 -0
- package/dist/src-astro/smart-bg/index.ts +1 -0
- package/package.json +1 -1
- package/dist/src-astro/card/CardCourse.astro +0 -156
package/dist/index-astro.ts
CHANGED
@@ -5,6 +5,7 @@ export * from './src-astro/banner';
|
|
5
5
|
export * from './src-astro/badge';
|
6
6
|
export * from './src-astro/button/index_astro';
|
7
7
|
export * from './src-astro/card';
|
8
|
+
export * from './src-astro/card-course';
|
8
9
|
export * from './src-astro/code-block';
|
9
10
|
export * from './src-astro/code-container';
|
10
11
|
export * from './src-astro/code-example';
|
@@ -39,6 +40,7 @@ export * from './src-astro/products';
|
|
39
40
|
export * from './src-astro/register';
|
40
41
|
export * from './src-astro/section';
|
41
42
|
export * from './src-astro/sidebar';
|
43
|
+
export * from './src-astro/smart-bg';
|
42
44
|
export * from './src-astro/speak';
|
43
45
|
export * from './src-astro/stack';
|
44
46
|
export * from './src-astro/team-member';
|
@@ -70,12 +70,21 @@
|
|
70
70
|
|
71
71
|
import '../../style.ts';
|
72
72
|
|
73
|
-
|
73
|
+
/**
|
74
|
+
* Card 组件的 Props 接口
|
75
|
+
*/
|
76
|
+
export interface CardProps {
|
77
|
+
/** 卡片标题 */
|
74
78
|
title: string;
|
79
|
+
/** 卡片副标题或描述 */
|
75
80
|
subtitle?: string;
|
81
|
+
/** 卡片顶部图片的URL */
|
76
82
|
imageUrl?: string;
|
83
|
+
/** 如果提供,卡片将变成可点击的链接 */
|
77
84
|
href?: string;
|
85
|
+
/** 是否使用紧凑模式 */
|
78
86
|
compact?: boolean;
|
87
|
+
/** 自定义CSS类,可用于覆盖默认样式 */
|
79
88
|
class?: string;
|
80
89
|
}
|
81
90
|
|
@@ -1,17 +1 @@
|
|
1
1
|
export { default as Card } from './Card.astro';
|
2
|
-
export { default as CardCourse } from './CardCourse.astro';
|
3
|
-
|
4
|
-
// Export types
|
5
|
-
export interface CardProps {
|
6
|
-
title: string;
|
7
|
-
subtitle?: string;
|
8
|
-
imageUrl?: string;
|
9
|
-
href?: string;
|
10
|
-
compact?: boolean;
|
11
|
-
class?: string;
|
12
|
-
}
|
13
|
-
|
14
|
-
export interface CardCourseProps {
|
15
|
-
title: string;
|
16
|
-
link: string;
|
17
|
-
}
|
@@ -0,0 +1,83 @@
|
|
1
|
+
---
|
2
|
+
/**
|
3
|
+
* @component CardCourse
|
4
|
+
*
|
5
|
+
* @description
|
6
|
+
* 课程卡片组件,用于展示课程信息,具有统一的设计风格。支持动态图标和渐变背景。
|
7
|
+
*
|
8
|
+
* @usage
|
9
|
+
* ```astro
|
10
|
+
* <CardCourse courseName="React 基础教程" lang="zh" href="/courses/react-basics" />
|
11
|
+
* ```
|
12
|
+
*
|
13
|
+
* @props
|
14
|
+
* - courseName: string - 课程标题
|
15
|
+
* - description?: string - 课程描述
|
16
|
+
* - lang: string - 语言("en" 或 "zh")
|
17
|
+
* - href: string - 课程链接
|
18
|
+
* - iconSize?: "sm" | "md" | "lg" | "xl" - 图标尺寸,默认为 "md"
|
19
|
+
*/
|
20
|
+
|
21
|
+
import '../../style.ts';
|
22
|
+
import { formatDisplayName, getIconSizeClasses } from './config';
|
23
|
+
import CardCourseIcon from './CardCourseIcon.astro';
|
24
|
+
import CardCourseContent from './CardCourseContent.astro';
|
25
|
+
import CardCourseButton from './CardCourseButton.astro';
|
26
|
+
import { SmartBg } from '../smart-bg';
|
27
|
+
|
28
|
+
interface Props {
|
29
|
+
courseName: string;
|
30
|
+
description?: string;
|
31
|
+
lang: string;
|
32
|
+
href: string;
|
33
|
+
iconSize?: 'sm' | 'md' | 'lg' | 'xl';
|
34
|
+
}
|
35
|
+
|
36
|
+
const {
|
37
|
+
courseName,
|
38
|
+
description = '',
|
39
|
+
lang,
|
40
|
+
href,
|
41
|
+
iconSize = 'md',
|
42
|
+
} = Astro.props;
|
43
|
+
|
44
|
+
const displayName = formatDisplayName(courseName);
|
45
|
+
const iconSizeClasses = getIconSizeClasses(iconSize);
|
46
|
+
---
|
47
|
+
|
48
|
+
<div
|
49
|
+
class={`
|
50
|
+
cosy:card
|
51
|
+
cosy:shadow-lg
|
52
|
+
cosy:hover:shadow-2xl
|
53
|
+
cosy:hover:scale-105
|
54
|
+
cosy:overflow-hidden
|
55
|
+
cosy:relative
|
56
|
+
cosy:group
|
57
|
+
cosy:cursor-pointer
|
58
|
+
cosy:transform
|
59
|
+
cosy:ease-in-out
|
60
|
+
cosy:transition-all
|
61
|
+
cosy:duration-300
|
62
|
+
cosy:border
|
63
|
+
cosy:border-base-content/30
|
64
|
+
cosy:backdrop-blur-sm`}>
|
65
|
+
<!-- 背景 -->
|
66
|
+
<SmartBg
|
67
|
+
keyword={courseName}
|
68
|
+
class="cosy:card-body cosy:p-6 cosy:relative cosy:z-10"
|
69
|
+
enableGradient={true}>
|
70
|
+
<!-- 背景图标 -->
|
71
|
+
<CardCourseIcon courseName={courseName} iconSizeClasses={iconSizeClasses} />
|
72
|
+
|
73
|
+
<div class="cosy:card-body cosy:p-6 cosy:relative cosy:z-10">
|
74
|
+
<!-- 内容区域 -->
|
75
|
+
<CardCourseContent displayName={displayName} description={description} />
|
76
|
+
|
77
|
+
<!-- 按钮区域 -->
|
78
|
+
<div class="cosy:card-actions cosy:justify-start cosy:mt-4">
|
79
|
+
<CardCourseButton href={href} lang={lang} />
|
80
|
+
</div>
|
81
|
+
</div>
|
82
|
+
</SmartBg>
|
83
|
+
</div>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
---
|
2
|
+
/**
|
3
|
+
* @component CardCourseButton
|
4
|
+
* @description 课程卡片按钮组件,使用组件库中的 Button 组件
|
5
|
+
*/
|
6
|
+
|
7
|
+
import { Button } from '../../index-astro';
|
8
|
+
|
9
|
+
interface Props {
|
10
|
+
href: string;
|
11
|
+
lang: string;
|
12
|
+
}
|
13
|
+
|
14
|
+
const { href, lang } = Astro.props;
|
15
|
+
---
|
16
|
+
|
17
|
+
<Button href={href} variant="primary" size="md">
|
18
|
+
{lang === 'en' ? 'Start Learning' : '开始学习'}
|
19
|
+
</Button>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
---
|
2
|
+
/**
|
3
|
+
* @component CardCourseContent
|
4
|
+
* @description 课程卡片内容区域组件,包含标题和描述
|
5
|
+
*/
|
6
|
+
|
7
|
+
interface Props {
|
8
|
+
displayName: string;
|
9
|
+
description?: string;
|
10
|
+
}
|
11
|
+
|
12
|
+
const { displayName, description } = Astro.props;
|
13
|
+
---
|
14
|
+
|
15
|
+
<!-- 标题和描述区域 -->
|
16
|
+
<div
|
17
|
+
class="cosy:mb-4 cosy:transition-all cosy:duration-300 hover:cosy:transform hover:cosy:translate-x-1">
|
18
|
+
<h3
|
19
|
+
class="cosy:text-lg cosy:font-semibold cosy:truncate cosy:text-start cosy:transition-all cosy:duration-300 hover:cosy:scale-105 cosy:origin-left cosy:group-hover:cosy:animate-bounce">
|
20
|
+
{displayName}
|
21
|
+
</h3>
|
22
|
+
{
|
23
|
+
description && (
|
24
|
+
<p class="cosy:text-sm cosy:mt-4 cosy:line-clamp-3 cosy:text-start cosy:transition-all cosy:duration-300 hover:cosy:opacity-80 cosy:transform hover:cosy:translate-x-1 cosy:group-hover:cosy:animate-pulse">
|
25
|
+
{description}
|
26
|
+
</p>
|
27
|
+
)
|
28
|
+
}
|
29
|
+
</div>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
---
|
2
|
+
/**
|
3
|
+
* @component CardCourseIcon
|
4
|
+
* @description 课程卡片背景图标组件,处理图标的显示和动画
|
5
|
+
*/
|
6
|
+
|
7
|
+
import { SmartIcon } from '../icons';
|
8
|
+
|
9
|
+
interface Props {
|
10
|
+
courseName: string;
|
11
|
+
iconSizeClasses: string;
|
12
|
+
}
|
13
|
+
|
14
|
+
const { courseName, iconSizeClasses } = Astro.props;
|
15
|
+
---
|
16
|
+
|
17
|
+
<div
|
18
|
+
class={`cosy:absolute cosy:top-2 cosy:right-2 cosy:opacity-30 hover:cosy:opacity-50 cosy:transition-all cosy:duration-500 cosy:ease-out hover:cosy:scale-110 hover:cosy:rotate-12 ${iconSizeClasses} cosy:group-hover:cosy:animate-pulse`}>
|
19
|
+
<SmartIcon keyword={courseName} class="cosy:w-full cosy:h-full" />
|
20
|
+
</div>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
/**
|
2
|
+
* 图标尺寸配置
|
3
|
+
* 预设的几种图标尺寸类名
|
4
|
+
*/
|
5
|
+
export const iconSizeConfig: Record<string, string> = {
|
6
|
+
sm: 'cosy:w-16 cosy:h-16',
|
7
|
+
md: 'cosy:w-24 cosy:h-24',
|
8
|
+
lg: 'cosy:w-32 cosy:h-32',
|
9
|
+
xl: 'cosy:w-40 cosy:h-40',
|
10
|
+
};
|
11
|
+
|
12
|
+
/**
|
13
|
+
* 获取图标尺寸类名
|
14
|
+
* @param size 图标尺寸
|
15
|
+
* @returns 对应的CSS类名
|
16
|
+
*/
|
17
|
+
export function getIconSizeClasses(size: "sm" | "md" | "lg" | "xl" = "md"): string {
|
18
|
+
return iconSizeConfig[size] || iconSizeConfig.md;
|
19
|
+
}
|
20
|
+
|
21
|
+
/**
|
22
|
+
* 标准化课程名称
|
23
|
+
* 将课程名称转换为小写并用下划线替换特殊字符
|
24
|
+
*/
|
25
|
+
export function normalizeName(name: string): string {
|
26
|
+
return name.toLowerCase().replace(/[^a-z0-9]/g, '_');
|
27
|
+
}
|
28
|
+
|
29
|
+
/**
|
30
|
+
* 格式化课程显示名称
|
31
|
+
* 将下划线替换为空格并首字母大写
|
32
|
+
* @param courseName 课程名称
|
33
|
+
* @returns 格式化后的显示名称
|
34
|
+
*/
|
35
|
+
export function formatDisplayName(courseName: string): string {
|
36
|
+
return courseName
|
37
|
+
.replace(/_/g, ' ')
|
38
|
+
.replace(/\b\w/g, (l) => l.toUpperCase());
|
39
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/**
|
2
|
+
* CardCourse 组件的 Props 接口
|
3
|
+
*/
|
4
|
+
export interface CardCourseProps {
|
5
|
+
/** 课程标题 */
|
6
|
+
courseName: string;
|
7
|
+
/** 课程描述 */
|
8
|
+
description?: string;
|
9
|
+
/** 语言("en" 或 "zh") */
|
10
|
+
lang: string;
|
11
|
+
/** 课程链接 */
|
12
|
+
href: string;
|
13
|
+
/** 图标尺寸,默认为 "md" */
|
14
|
+
iconSize?: "sm" | "md" | "lg" | "xl";
|
15
|
+
}
|
@@ -0,0 +1,195 @@
|
|
1
|
+
---
|
2
|
+
/**
|
3
|
+
* @component SmartIcon
|
4
|
+
* @description 根据关键词自动渲染最合适的图标组件,支持中英文关键词,未匹配时渲染默认图标。
|
5
|
+
* @props {string} keyword - 关键词
|
6
|
+
* @usage <SmartIcon keyword="用户" class="w-6 h-6" />
|
7
|
+
*/
|
8
|
+
import SocialIcon from './SocialIcon.astro';
|
9
|
+
import TwitterIcon from './TwitterIcon.astro';
|
10
|
+
import UserIcon from './UserIcon.astro';
|
11
|
+
import WarningIcon from './WarningIcon.astro';
|
12
|
+
import XCircle from './XCircle.astro';
|
13
|
+
import InfoIcon from './InfoIcon.astro';
|
14
|
+
import LinkIcon from './LinkIcon.astro';
|
15
|
+
import LinkedinIcon from './LinkedinIcon.astro';
|
16
|
+
import MenuIcon from './MenuIcon.astro';
|
17
|
+
import RefreshIcon from './RefreshIcon.astro';
|
18
|
+
import SearchIcon from './SearchIcon.astro';
|
19
|
+
import SuccessIcon from './SuccessIcon.astro';
|
20
|
+
import SunCloudyIcon from './SunCloudyIcon.astro';
|
21
|
+
import AlertTriangle from './AlertTriangle.astro';
|
22
|
+
import CalendarIcon from './CalendarIcon.astro';
|
23
|
+
import CheckCircle from './CheckCircle.astro';
|
24
|
+
import CheckIcon from './CheckIcon.astro';
|
25
|
+
import ClipboardIcon from './ClipboardIcon.astro';
|
26
|
+
import CloseIcon from './CloseIcon.astro';
|
27
|
+
import CodeIcon from './CodeIcon.astro';
|
28
|
+
import DeleteIcon from './DeleteIcon.astro';
|
29
|
+
import ErrorIcon from './ErrorIcon.astro';
|
30
|
+
import GithubIcon from './GithubIcon.astro';
|
31
|
+
import InfoCircle from './InfoCircle.astro';
|
32
|
+
import InboxArchive from './InboxArchive.astro';
|
33
|
+
import SettingsIcon from './SettingsIcon.astro';
|
34
|
+
import ChevronDownIcon from './ChevronDownIcon.astro';
|
35
|
+
import HomeIcon from './HomeIcon.astro';
|
36
|
+
import DashboardIcon from './DashboardIcon.astro';
|
37
|
+
import ChartIcon from './ChartIcon.astro';
|
38
|
+
import DocumentIcon from './DocumentIcon.astro';
|
39
|
+
import NotificationIcon from './NotificationIcon.astro';
|
40
|
+
import UsersIcon from './UsersIcon.astro';
|
41
|
+
import MessageIcon from './MessageIcon.astro';
|
42
|
+
import MailIcon from './MailIcon.astro';
|
43
|
+
import FolderIcon from './FolderIcon.astro';
|
44
|
+
import StarIcon from './StarIcon.astro';
|
45
|
+
import HeartIcon from './HeartIcon.astro';
|
46
|
+
import SaveIcon from './SaveIcon.astro';
|
47
|
+
import EditIcon from './EditIcon.astro';
|
48
|
+
import ToolsIcon from './ToolsIcon.astro';
|
49
|
+
import WalletIcon from './WalletIcon.astro';
|
50
|
+
import ReportIcon from './ReportIcon.astro';
|
51
|
+
import SecurityIcon from './SecurityIcon.astro';
|
52
|
+
import UploadIcon from './UploadIcon.astro';
|
53
|
+
import DownloadIcon from './DownloadIcon.astro';
|
54
|
+
import LogOut from './LogOut.astro';
|
55
|
+
import AppStoreIcon from './AppStoreIcon.astro';
|
56
|
+
import WebsiteIcon from './WebsiteIcon.astro';
|
57
|
+
|
58
|
+
const { keyword = '', ...rest } = Astro.props;
|
59
|
+
|
60
|
+
const zhMap: { [key: string]: any } = {
|
61
|
+
用户: UserIcon,
|
62
|
+
人: UserIcon,
|
63
|
+
账号: UserIcon,
|
64
|
+
个人: UserIcon,
|
65
|
+
警告: WarningIcon,
|
66
|
+
注意: WarningIcon,
|
67
|
+
信息: InfoIcon,
|
68
|
+
提示: InfoIcon,
|
69
|
+
链接: LinkIcon,
|
70
|
+
菜单: MenuIcon,
|
71
|
+
刷新: RefreshIcon,
|
72
|
+
搜索: SearchIcon,
|
73
|
+
成功: SuccessIcon,
|
74
|
+
太阳: SunCloudyIcon,
|
75
|
+
天气: SunCloudyIcon,
|
76
|
+
日历: CalendarIcon,
|
77
|
+
勾: CheckIcon,
|
78
|
+
对: CheckIcon,
|
79
|
+
完成: CheckIcon,
|
80
|
+
剪贴板: ClipboardIcon,
|
81
|
+
关闭: CloseIcon,
|
82
|
+
叉: CloseIcon,
|
83
|
+
代码: CodeIcon,
|
84
|
+
删除: DeleteIcon,
|
85
|
+
错误: ErrorIcon,
|
86
|
+
github: GithubIcon,
|
87
|
+
设置: SettingsIcon,
|
88
|
+
主页: HomeIcon,
|
89
|
+
首页: HomeIcon,
|
90
|
+
仪表盘: DashboardIcon,
|
91
|
+
图表: ChartIcon,
|
92
|
+
文档: DocumentIcon,
|
93
|
+
文件: DocumentIcon,
|
94
|
+
通知: NotificationIcon,
|
95
|
+
群: UsersIcon,
|
96
|
+
成员: UsersIcon,
|
97
|
+
消息: MessageIcon,
|
98
|
+
邮件: MailIcon,
|
99
|
+
文件夹: FolderIcon,
|
100
|
+
收藏: StarIcon,
|
101
|
+
星: StarIcon,
|
102
|
+
喜欢: HeartIcon,
|
103
|
+
心: HeartIcon,
|
104
|
+
保存: SaveIcon,
|
105
|
+
编辑: EditIcon,
|
106
|
+
工具: ToolsIcon,
|
107
|
+
钱包: WalletIcon,
|
108
|
+
报告: ReportIcon,
|
109
|
+
安全: SecurityIcon,
|
110
|
+
上传: UploadIcon,
|
111
|
+
下载: DownloadIcon,
|
112
|
+
退出: LogOut,
|
113
|
+
应用: AppStoreIcon,
|
114
|
+
网站: WebsiteIcon,
|
115
|
+
社交: SocialIcon,
|
116
|
+
推特: TwitterIcon,
|
117
|
+
};
|
118
|
+
|
119
|
+
const iconMap: { [key: string]: any } = {
|
120
|
+
social: SocialIcon,
|
121
|
+
twitter: TwitterIcon,
|
122
|
+
user: UserIcon,
|
123
|
+
warning: WarningIcon,
|
124
|
+
x_circle: XCircle,
|
125
|
+
info: InfoIcon,
|
126
|
+
link: LinkIcon,
|
127
|
+
linkedin: LinkedinIcon,
|
128
|
+
menu: MenuIcon,
|
129
|
+
refresh: RefreshIcon,
|
130
|
+
search: SearchIcon,
|
131
|
+
success: SuccessIcon,
|
132
|
+
suncloudy: SunCloudyIcon,
|
133
|
+
alerttriangle: AlertTriangle,
|
134
|
+
calendar: CalendarIcon,
|
135
|
+
checkcircle: CheckCircle,
|
136
|
+
check: CheckIcon,
|
137
|
+
clipboard: ClipboardIcon,
|
138
|
+
close: CloseIcon,
|
139
|
+
code: CodeIcon,
|
140
|
+
delete: DeleteIcon,
|
141
|
+
error: ErrorIcon,
|
142
|
+
github: GithubIcon,
|
143
|
+
infocircle: InfoCircle,
|
144
|
+
inboxarchive: InboxArchive,
|
145
|
+
settings: SettingsIcon,
|
146
|
+
chevrondown: ChevronDownIcon,
|
147
|
+
home: HomeIcon,
|
148
|
+
dashboard: DashboardIcon,
|
149
|
+
chart: ChartIcon,
|
150
|
+
document: DocumentIcon,
|
151
|
+
notification: NotificationIcon,
|
152
|
+
users: UsersIcon,
|
153
|
+
message: MessageIcon,
|
154
|
+
mail: MailIcon,
|
155
|
+
folder: FolderIcon,
|
156
|
+
star: StarIcon,
|
157
|
+
heart: HeartIcon,
|
158
|
+
save: SaveIcon,
|
159
|
+
edit: EditIcon,
|
160
|
+
tools: ToolsIcon,
|
161
|
+
wallet: WalletIcon,
|
162
|
+
report: ReportIcon,
|
163
|
+
security: SecurityIcon,
|
164
|
+
upload: UploadIcon,
|
165
|
+
download: DownloadIcon,
|
166
|
+
logout: LogOut,
|
167
|
+
appstore: AppStoreIcon,
|
168
|
+
website: WebsiteIcon,
|
169
|
+
};
|
170
|
+
|
171
|
+
let IconComponent = DocumentIcon;
|
172
|
+
if (keyword) {
|
173
|
+
for (const zh in zhMap) {
|
174
|
+
if (keyword.includes(zh)) {
|
175
|
+
IconComponent = zhMap[zh];
|
176
|
+
break;
|
177
|
+
}
|
178
|
+
}
|
179
|
+
if (IconComponent === DocumentIcon) {
|
180
|
+
const lower = keyword.toLowerCase();
|
181
|
+
if (iconMap[lower]) {
|
182
|
+
IconComponent = iconMap[lower];
|
183
|
+
} else {
|
184
|
+
for (const key in iconMap) {
|
185
|
+
if (lower.includes(key)) {
|
186
|
+
IconComponent = iconMap[key];
|
187
|
+
break;
|
188
|
+
}
|
189
|
+
}
|
190
|
+
}
|
191
|
+
}
|
192
|
+
}
|
193
|
+
---
|
194
|
+
|
195
|
+
<IconComponent {...rest} />
|
@@ -47,3 +47,6 @@ export { default as DownloadIcon } from './DownloadIcon.astro';
|
|
47
47
|
export { default as LogOut } from './LogOut.astro';
|
48
48
|
export { default as AppStoreIcon } from './AppStoreIcon.astro';
|
49
49
|
export { default as WebsiteIcon } from './WebsiteIcon.astro';
|
50
|
+
|
51
|
+
// 智能图标
|
52
|
+
export { default as SmartIcon } from './SmartIcon.astro';
|
@@ -0,0 +1,34 @@
|
|
1
|
+
---
|
2
|
+
/**
|
3
|
+
* @component SmartBg
|
4
|
+
* @description 根据关键词自动分配合适的背景色,支持中英文关键词,未匹配时使用默认色。可选启用渐变色。
|
5
|
+
* @props {string} keyword - 关键词
|
6
|
+
* @props {boolean} enableGradient - 是否启用渐变色,默认 false
|
7
|
+
* @usage <SmartBg keyword="JavaScript" enableGradient>内容</SmartBg>
|
8
|
+
*/
|
9
|
+
import { bgColorMap, bgGradientMap, mapKeywordToBgKey } from './bg-util';
|
10
|
+
|
11
|
+
const {
|
12
|
+
keyword = '',
|
13
|
+
class: className = '',
|
14
|
+
style = '',
|
15
|
+
enableGradient = false,
|
16
|
+
showKey = false,
|
17
|
+
} = Astro.props;
|
18
|
+
|
19
|
+
const bgKey = mapKeywordToBgKey(keyword);
|
20
|
+
const bgClass = enableGradient
|
21
|
+
? bgGradientMap[bgKey] || bgGradientMap['neutral']
|
22
|
+
: bgColorMap[bgKey] || bgColorMap['neutral'];
|
23
|
+
---
|
24
|
+
|
25
|
+
<div class={`${bgClass} ${className}`} style={style}>
|
26
|
+
<slot />
|
27
|
+
{
|
28
|
+
showKey && (
|
29
|
+
<span style="position:absolute;right:0.5rem;bottom:0.5rem;z-index:10;font-size:0.75rem;opacity:0.7;background:rgba(0,0,0,0.1);padding:0.1em 0.5em;border-radius:0.25em;pointer-events:none;">
|
30
|
+
{bgKey}
|
31
|
+
</span>
|
32
|
+
)
|
33
|
+
}
|
34
|
+
</div>
|
@@ -0,0 +1,76 @@
|
|
1
|
+
// 背景色 key 到类名的映射
|
2
|
+
export const bgColorMap: { [key: string]: string } = {
|
3
|
+
primary: 'cosy:bg-blue-500 cosy:dark:bg-blue-800',
|
4
|
+
success: 'cosy:bg-green-500 cosy:dark:bg-green-800',
|
5
|
+
danger: 'cosy:bg-red-500 cosy:dark:bg-red-800',
|
6
|
+
warning: 'cosy:bg-yellow-400 cosy:dark:bg-yellow-600',
|
7
|
+
info: 'cosy:bg-cyan-400 cosy:dark:bg-cyan-700',
|
8
|
+
neutral: 'cosy:bg-gray-200 cosy:dark:bg-gray-700',
|
9
|
+
forest: 'cosy:bg-green-700 cosy:dark:bg-green-900',
|
10
|
+
ocean: 'cosy:bg-blue-700 cosy:dark:bg-blue-900',
|
11
|
+
sky: 'cosy:bg-sky-400 cosy:dark:bg-sky-700',
|
12
|
+
lemon: 'cosy:bg-lime-300 cosy:dark:bg-lime-700',
|
13
|
+
orange: 'cosy:bg-orange-400 cosy:dark:bg-orange-700',
|
14
|
+
cherry: 'cosy:bg-rose-500 cosy:dark:bg-rose-800',
|
15
|
+
grape: 'cosy:bg-purple-500 cosy:dark:bg-purple-800',
|
16
|
+
banana: 'cosy:bg-yellow-300 cosy:dark:bg-yellow-600',
|
17
|
+
watermelon: 'cosy:bg-pink-400 cosy:dark:bg-pink-700',
|
18
|
+
peach: 'cosy:bg-orange-200 cosy:dark:bg-orange-500',
|
19
|
+
avocado: 'cosy:bg-lime-600 cosy:dark:bg-lime-900',
|
20
|
+
coconut: 'cosy:bg-stone-200 cosy:dark:bg-stone-600',
|
21
|
+
blueberry: 'cosy:bg-indigo-500 cosy:dark:bg-indigo-900',
|
22
|
+
kiwi: 'cosy:bg-green-400 cosy:dark:bg-green-700',
|
23
|
+
mint: 'cosy:bg-teal-300 cosy:dark:bg-teal-700',
|
24
|
+
sand: 'cosy:bg-yellow-200 cosy:dark:bg-yellow-700',
|
25
|
+
sunset: 'cosy:bg-pink-300 cosy:dark:bg-pink-700',
|
26
|
+
lavender: 'cosy:bg-purple-300 cosy:dark:bg-purple-700',
|
27
|
+
snow: 'cosy:bg-white cosy:dark:bg-gray-800',
|
28
|
+
};
|
29
|
+
|
30
|
+
// 渐变色 key 到类名的映射
|
31
|
+
export const bgGradientMap: { [key: string]: string } = {
|
32
|
+
primary: 'cosy:bg-gradient-to-r cosy:from-blue-300 cosy:via-blue-400 cosy:to-blue-500 cosy:dark:from-blue-700 cosy:dark:via-blue-800 cosy:dark:to-blue-900',
|
33
|
+
success: 'cosy:bg-gradient-to-r cosy:from-green-300 cosy:via-green-400 cosy:to-green-500 cosy:dark:from-green-700 cosy:dark:via-green-800 cosy:dark:to-green-900',
|
34
|
+
danger: 'cosy:bg-gradient-to-r cosy:from-red-300 cosy:via-red-400 cosy:to-red-500 cosy:dark:from-red-700 cosy:dark:via-red-800 cosy:dark:to-red-900',
|
35
|
+
warning: 'cosy:bg-gradient-to-r cosy:from-yellow-200 cosy:via-yellow-300 cosy:to-yellow-400 cosy:dark:from-yellow-600 cosy:dark:via-yellow-700 cosy:dark:to-yellow-800',
|
36
|
+
info: 'cosy:bg-gradient-to-r cosy:from-cyan-200 cosy:via-cyan-300 cosy:to-cyan-400 cosy:dark:from-cyan-600 cosy:dark:via-cyan-700 cosy:dark:to-cyan-800',
|
37
|
+
neutral: 'cosy:bg-gradient-to-r cosy:from-gray-100 cosy:via-gray-200 cosy:to-gray-300 cosy:dark:from-gray-700 cosy:dark:via-gray-800 cosy:dark:to-gray-900',
|
38
|
+
forest: 'cosy:bg-gradient-to-r cosy:from-green-600 cosy:via-green-700 cosy:to-green-800 cosy:dark:from-green-800 cosy:dark:via-green-900 cosy:dark:to-green-950',
|
39
|
+
ocean: 'cosy:bg-gradient-to-r cosy:from-blue-400 cosy:via-blue-600 cosy:to-blue-800 cosy:dark:from-blue-800 cosy:dark:via-blue-900 cosy:dark:to-blue-950',
|
40
|
+
sky: 'cosy:bg-gradient-to-r cosy:from-sky-200 cosy:via-sky-300 cosy:to-sky-400 cosy:dark:from-sky-700 cosy:dark:via-sky-800 cosy:dark:to-sky-900',
|
41
|
+
lemon: 'cosy:bg-gradient-to-r cosy:from-lime-200 cosy:via-lime-300 cosy:to-lime-400 cosy:dark:from-lime-700 cosy:dark:via-lime-800 cosy:dark:to-lime-900',
|
42
|
+
orange: 'cosy:bg-gradient-to-r cosy:from-orange-200 cosy:via-orange-300 cosy:to-orange-400 cosy:dark:from-orange-700 cosy:dark:via-orange-800 cosy:dark:to-orange-900',
|
43
|
+
cherry: 'cosy:bg-gradient-to-r cosy:from-rose-300 cosy:via-rose-400 cosy:to-rose-500 cosy:dark:from-rose-700 cosy:dark:via-rose-800 cosy:dark:to-rose-900',
|
44
|
+
grape: 'cosy:bg-gradient-to-r cosy:from-purple-300 cosy:via-purple-400 cosy:to-purple-500 cosy:dark:from-purple-700 cosy:dark:via-purple-800 cosy:dark:to-purple-900',
|
45
|
+
banana: 'cosy:bg-gradient-to-r cosy:from-yellow-100 cosy:via-yellow-200 cosy:to-yellow-300 cosy:dark:from-yellow-600 cosy:dark:via-yellow-700 cosy:dark:to-yellow-800',
|
46
|
+
watermelon: 'cosy:bg-gradient-to-r cosy:from-pink-200 cosy:via-pink-300 cosy:to-pink-400 cosy:dark:from-pink-700 cosy:dark:via-pink-800 cosy:dark:to-pink-900',
|
47
|
+
peach: 'cosy:bg-gradient-to-r cosy:from-orange-100 cosy:via-orange-200 cosy:to-orange-300 cosy:dark:from-orange-500 cosy:dark:via-orange-600 cosy:dark:to-orange-700',
|
48
|
+
avocado: 'cosy:bg-gradient-to-r cosy:from-lime-400 cosy:via-lime-500 cosy:to-lime-600 cosy:dark:from-lime-800 cosy:dark:via-lime-900 cosy:dark:to-lime-950',
|
49
|
+
coconut: 'cosy:bg-gradient-to-r cosy:from-stone-100 cosy:via-stone-200 cosy:to-stone-300 cosy:dark:from-stone-600 cosy:dark:via-stone-700 cosy:dark:to-stone-800',
|
50
|
+
blueberry: 'cosy:bg-gradient-to-r cosy:from-indigo-300 cosy:via-indigo-400 cosy:to-indigo-500 cosy:dark:from-indigo-800 cosy:dark:via-indigo-900 cosy:dark:to-indigo-950',
|
51
|
+
kiwi: 'cosy:bg-gradient-to-r cosy:from-green-200 cosy:via-green-300 cosy:to-green-400 cosy:dark:from-green-700 cosy:dark:via-green-800 cosy:dark:to-green-900',
|
52
|
+
mint: 'cosy:bg-gradient-to-r cosy:from-teal-200 cosy:via-teal-300 cosy:to-teal-400 cosy:dark:from-teal-700 cosy:dark:via-teal-800 cosy:dark:to-teal-900',
|
53
|
+
sand: 'cosy:bg-gradient-to-r cosy:from-yellow-100 cosy:via-yellow-200 cosy:to-yellow-300 cosy:dark:from-yellow-700 cosy:dark:via-yellow-800 cosy:dark:to-yellow-900',
|
54
|
+
sunset: 'cosy:bg-gradient-to-r cosy:from-pink-200 cosy:via-pink-300 cosy:to-pink-400 cosy:dark:from-pink-700 cosy:dark:via-pink-800 cosy:dark:to-pink-900',
|
55
|
+
lavender: 'cosy:bg-gradient-to-r cosy:from-purple-100 cosy:via-purple-200 cosy:to-purple-300 cosy:dark:from-purple-700 cosy:dark:via-purple-800 cosy:dark:to-purple-900',
|
56
|
+
snow: 'cosy:bg-gradient-to-r cosy:from-white cosy:via-gray-100 cosy:to-gray-200 cosy:dark:from-gray-800 cosy:dark:via-gray-900 cosy:dark:to-black',
|
57
|
+
};
|
58
|
+
|
59
|
+
// 哈希函数,将字符串映射为数字
|
60
|
+
function hashString(str: string): number {
|
61
|
+
let hash = 0;
|
62
|
+
for (let i = 0; i < str.length; i++) {
|
63
|
+
hash = ((hash << 5) - hash) + str.charCodeAt(i);
|
64
|
+
hash |= 0; // 转为32位整数
|
65
|
+
}
|
66
|
+
return Math.abs(hash);
|
67
|
+
}
|
68
|
+
|
69
|
+
// 关键词到 key 的哈希映射
|
70
|
+
export function mapKeywordToBgKey(keyword: string): string {
|
71
|
+
const keys = Object.keys(bgColorMap);
|
72
|
+
if (!keyword) return 'neutral';
|
73
|
+
const hash = hashString(keyword.toLowerCase());
|
74
|
+
const idx = hash % keys.length;
|
75
|
+
return keys[idx];
|
76
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default as SmartBg } from './SmartBg.astro';
|