@gopowerteam/modal-render 1.0.0 → 1.0.1
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/README.md +1065 -0
- package/package.json +7 -7
package/README.md
ADDED
|
@@ -0,0 +1,1065 @@
|
|
|
1
|
+
# @gopowerteam/modal-render
|
|
2
|
+
|
|
3
|
+
Vue 3 模态框/抽屉渲染组件库,基于 Promise 风格 API,提供灵活的对话框和抽屉功能。
|
|
4
|
+
|
|
5
|
+
## 目录
|
|
6
|
+
|
|
7
|
+
- [特性](#特性)
|
|
8
|
+
- [安装](#安装)
|
|
9
|
+
- [快速开始](#快速开始)
|
|
10
|
+
- [快速参考](#快速参考)
|
|
11
|
+
- [组件 API](#组件-api)
|
|
12
|
+
- [useModal Hook](#usemodal-hook)
|
|
13
|
+
- [OpenModalOptions 配置项](#openmodaloptions-配置项)
|
|
14
|
+
- [onSubmit Hook](#onsubmit-hook)
|
|
15
|
+
- [完整示例](#完整示例)
|
|
16
|
+
- [高级用法](#高级用法)
|
|
17
|
+
- [样式自定义](#样式自定义)
|
|
18
|
+
- [TypeScript 类型](#typescript-类型)
|
|
19
|
+
- [FAQ](#faq)
|
|
20
|
+
- [注意事项](#注意事项)
|
|
21
|
+
|
|
22
|
+
## 特性
|
|
23
|
+
|
|
24
|
+
- 支持 Dialog(对话框)和 Drawer(抽屉)两种模式
|
|
25
|
+
- Promise 风格 API,支持 async/await
|
|
26
|
+
- 预设对话框:confirm、info、warning、error、success
|
|
27
|
+
- 可拖拽、全屏、自定义尺寸
|
|
28
|
+
- 支持嵌套模态框
|
|
29
|
+
- 完整的 TypeScript 类型支持
|
|
30
|
+
|
|
31
|
+
## 安装
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pnpm add @gopowerteam/modal-render
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 快速开始
|
|
38
|
+
|
|
39
|
+
### 1. 配置 ModalProvider
|
|
40
|
+
|
|
41
|
+
在 `App.vue` 中配置 `ModalProvider`:
|
|
42
|
+
|
|
43
|
+
```vue
|
|
44
|
+
<script setup lang="ts">
|
|
45
|
+
import { ModalProvider } from '@gopowerteam/modal-render'
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<ModalProvider :offset="{ x: 0, y: 0 }">
|
|
50
|
+
<RouterView />
|
|
51
|
+
</ModalProvider>
|
|
52
|
+
</template>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 2. 导入样式
|
|
56
|
+
|
|
57
|
+
在入口文件 `main.ts` 中导入样式:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import '@gopowerteam/modal-render/dist/style.css'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 3. 基础使用
|
|
64
|
+
|
|
65
|
+
```vue
|
|
66
|
+
<script setup lang="ts">
|
|
67
|
+
import { useModal } from '@gopowerteam/modal-render'
|
|
68
|
+
import MyModalContent from './components/MyModalContent.vue'
|
|
69
|
+
|
|
70
|
+
const modal = useModal()
|
|
71
|
+
|
|
72
|
+
function openModal() {
|
|
73
|
+
modal.open(
|
|
74
|
+
MyModalContent,
|
|
75
|
+
{ /* props */ },
|
|
76
|
+
{
|
|
77
|
+
title: '标题',
|
|
78
|
+
footer: true,
|
|
79
|
+
onOk({ close }) {
|
|
80
|
+
// 处理确认
|
|
81
|
+
close()
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<template>
|
|
89
|
+
<button @click="openModal">打开弹窗</button>
|
|
90
|
+
</template>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 快速参考
|
|
96
|
+
|
|
97
|
+
### 导入
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
// 组件
|
|
101
|
+
import { ModalProvider, ModalHeader, ModalFooter } from '@gopowerteam/modal-render'
|
|
102
|
+
|
|
103
|
+
// Hook
|
|
104
|
+
import { useModal, onSubmit } from '@gopowerteam/modal-render'
|
|
105
|
+
|
|
106
|
+
// 类型
|
|
107
|
+
import type { OpenModalOptions, SizeOptions, ShowLoadingOptions } from '@gopowerteam/modal-render'
|
|
108
|
+
|
|
109
|
+
// 样式
|
|
110
|
+
import '@gopowerteam/modal-render/dist/style.css'
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### useModal 方法速查
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
const modal = useModal()
|
|
117
|
+
|
|
118
|
+
// 打开组件
|
|
119
|
+
modal.open(Component, props?, options?) → Promise<any> & { close }
|
|
120
|
+
|
|
121
|
+
// 预设对话框
|
|
122
|
+
modal.confirm({ title, content, onOk?, onCancel? })
|
|
123
|
+
modal.info({ title, content })
|
|
124
|
+
modal.success({ title, content })
|
|
125
|
+
modal.warning({ title, content })
|
|
126
|
+
modal.error({ title, content })
|
|
127
|
+
|
|
128
|
+
// 关闭
|
|
129
|
+
modal.close(data?) // 关闭当前模态框
|
|
130
|
+
modal.closeAll() // 关闭所有模态框
|
|
131
|
+
|
|
132
|
+
// 加载状态
|
|
133
|
+
modal.showLoading(options?) → () => void // 返回关闭函数
|
|
134
|
+
modal.hideLoading()
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### 常用 options 配置
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
// 基础对话框
|
|
141
|
+
{ title: '标题', footer: true }
|
|
142
|
+
|
|
143
|
+
// 抽屉
|
|
144
|
+
{ mode: 'drawer', position: 'right', title: '标题' }
|
|
145
|
+
|
|
146
|
+
// 全屏
|
|
147
|
+
{ fullscreen: true }
|
|
148
|
+
|
|
149
|
+
// 可拖拽
|
|
150
|
+
{ draggable: true }
|
|
151
|
+
|
|
152
|
+
// 点击遮罩关闭
|
|
153
|
+
{ maskClosable: true }
|
|
154
|
+
|
|
155
|
+
// 自定义尺寸
|
|
156
|
+
{ width: 800, height: 600 }
|
|
157
|
+
{ size: 'large' } // small | middle | large
|
|
158
|
+
|
|
159
|
+
// 隐藏头部
|
|
160
|
+
{ header: false }
|
|
161
|
+
|
|
162
|
+
// 表单提交
|
|
163
|
+
{ footer: true, form: 'formName', onOk: ({ close }) => {} }
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### onSubmit 用法
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
// 在模态框内容组件中
|
|
170
|
+
onSubmit((actions) => {
|
|
171
|
+
actions.showLoading()
|
|
172
|
+
// 异步操作完成后
|
|
173
|
+
actions.close(data)
|
|
174
|
+
})
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### ModalProvider 配置
|
|
178
|
+
|
|
179
|
+
```vue
|
|
180
|
+
<ModalProvider
|
|
181
|
+
:append-to-body="false"
|
|
182
|
+
:sizes="{ small: '50%', middle: '70%', large: '90%' }"
|
|
183
|
+
max-width="90%"
|
|
184
|
+
max-height="90%"
|
|
185
|
+
:offset="{ x: 0, y: 0 }"
|
|
186
|
+
>
|
|
187
|
+
<App />
|
|
188
|
+
</ModalProvider>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 组件 API
|
|
194
|
+
|
|
195
|
+
### ModalProvider
|
|
196
|
+
|
|
197
|
+
最外层容器组件,用于提供模态框上下文。
|
|
198
|
+
|
|
199
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
200
|
+
|------|------|--------|------|
|
|
201
|
+
| appendToBody | `boolean \| string` | `false` | 是否挂载到 body,传入字符串时作为选择器 |
|
|
202
|
+
| sizes | `SizeOptions` | `{ small: '50%', middle: '70%', large: '90%' }` | 预设尺寸配置 |
|
|
203
|
+
| maxWidth | `string \| number` | `'90%'` | 最大宽度 |
|
|
204
|
+
| maxHeight | `string \| number` | `'90%'` | 最大高度 |
|
|
205
|
+
| offset | `{ x?: number, y?: number }` | `{ x: 0, y: 0 }` | 偏移量 |
|
|
206
|
+
|
|
207
|
+
```vue
|
|
208
|
+
<ModalProvider
|
|
209
|
+
:append-to-body="true"
|
|
210
|
+
:sizes="{ small: '400px', middle: '600px', large: '80%' }"
|
|
211
|
+
max-width="1200px"
|
|
212
|
+
:offset="{ x: 100, y: 50 }"
|
|
213
|
+
>
|
|
214
|
+
<App />
|
|
215
|
+
</ModalProvider>
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### ModalHeader
|
|
219
|
+
|
|
220
|
+
自定义模态框头部,插入到默认头部位置。
|
|
221
|
+
|
|
222
|
+
```vue
|
|
223
|
+
<script setup lang="ts">
|
|
224
|
+
import { ModalHeader } from '@gopowerteam/modal-render'
|
|
225
|
+
</script>
|
|
226
|
+
|
|
227
|
+
<template>
|
|
228
|
+
<ModalHeader>
|
|
229
|
+
<span>自定义标题</span>
|
|
230
|
+
</ModalHeader>
|
|
231
|
+
</template>
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### ModalFooter
|
|
235
|
+
|
|
236
|
+
自定义模态框底部,插入到默认底部位置。
|
|
237
|
+
|
|
238
|
+
```vue
|
|
239
|
+
<script setup lang="ts">
|
|
240
|
+
import { ModalFooter, useModal } from '@gopowerteam/modal-render'
|
|
241
|
+
|
|
242
|
+
const modal = useModal()
|
|
243
|
+
</script>
|
|
244
|
+
|
|
245
|
+
<template>
|
|
246
|
+
<ModalFooter>
|
|
247
|
+
<button @click="modal.close()">关闭</button>
|
|
248
|
+
<button @click="modal.close({ saved: true })">保存</button>
|
|
249
|
+
</ModalFooter>
|
|
250
|
+
</template>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## useModal Hook
|
|
256
|
+
|
|
257
|
+
获取模态框操作方法,必须在 `ModalProvider` 内部使用。
|
|
258
|
+
|
|
259
|
+
```ts
|
|
260
|
+
const modal = useModal()
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### open()
|
|
264
|
+
|
|
265
|
+
打开自定义组件或预设对话框。
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
// 打开自定义组件
|
|
269
|
+
modal.open(component: Component, props?: Record<string, any>, options?: OpenModalOptions): Promise<any> & { close: () => void }
|
|
270
|
+
|
|
271
|
+
// 打开预设对话框
|
|
272
|
+
modal.open('confirm' | 'info' | 'warning' | 'error' | 'success', props: object, options?: OpenModalOptions): Promise<any> & { close: () => void }
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**返回值**:返回 Promise 和 close 方法,Promise resolve 的值即为 `close(data)` 传入的数据。
|
|
276
|
+
|
|
277
|
+
```vue
|
|
278
|
+
<script setup lang="ts">
|
|
279
|
+
const modal = useModal()
|
|
280
|
+
|
|
281
|
+
async function openAndWait() {
|
|
282
|
+
const result = await modal.open(
|
|
283
|
+
MyComponent,
|
|
284
|
+
{ message: 'Hello' },
|
|
285
|
+
{ title: '标题' }
|
|
286
|
+
)
|
|
287
|
+
console.log('模态框返回:', result)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// 或者使用 close 方法
|
|
291
|
+
const instance = modal.open(MyComponent, {}, { title: '标题' })
|
|
292
|
+
instance.then(result => console.log(result))
|
|
293
|
+
instance.close() // 主动关闭
|
|
294
|
+
</script>
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### close()
|
|
298
|
+
|
|
299
|
+
关闭当前所在模态框。
|
|
300
|
+
|
|
301
|
+
```ts
|
|
302
|
+
modal.close() // 不传值,相当于取消
|
|
303
|
+
modal.close(data) // 传递数据,Promise 会 resolve 此数据
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### closeAll()
|
|
307
|
+
|
|
308
|
+
关闭所有打开的模态框。
|
|
309
|
+
|
|
310
|
+
```ts
|
|
311
|
+
modal.closeAll()
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### 预设对话框
|
|
315
|
+
|
|
316
|
+
快捷方法打开预设对话框。
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
// 确认对话框
|
|
320
|
+
modal.confirm({
|
|
321
|
+
title: '提示',
|
|
322
|
+
content: '确定要执行此操作吗?',
|
|
323
|
+
async onOk() {
|
|
324
|
+
await doSomething()
|
|
325
|
+
},
|
|
326
|
+
onCancel() {
|
|
327
|
+
console.log('取消了')
|
|
328
|
+
},
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
// 信息对话框
|
|
332
|
+
modal.info({
|
|
333
|
+
title: '提示',
|
|
334
|
+
content: '操作成功',
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
// 成功/警告/错误对话框用法相同
|
|
338
|
+
modal.success({ title: '完成', content: '保存成功' })
|
|
339
|
+
modal.warning({ title: '警告', content: '请检查输入' })
|
|
340
|
+
modal.error({ title: '错误', content: '操作失败' })
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### showLoading() / hideLoading()
|
|
344
|
+
|
|
345
|
+
显示/隐藏加载状态。
|
|
346
|
+
|
|
347
|
+
```ts
|
|
348
|
+
// 在模态框内容组件内使用
|
|
349
|
+
const { showLoading, hideLoading } = modal
|
|
350
|
+
|
|
351
|
+
function handleAsync() {
|
|
352
|
+
const closeLoading = showLoading({ text: '处理中...' })
|
|
353
|
+
|
|
354
|
+
fetchData().then(() => {
|
|
355
|
+
closeLoading()
|
|
356
|
+
})
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// 全局 Loading(无需打开模态框)
|
|
360
|
+
function showGlobalLoading() {
|
|
361
|
+
const close = modal.showLoading({
|
|
362
|
+
text: '加载中...',
|
|
363
|
+
})
|
|
364
|
+
|
|
365
|
+
// 3秒后自动关闭
|
|
366
|
+
setTimeout(() => {
|
|
367
|
+
close()
|
|
368
|
+
}, 3000)
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## OpenModalOptions 配置项
|
|
375
|
+
|
|
376
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
377
|
+
|------|------|--------|------|
|
|
378
|
+
| mode | `'dialog' \| 'drawer'` | `'dialog'` | 显示模式 |
|
|
379
|
+
| position | `'top' \| 'right' \| 'bottom' \| 'left'` | `'right'` | 抽屉方向(drawer 模式) |
|
|
380
|
+
| size | `'small' \| 'middle' \| 'large'` | `'middle'` | 预设尺寸 |
|
|
381
|
+
| width | `string \| number` | - | 自定义宽度 |
|
|
382
|
+
| height | `string \| number` | - | 自定义高度 |
|
|
383
|
+
| fullscreen | `boolean` | `false` | 全屏显示 |
|
|
384
|
+
| draggable | `boolean` | `false` | 可拖拽移动 |
|
|
385
|
+
| title | `string` | - | 标题文字 |
|
|
386
|
+
| header | `boolean` | `true` | 是否显示头部 |
|
|
387
|
+
| footer | `boolean` | `false` | 是否显示底部按钮 |
|
|
388
|
+
| closeable | `boolean` | `true` | 是否显示关闭按钮 |
|
|
389
|
+
| esc | `boolean` | `false` | 按 ESC 键关闭 |
|
|
390
|
+
| mask | `boolean` | `true` | 是否显示遮罩 |
|
|
391
|
+
| maskClosable | `boolean` | `false` | 点击遮罩关闭 |
|
|
392
|
+
| bodyStyle | `CSSProperties` | - | 内容区样式 |
|
|
393
|
+
| backgroundColor | `string` | - | 背景色 |
|
|
394
|
+
| submitText | `string` | `'确定'` | 确认按钮文字 |
|
|
395
|
+
| cancelText | `string` | `'取消'` | 取消按钮文字 |
|
|
396
|
+
| form | `string` | - | 关联表单的 name,配合 `onSubmit` 使用 |
|
|
397
|
+
| onOk | `(options: { close: () => void }) => void` | - | 确认回调 |
|
|
398
|
+
| onCancel | `() => void` | - | 取消回调 |
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## onSubmit Hook
|
|
403
|
+
|
|
404
|
+
在模态框内容组件中监听底部按钮提交事件,通常配合 `form` 属性和表单组件使用。
|
|
405
|
+
|
|
406
|
+
```vue
|
|
407
|
+
<script setup lang="ts">
|
|
408
|
+
import { onSubmit, useModal } from '@gopowerteam/modal-render'
|
|
409
|
+
|
|
410
|
+
const modal = useModal()
|
|
411
|
+
|
|
412
|
+
// 监听提交事件
|
|
413
|
+
onSubmit((actions) => {
|
|
414
|
+
// 显示加载状态
|
|
415
|
+
actions.showLoading()
|
|
416
|
+
|
|
417
|
+
// 模拟异步操作
|
|
418
|
+
setTimeout(() => {
|
|
419
|
+
// 返回数据并关闭
|
|
420
|
+
actions.close({ success: true })
|
|
421
|
+
}, 1000)
|
|
422
|
+
})
|
|
423
|
+
</script>
|
|
424
|
+
|
|
425
|
+
<template>
|
|
426
|
+
<form name="myForm">
|
|
427
|
+
<!-- 表单内容 -->
|
|
428
|
+
</form>
|
|
429
|
+
</template>
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
使用时在 `open` 的 options 中指定 `form` 属性:
|
|
433
|
+
|
|
434
|
+
```ts
|
|
435
|
+
modal.open(
|
|
436
|
+
MyFormComponent,
|
|
437
|
+
{},
|
|
438
|
+
{
|
|
439
|
+
footer: true,
|
|
440
|
+
form: 'myForm',
|
|
441
|
+
onOk({ close }) {
|
|
442
|
+
// 触发 form 提交,会调用 onSubmit 回调
|
|
443
|
+
close()
|
|
444
|
+
},
|
|
445
|
+
}
|
|
446
|
+
)
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## 完整示例
|
|
452
|
+
|
|
453
|
+
### 示例 1:基础对话框
|
|
454
|
+
|
|
455
|
+
```vue
|
|
456
|
+
<!-- views/modal.vue -->
|
|
457
|
+
<script setup lang="ts">
|
|
458
|
+
import { useModal } from '@gopowerteam/modal-render'
|
|
459
|
+
import Test1 from '../components/test1.vue'
|
|
460
|
+
|
|
461
|
+
const modal = useModal()
|
|
462
|
+
|
|
463
|
+
function onClick() {
|
|
464
|
+
const instance = modal.open(
|
|
465
|
+
Test1,
|
|
466
|
+
{ content: 'asdasd' },
|
|
467
|
+
{
|
|
468
|
+
mode: 'dialog',
|
|
469
|
+
title: 'asdasd',
|
|
470
|
+
footer: true,
|
|
471
|
+
submitText: '提交',
|
|
472
|
+
onOk({ close }) {
|
|
473
|
+
console.log('确认')
|
|
474
|
+
close()
|
|
475
|
+
},
|
|
476
|
+
onCancel() {
|
|
477
|
+
console.log('取消')
|
|
478
|
+
},
|
|
479
|
+
bodyStyle: {
|
|
480
|
+
padding: '20px',
|
|
481
|
+
},
|
|
482
|
+
},
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
instance.then((data) => {
|
|
486
|
+
console.log('返回数据:', data)
|
|
487
|
+
})
|
|
488
|
+
}
|
|
489
|
+
</script>
|
|
490
|
+
|
|
491
|
+
<template>
|
|
492
|
+
<button @click="onClick">打开弹窗</button>
|
|
493
|
+
</template>
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### 示例 2:抽屉模式
|
|
497
|
+
|
|
498
|
+
```ts
|
|
499
|
+
modal.open(
|
|
500
|
+
MyComponent,
|
|
501
|
+
{},
|
|
502
|
+
{
|
|
503
|
+
mode: 'drawer',
|
|
504
|
+
position: 'right', // left, top, bottom
|
|
505
|
+
title: '右侧抽屉',
|
|
506
|
+
footer: true,
|
|
507
|
+
},
|
|
508
|
+
)
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
### 示例 3:表单提交
|
|
512
|
+
|
|
513
|
+
```vue
|
|
514
|
+
<!-- 调用方:views/UserModal.vue -->
|
|
515
|
+
<script setup lang="ts">
|
|
516
|
+
import { useModal } from '@gopowerteam/modal-render'
|
|
517
|
+
import UserForm from '../components/UserForm.vue'
|
|
518
|
+
|
|
519
|
+
const modal = useModal()
|
|
520
|
+
|
|
521
|
+
function openUserForm() {
|
|
522
|
+
modal.open(
|
|
523
|
+
UserForm,
|
|
524
|
+
{},
|
|
525
|
+
{
|
|
526
|
+
title: '编辑用户',
|
|
527
|
+
footer: true,
|
|
528
|
+
form: 'userForm',
|
|
529
|
+
width: 600,
|
|
530
|
+
onOk({ close }) {
|
|
531
|
+
// 触发 form 提交,会调用 onSubmit 回调
|
|
532
|
+
// 实际关闭在 onSubmit 中处理
|
|
533
|
+
},
|
|
534
|
+
},
|
|
535
|
+
)
|
|
536
|
+
}
|
|
537
|
+
</script>
|
|
538
|
+
|
|
539
|
+
<template>
|
|
540
|
+
<button @click="openUserForm">编辑用户</button>
|
|
541
|
+
</template>
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
```vue
|
|
545
|
+
<!-- 表单组件:components/UserForm.vue -->
|
|
546
|
+
<script setup lang="ts">
|
|
547
|
+
import type { FieldRule } from '@arco-design/web-vue'
|
|
548
|
+
import { Form as AForm } from '@arco-design/web-vue'
|
|
549
|
+
import { onSubmit } from '@gopowerteam/modal-render'
|
|
550
|
+
import { reactive } from 'vue'
|
|
551
|
+
|
|
552
|
+
const formModel = reactive({
|
|
553
|
+
name: '',
|
|
554
|
+
email: '',
|
|
555
|
+
})
|
|
556
|
+
|
|
557
|
+
const formRules: Record<string, FieldRule> = {
|
|
558
|
+
name: { required: true, message: '姓名不能为空' },
|
|
559
|
+
email: [
|
|
560
|
+
{ required: true, message: '邮箱不能为空' },
|
|
561
|
+
{ type: 'email', message: '请输入正确的邮箱格式' },
|
|
562
|
+
],
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// 监听提交事件
|
|
566
|
+
onSubmit((modal) => {
|
|
567
|
+
modal.showLoading()
|
|
568
|
+
// 模拟提交
|
|
569
|
+
setTimeout(() => {
|
|
570
|
+
modal.close(formModel)
|
|
571
|
+
}, 1000)
|
|
572
|
+
})
|
|
573
|
+
</script>
|
|
574
|
+
|
|
575
|
+
<template>
|
|
576
|
+
<AForm :model="formModel" name="userForm" :rules="formRules">
|
|
577
|
+
<AFormItem field="name" label="姓名">
|
|
578
|
+
<AInput v-model="formModel.name" />
|
|
579
|
+
</AFormItem>
|
|
580
|
+
<AFormItem field="email" label="邮箱">
|
|
581
|
+
<AInput v-model="formModel.email" />
|
|
582
|
+
</AFormItem>
|
|
583
|
+
</AForm>
|
|
584
|
+
</template>
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
### 示例 4:嵌套模态框
|
|
588
|
+
|
|
589
|
+
```vue
|
|
590
|
+
<!-- views/test1.vue -->
|
|
591
|
+
<script setup lang="ts">
|
|
592
|
+
import { useModal } from '@gopowerteam/modal-render'
|
|
593
|
+
import Test2 from '../components/test2.vue'
|
|
594
|
+
|
|
595
|
+
const modal = useModal()
|
|
596
|
+
|
|
597
|
+
function onOpen() {
|
|
598
|
+
modal.open(Test2, {}, { footer: true })
|
|
599
|
+
}
|
|
600
|
+
</script>
|
|
601
|
+
|
|
602
|
+
<template>
|
|
603
|
+
<AButton type="primary" @click="onOpen">打开</AButton>
|
|
604
|
+
</template>
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
```vue
|
|
608
|
+
<!-- components/test2.vue -->
|
|
609
|
+
<script setup lang="ts">
|
|
610
|
+
import { useModal } from '@gopowerteam/modal-render'
|
|
611
|
+
|
|
612
|
+
const modal = useModal()
|
|
613
|
+
|
|
614
|
+
function openNested() {
|
|
615
|
+
// 嵌套打开另一个模态框
|
|
616
|
+
modal.open(
|
|
617
|
+
AnotherComponent,
|
|
618
|
+
{},
|
|
619
|
+
{ title: '嵌套弹窗', footer: true },
|
|
620
|
+
)
|
|
621
|
+
}
|
|
622
|
+
</script>
|
|
623
|
+
|
|
624
|
+
<template>
|
|
625
|
+
<div>
|
|
626
|
+
<p>这是第一个模态框</p>
|
|
627
|
+
<button @click="openNested">打开嵌套</button>
|
|
628
|
+
</div>
|
|
629
|
+
</template>
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
---
|
|
633
|
+
|
|
634
|
+
## 高级用法
|
|
635
|
+
|
|
636
|
+
### 全屏模式
|
|
637
|
+
|
|
638
|
+
```ts
|
|
639
|
+
modal.open(
|
|
640
|
+
MyComponent,
|
|
641
|
+
{},
|
|
642
|
+
{
|
|
643
|
+
fullscreen: true,
|
|
644
|
+
title: '全屏模态框',
|
|
645
|
+
},
|
|
646
|
+
)
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
### 可拖拽对话框
|
|
650
|
+
|
|
651
|
+
```ts
|
|
652
|
+
modal.open(
|
|
653
|
+
MyComponent,
|
|
654
|
+
{},
|
|
655
|
+
{
|
|
656
|
+
draggable: true,
|
|
657
|
+
title: '可拖拽',
|
|
658
|
+
},
|
|
659
|
+
)
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
### 自定义背景色
|
|
663
|
+
|
|
664
|
+
```ts
|
|
665
|
+
modal.open(
|
|
666
|
+
MyComponent,
|
|
667
|
+
{},
|
|
668
|
+
{
|
|
669
|
+
backgroundColor: '#f0f2f5',
|
|
670
|
+
bodyStyle: { padding: '20px' },
|
|
671
|
+
},
|
|
672
|
+
)
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
### ESC 键关闭
|
|
676
|
+
|
|
677
|
+
```ts
|
|
678
|
+
modal.open(
|
|
679
|
+
MyComponent,
|
|
680
|
+
{},
|
|
681
|
+
{
|
|
682
|
+
esc: true,
|
|
683
|
+
closeable: true,
|
|
684
|
+
},
|
|
685
|
+
)
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
### 点击遮罩关闭
|
|
689
|
+
|
|
690
|
+
```ts
|
|
691
|
+
modal.open(
|
|
692
|
+
MyComponent,
|
|
693
|
+
{},
|
|
694
|
+
{
|
|
695
|
+
maskClosable: true,
|
|
696
|
+
title: '点击遮罩关闭',
|
|
697
|
+
},
|
|
698
|
+
)
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### 隐藏头部
|
|
702
|
+
|
|
703
|
+
```ts
|
|
704
|
+
modal.open(
|
|
705
|
+
MyComponent,
|
|
706
|
+
{},
|
|
707
|
+
{
|
|
708
|
+
header: false,
|
|
709
|
+
footer: true,
|
|
710
|
+
title: '无头部模态框',
|
|
711
|
+
},
|
|
712
|
+
)
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
### 自定义尺寸
|
|
716
|
+
|
|
717
|
+
```ts
|
|
718
|
+
// 自定义宽度
|
|
719
|
+
modal.open(
|
|
720
|
+
MyComponent,
|
|
721
|
+
{},
|
|
722
|
+
{
|
|
723
|
+
width: 800,
|
|
724
|
+
title: '固定宽度',
|
|
725
|
+
},
|
|
726
|
+
)
|
|
727
|
+
|
|
728
|
+
// 自定义高度(抽屉模式)
|
|
729
|
+
modal.open(
|
|
730
|
+
MyComponent,
|
|
731
|
+
{},
|
|
732
|
+
{
|
|
733
|
+
mode: 'drawer',
|
|
734
|
+
position: 'right',
|
|
735
|
+
height: '80%',
|
|
736
|
+
title: '自定义高度',
|
|
737
|
+
},
|
|
738
|
+
)
|
|
739
|
+
|
|
740
|
+
// 使用预设尺寸
|
|
741
|
+
modal.open(
|
|
742
|
+
MyComponent,
|
|
743
|
+
{},
|
|
744
|
+
{
|
|
745
|
+
size: 'large',
|
|
746
|
+
title: '大尺寸',
|
|
747
|
+
},
|
|
748
|
+
)
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
### 挂载到 body
|
|
752
|
+
|
|
753
|
+
适用于模态框内容需要脱离当前容器上下文的场景:
|
|
754
|
+
|
|
755
|
+
```vue
|
|
756
|
+
<!-- App.vue -->
|
|
757
|
+
<ModalProvider :append-to-body="true">
|
|
758
|
+
<RouterView />
|
|
759
|
+
</ModalProvider>
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
或者指定挂载位置:
|
|
763
|
+
|
|
764
|
+
```vue
|
|
765
|
+
<ModalProvider append-to-body="#modal-root">
|
|
766
|
+
<App />
|
|
767
|
+
</ModalProvider>
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
### 示例:完整的表单提交流程
|
|
771
|
+
|
|
772
|
+
```vue
|
|
773
|
+
<!-- 调用方:ParentComponent.vue -->
|
|
774
|
+
<script setup lang="ts">
|
|
775
|
+
import { useModal } from '@gopowerteam/modal-render'
|
|
776
|
+
import UserForm from './UserForm.vue'
|
|
777
|
+
|
|
778
|
+
const modal = useModal()
|
|
779
|
+
|
|
780
|
+
function openForm() {
|
|
781
|
+
modal.open(
|
|
782
|
+
UserForm,
|
|
783
|
+
{},
|
|
784
|
+
{
|
|
785
|
+
title: '新增用户',
|
|
786
|
+
footer: true,
|
|
787
|
+
form: 'userForm',
|
|
788
|
+
width: 600,
|
|
789
|
+
onOk({ close }) {
|
|
790
|
+
// 点击确定时触发 form 提交,会调用 onSubmit 回调
|
|
791
|
+
// 实际关闭在 onSubmit 中处理
|
|
792
|
+
},
|
|
793
|
+
},
|
|
794
|
+
)
|
|
795
|
+
}
|
|
796
|
+
</script>
|
|
797
|
+
|
|
798
|
+
<template>
|
|
799
|
+
<button @click="openForm">新增用户</button>
|
|
800
|
+
</template>
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
```vue
|
|
804
|
+
<!-- 表单组件:UserForm.vue -->
|
|
805
|
+
<script setup lang="ts">
|
|
806
|
+
import type { FieldRule } from '@arco-design/web-vue'
|
|
807
|
+
import { Form as AForm } from '@arco-design/web-vue'
|
|
808
|
+
import { onSubmit } from '@gopowerteam/modal-render'
|
|
809
|
+
import { reactive } from 'vue'
|
|
810
|
+
|
|
811
|
+
const formModel = reactive({
|
|
812
|
+
name: '',
|
|
813
|
+
email: '',
|
|
814
|
+
phone: '',
|
|
815
|
+
})
|
|
816
|
+
|
|
817
|
+
const formRules: Record<string, FieldRule> = {
|
|
818
|
+
name: { required: true, message: '请输入姓名' },
|
|
819
|
+
email: [
|
|
820
|
+
{ required: true, message: '请输入邮箱' },
|
|
821
|
+
{ type: 'email', message: '邮箱格式不正确' },
|
|
822
|
+
],
|
|
823
|
+
phone: { required: true, message: '请输入手机号' },
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// 监听表单提交
|
|
827
|
+
onSubmit((actions) => {
|
|
828
|
+
actions.showLoading({ text: '提交中...' })
|
|
829
|
+
|
|
830
|
+
// 模拟异步提交
|
|
831
|
+
setTimeout(() => {
|
|
832
|
+
console.log('表单数据:', formModel)
|
|
833
|
+
actions.close(formModel)
|
|
834
|
+
}, 1500)
|
|
835
|
+
})
|
|
836
|
+
</script>
|
|
837
|
+
|
|
838
|
+
<template>
|
|
839
|
+
<AForm :model="formModel" name="userForm" :rules="formRules" layout="vertical">
|
|
840
|
+
<AFormItem field="name" label="姓名">
|
|
841
|
+
<AInput v-model="formModel.name" placeholder="请输入姓名" />
|
|
842
|
+
</AFormItem>
|
|
843
|
+
<AFormItem field="email" label="邮箱">
|
|
844
|
+
<AInput v-model="formModel.email" placeholder="请输入邮箱" />
|
|
845
|
+
</AFormItem>
|
|
846
|
+
<AFormItem field="phone" label="手机号">
|
|
847
|
+
<AInput v-model="formModel.phone" placeholder="请输入手机号" />
|
|
848
|
+
</AFormItem>
|
|
849
|
+
</AForm>
|
|
850
|
+
</template>
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
---
|
|
854
|
+
|
|
855
|
+
## 样式自定义
|
|
856
|
+
|
|
857
|
+
### CSS 变量
|
|
858
|
+
|
|
859
|
+
组件使用以下 CSS 变量,可通过覆盖全局样式自定义:
|
|
860
|
+
|
|
861
|
+
```css
|
|
862
|
+
:root {
|
|
863
|
+
--color-border-1: rgb(232, 232, 232);
|
|
864
|
+
--color-text-2: #4e5969;
|
|
865
|
+
--color-fill-1: #f5f5f5;
|
|
866
|
+
--color-fill-3: #e5e6eb;
|
|
867
|
+
--color-fill-4: #c9cdd4;
|
|
868
|
+
--primary-5: rgb(28, 76, 207);
|
|
869
|
+
--primary-6: rgb(45, 106, 251);
|
|
870
|
+
--primary-7: rgb(14, 66, 210);
|
|
871
|
+
}
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
### bodyStyle 属性
|
|
875
|
+
|
|
876
|
+
通过 `bodyStyle` 属性自定义内容区样式:
|
|
877
|
+
|
|
878
|
+
```ts
|
|
879
|
+
modal.open(
|
|
880
|
+
MyComponent,
|
|
881
|
+
{},
|
|
882
|
+
{
|
|
883
|
+
bodyStyle: {
|
|
884
|
+
padding: '20px',
|
|
885
|
+
backgroundColor: '#fff',
|
|
886
|
+
},
|
|
887
|
+
},
|
|
888
|
+
)
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
### 自定义主题
|
|
892
|
+
|
|
893
|
+
在全局样式中覆盖组件样式:
|
|
894
|
+
|
|
895
|
+
```css
|
|
896
|
+
.modal-header {
|
|
897
|
+
background-color: #f5f7fa;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
.modal-footer button.submit-button {
|
|
901
|
+
background-color: #409eff;
|
|
902
|
+
}
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
---
|
|
906
|
+
|
|
907
|
+
## TypeScript 类型
|
|
908
|
+
|
|
909
|
+
### SizeOptions
|
|
910
|
+
|
|
911
|
+
```ts
|
|
912
|
+
interface SizeOptions {
|
|
913
|
+
small: string | number
|
|
914
|
+
middle: string | number
|
|
915
|
+
large: string | number
|
|
916
|
+
}
|
|
917
|
+
```
|
|
918
|
+
|
|
919
|
+
### ShowLoadingOptions
|
|
920
|
+
|
|
921
|
+
```ts
|
|
922
|
+
interface ShowLoadingOptions {
|
|
923
|
+
duration?: number // 自动关闭时间(毫秒)
|
|
924
|
+
text?: string // 加载提示文字
|
|
925
|
+
}
|
|
926
|
+
```
|
|
927
|
+
|
|
928
|
+
### OpenModalOptions
|
|
929
|
+
|
|
930
|
+
```ts
|
|
931
|
+
interface OpenModalOptions {
|
|
932
|
+
closeable?: boolean
|
|
933
|
+
esc?: boolean
|
|
934
|
+
mask?: boolean
|
|
935
|
+
maskClosable?: boolean
|
|
936
|
+
title?: string
|
|
937
|
+
header?: boolean
|
|
938
|
+
footer?: boolean
|
|
939
|
+
width?: number | string
|
|
940
|
+
height?: number | string
|
|
941
|
+
size?: 'large' | 'middle' | 'small'
|
|
942
|
+
fullscreen?: boolean
|
|
943
|
+
draggable?: boolean
|
|
944
|
+
form?: string
|
|
945
|
+
mode?: 'dialog' | 'drawer'
|
|
946
|
+
position?: 'top' | 'right' | 'bottom' | 'left'
|
|
947
|
+
backgroundColor?: string
|
|
948
|
+
bodyStyle?: CSSProperties
|
|
949
|
+
submitText?: string
|
|
950
|
+
cancelText?: string
|
|
951
|
+
onOk?: (options: { close: () => void }) => void
|
|
952
|
+
onCancel?: () => void
|
|
953
|
+
}
|
|
954
|
+
```
|
|
955
|
+
|
|
956
|
+
### ModalActions
|
|
957
|
+
|
|
958
|
+
```ts
|
|
959
|
+
interface ModalActions {
|
|
960
|
+
open: (component: Component | 'confirm' | 'info' | 'warning' | 'error' | 'success', props?: Record<string, any>, options?: OpenModalOptions) => Promise<any> & { close: () => void }
|
|
961
|
+
close: (id: string, data?: any) => void
|
|
962
|
+
closeAll: () => void
|
|
963
|
+
addEventListener: (id: string, event: 'submit', callback: (modal: ReturnType<typeof useModal>) => void) => void
|
|
964
|
+
showLoading: (id?: string, options?: ShowLoadingOptions) => () => void
|
|
965
|
+
hideLoading: (id?: string) => void
|
|
966
|
+
}
|
|
967
|
+
```
|
|
968
|
+
|
|
969
|
+
---
|
|
970
|
+
|
|
971
|
+
## FAQ
|
|
972
|
+
|
|
973
|
+
### 1. 为什么 useModal 报错 "Not Found Modal Provider Component"?
|
|
974
|
+
|
|
975
|
+
`useModal` 必须在 `ModalProvider` 组件内部调用,确保组件树中存在 Provider:
|
|
976
|
+
|
|
977
|
+
```vue
|
|
978
|
+
<!-- 正确 -->
|
|
979
|
+
<template>
|
|
980
|
+
<ModalProvider>
|
|
981
|
+
<App />
|
|
982
|
+
</ModalProvider>
|
|
983
|
+
</template>
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
### 2. 如何在模态框内部关闭?
|
|
987
|
+
|
|
988
|
+
两种方式:
|
|
989
|
+
|
|
990
|
+
```ts
|
|
991
|
+
// 方式1:在 onOk 回调中调用 close
|
|
992
|
+
onOk({ close }) {
|
|
993
|
+
close()
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
// 方式2:使用 useModal
|
|
997
|
+
const modal = useModal()
|
|
998
|
+
modal.close()
|
|
999
|
+
```
|
|
1000
|
+
|
|
1001
|
+
### 3. 如何阻止模态框关闭?
|
|
1002
|
+
|
|
1003
|
+
不调用 `close()` 方法即可阻止关闭:
|
|
1004
|
+
|
|
1005
|
+
```ts
|
|
1006
|
+
onOk({ close }) {
|
|
1007
|
+
validate().then(() => {
|
|
1008
|
+
close() // 只有验证通过才关闭
|
|
1009
|
+
})
|
|
1010
|
+
}
|
|
1011
|
+
```
|
|
1012
|
+
|
|
1013
|
+
### 4. 支持 SSR 吗?
|
|
1014
|
+
|
|
1015
|
+
支持,内部通过 `clientMounted` 处理了 SSR 场景。
|
|
1016
|
+
|
|
1017
|
+
### 5. 如何自定义按钮样式?
|
|
1018
|
+
|
|
1019
|
+
两种方式:
|
|
1020
|
+
|
|
1021
|
+
```ts
|
|
1022
|
+
// 方式1:自定义提交按钮文字
|
|
1023
|
+
modal.open(Component, {}, {
|
|
1024
|
+
submitText: '保存',
|
|
1025
|
+
cancelText: '放弃',
|
|
1026
|
+
})
|
|
1027
|
+
|
|
1028
|
+
// 方式2:完全自定义底部
|
|
1029
|
+
modal.open(Component, {}, {
|
|
1030
|
+
footer: false, // 隐藏默认底部
|
|
1031
|
+
})
|
|
1032
|
+
```
|
|
1033
|
+
|
|
1034
|
+
然后在组件内使用 `ModalFooter` 插槽自定义:
|
|
1035
|
+
|
|
1036
|
+
```vue
|
|
1037
|
+
<template>
|
|
1038
|
+
<div>
|
|
1039
|
+
<ModalFooter>
|
|
1040
|
+
<button @click="handleCancel">取消</button>
|
|
1041
|
+
<button @click="handleSave">保存</button>
|
|
1042
|
+
</ModalFooter>
|
|
1043
|
+
</div>
|
|
1044
|
+
</template>
|
|
1045
|
+
```
|
|
1046
|
+
|
|
1047
|
+
### 6. 多个模态框如何区分?
|
|
1048
|
+
|
|
1049
|
+
通过 `useModal()` 在不同组件中调用会自动定位到当前所在模态框,无需手动管理。
|
|
1050
|
+
|
|
1051
|
+
---
|
|
1052
|
+
|
|
1053
|
+
## 注意事项
|
|
1054
|
+
|
|
1055
|
+
1. **必须在 ModalProvider 内使用**:`useModal` 必须在 `ModalProvider` 组件树内调用
|
|
1056
|
+
2. **样式文件导入**:记得在入口文件中导入 `dist/style.css`
|
|
1057
|
+
3. **表单提交**:使用 `onSubmit` 时需要配合 `form` 属性指定表单 name
|
|
1058
|
+
4. **Promise 行为**:调用 `close()` 时传入的数据会作为 Promise 的 resolve 值
|
|
1059
|
+
5. **嵌套层级**:组件会自动处理多层嵌套,无需额外配置
|
|
1060
|
+
|
|
1061
|
+
---
|
|
1062
|
+
|
|
1063
|
+
## License
|
|
1064
|
+
|
|
1065
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gopowerteam/modal-render",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "zhuchentong",
|
|
7
7
|
"email": "2037630@gmail.com"
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"exports": {
|
|
19
19
|
".": {
|
|
20
20
|
"types": "./dist/es/index.d.ts",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
21
|
+
"import": "./dist/es/index.mjs",
|
|
22
|
+
"require": "./dist/cjs/index.cjs"
|
|
23
23
|
},
|
|
24
24
|
"./es": {
|
|
25
25
|
"types": "./dist/es/index.d.ts",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"require": "./dist/cjs/index.cjs"
|
|
31
31
|
},
|
|
32
32
|
"./dist/style.css": {
|
|
33
|
-
"
|
|
34
|
-
"
|
|
33
|
+
"import": "./dist/style.css",
|
|
34
|
+
"require": "./dist/style.css"
|
|
35
35
|
},
|
|
36
36
|
"./*": "./*"
|
|
37
37
|
},
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"module": "./dist/es/index.mjs",
|
|
40
40
|
"types": "./dist/es/index.d.ts",
|
|
41
41
|
"files": [
|
|
42
|
-
"
|
|
43
|
-
"
|
|
42
|
+
"README.md",
|
|
43
|
+
"dist"
|
|
44
44
|
],
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"vue": "^3.0.0"
|