@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.
@@ -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
- document.addEventListener('DOMContentLoaded', () => {
95
+ function initializeConfirmDialog() {
96
96
  const dialog = document.getElementById(id);
97
- if (!dialog) return;
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>
@@ -233,7 +233,6 @@ const debugClasses = debug
233
233
  ---
234
234
 
235
235
  <footer
236
- transition:persist
237
236
  class:list={[
238
237
  'cosy:footer cosy:z-50 cosy:sm:footer-horizontal cosy:bg-base-200 cosy:text-base-content cosy:p-10',
239
238
  debugClasses.footer,
@@ -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 '../../index-astro';
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,3 +1,6 @@
1
1
  import BaseLayout from './BaseLayout.astro';
2
2
 
3
3
  export { BaseLayout };
4
+
5
+ export type { IMetaProps } from './meta';
6
+ export type { IAppLayoutProps } from './layout';
@@ -1,8 +1,8 @@
1
- import type { IFooterProps } from './footer';
2
- import type { IHeaderProps } from './header';
3
- import type { IMainContentProps } from './main';
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 './sidebar';
5
+ import type { ISidebarProps } from '../types/sidebar';
6
6
 
7
7
  export interface IAppLayoutProps {
8
8
  /**
@@ -66,4 +66,8 @@ export interface IMetaProps {
66
66
  * @default 'default'
67
67
  */
68
68
  background?: 'default' | 'white' | 'gray' | 'dark' | 'gradient-blue' | 'gradient-pink' | 'gradient-green';
69
+
70
+
71
+ /** 最小显示时间(毫秒),默认300ms,确保用户能看到加载状态 */
72
+ loadingMinDisplayTime?: number;
69
73
  }
@@ -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 { Button } from '../../index-astro';
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
- showCloseButton && (
82
- <form method="dialog">
83
- <Button
84
- variant="ghost"
85
- size="sm"
86
- shape="circle"
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
- document.addEventListener('DOMContentLoaded', () => {
90
+ let handleClick;
91
+
92
+ function initializeModal() {
114
93
  const modal = document.getElementById(id);
115
- if (!modal) return;
94
+ if (!modal) {
95
+ return;
96
+ }
116
97
 
117
- // 为所有触发这个模态框的按钮添加点击事件
118
- document
119
- .querySelectorAll(`[data-modal-target="${id}"]`)
120
- .forEach((trigger) => {
121
- trigger.addEventListener('click', () => {
122
- modal.showModal();
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>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffic/cosy-ui",
3
- "version": "0.9.22",
3
+ "version": "0.9.24",
4
4
  "description": "An astro component library",
5
5
  "author": {
6
6
  "name": "nookery",