@coffic/cosy-ui 0.9.20 → 0.9.23
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 +1 -1
- package/dist/src-astro/alert/Alert.astro +28 -1
- package/dist/src-astro/confirm-dialog/ConfirmDialog.astro +29 -4
- package/dist/src-astro/container/Container.astro +40 -0
- package/dist/src-astro/container/index.ts +0 -15
- package/dist/src-astro/errors/404.astro +4 -8
- package/dist/src-astro/heading/Heading.astro +202 -83
- package/dist/src-astro/heading/HeadingAnchor.astro +33 -0
- package/dist/src-astro/language-switcher/LanguageSwitcher.astro +1 -3
- package/dist/src-astro/layout-app/AppLayout.astro +160 -4
- package/dist/src-astro/layout-basic/BaseLayout.astro +2 -5
- package/dist/src-astro/layout-basic/index.ts +2 -0
- package/dist/src-astro/{types → layout-basic}/meta.ts +4 -0
- package/dist/src-astro/layout-dashboard/index.ts +1 -1
- package/dist/src-astro/modal/CloseButton.astro +28 -0
- package/dist/src-astro/modal/Modal.astro +47 -44
- package/dist/src-astro/placeholder/PlaceHolder.astro +142 -0
- package/dist/src-astro/placeholder/index.ts +2 -0
- package/dist/src-astro/placeholder/types.ts +16 -0
- package/dist/src-astro/products/ProductCard.astro +3 -1
- package/dist/src-astro/products/Products.astro +48 -0
- package/dist/src-astro/sidebar/Sidebar.astro +19 -20
- package/dist/src-astro/sidebar/SidebarNav.astro +6 -9
- package/dist/src-astro/types/layout.ts +1 -1
- package/package.json +17 -17
- package/dist/src-astro/container/EContainerBasic.astro +0 -15
- package/dist/src-astro/container/EContainerBasicContainer.astro +0 -11
- package/dist/src-astro/container/EContainerFlexBetween.astro +0 -23
- package/dist/src-astro/container/EContainerFlexCenter.astro +0 -30
- package/dist/src-astro/container/EContainerFlexColumn.astro +0 -23
- package/dist/src-astro/container/EContainerFlexContainer.astro +0 -34
- package/dist/src-astro/container/EContainerFlexRow.astro +0 -23
- package/dist/src-astro/container/EContainerPadding.astro +0 -32
- package/dist/src-astro/container/EContainerPaddingContainer.astro +0 -11
- package/dist/src-astro/container/EContainerSizes.astro +0 -36
- package/dist/src-astro/container/EContainerSizesContainer.astro +0 -11
@@ -76,9 +76,7 @@ if (renderState.shouldRender && Astro.currentLocale) {
|
|
76
76
|
|
77
77
|
{
|
78
78
|
renderState.shouldRender && (
|
79
|
-
<div
|
80
|
-
transition:persist
|
81
|
-
class={`cosy:dropdown cosy:dropdown-end ${className}`}>
|
79
|
+
<div class={`cosy:dropdown cosy:dropdown-end ${className}`}>
|
82
80
|
<div tabindex="0" role="button" class:list={['cosy:btn cosy:btn-ghost']}>
|
83
81
|
<span class="cosy:mr-1">{renderState.currentLanguageName}</span>
|
84
82
|
<ChevronDownIcon size="16px" class="cosy:w-4 cosy:h-4" />
|
@@ -49,6 +49,12 @@
|
|
49
49
|
* @param {Object} metaConfig - 元数据配置
|
50
50
|
* @param {Object} rest - 其他属性
|
51
51
|
*
|
52
|
+
* @slot default - 主内容区域
|
53
|
+
* @slot navbar-start - 导航栏开始位置的内容
|
54
|
+
* @slot navbar-center - 导航栏中间位置的内容
|
55
|
+
* @slot navbar-end - 导航栏结束位置的内容
|
56
|
+
* @slot modal-search - 搜索模态框内容,当提供此slot时会显示搜索按钮
|
57
|
+
*
|
52
58
|
* @example
|
53
59
|
* ```astro
|
54
60
|
* ---
|
@@ -163,6 +169,72 @@
|
|
163
169
|
* <p>这是文档的主要内容</p>
|
164
170
|
* </AppLayout>
|
165
171
|
* ```
|
172
|
+
*
|
173
|
+
* 自定义导航栏示例:
|
174
|
+
* ```astro
|
175
|
+
* <AppLayout
|
176
|
+
* metaConfig={{
|
177
|
+
* title: "文档标题",
|
178
|
+
* description: "文档描述"
|
179
|
+
* }}
|
180
|
+
* sidebarConfig={{
|
181
|
+
* sidebarItems: sidebarItems
|
182
|
+
* }}
|
183
|
+
* >
|
184
|
+
* <!-- 导航栏开始位置 -->
|
185
|
+
* <div slot="navbar-start">
|
186
|
+
* <h1 class="cosy:text-xl cosy:font-bold">我的应用</h1>
|
187
|
+
* </div>
|
188
|
+
*
|
189
|
+
* <!-- 导航栏中间位置 -->
|
190
|
+
* <div slot="navbar-center">
|
191
|
+
* <nav class="cosy:flex cosy:gap-4">
|
192
|
+
* <a href="/docs" class="cosy:link cosy:link-hover">文档</a>
|
193
|
+
* <a href="/components" class="cosy:link cosy:link-hover">组件</a>
|
194
|
+
* <a href="/examples" class="cosy:link cosy:link-hover">示例</a>
|
195
|
+
* </nav>
|
196
|
+
* </div>
|
197
|
+
*
|
198
|
+
* <!-- 导航栏结束位置 -->
|
199
|
+
* <div slot="navbar-end">
|
200
|
+
* <button class="cosy:btn cosy:btn-primary">登录</button>
|
201
|
+
* </div>
|
202
|
+
*
|
203
|
+
* <h1>文档内容</h1>
|
204
|
+
* <p>这是文档的主要内容</p>
|
205
|
+
* </AppLayout>
|
206
|
+
* ```
|
207
|
+
*
|
208
|
+
* 搜索功能示例:
|
209
|
+
* ```astro
|
210
|
+
* <AppLayout
|
211
|
+
* metaConfig={{
|
212
|
+
* title: "文档标题",
|
213
|
+
* description: "文档描述"
|
214
|
+
* }}
|
215
|
+
* sidebarConfig={{
|
216
|
+
* sidebarItems: sidebarItems
|
217
|
+
* }}
|
218
|
+
* >
|
219
|
+
* <h1>文档内容</h1>
|
220
|
+
* <p>这是文档的主要内容</p>
|
221
|
+
*
|
222
|
+
* <!-- 提供搜索模态框内容,会自动显示搜索按钮 -->
|
223
|
+
* <div slot="modal-search">
|
224
|
+
* <div class="cosy:space-y-4">
|
225
|
+
* <input
|
226
|
+
* type="text"
|
227
|
+
* placeholder="搜索文档..."
|
228
|
+
* class="cosy:input cosy:input-bordered cosy:w-full"
|
229
|
+
* />
|
230
|
+
* <div class="cosy:flex cosy:gap-2">
|
231
|
+
* <button class="cosy:btn cosy:btn-primary">搜索</button>
|
232
|
+
* <button class="cosy:btn cosy:btn-ghost">清除</button>
|
233
|
+
* </div>
|
234
|
+
* </div>
|
235
|
+
* </div>
|
236
|
+
* </AppLayout>
|
237
|
+
* ```
|
166
238
|
*/
|
167
239
|
|
168
240
|
import '../../style.ts';
|
@@ -174,6 +246,9 @@ import {
|
|
174
246
|
Container,
|
175
247
|
Main,
|
176
248
|
Sidebar,
|
249
|
+
Modal,
|
250
|
+
SearchIcon,
|
251
|
+
Button,
|
177
252
|
} from '../../index-astro';
|
178
253
|
import SkeletonLoader from './SkeletonLoader.astro';
|
179
254
|
|
@@ -194,6 +269,60 @@ const {
|
|
194
269
|
loadingDelay = 100,
|
195
270
|
...rest
|
196
271
|
}: Props = Astro.props;
|
272
|
+
|
273
|
+
// 动态计算Container最小高度
|
274
|
+
function getContainerMinHeightClass(headerHeight: string = 'md') {
|
275
|
+
const heightValueMap = {
|
276
|
+
'3xs': 'cosy:min-h-[calc(100vh-1rem)]',
|
277
|
+
'2xs': 'cosy:min-h-[calc(100vh-1.5rem)]',
|
278
|
+
xs: 'cosy:min-h-[calc(100vh-2rem)]',
|
279
|
+
sm: 'cosy:min-h-[calc(100vh-2.5rem)]',
|
280
|
+
md: 'cosy:min-h-[calc(100vh-3rem)]',
|
281
|
+
lg: 'cosy:min-h-[calc(100vh-4rem)]',
|
282
|
+
xl: 'cosy:min-h-[calc(100vh-5rem)]',
|
283
|
+
};
|
284
|
+
return (
|
285
|
+
heightValueMap[headerHeight as keyof typeof heightValueMap] ||
|
286
|
+
'cosy:min-h-[calc(100vh-3rem)]'
|
287
|
+
);
|
288
|
+
}
|
289
|
+
|
290
|
+
const containerMinHeightClass = getContainerMinHeightClass(
|
291
|
+
headerConfig?.height
|
292
|
+
);
|
293
|
+
|
294
|
+
// 计算Sidebar的top值和高度值
|
295
|
+
function getSidebarTopClass(headerHeight: string = 'md') {
|
296
|
+
const topMap = {
|
297
|
+
'3xs': 'cosy:top-4',
|
298
|
+
'2xs': 'cosy:top-6',
|
299
|
+
xs: 'cosy:top-8',
|
300
|
+
sm: 'cosy:top-10',
|
301
|
+
md: 'cosy:top-12',
|
302
|
+
lg: 'cosy:top-16',
|
303
|
+
xl: 'cosy:top-20',
|
304
|
+
};
|
305
|
+
return topMap[headerHeight as keyof typeof topMap] || 'cosy:top-12';
|
306
|
+
}
|
307
|
+
|
308
|
+
function getSidebarHeightClass(headerHeight: string = 'md') {
|
309
|
+
const heightValueMap = {
|
310
|
+
'3xs': 'cosy:h-[calc(100vh-1rem)]',
|
311
|
+
'2xs': 'cosy:h-[calc(100vh-1.5rem)]',
|
312
|
+
xs: 'cosy:h-[calc(100vh-2rem)]',
|
313
|
+
sm: 'cosy:h-[calc(100vh-2.5rem)]',
|
314
|
+
md: 'cosy:h-[calc(100vh-3rem)]',
|
315
|
+
lg: 'cosy:h-[calc(100vh-4rem)]',
|
316
|
+
xl: 'cosy:h-[calc(100vh-5rem)]',
|
317
|
+
};
|
318
|
+
return (
|
319
|
+
heightValueMap[headerHeight as keyof typeof heightValueMap] ||
|
320
|
+
'cosy:h-[calc(100vh-3rem)]'
|
321
|
+
);
|
322
|
+
}
|
323
|
+
|
324
|
+
const sidebarTopClass = getSidebarTopClass(headerConfig?.height);
|
325
|
+
const sidebarHeightClass = getSidebarHeightClass(headerConfig?.height);
|
197
326
|
---
|
198
327
|
|
199
328
|
<BaseLayout {...metaConfig} debug={debug}>
|
@@ -207,23 +336,41 @@ const {
|
|
207
336
|
<slot name="navbar-center" />
|
208
337
|
</div>
|
209
338
|
<div slot="navbar-end">
|
339
|
+
{Astro.slots.has('modal-search') && (
|
340
|
+
<Button data-modal-target="modalSearch" variant="ghost" size="sm">
|
341
|
+
<SearchIcon size="24px" />
|
342
|
+
</Button>
|
343
|
+
)}
|
210
344
|
<slot name="navbar-end" />
|
211
345
|
</div>
|
212
346
|
</Header>
|
213
347
|
)
|
214
348
|
}
|
215
349
|
|
216
|
-
<Container
|
350
|
+
<Container
|
351
|
+
flex="row"
|
352
|
+
gap="none"
|
353
|
+
size="full"
|
354
|
+
padding="none"
|
355
|
+
class={containerMinHeightClass}>
|
217
356
|
<!-- 侧边栏容器 -->
|
218
|
-
{
|
357
|
+
{
|
358
|
+
showSidebar && (
|
359
|
+
<Sidebar
|
360
|
+
{...sidebarConfig}
|
361
|
+
topClass={sidebarTopClass}
|
362
|
+
heightClass={sidebarHeightClass}
|
363
|
+
/>
|
364
|
+
)
|
365
|
+
}
|
219
366
|
|
220
367
|
<!-- 主内容区域 -->
|
221
|
-
<Main {...mainContentConfig}>
|
368
|
+
<Main {...mainContentConfig} class="cosy:flex-1 cosy:min-w-0">
|
222
369
|
<SkeletonLoader
|
223
370
|
showLoading={true}
|
224
371
|
loadingSize="xl"
|
225
372
|
loadingDelay={loadingDelay}
|
226
|
-
skeletonClass="cosy:w-full cosy:h-screen
|
373
|
+
skeletonClass="cosy:w-full cosy:h-screen cosy:flex cosy:items-center cosy:justify-center">
|
227
374
|
<slot />
|
228
375
|
</SkeletonLoader>
|
229
376
|
</Main>
|
@@ -238,6 +385,15 @@ const {
|
|
238
385
|
)
|
239
386
|
}
|
240
387
|
|
388
|
+
<!-- 搜索模态框 -->
|
389
|
+
{
|
390
|
+
Astro.slots.has('modal-search') && (
|
391
|
+
<Modal id="modalSearch" title="搜索">
|
392
|
+
<slot name="modal-search" />
|
393
|
+
</Modal>
|
394
|
+
)
|
395
|
+
}
|
396
|
+
|
241
397
|
<script>
|
242
398
|
// Handle sidebar toggle
|
243
399
|
const sidebarToggle = document.getElementById('sidebar-toggle');
|
@@ -50,13 +50,10 @@
|
|
50
50
|
*/
|
51
51
|
|
52
52
|
import '../../style.ts';
|
53
|
-
import { type IMetaProps } from '
|
53
|
+
import { type IMetaProps } from './meta';
|
54
54
|
import { ClientRouter } from 'astro:transitions';
|
55
55
|
|
56
|
-
export interface Props extends IMetaProps {
|
57
|
-
/** 最小显示时间(毫秒),默认300ms,确保用户能看到加载状态 */
|
58
|
-
loadingMinDisplayTime?: number;
|
59
|
-
}
|
56
|
+
export interface Props extends IMetaProps {}
|
60
57
|
|
61
58
|
const {
|
62
59
|
title,
|
@@ -0,0 +1,28 @@
|
|
1
|
+
---
|
2
|
+
/**
|
3
|
+
* @component CloseButton
|
4
|
+
*
|
5
|
+
* @description
|
6
|
+
* 模态框的关闭按钮组件,用于关闭模态对话框。
|
7
|
+
* 使用 form method="dialog" 来关闭模态框。
|
8
|
+
*
|
9
|
+
* @usage
|
10
|
+
* ```astro
|
11
|
+
* <CloseButton />
|
12
|
+
* ```
|
13
|
+
*/
|
14
|
+
|
15
|
+
import '../../style.ts';
|
16
|
+
import { Button } from '../../index-astro';
|
17
|
+
---
|
18
|
+
|
19
|
+
<form method="dialog">
|
20
|
+
<Button
|
21
|
+
variant="accent"
|
22
|
+
size="sm"
|
23
|
+
shape="circle"
|
24
|
+
formmethod="dialog"
|
25
|
+
class="cosy:modal-close-button">
|
26
|
+
✕
|
27
|
+
</Button>
|
28
|
+
</form>
|
@@ -45,7 +45,8 @@
|
|
45
45
|
*/
|
46
46
|
|
47
47
|
import '../../style.ts';
|
48
|
-
import {
|
48
|
+
import { Heading } from '../../index-astro';
|
49
|
+
import CloseButton from './CloseButton.astro';
|
49
50
|
|
50
51
|
interface Props {
|
51
52
|
/**
|
@@ -56,43 +57,24 @@ interface Props {
|
|
56
57
|
* 模态框的标题
|
57
58
|
*/
|
58
59
|
title?: string;
|
59
|
-
/**
|
60
|
-
* 是否显示关闭按钮
|
61
|
-
* @default true
|
62
|
-
*/
|
63
|
-
showCloseButton?: boolean;
|
64
60
|
/**
|
65
61
|
* 自定义类名
|
66
62
|
*/
|
67
63
|
class?: string;
|
68
64
|
}
|
69
65
|
|
70
|
-
const {
|
71
|
-
id,
|
72
|
-
title,
|
73
|
-
showCloseButton = true,
|
74
|
-
class: className = '',
|
75
|
-
} = Astro.props;
|
66
|
+
const { id, title = '', class: className = '' } = Astro.props;
|
76
67
|
---
|
77
68
|
|
78
69
|
<dialog id={id} class="cosy:modal">
|
79
|
-
<div class:list={['cosy:modal-box', className]}>
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
formmethod="dialog"
|
88
|
-
class="cosy:modal-close-button">
|
89
|
-
✕
|
90
|
-
</Button>
|
91
|
-
</form>
|
92
|
-
)
|
93
|
-
}
|
94
|
-
|
95
|
-
{title && <h3 class="cosy:modal-title">{title}</h3>}
|
70
|
+
<div class:list={['cosy:modal-box cosy:pt-0', className]}>
|
71
|
+
<div
|
72
|
+
class="cosy:flex cosy:justify-between cosy:items-center cosy:border-b-1 cosy:border-base-300 cosy:mb-4 not-prose">
|
73
|
+
<Heading level={4} class="cosy:modal-title cosy:m-0">
|
74
|
+
{title}
|
75
|
+
</Heading>
|
76
|
+
<CloseButton class="cosy:absolute" />
|
77
|
+
</div>
|
96
78
|
|
97
79
|
<div class="cosy:modal-content">
|
98
80
|
<slot />
|
@@ -102,25 +84,46 @@ const {
|
|
102
84
|
<slot name="actions" />
|
103
85
|
</div>
|
104
86
|
</div>
|
105
|
-
|
106
|
-
<form method="dialog" class="cosy:modal-backdrop">
|
107
|
-
<button>关闭</button>
|
108
|
-
</form>
|
109
87
|
</dialog>
|
110
88
|
|
111
89
|
<script is:inline define:vars={{ id }}>
|
112
|
-
|
113
|
-
|
90
|
+
let handleClick;
|
91
|
+
|
92
|
+
function initializeModal() {
|
114
93
|
const modal = document.getElementById(id);
|
115
|
-
if (!modal)
|
94
|
+
if (!modal) {
|
95
|
+
return;
|
96
|
+
}
|
116
97
|
|
117
|
-
//
|
118
|
-
|
119
|
-
.
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
98
|
+
// 移除之前的事件监听器(如果存在)
|
99
|
+
if (handleClick) {
|
100
|
+
document.removeEventListener('click', handleClick);
|
101
|
+
}
|
102
|
+
|
103
|
+
// 使用事件委托来处理动态加载的内容
|
104
|
+
handleClick = (event) => {
|
105
|
+
const target = event.target;
|
106
|
+
// 使用 closest() 查找最近的匹配元素,包括按钮内部的元素
|
107
|
+
const trigger = target.closest(`[data-modal-target="${id}"]`);
|
108
|
+
if (trigger) {
|
109
|
+
console.log('Modal: 触发模态框', id);
|
110
|
+
modal.showModal();
|
111
|
+
}
|
112
|
+
};
|
113
|
+
|
114
|
+
document.addEventListener('click', handleClick);
|
115
|
+
}
|
116
|
+
|
117
|
+
// Astro 页面切换时初始化
|
118
|
+
document.addEventListener('astro:page-load', () => {
|
119
|
+
initializeModal();
|
120
|
+
});
|
121
|
+
|
122
|
+
// 页面卸载时清理事件监听器
|
123
|
+
document.addEventListener('astro:before-preparation', () => {
|
124
|
+
if (handleClick) {
|
125
|
+
document.removeEventListener('click', handleClick);
|
126
|
+
handleClick = null;
|
127
|
+
}
|
125
128
|
});
|
126
129
|
</script>
|
@@ -0,0 +1,142 @@
|
|
1
|
+
---
|
2
|
+
/**
|
3
|
+
* @component PlaceHolder
|
4
|
+
* @description 占位符组件,用于在布局中占用指定的空间
|
5
|
+
* @usage
|
6
|
+
* ```astro
|
7
|
+
* <PlaceHolder width="md" height="lg" padding="md" background="base-200">
|
8
|
+
* <p>内容</p>
|
9
|
+
* </PlaceHolder>
|
10
|
+
* ```
|
11
|
+
* @props
|
12
|
+
* - width: 宽度尺寸 ('none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | 'full')
|
13
|
+
* - height: 高度尺寸 ('none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | 'full')
|
14
|
+
* - padding: 内边距大小 ('none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl')
|
15
|
+
* - background: 背景色类名,如 'base-200', 'primary', 'secondary'
|
16
|
+
* - class: 自定义 CSS 类名
|
17
|
+
* @slots
|
18
|
+
* - default: 占位符内容
|
19
|
+
*/
|
20
|
+
import '../../style.ts';
|
21
|
+
import type { PlaceHolderProps } from './types';
|
22
|
+
|
23
|
+
interface Props extends PlaceHolderProps {
|
24
|
+
width?:
|
25
|
+
| 'none'
|
26
|
+
| 'xs'
|
27
|
+
| 'sm'
|
28
|
+
| 'md'
|
29
|
+
| 'lg'
|
30
|
+
| 'xl'
|
31
|
+
| '2xl'
|
32
|
+
| '3xl'
|
33
|
+
| '4xl'
|
34
|
+
| '5xl'
|
35
|
+
| '6xl'
|
36
|
+
| 'full';
|
37
|
+
height?:
|
38
|
+
| 'none'
|
39
|
+
| 'xs'
|
40
|
+
| 'sm'
|
41
|
+
| 'md'
|
42
|
+
| 'lg'
|
43
|
+
| 'xl'
|
44
|
+
| '2xl'
|
45
|
+
| '3xl'
|
46
|
+
| '4xl'
|
47
|
+
| '5xl'
|
48
|
+
| '6xl'
|
49
|
+
| 'full';
|
50
|
+
padding?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
51
|
+
background?: string;
|
52
|
+
class?: string;
|
53
|
+
}
|
54
|
+
|
55
|
+
const {
|
56
|
+
width = 'md',
|
57
|
+
height = 'md',
|
58
|
+
padding = 'none',
|
59
|
+
background,
|
60
|
+
class: className = '',
|
61
|
+
} = Astro.props;
|
62
|
+
|
63
|
+
// 宽度样式映射
|
64
|
+
const widthClassMap = {
|
65
|
+
none: '',
|
66
|
+
xs: 'cosy:w-8',
|
67
|
+
sm: 'cosy:w-16',
|
68
|
+
md: 'cosy:w-24',
|
69
|
+
lg: 'cosy:w-32',
|
70
|
+
xl: 'cosy:w-40',
|
71
|
+
'2xl': 'cosy:w-48',
|
72
|
+
'3xl': 'cosy:w-56',
|
73
|
+
'4xl': 'cosy:w-64',
|
74
|
+
'5xl': 'cosy:w-72',
|
75
|
+
'6xl': 'cosy:w-80',
|
76
|
+
full: 'cosy:w-full',
|
77
|
+
} as const;
|
78
|
+
|
79
|
+
// 高度样式映射
|
80
|
+
const heightClassMap = {
|
81
|
+
none: '',
|
82
|
+
xs: 'cosy:h-8',
|
83
|
+
sm: 'cosy:h-16',
|
84
|
+
md: 'cosy:h-24',
|
85
|
+
lg: 'cosy:h-32',
|
86
|
+
xl: 'cosy:h-40',
|
87
|
+
'2xl': 'cosy:h-48',
|
88
|
+
'3xl': 'cosy:h-56',
|
89
|
+
'4xl': 'cosy:h-64',
|
90
|
+
'5xl': 'cosy:h-72',
|
91
|
+
'6xl': 'cosy:h-80',
|
92
|
+
full: 'cosy:h-full',
|
93
|
+
} as const;
|
94
|
+
|
95
|
+
// 内边距样式映射
|
96
|
+
const paddingClassMap = {
|
97
|
+
none: '',
|
98
|
+
xs: 'cosy:p-1',
|
99
|
+
sm: 'cosy:p-2',
|
100
|
+
md: 'cosy:p-4',
|
101
|
+
lg: 'cosy:p-6',
|
102
|
+
xl: 'cosy:p-8',
|
103
|
+
} as const;
|
104
|
+
|
105
|
+
// 背景色样式映射
|
106
|
+
const backgroundClassMap = {
|
107
|
+
'base-100': 'cosy:bg-base-100',
|
108
|
+
'base-200': 'cosy:bg-base-200',
|
109
|
+
'base-300': 'cosy:bg-base-300',
|
110
|
+
primary: 'cosy:bg-primary',
|
111
|
+
secondary: 'cosy:bg-secondary',
|
112
|
+
accent: 'cosy:bg-accent',
|
113
|
+
info: 'cosy:bg-info',
|
114
|
+
success: 'cosy:bg-success',
|
115
|
+
warning: 'cosy:bg-warning',
|
116
|
+
error: 'cosy:bg-error',
|
117
|
+
} as const;
|
118
|
+
|
119
|
+
const widthClass = widthClassMap[width as keyof typeof widthClassMap] || '';
|
120
|
+
const heightClass = heightClassMap[height as keyof typeof heightClassMap] || '';
|
121
|
+
const paddingClass =
|
122
|
+
paddingClassMap[padding as keyof typeof paddingClassMap] || '';
|
123
|
+
const backgroundClass = background
|
124
|
+
? backgroundClassMap[background as keyof typeof backgroundClassMap] || ''
|
125
|
+
: '';
|
126
|
+
|
127
|
+
const combinedClass =
|
128
|
+
`placeholder ${widthClass} ${heightClass} ${paddingClass} ${backgroundClass} ${className}`.trim();
|
129
|
+
---
|
130
|
+
|
131
|
+
<div class={combinedClass}>
|
132
|
+
<slot />
|
133
|
+
</div>
|
134
|
+
|
135
|
+
<style>
|
136
|
+
.placeholder {
|
137
|
+
display: flex;
|
138
|
+
align-items: center;
|
139
|
+
justify-content: center;
|
140
|
+
border-radius: 0.5rem;
|
141
|
+
}
|
142
|
+
</style>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
export type PlaceHolderWidth = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | 'full';
|
2
|
+
export type PlaceHolderHeight = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | 'full';
|
3
|
+
export type PlaceHolderPadding = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
4
|
+
|
5
|
+
export interface PlaceHolderProps {
|
6
|
+
/** 占位符宽度 */
|
7
|
+
width?: PlaceHolderWidth;
|
8
|
+
/** 占位符高度 */
|
9
|
+
height?: PlaceHolderHeight;
|
10
|
+
/** 内边距大小 */
|
11
|
+
padding?: PlaceHolderPadding;
|
12
|
+
/** 背景色类名,如 'base-200', 'primary', 'secondary' */
|
13
|
+
background?: string;
|
14
|
+
/** 自定义 CSS 类名 */
|
15
|
+
class?: string;
|
16
|
+
}
|
@@ -81,6 +81,8 @@
|
|
81
81
|
* description="无阴影的简洁风格"
|
82
82
|
* />
|
83
83
|
* ```
|
84
|
+
*
|
85
|
+
|
84
86
|
*/
|
85
87
|
|
86
88
|
import {
|
@@ -321,7 +323,7 @@ const buttonsContainerClass =
|
|
321
323
|
|
322
324
|
<div
|
323
325
|
class:list={[
|
324
|
-
'cosy:card cosy:bg-base-
|
326
|
+
'cosy:card cosy:bg-base-200 cosy:transition-shadow cosy:duration-300',
|
325
327
|
shadowStyles[shadow],
|
326
328
|
currentSize.card,
|
327
329
|
equalHeight && currentSize.cardHeight,
|
@@ -60,6 +60,22 @@
|
|
60
60
|
* products={products}
|
61
61
|
* />
|
62
62
|
* ```
|
63
|
+
*
|
64
|
+
* 显示容器边框:
|
65
|
+
* ```astro
|
66
|
+
* <Products
|
67
|
+
* showBorder={true}
|
68
|
+
* products={products}
|
69
|
+
* />
|
70
|
+
* ```
|
71
|
+
*
|
72
|
+
* 设置上下外边距:
|
73
|
+
* ```astro
|
74
|
+
* <Products
|
75
|
+
* margin="lg"
|
76
|
+
* products={products}
|
77
|
+
* />
|
78
|
+
* ```
|
63
79
|
*/
|
64
80
|
|
65
81
|
import { ProductCard } from '../../index-astro';
|
@@ -81,6 +97,9 @@ type ResponsiveColumns = {
|
|
81
97
|
// 定义间距大小
|
82
98
|
type GapSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
83
99
|
|
100
|
+
// 定义外边距大小
|
101
|
+
type MarginSize = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
102
|
+
|
84
103
|
// 定义布局类型
|
85
104
|
type LayoutType = 'grid' | 'list';
|
86
105
|
|
@@ -125,6 +144,21 @@ export interface Props {
|
|
125
144
|
* 应用于所有ProductCard
|
126
145
|
*/
|
127
146
|
descriptionLines?: number;
|
147
|
+
/**
|
148
|
+
* 是否显示容器边框
|
149
|
+
* 控制Products组件整体容器的边框显示
|
150
|
+
*/
|
151
|
+
showBorder?: boolean;
|
152
|
+
/**
|
153
|
+
* 上下外边距
|
154
|
+
* - none: 无外边距
|
155
|
+
* - xs: 超小外边距
|
156
|
+
* - sm: 小外边距
|
157
|
+
* - md: 中等外边距(默认)
|
158
|
+
* - lg: 大外边距
|
159
|
+
* - xl: 超大外边距
|
160
|
+
*/
|
161
|
+
margin?: MarginSize;
|
128
162
|
/**
|
129
163
|
* 自定义类名
|
130
164
|
*/
|
@@ -139,6 +173,8 @@ const {
|
|
139
173
|
gap = 'md',
|
140
174
|
equalHeight = true,
|
141
175
|
descriptionLines,
|
176
|
+
showBorder = false,
|
177
|
+
margin = 'md',
|
142
178
|
class: className = '',
|
143
179
|
} = Astro.props;
|
144
180
|
|
@@ -151,6 +187,16 @@ const gapMap = {
|
|
151
187
|
xl: 'cosy:gap-8',
|
152
188
|
};
|
153
189
|
|
190
|
+
// 外边距映射
|
191
|
+
const marginMap = {
|
192
|
+
none: '',
|
193
|
+
xs: 'cosy:my-1',
|
194
|
+
sm: 'cosy:my-2',
|
195
|
+
md: 'cosy:my-4',
|
196
|
+
lg: 'cosy:my-6',
|
197
|
+
xl: 'cosy:my-8',
|
198
|
+
};
|
199
|
+
|
154
200
|
// 获取响应式列数类名
|
155
201
|
const getColumnsClasses = () => {
|
156
202
|
if (typeof columns === 'number') {
|
@@ -181,7 +227,9 @@ const getLayoutClasses = () => {
|
|
181
227
|
const containerClasses = [
|
182
228
|
...getLayoutClasses(),
|
183
229
|
gapMap[gap],
|
230
|
+
marginMap[margin],
|
184
231
|
'cosy:w-full',
|
232
|
+
showBorder && 'cosy:border cosy:border-base-300 cosy:p-4 cosy:rounded-lg',
|
185
233
|
className,
|
186
234
|
];
|
187
235
|
---
|