@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.
@@ -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
- <div
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
  // 全局函数,用于处理状态栏时间更新
@@ -15,7 +15,8 @@ import iphoneFrame from "../../src/components/apple-phone/assets/iPhone14ProDeep
15
15
  position: absolute;
16
16
  top: 0;
17
17
  left: 0;
18
- z-index: 100;
18
+ z-index: 10;
19
+ pointer-events: none;
19
20
  ">
20
21
  <Image src={iphoneFrame} alt="iPhone frame" />
21
22
  </div>
@@ -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:bg-gradient-to-br cosy:from-primary/10 cosy:to-secondary/10 cosy:dark:from-primary/20 cosy:dark:to-secondary/20 cosy:rounded-b">
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 Link from "../link/Link.astro";
111
- import type { BackgroundColor } from "../../src/common/backgrounds";
112
- import {
113
- FacebookIcon,
114
- GithubIcon,
115
- LinkedinIcon,
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
- // 构建自定义样式类(用于覆盖Card组件的默认样式)
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
- title={title}
186
- subtitle={description}
187
- compact={compact}
188
- background={background}
189
- class={customClasses}>
190
- <div class="cosy:space-y-0">
191
- {
192
- address && (
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
- phone && (
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
- twitter && (
257
- <div class={contactItemClass}>
258
- <TwitterIcon class={iconClass} />
259
- <Link href={twitter} external variant="text" noUnderline={false}>
260
- Twitter
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
- website && (
268
- <div class={contactItemClass}>
269
- <WebsiteIcon class={iconClass} />
270
- <Link href={website} external variant="text" noUnderline={false}>
271
- {website.replace(/^https?:\/\//, '')}
272
- </Link>
273
- </div>
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 type { ContactProps } from "./Contact.astro";
2
+ export { default as ContactItem } from "./ContactItem.astro";
3
+ export { default as SocialLink } from "./SocialLink.astro";
4
+ export type { ContactProps } from "./props";