@coffic/cosy-ui 0.9.72 → 0.9.73
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/src-astro/apple-phone/ApplePhone.astro +7 -5
- package/dist/src-astro/apple-phone/PhoneFrame.astro +2 -1
- package/dist/src-astro/card/Card.astro +0 -7
- package/dist/src-astro/code-container/CodeContainer.astro +1 -14
- package/dist/src-astro/contact/AddressItem.astro +26 -0
- package/dist/src-astro/contact/Contact.astro +40 -228
- package/dist/src-astro/contact/ContactItem.astro +45 -0
- package/dist/src-astro/contact/EmailItem.astro +27 -0
- package/dist/src-astro/contact/PhoneItem.astro +27 -0
- package/dist/src-astro/contact/SocialLink.astro +44 -0
- package/dist/src-astro/contact/SocialMediaItem.astro +81 -0
- package/dist/src-astro/contact/class.ts +38 -0
- package/dist/src-astro/contact/index.ts +3 -1
- package/dist/src-astro/contact/props.ts +52 -0
- package/dist/src-vue/apple-phone/ApplePhone.vue +5 -7
- package/dist/src-vue/apple-phone/PhoneFrame.vue +3 -2
- package/package.json +1 -1
|
@@ -82,6 +82,10 @@ const scaleRatio = currentHeight / 500;
|
|
|
82
82
|
|
|
83
83
|
// 生成唯一的ID
|
|
84
84
|
const uniqueId = `apple-phone-${Math.random().toString(36).substr(2, 9)}`;
|
|
85
|
+
|
|
86
|
+
// 响应式数据
|
|
87
|
+
let showAlertDialog = false;
|
|
88
|
+
let alertMessage = "";
|
|
85
89
|
---
|
|
86
90
|
|
|
87
91
|
<div
|
|
@@ -105,16 +109,14 @@ const uniqueId = `apple-phone-${Math.random().toString(36).substr(2, 9)}`;
|
|
|
105
109
|
<Container
|
|
106
110
|
rounded="lg"
|
|
107
111
|
height="full"
|
|
112
|
+
class="cosy:h-full cosy:overflow-y-auto cosy:overscroll-y-contain"
|
|
108
113
|
background={backgroundColor || 'accent/90'}>
|
|
109
|
-
<
|
|
110
|
-
class="cosy:h-full cosy:overflow-y-auto cosy:overscroll-y-contain">
|
|
111
|
-
<slot />
|
|
112
|
-
</div>
|
|
114
|
+
<slot />
|
|
113
115
|
</Container>
|
|
114
116
|
</div>
|
|
115
117
|
</div>
|
|
116
118
|
|
|
117
|
-
<AlertDialog id={`${uniqueId}-alert`} message=
|
|
119
|
+
<AlertDialog id={`${uniqueId}-alert`} message={alertMessage} />
|
|
118
120
|
|
|
119
121
|
<script>
|
|
120
122
|
// 全局函数,用于处理状态栏时间更新
|
|
@@ -6,13 +6,6 @@
|
|
|
6
6
|
* Card 组件用于在页面中展示相关内容的容器,通常包含标题、描述和可选的图片。
|
|
7
7
|
* 组件设计简洁大方,具有平滑的动画效果和交互反馈,适合展示产品、文章或功能介绍等内容。
|
|
8
8
|
*
|
|
9
|
-
* @design
|
|
10
|
-
* 设计理念:
|
|
11
|
-
* 1. 视觉层次感 - 通过阴影、悬停效果和微妙的动画创造深度感
|
|
12
|
-
* 2. 内容聚焦 - 简洁的布局让用户关注卡片内容
|
|
13
|
-
* 3. 交互反馈 - 悬停和点击时提供明确的视觉反馈
|
|
14
|
-
* 4. 适应性强 - 响应式设计,适应不同屏幕尺寸
|
|
15
|
-
*
|
|
16
9
|
* @usage
|
|
17
10
|
* 基本用法:
|
|
18
11
|
* ```astro
|
|
@@ -7,19 +7,6 @@
|
|
|
7
7
|
* 支持样式重置模式。
|
|
8
8
|
* 使用时只需在默认slot中传入内容,并为每个示例设置对应的id (tab-1, tab-2等)
|
|
9
9
|
*
|
|
10
|
-
* @design
|
|
11
|
-
* 设计理念:
|
|
12
|
-
* 1. 样式隔离 - 防止外部样式影响内部组件展示
|
|
13
|
-
* 2. 代码预览 - 支持预览和代码视图切换
|
|
14
|
-
* 3. 多标签页 - 支持多个示例的标签页展示
|
|
15
|
-
* 4. 样式重置 - 重置内部样式,避免样式冲突
|
|
16
|
-
*
|
|
17
|
-
* 视觉特点:
|
|
18
|
-
* - 卡片式设计:清晰的视觉层次
|
|
19
|
-
* - 渐变背景:美观的预览区域
|
|
20
|
-
* - 标签页切换:直观的示例切换
|
|
21
|
-
* - 代码高亮:清晰的代码展示
|
|
22
|
-
*
|
|
23
10
|
* @usage
|
|
24
11
|
* 基础用法:
|
|
25
12
|
* ```astro
|
|
@@ -114,7 +101,7 @@ const {
|
|
|
114
101
|
<Description text={descriptions[index]} />
|
|
115
102
|
|
|
116
103
|
<Container background="dot-grid" width="full">
|
|
117
|
-
<div class="cosy:relative cosy:p-4 cosy:
|
|
104
|
+
<div class="cosy:relative cosy:p-4 cosy:rounded-b">
|
|
118
105
|
<Preview>
|
|
119
106
|
<div
|
|
120
107
|
class={`cosy:code-preview-area ${resetStyles ? 'cosy:reset-styles' : ''}`}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* AddressItem 组件用于显示地址信息
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import "../../style.ts";
|
|
7
|
+
import ContactItem from "./ContactItem.astro";
|
|
8
|
+
import { MapPinIcon } from "../icons";
|
|
9
|
+
import { getContactItemClass, getIconClass } from "./class";
|
|
10
|
+
|
|
11
|
+
export interface AddressItemProps {
|
|
12
|
+
address: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { address } = Astro.props as AddressItemProps;
|
|
16
|
+
|
|
17
|
+
const contactItemClass = getContactItemClass();
|
|
18
|
+
const iconClass = getIconClass();
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
<ContactItem
|
|
22
|
+
icon={MapPinIcon}
|
|
23
|
+
text={address}
|
|
24
|
+
contactItemClass={contactItemClass}
|
|
25
|
+
iconClass={iconClass}
|
|
26
|
+
/>
|
|
@@ -107,43 +107,16 @@
|
|
|
107
107
|
|
|
108
108
|
import "../../style.ts";
|
|
109
109
|
import Card from "../card/Card.astro";
|
|
110
|
-
import
|
|
111
|
-
import
|
|
112
|
-
import
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
MailIcon,
|
|
117
|
-
MapPinIcon,
|
|
118
|
-
PhoneIcon,
|
|
119
|
-
TwitterIcon,
|
|
120
|
-
WebsiteIcon,
|
|
121
|
-
WechatIcon,
|
|
122
|
-
WhatsappIcon,
|
|
123
|
-
} from "../icons";
|
|
124
|
-
|
|
125
|
-
export interface ContactProps {
|
|
126
|
-
address?: string;
|
|
127
|
-
background?: BackgroundColor;
|
|
128
|
-
class?: string;
|
|
129
|
-
compact?: boolean;
|
|
130
|
-
description?: string;
|
|
131
|
-
email?: string;
|
|
132
|
-
facebook?: string;
|
|
133
|
-
github?: string;
|
|
134
|
-
linkedin?: string;
|
|
135
|
-
phone?: string;
|
|
136
|
-
title?: string;
|
|
137
|
-
twitter?: string;
|
|
138
|
-
website?: string;
|
|
139
|
-
wechatQR?: any; // ImageSource 类型
|
|
140
|
-
whatsappQR?: any; // ImageSource 类型
|
|
141
|
-
}
|
|
110
|
+
import type { ContactProps } from "./props";
|
|
111
|
+
import { getContactCombinedClasses } from "./class";
|
|
112
|
+
import AddressItem from "./AddressItem.astro";
|
|
113
|
+
import EmailItem from "./EmailItem.astro";
|
|
114
|
+
import PhoneItem from "./PhoneItem.astro";
|
|
115
|
+
import SocialMediaItem from "./SocialMediaItem.astro";
|
|
142
116
|
|
|
143
117
|
const {
|
|
144
118
|
address,
|
|
145
|
-
background,
|
|
146
|
-
class: className = "",
|
|
119
|
+
background = "base-100",
|
|
147
120
|
compact,
|
|
148
121
|
description,
|
|
149
122
|
email,
|
|
@@ -158,209 +131,48 @@ const {
|
|
|
158
131
|
whatsappQR,
|
|
159
132
|
} = Astro.props as ContactProps;
|
|
160
133
|
|
|
161
|
-
//
|
|
162
|
-
const customClasses =
|
|
163
|
-
"cosy:shadow-lg",
|
|
164
|
-
"hover:cosy:shadow-xl",
|
|
165
|
-
"hover:cosy:bg-base-200",
|
|
166
|
-
className,
|
|
167
|
-
]
|
|
168
|
-
.filter(Boolean)
|
|
169
|
-
.join(" ");
|
|
170
|
-
|
|
171
|
-
// 联系信息项的样式
|
|
172
|
-
const contactItemClass =
|
|
173
|
-
"cosy:flex cosy:items-center cosy:gap-3 cosy:mb-4 last:cosy:mb-0 cosy:transition-all cosy:duration-200 cosy:ease-in-out hover:cosy:bg-base-200/50 hover:cosy:rounded-lg hover:cosy:p-2 hover:cosy:-mx-2";
|
|
174
|
-
const iconClass =
|
|
175
|
-
"cosy:w-5 cosy:h-5 cosy:text-primary cosy:flex-shrink-0 cosy:transition-all cosy:duration-200 hover:cosy:scale-110 hover:cosy:text-primary/80";
|
|
176
|
-
|
|
177
|
-
// 社交媒体链接样式
|
|
178
|
-
const socialLinksClass =
|
|
179
|
-
"cosy:flex cosy:gap-4 cosy:mt-6 cosy:pt-4 cosy:border-t cosy:border-base-300";
|
|
180
|
-
const socialLinkClass =
|
|
181
|
-
"cosy:btn cosy:btn-ghost cosy:btn-circle cosy:btn-sm cosy:text-base-content hover:cosy:text-primary hover:cosy:bg-primary/10";
|
|
134
|
+
// 获取样式类
|
|
135
|
+
const customClasses = getContactCombinedClasses(Astro.props as ContactProps);
|
|
182
136
|
---
|
|
183
137
|
|
|
184
138
|
<Card
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
<div class={contactItemClass}>
|
|
194
|
-
<MapPinIcon class={iconClass} />
|
|
195
|
-
<span class="cosy:text-base-content">{address}</span>
|
|
196
|
-
</div>
|
|
197
|
-
)
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
{
|
|
201
|
-
email && (
|
|
202
|
-
<div class={contactItemClass}>
|
|
203
|
-
<MailIcon class={iconClass} />
|
|
204
|
-
<Link href={`mailto:${email}`} variant="text" noUnderline={false}>
|
|
205
|
-
{email}
|
|
206
|
-
</Link>
|
|
207
|
-
</div>
|
|
208
|
-
)
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
{
|
|
212
|
-
facebook && (
|
|
213
|
-
<div class={contactItemClass}>
|
|
214
|
-
<FacebookIcon class={iconClass} />
|
|
215
|
-
<Link href={facebook} external variant="text" noUnderline={false}>
|
|
216
|
-
Facebook
|
|
217
|
-
</Link>
|
|
218
|
-
</div>
|
|
219
|
-
)
|
|
220
|
-
}
|
|
139
|
+
title={title}
|
|
140
|
+
subtitle={description}
|
|
141
|
+
compact={compact}
|
|
142
|
+
background={background}
|
|
143
|
+
padding="none"
|
|
144
|
+
class={customClasses}>
|
|
145
|
+
<div class="cosy:space-y-0 cosy:flex cosy:flex-col">
|
|
146
|
+
{address && <AddressItem address={address} />}
|
|
221
147
|
|
|
222
|
-
|
|
223
|
-
github && (
|
|
224
|
-
<div class={contactItemClass}>
|
|
225
|
-
<GithubIcon class={iconClass} />
|
|
226
|
-
<Link href={github} external variant="text" noUnderline={false}>
|
|
227
|
-
GitHub
|
|
228
|
-
</Link>
|
|
229
|
-
</div>
|
|
230
|
-
)
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
{
|
|
234
|
-
linkedin && (
|
|
235
|
-
<div class={contactItemClass}>
|
|
236
|
-
<LinkedinIcon class={iconClass} />
|
|
237
|
-
<Link href={linkedin} external variant="text" noUnderline={false}>
|
|
238
|
-
LinkedIn
|
|
239
|
-
</Link>
|
|
240
|
-
</div>
|
|
241
|
-
)
|
|
242
|
-
}
|
|
148
|
+
{email && <EmailItem email={email} />}
|
|
243
149
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
<div class={contactItemClass}>
|
|
247
|
-
<PhoneIcon class={iconClass} />
|
|
248
|
-
<Link href={`tel:${phone}`} variant="text" noUnderline={false}>
|
|
249
|
-
{phone}
|
|
250
|
-
</Link>
|
|
251
|
-
</div>
|
|
252
|
-
)
|
|
253
|
-
}
|
|
150
|
+
{phone && <PhoneItem phone={phone} />}
|
|
151
|
+
</div>
|
|
254
152
|
|
|
255
153
|
{
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
</Link>
|
|
262
|
-
</div>
|
|
263
|
-
)
|
|
154
|
+
Astro.slots.has('default') && (
|
|
155
|
+
<div class="cosy:mt-4">
|
|
156
|
+
<slot />
|
|
157
|
+
</div>
|
|
158
|
+
)
|
|
264
159
|
}
|
|
265
160
|
|
|
266
161
|
{
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
162
|
+
(github ||
|
|
163
|
+
twitter ||
|
|
164
|
+
facebook ||
|
|
165
|
+
linkedin ||
|
|
166
|
+
wechatQR ||
|
|
167
|
+
whatsappQR) && (
|
|
168
|
+
<SocialMediaItem
|
|
169
|
+
github={github}
|
|
170
|
+
twitter={twitter}
|
|
171
|
+
facebook={facebook}
|
|
172
|
+
linkedin={linkedin}
|
|
173
|
+
wechatQR={wechatQR}
|
|
174
|
+
whatsappQR={whatsappQR}
|
|
175
|
+
/>
|
|
176
|
+
)
|
|
275
177
|
}
|
|
276
|
-
</div>
|
|
277
|
-
|
|
278
|
-
{
|
|
279
|
-
Astro.slots.has('default') && (
|
|
280
|
-
<div class="cosy:mt-4">
|
|
281
|
-
<slot />
|
|
282
|
-
</div>
|
|
283
|
-
)
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
{
|
|
287
|
-
(github || twitter || facebook || linkedin || wechatQR || whatsappQR) && (
|
|
288
|
-
<div class={socialLinksClass}>
|
|
289
|
-
{github && (
|
|
290
|
-
<Link
|
|
291
|
-
href={github}
|
|
292
|
-
external
|
|
293
|
-
btn
|
|
294
|
-
circle
|
|
295
|
-
size="sm"
|
|
296
|
-
class={socialLinkClass}
|
|
297
|
-
aria-label="GitHub">
|
|
298
|
-
<GithubIcon />
|
|
299
|
-
</Link>
|
|
300
|
-
)}
|
|
301
|
-
{twitter && (
|
|
302
|
-
<Link
|
|
303
|
-
href={twitter}
|
|
304
|
-
external
|
|
305
|
-
btn
|
|
306
|
-
circle
|
|
307
|
-
size="sm"
|
|
308
|
-
class={socialLinkClass}
|
|
309
|
-
aria-label="Twitter">
|
|
310
|
-
<TwitterIcon />
|
|
311
|
-
</Link>
|
|
312
|
-
)}
|
|
313
|
-
{facebook && (
|
|
314
|
-
<Link
|
|
315
|
-
href={facebook}
|
|
316
|
-
external
|
|
317
|
-
btn
|
|
318
|
-
circle
|
|
319
|
-
size="sm"
|
|
320
|
-
class={socialLinkClass}
|
|
321
|
-
aria-label="Facebook">
|
|
322
|
-
<FacebookIcon />
|
|
323
|
-
</Link>
|
|
324
|
-
)}
|
|
325
|
-
{linkedin && (
|
|
326
|
-
<Link
|
|
327
|
-
href={linkedin}
|
|
328
|
-
external
|
|
329
|
-
btn
|
|
330
|
-
circle
|
|
331
|
-
size="sm"
|
|
332
|
-
class={socialLinkClass}
|
|
333
|
-
aria-label="LinkedIn">
|
|
334
|
-
<LinkedinIcon />
|
|
335
|
-
</Link>
|
|
336
|
-
)}
|
|
337
|
-
{wechatQR && (
|
|
338
|
-
<Link
|
|
339
|
-
href="#"
|
|
340
|
-
btn
|
|
341
|
-
circle
|
|
342
|
-
size="sm"
|
|
343
|
-
class={socialLinkClass}
|
|
344
|
-
hoverImage={wechatQR}
|
|
345
|
-
hoverImageAlt="微信二维码"
|
|
346
|
-
aria-label="微信">
|
|
347
|
-
<WechatIcon />
|
|
348
|
-
</Link>
|
|
349
|
-
)}
|
|
350
|
-
{whatsappQR && (
|
|
351
|
-
<Link
|
|
352
|
-
href="#"
|
|
353
|
-
btn
|
|
354
|
-
circle
|
|
355
|
-
size="sm"
|
|
356
|
-
class={socialLinkClass}
|
|
357
|
-
hoverImage={whatsappQR}
|
|
358
|
-
hoverImageAlt="WhatsApp 二维码"
|
|
359
|
-
aria-label="WhatsApp">
|
|
360
|
-
<WhatsappIcon />
|
|
361
|
-
</Link>
|
|
362
|
-
)}
|
|
363
|
-
</div>
|
|
364
|
-
)
|
|
365
|
-
}
|
|
366
178
|
</Card>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* ContactItem 组件用于显示单个联系信息项
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import "../../style.ts";
|
|
7
|
+
import Link from "../link/Link.astro";
|
|
8
|
+
import type { HTMLAttributes } from "astro/types";
|
|
9
|
+
|
|
10
|
+
export interface ContactItemProps extends HTMLAttributes<"div"> {
|
|
11
|
+
icon: any; // 图标组件
|
|
12
|
+
text: string;
|
|
13
|
+
href?: string;
|
|
14
|
+
isExternal?: boolean;
|
|
15
|
+
contactItemClass: string;
|
|
16
|
+
iconClass: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
icon: IconComponent,
|
|
21
|
+
text,
|
|
22
|
+
href,
|
|
23
|
+
isExternal = false,
|
|
24
|
+
contactItemClass,
|
|
25
|
+
iconClass,
|
|
26
|
+
...rest
|
|
27
|
+
} = Astro.props as ContactItemProps;
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
<div class={contactItemClass} {...rest}>
|
|
31
|
+
<IconComponent class={iconClass} />
|
|
32
|
+
{
|
|
33
|
+
href ? (
|
|
34
|
+
<Link
|
|
35
|
+
href={href}
|
|
36
|
+
external={isExternal}
|
|
37
|
+
variant="text"
|
|
38
|
+
noUnderline={false}>
|
|
39
|
+
{text}
|
|
40
|
+
</Link>
|
|
41
|
+
) : (
|
|
42
|
+
<span class="cosy:text-base-content">{text}</span>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
</div>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* EmailItem 组件用于显示邮箱信息
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import "../../style.ts";
|
|
7
|
+
import ContactItem from "./ContactItem.astro";
|
|
8
|
+
import { MailIcon } from "../icons";
|
|
9
|
+
import { getContactItemClass, getIconClass } from "./class";
|
|
10
|
+
|
|
11
|
+
export interface EmailItemProps {
|
|
12
|
+
email: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { email } = Astro.props as EmailItemProps;
|
|
16
|
+
|
|
17
|
+
const contactItemClass = getContactItemClass();
|
|
18
|
+
const iconClass = getIconClass();
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
<ContactItem
|
|
22
|
+
icon={MailIcon}
|
|
23
|
+
text={email}
|
|
24
|
+
href={`mailto:${email}`}
|
|
25
|
+
contactItemClass={contactItemClass}
|
|
26
|
+
iconClass={iconClass}
|
|
27
|
+
/>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* PhoneItem 组件用于显示电话信息
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import "../../style.ts";
|
|
7
|
+
import ContactItem from "./ContactItem.astro";
|
|
8
|
+
import { PhoneIcon } from "../icons";
|
|
9
|
+
import { getContactItemClass, getIconClass } from "./class";
|
|
10
|
+
|
|
11
|
+
export interface PhoneItemProps {
|
|
12
|
+
phone: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { phone } = Astro.props as PhoneItemProps;
|
|
16
|
+
|
|
17
|
+
const contactItemClass = getContactItemClass();
|
|
18
|
+
const iconClass = getIconClass();
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
<ContactItem
|
|
22
|
+
icon={PhoneIcon}
|
|
23
|
+
text={phone}
|
|
24
|
+
href={`tel:${phone}`}
|
|
25
|
+
contactItemClass={contactItemClass}
|
|
26
|
+
iconClass={iconClass}
|
|
27
|
+
/>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* SocialLink 组件用于显示单个社交媒体链接
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import "../../style.ts";
|
|
7
|
+
import Link from "../link/Link.astro";
|
|
8
|
+
import type { HTMLAttributes } from "astro/types";
|
|
9
|
+
|
|
10
|
+
export interface SocialLinkProps extends HTMLAttributes<"a"> {
|
|
11
|
+
icon: any; // 图标组件
|
|
12
|
+
href: string;
|
|
13
|
+
ariaLabel: string;
|
|
14
|
+
isExternal?: boolean;
|
|
15
|
+
hoverImage?: any;
|
|
16
|
+
hoverImageAlt?: string;
|
|
17
|
+
socialLinkClass: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
icon: IconComponent,
|
|
22
|
+
href,
|
|
23
|
+
ariaLabel,
|
|
24
|
+
isExternal = true,
|
|
25
|
+
hoverImage,
|
|
26
|
+
hoverImageAlt,
|
|
27
|
+
socialLinkClass,
|
|
28
|
+
...rest
|
|
29
|
+
} = Astro.props as SocialLinkProps;
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
<Link
|
|
33
|
+
href={href}
|
|
34
|
+
external={isExternal}
|
|
35
|
+
btn
|
|
36
|
+
circle
|
|
37
|
+
size="sm"
|
|
38
|
+
class={socialLinkClass}
|
|
39
|
+
aria-label={ariaLabel}
|
|
40
|
+
hoverImage={hoverImage}
|
|
41
|
+
hoverImageAlt={hoverImageAlt}
|
|
42
|
+
{...rest}>
|
|
43
|
+
<IconComponent />
|
|
44
|
+
</Link>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* SocialMediaItem 组件用于显示社交媒体链接
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import "../../style.ts";
|
|
7
|
+
import SocialLink from "./SocialLink.astro";
|
|
8
|
+
import {
|
|
9
|
+
FacebookIcon,
|
|
10
|
+
GithubIcon,
|
|
11
|
+
LinkedinIcon,
|
|
12
|
+
TwitterIcon,
|
|
13
|
+
WechatIcon,
|
|
14
|
+
WhatsappIcon,
|
|
15
|
+
} from "../icons";
|
|
16
|
+
|
|
17
|
+
export interface SocialMediaItemProps {
|
|
18
|
+
github?: string;
|
|
19
|
+
twitter?: string;
|
|
20
|
+
facebook?: string;
|
|
21
|
+
linkedin?: string;
|
|
22
|
+
wechatQR?: any;
|
|
23
|
+
whatsappQR?: any;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const { github, twitter, facebook, linkedin, wechatQR, whatsappQR } =
|
|
27
|
+
Astro.props as SocialMediaItemProps;
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
<div class="cosy:flex cosy:flex-row cosy:gap-2">
|
|
31
|
+
{
|
|
32
|
+
github && (
|
|
33
|
+
<SocialLink icon={GithubIcon} href={github} ariaLabel="GitHub" />
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
{
|
|
37
|
+
twitter && (
|
|
38
|
+
<SocialLink icon={TwitterIcon} href={twitter} ariaLabel="Twitter" />
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
{
|
|
42
|
+
facebook && (
|
|
43
|
+
<SocialLink
|
|
44
|
+
icon={FacebookIcon}
|
|
45
|
+
href={facebook}
|
|
46
|
+
ariaLabel="Facebook"
|
|
47
|
+
/>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
{
|
|
51
|
+
linkedin && (
|
|
52
|
+
<SocialLink
|
|
53
|
+
icon={LinkedinIcon}
|
|
54
|
+
href={linkedin}
|
|
55
|
+
ariaLabel="LinkedIn"
|
|
56
|
+
/>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
{
|
|
60
|
+
wechatQR && (
|
|
61
|
+
<SocialLink
|
|
62
|
+
icon={WechatIcon}
|
|
63
|
+
href="#"
|
|
64
|
+
ariaLabel="微信"
|
|
65
|
+
hoverImage={wechatQR}
|
|
66
|
+
hoverImageAlt="微信二维码"
|
|
67
|
+
/>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
{
|
|
71
|
+
whatsappQR && (
|
|
72
|
+
<SocialLink
|
|
73
|
+
icon={WhatsappIcon}
|
|
74
|
+
href="#"
|
|
75
|
+
ariaLabel="WhatsApp"
|
|
76
|
+
hoverImage={whatsappQR}
|
|
77
|
+
hoverImageAlt="WhatsApp 二维码"
|
|
78
|
+
/>
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
</div>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ContactProps } from "./props";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 计算 Contact 组件的组合类名
|
|
5
|
+
* @param props Contact 组件的 props
|
|
6
|
+
* @returns 组合后的类名字符串
|
|
7
|
+
*/
|
|
8
|
+
export function getContactCombinedClasses(props: ContactProps): string {
|
|
9
|
+
const { class: className = "" } = props;
|
|
10
|
+
|
|
11
|
+
// 构建自定义样式类(用于覆盖Card组件的默认样式)
|
|
12
|
+
const customClasses = [
|
|
13
|
+
"cosy:shadow-lg",
|
|
14
|
+
"hover:cosy:shadow-xl",
|
|
15
|
+
"hover:cosy:bg-base-200",
|
|
16
|
+
className,
|
|
17
|
+
]
|
|
18
|
+
.filter(Boolean)
|
|
19
|
+
.join(" ");
|
|
20
|
+
|
|
21
|
+
return customClasses;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 获取联系信息项的样式类
|
|
26
|
+
* @returns 联系信息项的样式类
|
|
27
|
+
*/
|
|
28
|
+
export function getContactItemClass(): string {
|
|
29
|
+
return "cosy:flex cosy:items-center cosy:gap-3 cosy:mb-4 last:cosy:mb-0 cosy:transition-all cosy:duration-200 cosy:ease-in-out hover:cosy:bg-base-200/50 hover:cosy:rounded-lg hover:cosy:p-2 hover:cosy:-mx-2";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 获取图标样式类
|
|
34
|
+
* @returns 图标样式类
|
|
35
|
+
*/
|
|
36
|
+
export function getIconClass(): string {
|
|
37
|
+
return "cosy:w-5 cosy:h-5 cosy:text-primary cosy:flex-shrink-0 cosy:transition-all cosy:duration-200 hover:cosy:scale-110 hover:cosy:text-primary/80";
|
|
38
|
+
}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
export { default as Contact } from "./Contact.astro";
|
|
2
|
-
export
|
|
2
|
+
export { default as ContactItem } from "./ContactItem.astro";
|
|
3
|
+
export { default as SocialLink } from "./SocialLink.astro";
|
|
4
|
+
export type { ContactProps } from "./props";
|