@coffic/cosy-ui 0.9.22 → 0.9.24
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 +0 -2
- package/dist/src-astro/confirm-dialog/ConfirmDialog.astro +29 -4
- package/dist/src-astro/footer/Footer.astro +0 -1
- package/dist/src-astro/layout-app/AppLayout.astro +89 -0
- package/dist/src-astro/layout-basic/BaseLayout.astro +2 -5
- package/dist/src-astro/layout-basic/index.ts +3 -0
- package/dist/src-astro/{types → layout-basic}/layout.ts +4 -4
- package/dist/src-astro/{types → layout-basic}/meta.ts +4 -0
- package/dist/src-astro/modal/CloseButton.astro +28 -0
- package/dist/src-astro/modal/Modal.astro +57 -44
- package/package.json +1 -1
package/dist/index-astro.ts
CHANGED
@@ -58,9 +58,7 @@ export * from './src-astro/types/article';
|
|
58
58
|
export * from './src-astro/types/footer';
|
59
59
|
export * from './src-astro/types/header';
|
60
60
|
export * from './src-astro/types/heading';
|
61
|
-
export * from './src-astro/types/layout';
|
62
61
|
export * from './src-astro/types/main';
|
63
|
-
export * from './src-astro/types/meta';
|
64
62
|
export * from './src-astro/types/nav';
|
65
63
|
export * from './src-astro/types/product';
|
66
64
|
export * from './src-astro/types/sidebar';
|
@@ -92,11 +92,27 @@ const style = getConfirmDialogStyle();
|
|
92
92
|
|
93
93
|
<script is:inline define:vars={{ id }}>
|
94
94
|
// 为了方便使用,我们提供一些辅助方法
|
95
|
-
|
95
|
+
function initializeConfirmDialog() {
|
96
96
|
const dialog = document.getElementById(id);
|
97
|
-
if (!dialog)
|
97
|
+
if (!dialog) {
|
98
|
+
console.log('ConfirmDialog: dialog is null', id);
|
99
|
+
return;
|
100
|
+
}
|
101
|
+
|
102
|
+
console.log('ConfirmDialog: 初始化确认对话框', id);
|
103
|
+
|
104
|
+
// 使用事件委托来处理动态加载的内容
|
105
|
+
document.addEventListener('click', (event) => {
|
106
|
+
const target = event.target;
|
107
|
+
// 使用 closest() 查找最近的匹配元素,包括按钮内部的元素
|
108
|
+
const trigger = target.closest(`[data-confirm-dialog-target="${id}"]`);
|
109
|
+
if (trigger) {
|
110
|
+
console.log('ConfirmDialog: 触发确认对话框', id);
|
111
|
+
dialog.showModal();
|
112
|
+
}
|
113
|
+
});
|
98
114
|
|
99
|
-
//
|
115
|
+
// 为已存在的按钮添加点击事件(向后兼容)
|
100
116
|
document
|
101
117
|
.querySelectorAll(`[data-confirm-dialog-target="${id}"]`)
|
102
118
|
.forEach((trigger) => {
|
@@ -115,5 +131,14 @@ const style = getConfirmDialogStyle();
|
|
115
131
|
document.dispatchEvent(event);
|
116
132
|
};
|
117
133
|
}
|
118
|
-
}
|
134
|
+
}
|
135
|
+
|
136
|
+
// 初始加载时初始化
|
137
|
+
document.addEventListener('DOMContentLoaded', initializeConfirmDialog);
|
138
|
+
|
139
|
+
// Astro 页面切换时重新初始化
|
140
|
+
document.addEventListener('astro:page-load', initializeConfirmDialog);
|
141
|
+
|
142
|
+
// 确保脚本加载后立即初始化
|
143
|
+
initializeConfirmDialog();
|
119
144
|
</script>
|
@@ -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
|
|
@@ -261,6 +336,11 @@ const sidebarHeightClass = getSidebarHeightClass(headerConfig?.height);
|
|
261
336
|
<slot name="navbar-center" />
|
262
337
|
</div>
|
263
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
|
+
)}
|
264
344
|
<slot name="navbar-end" />
|
265
345
|
</div>
|
266
346
|
</Header>
|
@@ -305,6 +385,15 @@ const sidebarHeightClass = getSidebarHeightClass(headerConfig?.height);
|
|
305
385
|
)
|
306
386
|
}
|
307
387
|
|
388
|
+
<!-- 搜索模态框 -->
|
389
|
+
{
|
390
|
+
Astro.slots.has('modal-search') && (
|
391
|
+
<Modal id="modalSearch" title="搜索">
|
392
|
+
<slot name="modal-search" />
|
393
|
+
</Modal>
|
394
|
+
)
|
395
|
+
}
|
396
|
+
|
308
397
|
<script>
|
309
398
|
// Handle sidebar toggle
|
310
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,
|
@@ -1,8 +1,8 @@
|
|
1
|
-
import type { IFooterProps } from '
|
2
|
-
import type { IHeaderProps } from '
|
3
|
-
import type { IMainContentProps } from '
|
1
|
+
import type { IFooterProps } from '../types/footer';
|
2
|
+
import type { IHeaderProps } from '../types/header';
|
3
|
+
import type { IMainContentProps } from '../types/main';
|
4
4
|
import type { IMetaProps } from './meta';
|
5
|
-
import type { ISidebarProps } from '
|
5
|
+
import type { ISidebarProps } from '../types/sidebar';
|
6
6
|
|
7
7
|
export interface IAppLayoutProps {
|
8
8
|
/**
|
@@ -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,56 @@ 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
|
+
// 在modal显示后自动focus到第一个input元素
|
113
|
+
setTimeout(() => {
|
114
|
+
const firstInput = modal.querySelector(
|
115
|
+
'input, textarea, select, [contenteditable="true"]'
|
116
|
+
);
|
117
|
+
if (firstInput) {
|
118
|
+
firstInput.focus();
|
119
|
+
}
|
120
|
+
}, 100); // 延迟100ms确保modal完全显示
|
121
|
+
}
|
122
|
+
};
|
123
|
+
|
124
|
+
document.addEventListener('click', handleClick);
|
125
|
+
}
|
126
|
+
|
127
|
+
// Astro 页面切换时初始化
|
128
|
+
document.addEventListener('astro:page-load', () => {
|
129
|
+
initializeModal();
|
130
|
+
});
|
131
|
+
|
132
|
+
// 页面卸载时清理事件监听器
|
133
|
+
document.addEventListener('astro:before-preparation', () => {
|
134
|
+
if (handleClick) {
|
135
|
+
document.removeEventListener('click', handleClick);
|
136
|
+
handleClick = null;
|
137
|
+
}
|
125
138
|
});
|
126
139
|
</script>
|