@coffic/cosy-ui 1.0.13 → 1.0.15

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/index-astro.ts +1 -0
  3. package/dist/index-vue.ts +1 -0
  4. package/dist/src/components/apple-pad/applePadPropsBase.d.ts +31 -0
  5. package/dist/src/components/apple-pad/applePadPropsBase.js +1 -0
  6. package/dist/src/components/apple-pad/assets/iPad Air 11/" - M2 - Blue - Landscape.png +0 -0
  7. package/dist/src/components/apple-pad/assets/iPad Air 11/" - M2 - Blue - Portrait.png +0 -0
  8. package/dist/src/components/apple-pad/assets/iPad Air 11/" - M2 - Purple - Landscape.png +0 -0
  9. package/dist/src/components/apple-pad/assets/iPad Air 11/" - M2 - Purple - Portrait.png +0 -0
  10. package/dist/src/components/apple-pad/assets/iPad Air 11/" - M2 - Space Gray - Landscape.png +0 -0
  11. package/dist/src/components/apple-pad/assets/iPad Air 11/" - M2 - Space Gray - Portrait.png +0 -0
  12. package/dist/src/components/apple-pad/assets/iPad Air 11/" - M2 - Stardust - Landscape.png +0 -0
  13. package/dist/src/components/apple-pad/assets/iPad Air 11/" - M2 - Stardust - Portrait.png +0 -0
  14. package/dist/src/components/apple-pad/assets/iPad Air 13/" - M2 - Blue - Landscape.png +0 -0
  15. package/dist/src/components/apple-pad/assets/iPad Air 13/" - M2 - Blue - Portrait.png +0 -0
  16. package/dist/src/components/apple-pad/assets/iPad Air 13/" - M2 - Purple - Landscape.png +0 -0
  17. package/dist/src/components/apple-pad/assets/iPad Air 13/" - M2 - Purple - Portrait.png +0 -0
  18. package/dist/src/components/apple-pad/assets/iPad Air 13/" - M2 - Space Gray - Landscape.png +0 -0
  19. package/dist/src/components/apple-pad/assets/iPad Air 13/" - M2 - Space Gray - Portrait.png +0 -0
  20. package/dist/src/components/apple-pad/assets/iPad Air 13/" - M2 - Stardust - Landscape.png +0 -0
  21. package/dist/src/components/apple-pad/assets/iPad Air 13/" - M2 - Stardust - Portrait.png +0 -0
  22. package/dist/src/components/apple-pad/constants.d.ts +36 -0
  23. package/dist/src/components/apple-pad/constants.js +43 -0
  24. package/dist/src/styles/prose/prose-table.css +5 -86
  25. package/dist/src-astro/apple-pad/ApplePad.astro +165 -0
  26. package/dist/src-astro/apple-pad/PadFrame.astro +23 -0
  27. package/dist/src-astro/apple-pad/StatusBarContent.astro +119 -0
  28. package/dist/src-astro/apple-pad/index.ts +5 -0
  29. package/dist/src-astro/apple-pad/props.ts +6 -0
  30. package/dist/src-vue/apple-pad/ApplePad.vue +117 -0
  31. package/dist/src-vue/apple-pad/PadFrame.vue +20 -0
  32. package/dist/src-vue/apple-pad/StatusBarContent.vue +153 -0
  33. package/dist/src-vue/apple-pad/index.ts +2 -0
  34. package/dist/src-vue/apple-pad/props.ts +6 -0
  35. package/package.json +1 -1
@@ -20,6 +20,7 @@ export * from "./src/utils/url";
20
20
  export * from "./src-astro/alert";
21
21
  export * from "./src-astro/alert-dialog";
22
22
  export * from "./src-astro/api-test";
23
+ export * from "./src-astro/apple-pad";
23
24
  export * from "./src-astro/apple-phone";
24
25
  export * from "./src-astro/article";
25
26
  export * from "./src-astro/avatar";
package/dist/index-vue.ts CHANGED
@@ -3,6 +3,7 @@ import "./app.css";
3
3
  export * from "./src-vue/alert/index";
4
4
  // 导出组件,按照字母排序
5
5
  export * from "./src-vue/alert-dialog/index";
6
+ export * from "./src-vue/apple-pad/index";
6
7
  export * from "./src-vue/apple-phone/index";
7
8
  export * from "./src-vue/avatar/index";
8
9
  export * from "./src-vue/badge/index";
@@ -0,0 +1,31 @@
1
+ import type { BackgroundColor } from "../../../src/common/backgrounds";
2
+ /**
3
+ * ApplePad 组件的基础属性接口(与框架无关)
4
+ */
5
+ export interface IApplePadPropsBase {
6
+ /**
7
+ * 窗口高度选项
8
+ * @default 'lg'
9
+ */
10
+ height?: "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl" | "5xl";
11
+ /**
12
+ * 窗口标题
13
+ * @default ''
14
+ */
15
+ title?: string;
16
+ /**
17
+ * 是否显示阴影效果
18
+ * @default true
19
+ */
20
+ withShadow?: boolean;
21
+ /**
22
+ * 是否显示 iPad 边框
23
+ * @default true
24
+ */
25
+ showFrame?: boolean;
26
+ /**
27
+ * 内容区域背景色
28
+ * @default undefined
29
+ */
30
+ backgroundColor?: BackgroundColor;
31
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,36 @@
1
+ /**
2
+ * ApplePad 组件的常量定义
3
+ *
4
+ * 基于 iPad Air 11" M2 竖屏模式
5
+ * 边框图片: 1900 × 2620 px
6
+ * 设备屏幕: 1640 × 2360 点
7
+ */
8
+ export declare const IPAD_FRAME_WIDTH = 1900;
9
+ export declare const IPAD_FRAME_HEIGHT = 2620;
10
+ export declare const IPAD_FRAME_STATUS_BAR_TOP = 155;
11
+ export declare const IPAD_FRAME_STATUS_BAR_HEIGHT = 70;
12
+ export declare const MAIN_CONTENT_WIDTH_ASPECT_RATIO: number;
13
+ export declare const MAIN_CONTENT_HEIGHT_ASPECT_RATIO: number;
14
+ export declare const IPAD_FRAME_STATUS_BAR_HEIGHT_ASPECT_RATIO: number;
15
+ export declare const IPAD_FRAME_STATUS_BAR_TOP_ASPECT_RATIO: number;
16
+ export declare const HEIGHT_CLASSES: {
17
+ readonly sm: "cosy:h-[400px]";
18
+ readonly md: "cosy:h-[500px]";
19
+ readonly lg: "cosy:h-[600px]";
20
+ readonly xl: "cosy:h-[700px]";
21
+ readonly "2xl": "cosy:h-[800px]";
22
+ readonly "3xl": "cosy:h-[900px]";
23
+ readonly "4xl": "cosy:h-[1000px]";
24
+ readonly "5xl": "cosy:h-[1100px]";
25
+ };
26
+ export declare const HEIGHT_VALUES: {
27
+ readonly sm: 400;
28
+ readonly md: 500;
29
+ readonly lg: 600;
30
+ readonly xl: 700;
31
+ readonly "2xl": 800;
32
+ readonly "3xl": 900;
33
+ readonly "4xl": 1000;
34
+ readonly "5xl": 1100;
35
+ };
36
+ export declare const DEFAULT_HEIGHT: keyof typeof HEIGHT_VALUES;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * ApplePad 组件的常量定义
3
+ *
4
+ * 基于 iPad Air 11" M2 竖屏模式
5
+ * 边框图片: 1900 × 2620 px
6
+ * 设备屏幕: 1640 × 2360 点
7
+ */
8
+ // iPad 边框图片尺寸
9
+ export const IPAD_FRAME_WIDTH = 1900;
10
+ export const IPAD_FRAME_HEIGHT = 2620;
11
+ // iPad 边框图片 - 状态栏离上边框的距离
12
+ export const IPAD_FRAME_STATUS_BAR_TOP = 155;
13
+ // iPad 边框图片 - 状态栏高度
14
+ export const IPAD_FRAME_STATUS_BAR_HEIGHT = 70;
15
+ // 比例计算
16
+ export const MAIN_CONTENT_WIDTH_ASPECT_RATIO = 1640 / IPAD_FRAME_WIDTH;
17
+ export const MAIN_CONTENT_HEIGHT_ASPECT_RATIO = 2360 / IPAD_FRAME_HEIGHT;
18
+ export const IPAD_FRAME_STATUS_BAR_HEIGHT_ASPECT_RATIO = IPAD_FRAME_STATUS_BAR_HEIGHT / IPAD_FRAME_HEIGHT;
19
+ export const IPAD_FRAME_STATUS_BAR_TOP_ASPECT_RATIO = IPAD_FRAME_STATUS_BAR_TOP / IPAD_FRAME_HEIGHT;
20
+ // 预定义的高度选项(iPad 比 iPhone 大,默认值也更大)
21
+ export const HEIGHT_CLASSES = {
22
+ sm: "cosy:h-[400px]", // 400px
23
+ md: "cosy:h-[500px]", // 500px
24
+ lg: "cosy:h-[600px]", // 600px
25
+ xl: "cosy:h-[700px]", // 700px
26
+ "2xl": "cosy:h-[800px]", // 800px
27
+ "3xl": "cosy:h-[900px]", // 900px
28
+ "4xl": "cosy:h-[1000px]", // 1000px
29
+ "5xl": "cosy:h-[1100px]", // 1100px
30
+ };
31
+ // 高度值映射
32
+ export const HEIGHT_VALUES = {
33
+ sm: 400,
34
+ md: 500,
35
+ lg: 600,
36
+ xl: 700,
37
+ "2xl": 800,
38
+ "3xl": 900,
39
+ "4xl": 1000,
40
+ "5xl": 1100,
41
+ };
42
+ // 默认高度
43
+ export const DEFAULT_HEIGHT = "lg";
@@ -1,9 +1,8 @@
1
1
  /* Prose 表格样式 - 现代化设计 */
2
2
 
3
3
  /* 表格 */
4
- .prose :where(table):not(:where([class~='not-prose'], [class~='not-prose'] *)),
5
4
  .cosy\:prose
6
- :where(table):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
5
+ :where(table):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
7
6
  width: 100%;
8
7
  table-layout: auto;
9
8
  text-align: left;
@@ -23,7 +22,6 @@
23
22
  background-color: #ffffff;
24
23
  }
25
24
 
26
- .prose :where(thead):not(:where([class~='not-prose'], [class~='not-prose'] *)),
27
25
  .cosy\:prose
28
26
  :where(thead):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
29
27
  border-bottom-width: 2px;
@@ -56,8 +54,6 @@
56
54
  border-right: none;
57
55
  }
58
56
 
59
- .prose
60
- :where(tbody tr):not(:where([class~='not-prose'], [class~='not-prose'] *)),
61
57
  .cosy\:prose
62
58
  :where(tbody tr):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
63
59
  border-bottom: 1px solid var(--tw-prose-td-borders, #e5e7eb);
@@ -76,14 +72,10 @@
76
72
  }
77
73
 
78
74
  /* Hover 效果 */
79
- .prose
75
+ .cosy\:prose
80
76
  :where(tbody tr):hover:not(
81
77
  :where([class~='not-prose'], [class~='not-prose'] *)
82
- ),
83
- .cosy\:prose
84
- :where(tbody tr):hover:not(
85
- :where([class~='not-prose'], [class~='not-prose'] *)
86
- ) {
78
+ ) {
87
79
  background-color: #f9fafb;
88
80
  transform: scale(1.01);
89
81
  box-shadow:
@@ -92,19 +84,13 @@
92
84
  }
93
85
 
94
86
  /* 斑马纹效果 */
95
- .prose
87
+ .cosy\:prose
96
88
  :where(tbody tr:nth-child(even)):not(
97
89
  :where([class~='not-prose'], [class~='not-prose'] *)
98
- ),
99
- .cosy\:prose
100
- :where(tbody tr:nth-child(even)):not(
101
- :where([class~='not-prose'], [class~='not-prose'] *)
102
- ) {
90
+ ) {
103
91
  background-color: rgba(249, 250, 251, 0.5);
104
92
  }
105
93
 
106
- .prose
107
- :where(tbody td):not(:where([class~='not-prose'], [class~='not-prose'] *)),
108
94
  .cosy\:prose
109
95
  :where(tbody td):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
110
96
  vertical-align: middle;
@@ -112,10 +98,6 @@
112
98
  border-right: 1px solid rgba(0, 0, 0, 0.03);
113
99
  }
114
100
 
115
- .prose
116
- :where(tbody td:last-child):not(
117
- :where([class~='not-prose'], [class~='not-prose'] *)
118
- ),
119
101
  .cosy\:prose
120
102
  :where(tbody td:last-child):not(
121
103
  :where([class~='not-prose'], [class~='not-prose'] *)
@@ -123,7 +105,6 @@
123
105
  border-right: none;
124
106
  }
125
107
 
126
- .prose :where(tfoot):not(:where([class~='not-prose'], [class~='not-prose'] *)),
127
108
  .cosy\:prose
128
109
  :where(tfoot):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
129
110
  border-top: 2px solid var(--tw-prose-th-borders, #d1d5db);
@@ -131,8 +112,6 @@
131
112
  font-weight: 600;
132
113
  }
133
114
 
134
- .prose
135
- :where(tfoot td):not(:where([class~='not-prose'], [class~='not-prose'] *)),
136
115
  .cosy\:prose
137
116
  :where(tfoot td):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
138
117
  vertical-align: middle;
@@ -140,10 +119,6 @@
140
119
  border-right: 1px solid rgba(0, 0, 0, 0.05);
141
120
  }
142
121
 
143
- .prose
144
- :where(tfoot td:last-child):not(
145
- :where([class~='not-prose'], [class~='not-prose'] *)
146
- ),
147
122
  .cosy\:prose
148
123
  :where(tfoot td:last-child):not(
149
124
  :where([class~='not-prose'], [class~='not-prose'] *)
@@ -155,9 +130,6 @@
155
130
 
156
131
  /* 默认主题跟随系统主题 - 当 data-theme='default' 且系统是暗黑模式时生效 */
157
132
  @media (prefers-color-scheme: dark) {
158
- [data-theme='default']
159
- .prose.dark\:prose-invert
160
- :where(table):not(:where([class~='not-prose'], [class~='not-prose'] *)),
161
133
  [data-theme='default']
162
134
  .cosy\:prose.cosy\:dark\:prose-invert
163
135
  :where(table):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
@@ -168,29 +140,18 @@
168
140
  0 1px 2px -1px rgba(0, 0, 0, 0.3);
169
141
  }
170
142
 
171
- [data-theme='default']
172
- .prose.dark\:prose-invert
173
- :where(thead):not(:where([class~='not-prose'], [class~='not-prose'] *)),
174
143
  [data-theme='default']
175
144
  .cosy\:prose.cosy\:dark\:prose-invert
176
145
  :where(thead):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
177
146
  background: linear-gradient(to bottom, #374151 0%, #1f2937 100%);
178
147
  }
179
148
 
180
- [data-theme='default']
181
- .prose.dark\:prose-invert
182
- :where(thead th):not(:where([class~='not-prose'], [class~='not-prose'] *)),
183
149
  [data-theme='default']
184
150
  .cosy\:prose.cosy\:dark\:prose-invert
185
151
  :where(thead th):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
186
152
  border-right: 1px solid rgba(255, 255, 255, 0.1);
187
153
  }
188
154
 
189
- [data-theme='default']
190
- .prose.dark\:prose-invert
191
- :where(tbody tr):hover:not(
192
- :where([class~='not-prose'], [class~='not-prose'] *)
193
- ),
194
155
  [data-theme='default']
195
156
  .cosy\:prose.cosy\:dark\:prose-invert
196
157
  :where(tbody tr):hover:not(
@@ -202,11 +163,6 @@
202
163
  0 4px 6px -1px rgba(0, 0, 0, 0.3);
203
164
  }
204
165
 
205
- [data-theme='default']
206
- .prose.dark\:prose-invert
207
- :where(tbody tr:nth-child(even)):not(
208
- :where([class~='not-prose'], [class~='not-prose'] *)
209
- ),
210
166
  [data-theme='default']
211
167
  .cosy\:prose.cosy\:dark\:prose-invert
212
168
  :where(tbody tr:nth-child(even)):not(
@@ -215,27 +171,18 @@
215
171
  background-color: rgba(55, 65, 81, 0.3);
216
172
  }
217
173
 
218
- [data-theme='default']
219
- .prose.dark\:prose-invert
220
- :where(tbody td):not(:where([class~='not-prose'], [class~='not-prose'] *)),
221
174
  [data-theme='default']
222
175
  .cosy\:prose.cosy\:dark\:prose-invert
223
176
  :where(tbody td):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
224
177
  border-right: 1px solid rgba(255, 255, 255, 0.05);
225
178
  }
226
179
 
227
- [data-theme='default']
228
- .prose.dark\:prose-invert
229
- :where(tfoot):not(:where([class~='not-prose'], [class~='not-prose'] *)),
230
180
  [data-theme='default']
231
181
  .cosy\:prose.cosy\:dark\:prose-invert
232
182
  :where(tfoot):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
233
183
  background: linear-gradient(to top, #374151 0%, #1f2937 100%);
234
184
  }
235
185
 
236
- [data-theme='default']
237
- .prose.dark\:prose-invert
238
- :where(tfoot td):not(:where([class~='not-prose'], [class~='not-prose'] *)),
239
186
  [data-theme='default']
240
187
  .cosy\:prose.cosy\:dark\:prose-invert
241
188
  :where(tfoot td):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
@@ -244,9 +191,6 @@
244
191
  }
245
192
 
246
193
  /* 所有暗色主题的通用样式 - 通过 data-theme-tone='dark' 判断 */
247
- [data-theme-tone='dark']
248
- .prose.dark\:prose-invert
249
- :where(table):not(:where([class~='not-prose'], [class~='not-prose'] *)),
250
194
  [data-theme-tone='dark']
251
195
  .cosy\:prose.cosy\:dark\:prose-invert
252
196
  :where(table):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
@@ -257,29 +201,18 @@
257
201
  0 1px 2px -1px rgba(0, 0, 0, 0.3);
258
202
  }
259
203
 
260
- [data-theme-tone='dark']
261
- .prose.dark\:prose-invert
262
- :where(thead):not(:where([class~='not-prose'], [class~='not-prose'] *)),
263
204
  [data-theme-tone='dark']
264
205
  .cosy\:prose.cosy\:dark\:prose-invert
265
206
  :where(thead):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
266
207
  background: linear-gradient(to bottom, #374151 0%, #1f2937 100%);
267
208
  }
268
209
 
269
- [data-theme-tone='dark']
270
- .prose.dark\:prose-invert
271
- :where(thead th):not(:where([class~='not-prose'], [class~='not-prose'] *)),
272
210
  [data-theme-tone='dark']
273
211
  .cosy\:prose.cosy\:dark\:prose-invert
274
212
  :where(thead th):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
275
213
  border-right: 1px solid rgba(255, 255, 255, 0.1);
276
214
  }
277
215
 
278
- [data-theme-tone='dark']
279
- .prose.dark\:prose-invert
280
- :where(tbody tr):hover:not(
281
- :where([class~='not-prose'], [class~='not-prose'] *)
282
- ),
283
216
  [data-theme-tone='dark']
284
217
  .cosy\:prose.cosy\:dark\:prose-invert
285
218
  :where(tbody tr):hover:not(
@@ -291,11 +224,6 @@
291
224
  0 4px 6px -1px rgba(0, 0, 0, 0.3);
292
225
  }
293
226
 
294
- [data-theme-tone='dark']
295
- .prose.dark\:prose-invert
296
- :where(tbody tr:nth-child(even)):not(
297
- :where([class~='not-prose'], [class~='not-prose'] *)
298
- ),
299
227
  [data-theme-tone='dark']
300
228
  .cosy\:prose.cosy\:dark\:prose-invert
301
229
  :where(tbody tr:nth-child(even)):not(
@@ -304,27 +232,18 @@
304
232
  background-color: rgba(55, 65, 81, 0.3);
305
233
  }
306
234
 
307
- [data-theme-tone='dark']
308
- .prose.dark\:prose-invert
309
- :where(tbody td):not(:where([class~='not-prose'], [class~='not-prose'] *)),
310
235
  [data-theme-tone='dark']
311
236
  .cosy\:prose.cosy\:dark\:prose-invert
312
237
  :where(tbody td):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
313
238
  border-right: 1px solid rgba(255, 255, 255, 0.05);
314
239
  }
315
240
 
316
- [data-theme-tone='dark']
317
- .prose.dark\:prose-invert
318
- :where(tfoot):not(:where([class~='not-prose'], [class~='not-prose'] *)),
319
241
  [data-theme-tone='dark']
320
242
  .cosy\:prose.cosy\:dark\:prose-invert
321
243
  :where(tfoot):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
322
244
  background: linear-gradient(to top, #374151 0%, #1f2937 100%);
323
245
  }
324
246
 
325
- [data-theme-tone='dark']
326
- .prose.dark\:prose-invert
327
- :where(tfoot td):not(:where([class~='not-prose'], [class~='not-prose'] *)),
328
247
  [data-theme-tone='dark']
329
248
  .cosy\:prose.cosy\:dark\:prose-invert
330
249
  :where(tfoot td):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
@@ -0,0 +1,165 @@
1
+ ---
2
+ /**
3
+ * @component ApplePad
4
+ *
5
+ * @description
6
+ * ApplePad 组件模拟 iPad 设备的外观,包含状态栏、时间显示和设备边框。
7
+ * 适用于创建平板应用界面原型或展示平板端设计效果。
8
+ *
9
+ * @usage
10
+ * 基本用法:
11
+ * ```astro
12
+ * <ApplePad title="我的应用">
13
+ * <div>应用内容</div>
14
+ * </ApplePad>
15
+ * ```
16
+ *
17
+ * 自定义高度和背景色:
18
+ * ```astro
19
+ * <ApplePad height="xl" backgroundColor="primary/10">
20
+ * <div>应用内容</div>
21
+ * </ApplePad>
22
+ * ```
23
+ *
24
+ * 不显示边框:
25
+ * ```astro
26
+ * <ApplePad showFrame={false}>
27
+ * <div>应用内容</div>
28
+ * </ApplePad>
29
+ * ```
30
+ *
31
+ * @props
32
+ * @prop {'sm'|'md'|'lg'|'xl'|'2xl'|'3xl'|'4xl'|'5xl'} [height='lg'] - 窗口高度选项
33
+ * - sm: 400px
34
+ * - md: 500px
35
+ * - lg: 600px - 默认值
36
+ * - xl: 700px
37
+ * - 2xl: 800px
38
+ * - 3xl: 900px
39
+ * - 4xl: 1000px
40
+ * - 5xl: 1100px
41
+ * @prop {String} [title=''] - 窗口标题
42
+ * @prop {Boolean} [withShadow=true] - 是否显示阴影效果
43
+ * @prop {Boolean} [showFrame=true] - 是否显示 iPad 边框
44
+ * @prop {BackgroundColor} [backgroundColor=''] - 内容区域背景色,等同于为其内部的 Container 设置背景色
45
+ *
46
+ * @slots
47
+ * @slot default - 主要内容区域
48
+ */
49
+
50
+ import { cn } from '../../src/class';
51
+ import type { IApplePadPropsBase } from '../../src/components/apple-pad/applePadPropsBase';
52
+ import {
53
+ DEFAULT_HEIGHT,
54
+ HEIGHT_CLASSES,
55
+ HEIGHT_VALUES,
56
+ IPAD_FRAME_HEIGHT,
57
+ IPAD_FRAME_STATUS_BAR_HEIGHT_ASPECT_RATIO,
58
+ IPAD_FRAME_STATUS_BAR_TOP_ASPECT_RATIO,
59
+ IPAD_FRAME_WIDTH,
60
+ MAIN_CONTENT_HEIGHT_ASPECT_RATIO,
61
+ MAIN_CONTENT_WIDTH_ASPECT_RATIO,
62
+ } from '../../src/components/apple-pad/constants';
63
+ import { AlertDialog } from '../alert-dialog';
64
+ import { Container } from '../container';
65
+ import PadFrame from './PadFrame.astro';
66
+ import StatusBarContent from './StatusBarContent.astro';
67
+
68
+ // Props 定义 - 使用共享接口
69
+ interface Props extends IApplePadPropsBase {}
70
+
71
+ const {
72
+ height = DEFAULT_HEIGHT,
73
+ showFrame = true,
74
+ backgroundColor = undefined,
75
+ } = Astro.props as Props;
76
+
77
+ // 计算当前高度的缩放比例
78
+ const currentHeight = HEIGHT_VALUES[height];
79
+ const scaleRatio = currentHeight / 600;
80
+
81
+ // 生成唯一的ID
82
+ const uniqueId = `apple-pad-${Math.random().toString(36).slice(2, 11)}`;
83
+
84
+ // 响应式数据
85
+ const alertMessage = '';
86
+
87
+ // 使用 classBuilder 构建各个部分的类名
88
+ const padContainerClass = cn()
89
+ .relative()
90
+ .add('not-prose', 'cosy:mx-auto', HEIGHT_CLASSES[height])
91
+ .build();
92
+
93
+ const statusBarClass = cn().absolute().w('full').add('cosy:z-50').build();
94
+
95
+ const contentAreaClass = cn()
96
+ .absolute()
97
+ .add('cosy:inset-0')
98
+ .h('full')
99
+ .flex('col')
100
+ .build();
101
+
102
+ const containerClass = cn()
103
+ .h('full')
104
+ .add('cosy:overflow-y-auto', 'cosy:overscroll-y-contain')
105
+ .build();
106
+ ---
107
+
108
+ <div
109
+ class={padContainerClass}
110
+ style={`aspect-ratio: ${IPAD_FRAME_WIDTH}/${IPAD_FRAME_HEIGHT};`}
111
+ apple-pad>
112
+ <!-- iPad 边框 -->
113
+ {showFrame && <PadFrame />}
114
+
115
+ <!-- 顶部状态栏 -->
116
+ <div
117
+ class={statusBarClass}
118
+ style={`top: ${IPAD_FRAME_STATUS_BAR_TOP_ASPECT_RATIO * 100}%; height: ${IPAD_FRAME_STATUS_BAR_HEIGHT_ASPECT_RATIO * 100}%; width: ${MAIN_CONTENT_WIDTH_ASPECT_RATIO * 100}%; left: 50%; transform: translate(-50%, 0); padding-left: 5%; padding-right: 5%;`}>
119
+ <!-- StatusBarContent 组件 -->
120
+ <StatusBarContent scaleRatio={scaleRatio} />
121
+ </div>
122
+
123
+ <!-- 内容区域 -->
124
+ <div
125
+ class={contentAreaClass}
126
+ style={`width: ${MAIN_CONTENT_WIDTH_ASPECT_RATIO * 100}%; height: ${MAIN_CONTENT_HEIGHT_ASPECT_RATIO * 100}%; left: 50%; top: 50%; transform: translate(-50%, -50%);`}>
127
+ <Container
128
+ rounded="lg"
129
+ height="full"
130
+ padding="none"
131
+ class={containerClass}
132
+ background={backgroundColor || 'accent/90'}>
133
+ <slot />
134
+ </Container>
135
+ </div>
136
+
137
+ <!-- iPad 边框(第二次渲染,盖住内容四角) -->
138
+ {showFrame && <PadFrame />}
139
+ </div>
140
+
141
+ <AlertDialog id={`${uniqueId}-alert`} message={alertMessage} />
142
+
143
+ <script>
144
+ // 全局函数,用于处理状态栏时间更新
145
+ function updateTime() {
146
+ const now = new Date();
147
+ const hours = now.getHours().toString().padStart(2, '0');
148
+ const minutes = now.getMinutes().toString().padStart(2, '0');
149
+ return `${hours}:${minutes}`;
150
+ }
151
+
152
+ // 更新时间显示
153
+ function updateStatusBarTime() {
154
+ const timeElements = document.querySelectorAll('[data-time-text]');
155
+ timeElements.forEach((element) => {
156
+ (element as HTMLElement).textContent = updateTime();
157
+ });
158
+ }
159
+
160
+ // 初始化并设置定时器
161
+ document.addEventListener('DOMContentLoaded', () => {
162
+ updateStatusBarTime();
163
+ setInterval(updateStatusBarTime, 60000); // 每分钟更新一次
164
+ });
165
+ </script>
@@ -0,0 +1,23 @@
1
+ ---
2
+ /**
3
+ * @component PadFrame
4
+ * @description ApplePad 组件的内部边框组件,用于显示 iPad 设备的边框
5
+ */
6
+
7
+ import { cn } from '../../src/class';
8
+ import ipadFrame from '../../src/components/apple-pad/assets/iPad Air 11" - M2 - Purple - Portrait.png';
9
+ import { Image } from '../image';
10
+
11
+ // 使用 class builder 构建类名
12
+ const frameClass = cn()
13
+ .add('cosy:max-w-full', 'cosy:max-h-full')
14
+ .absolute()
15
+ .add('cosy:top-0', 'cosy:left-0')
16
+ .add('cosy:z-10')
17
+ .add('cosy:pointer-events-none')
18
+ .build();
19
+ ---
20
+
21
+ <div class={frameClass}>
22
+ <Image src={ipadFrame} alt="iPad frame" />
23
+ </div>