sodialog 0.1.11 → 0.1.14
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 +129 -2
- package/dist/favicon.ico +0 -0
- package/dist/logo.ico +0 -0
- package/dist/sodialog.css +1 -1
- package/dist/sodialog.es.js +568 -135
- package/dist/sodialog.umd.js +1 -1
- package/dist/types/lib.d.ts +104 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -34,6 +34,18 @@ openOffcanvas({
|
|
|
34
34
|
animation: 'slide',
|
|
35
35
|
content: '<p>这是 Offcanvas</p>',
|
|
36
36
|
})
|
|
37
|
+
|
|
38
|
+
// Toast
|
|
39
|
+
import { toast } from 'sodialog'
|
|
40
|
+
|
|
41
|
+
toast({
|
|
42
|
+
title: '保存成功',
|
|
43
|
+
content: '配置已更新',
|
|
44
|
+
placement: 'top-end',
|
|
45
|
+
variant: 'success',
|
|
46
|
+
duration: 2500,
|
|
47
|
+
maxVisible: 3,
|
|
48
|
+
})
|
|
37
49
|
```
|
|
38
50
|
|
|
39
51
|
## API
|
|
@@ -50,7 +62,7 @@ openOffcanvas({
|
|
|
50
62
|
- `animation?: 'slide' | 'fade' | 'zoom'` (默认 `fade`)
|
|
51
63
|
- `useModal?: boolean` (默认 `true`,`true` 使用 `showModal()`,`false` 使用 `show()`)
|
|
52
64
|
- `draggable?: boolean` (默认 `false`)
|
|
53
|
-
- `dragHandle?: 'header' | 'title' | 'body' | 'panel' | string
|
|
65
|
+
- `dragHandle?: ('header' | 'title' | 'body' | 'panel' | string) | Array<'header' | 'title' | 'body' | 'panel' | string>` (默认 `header`,支持传数组开启多拖动区域,也可传 CSS 选择器)
|
|
54
66
|
- `autoFitSize?: boolean` (默认 `true`,会根据 body 内容变化自动扩/缩尺寸,例如图片加载完成后)
|
|
55
67
|
- `scrollMode?: 'body' | 'hybrid' | 'viewport' | 'none'` (默认 `body`)
|
|
56
68
|
- `hybridSwitchRatio?: number` (默认 `1.35`,仅 `scrollMode: 'hybrid'` 时生效,最小值 `1`)
|
|
@@ -60,11 +72,30 @@ openOffcanvas({
|
|
|
60
72
|
- `autoFitMinHeight?: number` (默认 `160`)
|
|
61
73
|
- `confirmText?: string`
|
|
62
74
|
- `cancelText?: string`
|
|
75
|
+
- `footerButtons?: SoDialogFooterButton[]`(自定义底部按钮。未传时默认“取消 + 确认”)
|
|
76
|
+
- `hideFooter?: boolean`(默认 `false`,可隐藏底部按钮区)
|
|
77
|
+
- `footerAlign?: 'start' | 'center' | 'end' | 'between'`(默认 `end`)
|
|
63
78
|
- `confirmAction?: 'hide' | 'destroy'`(默认 `hide`;显式传入 `id` 时默认 `destroy`)
|
|
64
79
|
- `closeOnBackdrop?: boolean` (默认 `true`)
|
|
65
80
|
- `closeOnEsc?: boolean` (默认 `true`)
|
|
66
81
|
- `onConfirm?: () => void`
|
|
67
82
|
- `onCancel?: () => void`
|
|
83
|
+
- `onAction?: (context) => void`(监听所有 footer 按钮动作)
|
|
84
|
+
- `handle.setFooterButtons(buttons): void`(运行时整体替换 footer 按钮)
|
|
85
|
+
- `handle.updateFooterButton(id, updates): boolean`(按 id 更新某个 footer 按钮)
|
|
86
|
+
- `handle.onAction(listener): () => void`(追加动作监听,返回取消监听函数)
|
|
87
|
+
|
|
88
|
+
`SoDialogFooterButton` 字段:
|
|
89
|
+
|
|
90
|
+
- `id?: string`(动作标识,推荐传)
|
|
91
|
+
- `label: string | Node`
|
|
92
|
+
- `role?: 'confirm' | 'cancel' | 'custom'`
|
|
93
|
+
- `variant?: 'primary' | 'outline' | 'danger' | 'success' | 'ghost' | 'link'`
|
|
94
|
+
- `action?: 'none' | 'hide' | 'destroy'`
|
|
95
|
+
- `className?: string`
|
|
96
|
+
- `disabled?: boolean`
|
|
97
|
+
- `attrs?: Record<string, string>`
|
|
98
|
+
- `onClick?: (context) => void | boolean | Promise<void | boolean>`(返回 `false` 可阻止后续默认动作)
|
|
68
99
|
|
|
69
100
|
说明:
|
|
70
101
|
|
|
@@ -72,6 +103,38 @@ openOffcanvas({
|
|
|
72
103
|
- `取消/关闭` 语义是 `dialog.close()`(隐藏)
|
|
73
104
|
- `confirmAction: 'destroy'` 语义是 `dialog.remove()`(销毁)
|
|
74
105
|
|
|
106
|
+
示例(自定义 footer 按钮、动作监听、运行时更新):
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
const handle = openModal({
|
|
110
|
+
title: '订单操作',
|
|
111
|
+
content: '<p>请选择一个动作</p>',
|
|
112
|
+
footerAlign: 'between',
|
|
113
|
+
footerButtons: [
|
|
114
|
+
{ id: 'help', label: '帮助', variant: 'link', action: 'none' },
|
|
115
|
+
{ id: 'cancel', label: '取消', role: 'cancel', variant: 'outline' },
|
|
116
|
+
{ id: 'delete', label: '删除', variant: 'danger', action: 'destroy' },
|
|
117
|
+
],
|
|
118
|
+
onAction: ({ action }) => {
|
|
119
|
+
console.log('global action:', action)
|
|
120
|
+
},
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
const off = handle.onAction(({ action, dialog }) => {
|
|
124
|
+
if (action === 'help') {
|
|
125
|
+
dialog.querySelector('.sod-body')?.insertAdjacentHTML('beforeend', '<p>帮助信息已展开</p>')
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
handle.updateFooterButton('delete', { label: '确认删除', disabled: false })
|
|
130
|
+
handle.setFooterButtons([
|
|
131
|
+
{ id: 'close', label: '关闭', role: 'cancel', variant: 'ghost' },
|
|
132
|
+
{ id: 'confirm', label: '提交', role: 'confirm', variant: 'primary' },
|
|
133
|
+
])
|
|
134
|
+
|
|
135
|
+
off()
|
|
136
|
+
```
|
|
137
|
+
|
|
75
138
|
### `openOffcanvas(options)`
|
|
76
139
|
|
|
77
140
|
在 `openModal` 参数基础上新增:
|
|
@@ -92,17 +155,71 @@ openOffcanvas({ title: 'Bottom', placement: 'bottom', animation: 'zoom', content
|
|
|
92
155
|
|
|
93
156
|
通用入口,`options.kind` 可为 `modal` 或 `offcanvas`。
|
|
94
157
|
|
|
158
|
+
### `toast(options)` / `SoToast.show(options)`
|
|
159
|
+
|
|
160
|
+
- `content: string | Node`
|
|
161
|
+
- `title?: string`
|
|
162
|
+
- `placement?: 'top-start' | 'top-center' | 'top-end' | 'bottom-start' | 'bottom-center' | 'bottom-end'`(默认 `top-end`)
|
|
163
|
+
- `variant?: 'default' | 'info' | 'success' | 'warning' | 'danger'`(默认 `default`)
|
|
164
|
+
- `duration?: number | false`(默认 `3000`,`false` 表示不自动消失)
|
|
165
|
+
- `showProgress?: boolean`(默认 `true`,显示自动消失倒计时进度条)
|
|
166
|
+
- `maxVisible?: number`(默认 `3`,按同位置队列生效)
|
|
167
|
+
- `closable?: boolean`(默认 `true`)
|
|
168
|
+
- `pauseOnHover?: boolean`(默认 `true`)
|
|
169
|
+
- `pauseOnWindowBlur?: boolean`(默认 `false`,切换窗口时暂停倒计时)
|
|
170
|
+
- `duplicateStrategy?: 'update' | 'ignore' | 'restart-timer' | 'stack'`(默认 `update`)
|
|
171
|
+
- `onShown?: (handle) => void`
|
|
172
|
+
- `onClose?: (reason, handle) => void`
|
|
173
|
+
|
|
174
|
+
队列与控制:
|
|
175
|
+
|
|
176
|
+
- 超过 `maxVisible` 的消息会进入队列,前面的 toast 关闭后自动补位
|
|
177
|
+
- 相同 `id` 再次调用会按 `duplicateStrategy` 处理
|
|
178
|
+
- `update`: 更新内容与配置;若 `placement` 改变会迁移到新位置
|
|
179
|
+
- `ignore`: 保留已有 toast,忽略本次重复调用
|
|
180
|
+
- `restart-timer`: 更新并强制重启倒计时
|
|
181
|
+
- `stack`: 自动生成新 id,保留已有 toast 并叠加新 toast
|
|
182
|
+
- 返回 `handle`,支持 `close / update / pause / resume`
|
|
183
|
+
- 可用 `SoToast.clear(placement?)` 清空指定位置或全部 toast
|
|
184
|
+
- 可用 `SoToast.closeAll()` 清空全部 toast
|
|
185
|
+
- 便捷方法:`SoToast.success/error/info/warning`
|
|
186
|
+
|
|
95
187
|
## 开发
|
|
96
188
|
|
|
97
189
|
```bash
|
|
98
190
|
npm run dev
|
|
99
191
|
npm run lint
|
|
100
192
|
npm run build
|
|
193
|
+
npm run docs:changelog
|
|
101
194
|
```
|
|
102
195
|
|
|
196
|
+
## GitHub Pages 首页
|
|
197
|
+
|
|
198
|
+
本仓库已将文档主页入口放在 `index.html + src/main.ts`,用于展示开发文档与使用说明。
|
|
199
|
+
|
|
200
|
+
- 本地构建主页:`npm run build:demo`
|
|
201
|
+
- 产物目录:`dist-pages/`
|
|
202
|
+
- 线上部署:`.github/workflows/pages.yml`(推送到 `master` 自动部署)
|
|
203
|
+
- 仓库设置:`Settings -> Pages -> Source` 选择 `GitHub Actions`
|
|
204
|
+
|
|
205
|
+
默认线上地址:`https://sohophp.github.io/sodialog/`
|
|
206
|
+
|
|
207
|
+
## 文档体系
|
|
208
|
+
|
|
209
|
+
- `README.md`:使用方式、API、发布流程总览
|
|
210
|
+
- `CHANGELOG.md`:版本变更记录(按 git tag 自动生成)
|
|
211
|
+
- `RELEASE_CHECKLIST.md`:发布前人工检查清单
|
|
212
|
+
|
|
213
|
+
### 文档自动更新
|
|
214
|
+
|
|
215
|
+
- 本地可执行:`npm run docs:changelog`
|
|
216
|
+
- 仓库内置工作流:`.github/workflows/docs-changelog.yml`
|
|
217
|
+
- 当推送版本 tag(`v*.*.*`)时,工作流会自动重建 `CHANGELOG.md` 并回推到 `master`
|
|
218
|
+
|
|
103
219
|
Demo 中已包含:
|
|
104
220
|
|
|
105
221
|
- 预设默认值:`center`、`zoom`、`medium`、`showModal`、不可拖动、自动适配
|
|
222
|
+
- 拖动区域支持多选(`header/title/body/panel` 可组合)
|
|
106
223
|
- `Modal ID` 留空自动生成,输入后可复用唤醒同 ID
|
|
107
224
|
- Modal 内切换不同尺寸图片,验证 `autoFitSize` 自动扩缩
|
|
108
225
|
- 包含超大图(`xlarge`)、超长单词、超宽表格的溢出测试
|
|
@@ -110,6 +227,10 @@ Demo 中已包含:
|
|
|
110
227
|
- 子窗口包含多种表单元素(input/select/checkbox/textarea)演示
|
|
111
228
|
- 新增 Markdown 编辑器子窗口(工具栏插入、实时预览)
|
|
112
229
|
- 编辑器支持“仅编辑 / 编辑 + 预览”模式切换
|
|
230
|
+
- Modal 新增“启用自定义 Footer API”开关(可切换默认按钮与自定义按钮)
|
|
231
|
+
- Footer 按钮支持样式变体演示(`link / outline / danger / success / ghost`)
|
|
232
|
+
- Footer 动作统一监听(`onAction`)与事件日志输出
|
|
233
|
+
- 运行时按钮更新演示(`handle.updateFooterButton` / `handle.setFooterButtons`)
|
|
113
234
|
|
|
114
235
|
## 发布到 NPM
|
|
115
236
|
|
|
@@ -129,16 +250,22 @@ Demo 中已包含:
|
|
|
129
250
|
|
|
130
251
|
1. 在 npm 包页面启用 Trusted Publishing,并绑定 GitHub 仓库与该工作流
|
|
131
252
|
2. 确保工作流权限包含 `id-token: write`(本仓库已配置)
|
|
253
|
+
3. 本地先做版本校验(tag 必须和 `package.json` 一致)
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
npm run release:check -- vX.Y.Z
|
|
257
|
+
```
|
|
132
258
|
|
|
133
259
|
说明:当前工作流优先使用 `NPM_AUTOMATION_TOKEN` 发布;未配置时回退到 Trusted Publishing(OIDC)。
|
|
134
260
|
|
|
135
|
-
- 若使用 token 路径,`NPM_AUTOMATION_TOKEN`
|
|
261
|
+
- 若使用 token 路径,`NPM_AUTOMATION_TOKEN` 请使用 npm Granular access token(Write 权限),并启用 `Bypass 2FA`,否则 CI 发布会报 `EOTP`。
|
|
136
262
|
- 若使用 Trusted Publishing 路径,需先在 npm 包设置里完成仓库和 workflow 绑定,否则发布阶段可能出现 `E404`。
|
|
137
263
|
|
|
138
264
|
推荐发布命令:
|
|
139
265
|
|
|
140
266
|
```bash
|
|
141
267
|
npm version patch --no-git-tag-version
|
|
268
|
+
npm run release:check -- vX.Y.Z
|
|
142
269
|
git add -A
|
|
143
270
|
git commit -m "release: vX.Y.Z"
|
|
144
271
|
git tag -a vX.Y.Z -m "vX.Y.Z"
|
package/dist/favicon.ico
ADDED
|
Binary file
|
package/dist/logo.ico
ADDED
|
Binary file
|
package/dist/sodialog.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.sod-dialog{border:0;padding:0;margin:auto;background:transparent;max-width:none;max-height:none;overflow:visible}.sod-dialog::backdrop{background:#0000007f}.sod-panel{box-sizing:border-box;background:#fff;color:#212529;border-radius:.5rem;box-shadow:0 .5rem 1rem #00000040;min-width:min(520px,calc(100vw - 2rem));max-width:min(520px,calc(100vw - 2rem))}.sod-modal .sod-panel{position:relative;margin:0}.sod-modal[open]{width:100vw;height:100vh;display:flex;justify-content:center;align-items:center}.sod-modal[open].sod-modal-viewport-scroll{align-items:flex-start;overflow:auto;padding:1rem 0}.sod-modal .sod-panel.sod-modal-pos-center{align-self:center}.sod-modal .sod-panel.sod-modal-pos-top{align-self:flex-start;margin-top:1rem}.sod-modal .sod-panel.sod-modal-pos-bottom{align-self:flex-end;margin-bottom:1rem}.sod-modal .sod-panel.sod-modal-autofit{min-width:0;width:auto;height:auto;max-width:calc(100vw - 2rem);max-height:calc(100vh - 2rem);display:flex;flex-direction:column}.sod-modal .sod-panel.sod-modal-draggable{touch-action:none}.sod-modal .sod-panel.sod-is-dragging{animation:none!important;transition:none!important}.sod-modal .sod-panel .sod-drag-handle{cursor:move;-webkit-user-select:none;user-select:none}.sod-modal .sod-panel .sod-drag-handle.is-dragging{cursor:grabbing}.sod-modal .sod-panel.sod-modal-anim-fade{animation:sod-fade-in .18s ease-out}.sod-modal .sod-panel.sod-modal-anim-fade.is-closing{animation:sod-fade-out .18s ease-in forwards}.sod-modal .sod-panel.sod-modal-anim-zoom{animation:sod-modal-zoom-in .18s ease-out}.sod-modal .sod-panel.sod-modal-anim-zoom.is-closing{animation:sod-modal-zoom-out .18s ease-in forwards}.sod-modal .sod-panel.sod-modal-anim-slide{animation:sod-modal-slide-in .18s ease-out}.sod-modal .sod-panel.sod-modal-anim-slide.is-closing{animation:sod-modal-slide-out .18s ease-in forwards}.sod-header{display:flex;align-items:center;justify-content:space-between;padding:1rem 1rem .75rem;border-bottom:1px solid #dee2e6}.sod-title{margin:0;font-size:1.1rem}.sod-close{border:0;background:transparent;color:#6c757d;font-size:1.5rem;line-height:1;cursor:pointer}.sod-body{box-sizing:border-box;padding:1rem;overflow-wrap:anywhere;word-break:break-word}.sod-body>*{max-width:100%}.sod-body input,.sod-body select,.sod-body textarea,.sod-body button{max-width:100%;box-sizing:border-box}.sod-body img,.sod-body video,.sod-body canvas,.sod-body iframe,.sod-body table{max-width:100%}.sod-modal .sod-panel.sod-modal-autofit .sod-body{flex:1 1 auto;min-height:0}.sod-body p{margin:0 0 .5rem}.sod-body ul{margin:.5rem 0 0;padding-left:1.2rem}.sod-footer{padding:.75rem 1rem 1rem;border-top:1px solid #dee2e6;display:flex;justify-content:flex-end;gap:.5rem}.sod-btn{display:inline-flex;align-items:center;justify-content:center;border-radius:.375rem;border:1px solid transparent;padding:.5rem 1rem;font-size:.95rem;font-weight:500;cursor:pointer;transition:all .15s ease-in-out}.sod-btn:focus-visible{outline:2px solid #86b7fe;outline-offset:1px}.sod-btn-primary{background:#0d6efd;color:#fff;border-color:#0d6efd}.sod-btn-primary:hover{background:#0b5ed7;border-color:#0a58ca}.sod-btn-outline{background:transparent;color:#6c757d;border-color:#6c757d}.sod-btn-outline:hover{color:#fff;background:#6c757d}.sod-offcanvas[open]{width:100vw;height:100vh}.sod-offcanvas .sod-panel{position:fixed;margin:0;min-width:0;max-width:none;border-radius:0;width:min(360px,90vw);height:100vh}.sod-offcanvas .sod-panel.sod-placement-start{left:0;top:0}.sod-offcanvas .sod-panel.sod-placement-end{right:0;top:0}.sod-offcanvas .sod-panel.sod-placement-top{top:0;left:0;width:100vw;height:300px}.sod-offcanvas .sod-panel.sod-placement-bottom{bottom:0;left:0;width:100vw;height:300px}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-start{animation:sod-slide-in-start .18s ease-out}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-start.is-closing{animation:sod-slide-out-start .18s ease-in forwards}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-end{animation:sod-slide-in-end .18s ease-out}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-end.is-closing{animation:sod-slide-out-end .18s ease-in forwards}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-top{animation:sod-slide-in-top .18s ease-out}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-top.is-closing{animation:sod-slide-out-top .18s ease-in forwards}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-bottom{animation:sod-slide-in-bottom .18s ease-out}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-bottom.is-closing{animation:sod-slide-out-bottom .18s ease-in forwards}.sod-offcanvas .sod-panel.sod-anim-fade{animation:sod-fade-in .18s ease-out}.sod-offcanvas .sod-panel.sod-anim-fade.is-closing{animation:sod-fade-out .18s ease-in forwards}.sod-offcanvas .sod-panel.sod-anim-zoom{animation:sod-zoom-in .18s ease-out}.sod-offcanvas .sod-panel.sod-anim-zoom.is-closing{animation:sod-zoom-out .18s ease-in forwards}@keyframes sod-modal-zoom-in{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}@keyframes sod-modal-zoom-out{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.96)}}@keyframes sod-modal-slide-in{0%{opacity:0;transform:translateY(-16px)}to{opacity:1;transform:translateY(0)}}@keyframes sod-modal-slide-out{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-12px)}}@keyframes sod-slide-in-start{0%{transform:translate(-100%)}to{transform:translate(0)}}@keyframes sod-slide-out-start{0%{transform:translate(0)}to{transform:translate(-100%)}}@keyframes sod-slide-in-end{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes sod-slide-out-end{0%{transform:translate(0)}to{transform:translate(100%)}}@keyframes sod-slide-in-top{0%{transform:translateY(-100%)}to{transform:translateY(0)}}@keyframes sod-slide-out-top{0%{transform:translateY(0)}to{transform:translateY(-100%)}}@keyframes sod-slide-in-bottom{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes sod-slide-out-bottom{0%{transform:translateY(0)}to{transform:translateY(100%)}}@keyframes sod-fade-in{0%{opacity:0}to{opacity:1}}@keyframes sod-fade-out{0%{opacity:1}to{opacity:0}}@keyframes sod-zoom-in{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}@keyframes sod-zoom-out{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.96)}}
|
|
1
|
+
.sod-dialog{border:0;padding:0;margin:auto;background:transparent;max-width:none;max-height:none;overflow:visible}.sod-dialog::backdrop{background:#0000007f}.sod-panel{box-sizing:border-box;background:#fff;color:#212529;border-radius:.5rem;box-shadow:0 .5rem 1rem #00000040;min-width:min(520px,calc(100vw - 2rem));max-width:min(520px,calc(100vw - 2rem))}.sod-modal .sod-panel{position:relative;margin:0}.sod-modal[open]{width:100vw;height:100vh;display:flex;justify-content:center;align-items:center}.sod-modal[open].sod-modal-viewport-scroll{align-items:flex-start;overflow:auto;padding:1rem 0}.sod-modal .sod-panel.sod-modal-pos-center{align-self:center}.sod-modal .sod-panel.sod-modal-pos-top{align-self:flex-start;margin-top:1rem}.sod-modal .sod-panel.sod-modal-pos-bottom{align-self:flex-end;margin-bottom:1rem}.sod-modal .sod-panel.sod-modal-autofit{min-width:0;width:auto;height:auto;max-width:calc(100vw - 2rem);max-height:calc(100vh - 2rem);display:flex;flex-direction:column}.sod-modal .sod-panel.sod-modal-draggable{touch-action:none}.sod-modal .sod-panel.sod-is-dragging{animation:none!important;transition:none!important}.sod-modal .sod-panel .sod-drag-handle{cursor:move;-webkit-user-select:none;user-select:none}.sod-modal .sod-panel .sod-drag-handle.is-dragging{cursor:grabbing}.sod-modal .sod-panel.sod-modal-anim-fade{animation:sod-fade-in .18s ease-out}.sod-modal .sod-panel.sod-modal-anim-fade.is-closing{animation:sod-fade-out .18s ease-in forwards}.sod-modal .sod-panel.sod-modal-anim-zoom{animation:sod-modal-zoom-in .18s ease-out}.sod-modal .sod-panel.sod-modal-anim-zoom.is-closing{animation:sod-modal-zoom-out .18s ease-in forwards}.sod-modal .sod-panel.sod-modal-anim-slide{animation:sod-modal-slide-in .18s ease-out}.sod-modal .sod-panel.sod-modal-anim-slide.is-closing{animation:sod-modal-slide-out .18s ease-in forwards}.sod-header{display:flex;align-items:center;justify-content:space-between;padding:1rem 1rem .75rem;border-bottom:1px solid #dee2e6}.sod-title{margin:0;font-size:1.1rem}.sod-close{border:0;background:transparent;color:#6c757d;font-size:1.5rem;line-height:1;cursor:pointer}.sod-body{box-sizing:border-box;padding:1rem;overflow-wrap:anywhere;word-break:break-word}.sod-body>*{max-width:100%}.sod-body input,.sod-body select,.sod-body textarea,.sod-body button{max-width:100%;box-sizing:border-box}.sod-body img,.sod-body video,.sod-body canvas,.sod-body iframe,.sod-body table{max-width:100%}.sod-modal .sod-panel.sod-modal-autofit .sod-body{flex:1 1 auto;min-height:0}.sod-body p{margin:0 0 .5rem}.sod-body ul{margin:.5rem 0 0;padding-left:1.2rem}.sod-footer{padding:.75rem 1rem 1rem;border-top:1px solid #dee2e6;display:flex;justify-content:flex-end;gap:.5rem}.sod-footer[data-align=start]{justify-content:flex-start}.sod-footer[data-align=center]{justify-content:center}.sod-footer[data-align=between]{justify-content:space-between}.sod-btn{display:inline-flex;align-items:center;justify-content:center;border-radius:.375rem;border:1px solid transparent;padding:.5rem 1rem;font-size:.95rem;font-weight:500;cursor:pointer;transition:all .15s ease-in-out}.sod-btn:focus-visible{outline:2px solid #86b7fe;outline-offset:1px}.sod-btn-primary{background:#0d6efd;color:#fff;border-color:#0d6efd}.sod-btn-primary:hover{background:#0b5ed7;border-color:#0a58ca}.sod-btn-outline{background:transparent;color:#6c757d;border-color:#6c757d}.sod-btn-outline:hover{color:#fff;background:#6c757d}.sod-btn-danger{background:#dc3545;color:#fff;border-color:#dc3545}.sod-btn-danger:hover{background:#bb2d3b;border-color:#b02a37}.sod-btn-success{background:#198754;color:#fff;border-color:#198754}.sod-btn-success:hover{background:#157347;border-color:#146c43}.sod-btn-ghost{background:transparent;color:#495057;border-color:transparent}.sod-btn-ghost:hover{background:#e9ecef}.sod-btn-link{background:transparent;color:#0d6efd;border-color:transparent;text-decoration:underline;text-underline-offset:2px}.sod-btn-link:hover{color:#0a58ca}.sod-offcanvas[open]{width:100vw;height:100vh}.sod-offcanvas .sod-panel{position:fixed;margin:0;min-width:0;max-width:none;border-radius:0;width:min(360px,90vw);height:100vh}.sod-offcanvas .sod-panel.sod-placement-start{left:0;top:0}.sod-offcanvas .sod-panel.sod-placement-end{right:0;top:0}.sod-offcanvas .sod-panel.sod-placement-top{top:0;left:0;width:100vw;height:300px}.sod-offcanvas .sod-panel.sod-placement-bottom{bottom:0;left:0;width:100vw;height:300px}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-start{animation:sod-slide-in-start .18s ease-out}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-start.is-closing{animation:sod-slide-out-start .18s ease-in forwards}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-end{animation:sod-slide-in-end .18s ease-out}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-end.is-closing{animation:sod-slide-out-end .18s ease-in forwards}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-top{animation:sod-slide-in-top .18s ease-out}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-top.is-closing{animation:sod-slide-out-top .18s ease-in forwards}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-bottom{animation:sod-slide-in-bottom .18s ease-out}.sod-offcanvas .sod-panel.sod-anim-slide.sod-placement-bottom.is-closing{animation:sod-slide-out-bottom .18s ease-in forwards}.sod-offcanvas .sod-panel.sod-anim-fade{animation:sod-fade-in .18s ease-out}.sod-offcanvas .sod-panel.sod-anim-fade.is-closing{animation:sod-fade-out .18s ease-in forwards}.sod-offcanvas .sod-panel.sod-anim-zoom{animation:sod-zoom-in .18s ease-out}.sod-offcanvas .sod-panel.sod-anim-zoom.is-closing{animation:sod-zoom-out .18s ease-in forwards}@keyframes sod-modal-zoom-in{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}@keyframes sod-modal-zoom-out{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.96)}}@keyframes sod-modal-slide-in{0%{opacity:0;transform:translateY(-16px)}to{opacity:1;transform:translateY(0)}}@keyframes sod-modal-slide-out{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-12px)}}@keyframes sod-slide-in-start{0%{transform:translate(-100%)}to{transform:translate(0)}}@keyframes sod-slide-out-start{0%{transform:translate(0)}to{transform:translate(-100%)}}@keyframes sod-slide-in-end{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes sod-slide-out-end{0%{transform:translate(0)}to{transform:translate(100%)}}@keyframes sod-slide-in-top{0%{transform:translateY(-100%)}to{transform:translateY(0)}}@keyframes sod-slide-out-top{0%{transform:translateY(0)}to{transform:translateY(-100%)}}@keyframes sod-slide-in-bottom{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes sod-slide-out-bottom{0%{transform:translateY(0)}to{transform:translateY(100%)}}@keyframes sod-fade-in{0%{opacity:0}to{opacity:1}}@keyframes sod-fade-out{0%{opacity:1}to{opacity:0}}@keyframes sod-zoom-in{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}.sod-toast-layer{position:fixed;z-index:1200;display:flex;flex-direction:column;gap:.5rem;width:min(360px,calc(100vw - 1.5rem));pointer-events:none}.sod-toast-layer-top-start{top:.75rem;left:.75rem;align-items:flex-start}.sod-toast-layer-top-center{top:.75rem;left:50%;transform:translate(-50%);align-items:center}.sod-toast-layer-top-end{top:.75rem;right:.75rem;align-items:flex-end}.sod-toast-layer-bottom-start{bottom:.75rem;left:.75rem;align-items:flex-start}.sod-toast-layer-bottom-center{bottom:.75rem;left:50%;transform:translate(-50%);align-items:center}.sod-toast-layer-bottom-end{bottom:.75rem;right:.75rem;align-items:flex-end}.sod-toast{--sod-toast-accent: #6c757d;pointer-events:auto;width:100%;box-sizing:border-box;border-radius:.5rem;border:1px solid #dee2e6;background:#fff;color:#212529;box-shadow:0 .5rem 1rem #0000002e;overflow:hidden;animation:sod-toast-enter .18s ease-out}.sod-toast.is-closing{animation:sod-toast-exit .18s ease-in forwards}.sod-toast-header{display:flex;align-items:center;justify-content:space-between;gap:.5rem;padding:.5rem .75rem 0}.sod-toast-title{font-size:.92rem;font-weight:700}.sod-toast-close{border:0;background:transparent;color:#6c757d;font-size:1.15rem;line-height:1;cursor:pointer;padding:0}.sod-toast-body{padding:.55rem .75rem .75rem;font-size:.92rem;line-height:1.45;overflow-wrap:anywhere;word-break:break-word}.sod-toast-progress{width:100%;height:3px;background:var(--sod-toast-accent);opacity:.9;transform-origin:left center;animation:sod-toast-progress-countdown 3s linear forwards}.sod-toast-default{--sod-toast-accent: #6c757d;border-left:4px solid #6c757d}.sod-toast-info{--sod-toast-accent: #0dcaf0;border-left:4px solid #0dcaf0}.sod-toast-success{--sod-toast-accent: #198754;border-left:4px solid #198754}.sod-toast-warning{--sod-toast-accent: #ffc107;border-left:4px solid #ffc107}.sod-toast-danger{--sod-toast-accent: #dc3545;border-left:4px solid #dc3545}@keyframes sod-toast-enter{0%{opacity:0;transform:translateY(-8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes sod-toast-exit{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.96)}}@keyframes sod-toast-progress-countdown{0%{transform:scaleX(1)}to{transform:scaleX(0)}}@keyframes sod-zoom-out{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.96)}}
|
package/dist/sodialog.es.js
CHANGED
|
@@ -1,186 +1,299 @@
|
|
|
1
|
-
function
|
|
1
|
+
function W(n, e) {
|
|
2
2
|
if (typeof e == "string") {
|
|
3
|
-
|
|
3
|
+
n.innerHTML = e;
|
|
4
4
|
return;
|
|
5
5
|
}
|
|
6
|
-
|
|
6
|
+
n.append(e);
|
|
7
7
|
}
|
|
8
|
-
function
|
|
8
|
+
function B(n, e = "hide") {
|
|
9
9
|
if (e === "destroy") {
|
|
10
|
-
|
|
10
|
+
n.dataset.sodDestroy = "true", n.open && n.close(), n.remove();
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
|
-
|
|
13
|
+
n.open && n.close();
|
|
14
14
|
}
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
return i === "panel" ? t : i === "header" ? t.querySelector(".sod-header") : i === "title" ? t.querySelector(".sod-title") : i === "body" ? t.querySelector(".sod-body") : t.querySelector(i) ?? t.querySelector(".sod-header");
|
|
15
|
+
function $(n, e) {
|
|
16
|
+
return n.action ? n.action : n.role === "confirm" ? e : n.role === "cancel" ? "hide" : "none";
|
|
18
17
|
}
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
function N(n) {
|
|
19
|
+
return n === "danger" ? "sod-btn-danger" : n === "success" ? "sod-btn-success" : n === "ghost" ? "sod-btn-ghost" : n === "link" ? "sod-btn-link" : n === "outline" ? "sod-btn-outline" : "sod-btn-primary";
|
|
20
|
+
}
|
|
21
|
+
function F(n, e) {
|
|
22
|
+
const t = Array.isArray(e) ? e.length > 0 ? e : ["header"] : [e ?? "header"], s = [], i = (o) => {
|
|
23
|
+
o && (s.includes(o) || s.push(o));
|
|
24
|
+
};
|
|
25
|
+
for (const o of t) {
|
|
26
|
+
if (o === "panel") {
|
|
27
|
+
i(n);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (o === "header") {
|
|
31
|
+
i(n.querySelector(".sod-header"));
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (o === "title") {
|
|
35
|
+
i(n.querySelector(".sod-title"));
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (o === "body") {
|
|
39
|
+
i(n.querySelector(".sod-body"));
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
n.querySelectorAll(o).forEach((r) => {
|
|
43
|
+
i(r);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return s.length === 0 && i(n.querySelector(".sod-header")), s;
|
|
47
|
+
}
|
|
48
|
+
function k(n, e) {
|
|
49
|
+
const t = F(n, e);
|
|
50
|
+
if (t.length === 0)
|
|
22
51
|
return;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
52
|
+
n.classList.add("sod-modal-draggable"), t.forEach((m) => {
|
|
53
|
+
m.classList.add("sod-drag-handle");
|
|
54
|
+
});
|
|
55
|
+
let s = !1, i = 0, o = 0, r = null, d = null, h = 0, a = 0, f = 0;
|
|
56
|
+
const v = document.body.style.userSelect, E = (m, u) => {
|
|
57
|
+
const y = n.getBoundingClientRect(), p = Math.max(0, window.innerWidth - y.width), S = Math.max(0, window.innerHeight - y.height), A = Math.min(0, window.innerWidth - y.width), b = Math.min(0, window.innerHeight - y.height);
|
|
27
58
|
return {
|
|
28
|
-
left: Math.min(
|
|
29
|
-
top: Math.min(
|
|
59
|
+
left: Math.min(p, Math.max(A, m)),
|
|
60
|
+
top: Math.min(S, Math.max(b, u))
|
|
30
61
|
};
|
|
31
|
-
},
|
|
62
|
+
}, R = (m) => {
|
|
32
63
|
if (!s)
|
|
33
64
|
return;
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
65
|
+
const u = E(m.clientX - i, m.clientY - o);
|
|
66
|
+
a = u.left, f = u.top, h === 0 && (h = window.requestAnimationFrame(() => {
|
|
67
|
+
h = 0, n.style.inset = "auto", n.style.left = `${a}px`, n.style.top = `${f}px`, n.style.right = "auto", n.style.bottom = "auto", n.style.margin = "0", n.style.transform = "none";
|
|
37
68
|
}));
|
|
38
|
-
},
|
|
39
|
-
s = !1,
|
|
69
|
+
}, x = () => {
|
|
70
|
+
s = !1, t.forEach((m) => {
|
|
71
|
+
m.classList.remove("is-dragging");
|
|
72
|
+
}), n.classList.remove("sod-is-dragging"), n.style.willChange = "", document.body.style.userSelect = v, h !== 0 && (window.cancelAnimationFrame(h), h = 0), r !== null && d !== null && d.hasPointerCapture && d.hasPointerCapture(r) && d.releasePointerCapture(r), r = null, d = null, window.removeEventListener("pointermove", R), window.removeEventListener("pointerup", x), window.removeEventListener("pointercancel", x);
|
|
40
73
|
};
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
74
|
+
t.forEach((m) => {
|
|
75
|
+
m.addEventListener("pointerdown", (u) => {
|
|
76
|
+
if (u.button !== 0 || u.target?.closest("button, input, select, textarea, a"))
|
|
77
|
+
return;
|
|
78
|
+
u.preventDefault(), n.classList.add("sod-is-dragging"), n.style.animation = "none", n.style.transition = "none", n.style.transform = "none";
|
|
79
|
+
const p = n.getBoundingClientRect();
|
|
80
|
+
i = u.clientX - p.left, o = u.clientY - p.top, s = !0, r = u.pointerId, d = m, m.setPointerCapture(u.pointerId), n.style.position = "fixed", n.style.left = `${p.left}px`, n.style.top = `${p.top}px`, n.style.width = `${Math.round(p.width)}px`, n.style.height = `${Math.round(p.height)}px`, n.style.inset = "auto", n.style.right = "auto", n.style.bottom = "auto", n.style.margin = "0", n.style.willChange = "left, top", m.classList.add("is-dragging"), document.body.style.userSelect = "none", window.addEventListener("pointermove", R), window.addEventListener("pointerup", x), window.addEventListener("pointercancel", x);
|
|
81
|
+
});
|
|
47
82
|
});
|
|
48
83
|
}
|
|
49
|
-
function
|
|
50
|
-
const
|
|
51
|
-
let
|
|
52
|
-
const
|
|
53
|
-
if (
|
|
84
|
+
function D(n, e, t, s, i, o) {
|
|
85
|
+
const d = Math.max(1, o?.hybridSwitchRatio ?? 1.35), h = o?.refitOnContentChange ?? !0, a = Math.max(120, o?.autoFitMinWidth ?? 280), f = Math.max(100, o?.autoFitMinHeight ?? 160), v = o?.scrollMode ? o.scrollMode : o?.autoFitUseScrollbar === !1 ? "viewport" : "body";
|
|
86
|
+
let E = 0;
|
|
87
|
+
const R = (b, M, L) => Math.min(L, Math.max(M, b)), x = () => {
|
|
88
|
+
if (E = 0, !n.isConnected || !n.open)
|
|
54
89
|
return;
|
|
55
|
-
const
|
|
90
|
+
const b = Math.max(a, window.innerWidth - 32), M = Math.max(f, window.innerHeight - 32);
|
|
56
91
|
e.style.width = "auto", e.style.height = "auto", e.style.maxHeight = "none", s.style.maxHeight = "none", s.style.overflowY = "visible", s.style.overflowX = "visible";
|
|
57
|
-
const
|
|
58
|
-
if (
|
|
59
|
-
const
|
|
60
|
-
e.style.width = `${
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
} else if (
|
|
64
|
-
if (
|
|
65
|
-
const
|
|
66
|
-
e.style.width = `${
|
|
92
|
+
const L = Math.ceil(e.scrollWidth), l = Math.ceil(e.scrollHeight), c = L > b, g = l > M;
|
|
93
|
+
if (v === "body") {
|
|
94
|
+
const w = R(L, a, b), O = R(l, f, M);
|
|
95
|
+
e.style.width = `${w}px`, e.style.maxWidth = `${b}px`, e.style.height = `${O}px`, e.style.maxHeight = `${M}px`;
|
|
96
|
+
const H = t.offsetHeight, T = i.offsetHeight, I = Math.max(64, O - H - T);
|
|
97
|
+
g ? (s.style.maxHeight = `${I}px`, s.style.overflowY = "auto") : (s.style.maxHeight = "none", s.style.overflowY = "hidden"), s.style.overflowX = c ? "auto" : "hidden", n.classList.remove("sod-modal-viewport-scroll");
|
|
98
|
+
} else if (v === "hybrid")
|
|
99
|
+
if (l > M * d) {
|
|
100
|
+
const O = Math.max(L, a), H = Math.max(l, f);
|
|
101
|
+
e.style.width = `${O}px`, e.style.maxWidth = "none", e.style.height = `${H}px`, e.style.maxHeight = "none", s.style.maxHeight = "none", s.style.overflowY = "visible", s.style.overflowX = "visible", n.classList.add("sod-modal-viewport-scroll");
|
|
67
102
|
} else {
|
|
68
|
-
const
|
|
69
|
-
e.style.width = `${
|
|
70
|
-
const
|
|
71
|
-
|
|
103
|
+
const O = R(L, a, b), H = R(l, f, M);
|
|
104
|
+
e.style.width = `${O}px`, e.style.maxWidth = `${b}px`, e.style.height = `${H}px`, e.style.maxHeight = `${M}px`;
|
|
105
|
+
const T = t.offsetHeight, I = i.offsetHeight, C = Math.max(64, H - T - I);
|
|
106
|
+
g ? (s.style.maxHeight = `${C}px`, s.style.overflowY = "auto") : (s.style.maxHeight = "none", s.style.overflowY = "hidden"), s.style.overflowX = c ? "auto" : "hidden", n.classList.remove("sod-modal-viewport-scroll");
|
|
72
107
|
}
|
|
73
|
-
else if (
|
|
74
|
-
const
|
|
75
|
-
e.style.width = `${
|
|
108
|
+
else if (v === "viewport") {
|
|
109
|
+
const w = Math.max(L, a), O = Math.max(l, f);
|
|
110
|
+
e.style.width = `${w}px`, e.style.maxWidth = "none", e.style.height = `${O}px`, e.style.maxHeight = "none", s.style.maxHeight = "none", s.style.overflowY = "visible", s.style.overflowX = "visible", O > M ? n.classList.add("sod-modal-viewport-scroll") : n.classList.remove("sod-modal-viewport-scroll");
|
|
76
111
|
} else {
|
|
77
|
-
const
|
|
78
|
-
if (
|
|
79
|
-
const
|
|
80
|
-
e.style.width = `${
|
|
112
|
+
const w = c ? Math.max(L, a) : R(L, a, b);
|
|
113
|
+
if (c || g) {
|
|
114
|
+
const O = Math.max(l, f);
|
|
115
|
+
e.style.width = `${w}px`, e.style.maxWidth = "none", e.style.height = `${O}px`, e.style.maxHeight = "none", s.style.maxHeight = "none", s.style.overflowY = "visible", s.style.overflowX = "visible", n.classList.add("sod-modal-viewport-scroll");
|
|
81
116
|
} else
|
|
82
|
-
e.style.width = `${
|
|
117
|
+
e.style.width = `${w}px`, e.style.maxWidth = `${b}px`, e.style.height = "auto", e.style.maxHeight = "none", s.style.maxHeight = "none", s.style.overflowY = "visible", s.style.overflowX = "visible", n.classList.remove("sod-modal-viewport-scroll");
|
|
83
118
|
}
|
|
84
119
|
}, m = () => {
|
|
85
|
-
|
|
86
|
-
},
|
|
120
|
+
E === 0 && (E = window.requestAnimationFrame(x));
|
|
121
|
+
}, u = new ResizeObserver(() => {
|
|
87
122
|
m();
|
|
88
|
-
}),
|
|
123
|
+
}), y = new MutationObserver(() => {
|
|
89
124
|
m();
|
|
90
|
-
}),
|
|
125
|
+
}), p = () => {
|
|
91
126
|
m();
|
|
92
|
-
},
|
|
127
|
+
}, S = () => {
|
|
93
128
|
m();
|
|
94
129
|
};
|
|
95
|
-
|
|
130
|
+
n.addEventListener("sod:refit", S), u.observe(s), u.observe(t), u.observe(i), h && (y.observe(s, {
|
|
96
131
|
subtree: !0,
|
|
97
132
|
childList: !0,
|
|
98
133
|
characterData: !0,
|
|
99
134
|
attributes: !0
|
|
100
|
-
}), s.addEventListener("load",
|
|
101
|
-
const
|
|
135
|
+
}), s.addEventListener("load", p, !0), s.addEventListener("error", p, !0));
|
|
136
|
+
const A = () => {
|
|
102
137
|
m();
|
|
103
138
|
};
|
|
104
|
-
return window.addEventListener("resize",
|
|
105
|
-
|
|
139
|
+
return window.addEventListener("resize", A), m(), () => {
|
|
140
|
+
E !== 0 && (window.cancelAnimationFrame(E), E = 0), u.disconnect(), y.disconnect(), window.removeEventListener("resize", A), n.removeEventListener("sod:refit", S), s.removeEventListener("load", p, !0), s.removeEventListener("error", p, !0), n.classList.remove("sod-modal-viewport-scroll"), s.style.maxHeight = "", s.style.overflowY = "", s.style.overflowX = "";
|
|
106
141
|
};
|
|
107
142
|
}
|
|
108
|
-
class
|
|
143
|
+
class P {
|
|
109
144
|
static modalRegistry = /* @__PURE__ */ new Map();
|
|
145
|
+
static handleRegistry = /* @__PURE__ */ new WeakMap();
|
|
110
146
|
static modalIdSeed = 0;
|
|
111
147
|
static createAutoModalId() {
|
|
112
148
|
return this.modalIdSeed += 1, `sod-modal-${this.modalIdSeed}`;
|
|
113
149
|
}
|
|
114
|
-
static revealExisting(e,
|
|
150
|
+
static revealExisting(e, t) {
|
|
115
151
|
if (!e.isConnected)
|
|
116
|
-
return
|
|
152
|
+
return {
|
|
153
|
+
dialog: e,
|
|
154
|
+
close: () => B(e),
|
|
155
|
+
refit: () => e.dispatchEvent(new Event("sod:refit")),
|
|
156
|
+
setFooterButtons: () => {
|
|
157
|
+
},
|
|
158
|
+
updateFooterButton: () => !1,
|
|
159
|
+
onAction: () => () => {
|
|
160
|
+
},
|
|
161
|
+
id: e.dataset.sodId
|
|
162
|
+
};
|
|
117
163
|
const s = e.querySelector(".sod-panel");
|
|
118
|
-
s?.classList.remove("is-closing"), document.body.append(e), e.open || (
|
|
164
|
+
s?.classList.remove("is-closing"), document.body.append(e), e.open || (t ? e.showModal() : e.show()), e.dispatchEvent(new Event("sod:refit")), s?.focus();
|
|
165
|
+
const i = this.handleRegistry.get(e);
|
|
166
|
+
return i ? i() : {
|
|
167
|
+
dialog: e,
|
|
168
|
+
close: () => B(e),
|
|
169
|
+
refit: () => e.dispatchEvent(new Event("sod:refit")),
|
|
170
|
+
setFooterButtons: () => {
|
|
171
|
+
},
|
|
172
|
+
updateFooterButton: () => !1,
|
|
173
|
+
onAction: () => () => {
|
|
174
|
+
},
|
|
175
|
+
id: e.dataset.sodId
|
|
176
|
+
};
|
|
119
177
|
}
|
|
120
178
|
static open(e) {
|
|
121
|
-
const
|
|
122
|
-
let
|
|
123
|
-
if (
|
|
179
|
+
const t = e.kind ?? "modal", s = "useModal" in e ? e.useModal ?? !0 : !0, i = t === "modal" ? e : void 0, o = t === "modal" && ("autoFitSize" in e ? e.autoFitSize !== !1 : !0);
|
|
180
|
+
let r, d = !1, h = e.confirmAction ?? "hide";
|
|
181
|
+
if (t === "modal") {
|
|
124
182
|
const l = "id" in e && e.id?.trim() ? e.id.trim() : void 0;
|
|
125
|
-
if (
|
|
126
|
-
const
|
|
127
|
-
if (
|
|
128
|
-
this.revealExisting(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
close:
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
};
|
|
135
|
-
return "onReused" in e && e.onReused?.(f), f;
|
|
183
|
+
if (d = !!l, r = l ?? this.createAutoModalId(), e.confirmAction === void 0 && d && (h = "destroy"), l) {
|
|
184
|
+
const c = this.modalRegistry.get(r);
|
|
185
|
+
if (c && c.isConnected) {
|
|
186
|
+
const g = this.revealExisting(c, s);
|
|
187
|
+
if (e.onAction) {
|
|
188
|
+
const w = g.onAction(e.onAction);
|
|
189
|
+
c.addEventListener("close", w, { once: !0 });
|
|
190
|
+
}
|
|
191
|
+
return "onReused" in e && e.onReused?.(g), g;
|
|
136
192
|
}
|
|
137
193
|
}
|
|
138
|
-
this.modalRegistry.delete(
|
|
139
|
-
}
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
const
|
|
145
|
-
if (
|
|
146
|
-
const l = "placement" in e ? e.placement ?? "end" : "end",
|
|
147
|
-
|
|
194
|
+
this.modalRegistry.delete(r);
|
|
195
|
+
}
|
|
196
|
+
const a = document.createElement("dialog");
|
|
197
|
+
a.className = `sod-dialog sod-${t}`;
|
|
198
|
+
const f = [];
|
|
199
|
+
r && (a.dataset.sodId = r, d && (a.dataset.sodPersistent = "true"));
|
|
200
|
+
const v = document.createElement("section");
|
|
201
|
+
if (v.className = "sod-panel", v.tabIndex = -1, t === "offcanvas") {
|
|
202
|
+
const l = "placement" in e ? e.placement ?? "end" : "end", c = "animation" in e ? e.animation ?? "slide" : "slide";
|
|
203
|
+
v.classList.add(`sod-placement-${l}`), v.classList.add(`sod-anim-${c}`);
|
|
148
204
|
} else {
|
|
149
|
-
const l = "position" in e ? e.position ?? "center" : "center",
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
const
|
|
157
|
-
|
|
205
|
+
const l = "position" in e ? e.position ?? "center" : "center", c = "animation" in e ? e.animation ?? "fade" : "fade";
|
|
206
|
+
v.classList.add(`sod-modal-pos-${l}`), v.classList.add(`sod-modal-anim-${c}`), o && v.classList.add("sod-modal-autofit");
|
|
207
|
+
}
|
|
208
|
+
const E = document.createElement("header");
|
|
209
|
+
E.className = "sod-header";
|
|
210
|
+
const R = document.createElement("h2");
|
|
211
|
+
R.className = "sod-title", R.textContent = e.title;
|
|
212
|
+
const x = document.createElement("button");
|
|
213
|
+
x.type = "button", x.className = "sod-close", x.setAttribute("aria-label", "Close"), x.textContent = "×", x.addEventListener("click", () => B(a)), E.append(R, x);
|
|
158
214
|
const m = document.createElement("div");
|
|
159
|
-
m.className = "sod-body",
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
215
|
+
m.className = "sod-body", W(m, e.content);
|
|
216
|
+
const u = document.createElement("footer");
|
|
217
|
+
u.className = "sod-footer", u.dataset.align = e.footerAlign ?? "end";
|
|
218
|
+
const y = /* @__PURE__ */ new Set();
|
|
219
|
+
e.onAction && y.add(e.onAction);
|
|
220
|
+
const p = (l) => (y.add(l), () => {
|
|
221
|
+
y.delete(l);
|
|
165
222
|
});
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
223
|
+
let S = e.footerButtons ? [...e.footerButtons] : [
|
|
224
|
+
{
|
|
225
|
+
id: "cancel",
|
|
226
|
+
label: e.cancelText ?? "取消",
|
|
227
|
+
role: "cancel",
|
|
228
|
+
variant: "outline"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
id: "confirm",
|
|
232
|
+
label: e.confirmText ?? "确认",
|
|
233
|
+
role: "confirm",
|
|
234
|
+
variant: "primary"
|
|
235
|
+
}
|
|
236
|
+
];
|
|
237
|
+
const A = () => ({
|
|
238
|
+
dialog: a,
|
|
239
|
+
close: () => B(a),
|
|
240
|
+
refit: () => a.dispatchEvent(new Event("sod:refit")),
|
|
241
|
+
setFooterButtons: (l) => {
|
|
242
|
+
S = [...l], M(), a.dispatchEvent(new Event("sod:refit"));
|
|
243
|
+
},
|
|
244
|
+
updateFooterButton: (l, c) => {
|
|
245
|
+
const g = S.findIndex((w) => w.id === l);
|
|
246
|
+
return g < 0 ? !1 : (S[g] = { ...S[g], ...c }, M(), a.dispatchEvent(new Event("sod:refit")), !0);
|
|
247
|
+
},
|
|
248
|
+
onAction: (l) => p(l),
|
|
249
|
+
id: r
|
|
250
|
+
}), b = (l, c) => {
|
|
251
|
+
if (typeof c == "string") {
|
|
252
|
+
l.textContent = c;
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
l.append(c);
|
|
256
|
+
}, M = () => {
|
|
257
|
+
if (u.replaceChildren(), e.hideFooter || S.length === 0) {
|
|
258
|
+
u.hidden = !0;
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
u.hidden = !1;
|
|
262
|
+
for (const l of S) {
|
|
263
|
+
const c = document.createElement("button");
|
|
264
|
+
c.type = "button", c.className = `sod-btn ${N(l.variant)}`, l.className?.trim() && (c.className = `${c.className} ${l.className.trim()}`), l.id?.trim() && (c.dataset.action = l.id.trim()), l.disabled && (c.disabled = !0), l.attrs && Object.entries(l.attrs).forEach(([g, w]) => {
|
|
265
|
+
c.setAttribute(g, w);
|
|
266
|
+
}), b(c, l.label), c.addEventListener("click", (g) => {
|
|
267
|
+
(async () => {
|
|
268
|
+
const w = A(), H = {
|
|
269
|
+
action: l.id ?? l.role ?? "custom",
|
|
270
|
+
button: l,
|
|
271
|
+
buttonElement: c,
|
|
272
|
+
dialog: a,
|
|
273
|
+
event: g,
|
|
274
|
+
handle: w
|
|
275
|
+
};
|
|
276
|
+
if (await l.onClick?.(H) === !1)
|
|
277
|
+
return;
|
|
278
|
+
l.role === "cancel" && e.onCancel?.(), l.role === "confirm" && e.onConfirm?.(), y.forEach((C) => {
|
|
279
|
+
C(H);
|
|
280
|
+
});
|
|
281
|
+
const I = $(l, h);
|
|
282
|
+
I === "hide" && B(a, "hide"), I === "destroy" && B(a, "destroy");
|
|
283
|
+
})();
|
|
284
|
+
}), u.append(c);
|
|
285
|
+
}
|
|
182
286
|
};
|
|
183
|
-
|
|
287
|
+
M(), v.append(E, m, u), o && f.push(D(a, v, E, m, u, i)), t === "modal" && "draggable" in e && e.draggable && k(v, e.dragHandle), a.append(v), (e.closeOnBackdrop ?? !0) && a.addEventListener("click", (l) => {
|
|
288
|
+
l.target === a && B(a);
|
|
289
|
+
}), (e.closeOnEsc ?? !0) || a.addEventListener("cancel", (l) => {
|
|
290
|
+
l.preventDefault();
|
|
291
|
+
}), a.addEventListener("close", () => {
|
|
292
|
+
const l = a.dataset.sodPersistent === "true", c = a.dataset.sodDestroy === "true";
|
|
293
|
+
(!l || c) && (f.forEach((g) => g()), y.clear(), a.remove(), r && this.modalRegistry.delete(r), this.handleRegistry.delete(a), delete a.dataset.sodDestroy);
|
|
294
|
+
}), document.body.append(a), s ? a.showModal() : a.show(), a.dispatchEvent(new Event("sod:refit")), r && this.modalRegistry.set(r, a), this.handleRegistry.set(a, A);
|
|
295
|
+
const L = A();
|
|
296
|
+
return t === "modal" && "onCreated" in e && e.onCreated?.(L), L;
|
|
184
297
|
}
|
|
185
298
|
static openModal(e) {
|
|
186
299
|
return this.open({ ...e, kind: "modal" });
|
|
@@ -189,14 +302,334 @@ class O {
|
|
|
189
302
|
return this.open({ ...e, kind: "offcanvas" });
|
|
190
303
|
}
|
|
191
304
|
}
|
|
192
|
-
|
|
193
|
-
|
|
305
|
+
class V {
|
|
306
|
+
static placementState = /* @__PURE__ */ new Map();
|
|
307
|
+
static recordById = /* @__PURE__ */ new Map();
|
|
308
|
+
static idSeed = 0;
|
|
309
|
+
static defaults = {
|
|
310
|
+
placement: "top-end",
|
|
311
|
+
variant: "default",
|
|
312
|
+
duration: 3e3,
|
|
313
|
+
showProgress: !0,
|
|
314
|
+
closable: !0,
|
|
315
|
+
pauseOnHover: !0,
|
|
316
|
+
pauseOnWindowBlur: !1,
|
|
317
|
+
duplicateStrategy: "update",
|
|
318
|
+
newestOnTop: !0,
|
|
319
|
+
maxVisible: 3
|
|
320
|
+
};
|
|
321
|
+
static normalizeOptions(e) {
|
|
322
|
+
const t = e.duration === !1 ? !1 : Math.max(0, e.duration ?? this.defaults.duration);
|
|
323
|
+
return {
|
|
324
|
+
placement: e.placement ?? this.defaults.placement,
|
|
325
|
+
variant: e.variant ?? this.defaults.variant,
|
|
326
|
+
duration: t,
|
|
327
|
+
showProgress: e.showProgress ?? this.defaults.showProgress,
|
|
328
|
+
closable: e.closable ?? this.defaults.closable,
|
|
329
|
+
pauseOnHover: e.pauseOnHover ?? this.defaults.pauseOnHover,
|
|
330
|
+
pauseOnWindowBlur: e.pauseOnWindowBlur ?? this.defaults.pauseOnWindowBlur,
|
|
331
|
+
duplicateStrategy: e.duplicateStrategy ?? this.defaults.duplicateStrategy,
|
|
332
|
+
newestOnTop: e.newestOnTop ?? this.defaults.newestOnTop,
|
|
333
|
+
maxVisible: Math.max(1, e.maxVisible ?? this.defaults.maxVisible),
|
|
334
|
+
title: e.title,
|
|
335
|
+
content: e.content,
|
|
336
|
+
className: e.className,
|
|
337
|
+
attrs: e.attrs,
|
|
338
|
+
onShown: e.onShown,
|
|
339
|
+
onClose: e.onClose
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
static createAutoToastId() {
|
|
343
|
+
return this.idSeed += 1, `sot-toast-${this.idSeed}`;
|
|
344
|
+
}
|
|
345
|
+
static createStackedToastId(e) {
|
|
346
|
+
let t = 1, s = `${e}-${t}`;
|
|
347
|
+
for (; this.recordById.has(s); )
|
|
348
|
+
t += 1, s = `${e}-${t}`;
|
|
349
|
+
return s;
|
|
350
|
+
}
|
|
351
|
+
static resolveRole(e) {
|
|
352
|
+
return e === "danger" ? "alert" : "status";
|
|
353
|
+
}
|
|
354
|
+
static getPlacementState(e) {
|
|
355
|
+
const t = this.placementState.get(e);
|
|
356
|
+
if (t)
|
|
357
|
+
return t;
|
|
358
|
+
const s = document.createElement("div");
|
|
359
|
+
s.className = `sod-toast-layer sod-toast-layer-${e}`, s.setAttribute("aria-live", "polite"), s.setAttribute("aria-atomic", "false"), document.body.append(s);
|
|
360
|
+
const i = {
|
|
361
|
+
container: s,
|
|
362
|
+
active: [],
|
|
363
|
+
pending: []
|
|
364
|
+
};
|
|
365
|
+
return this.placementState.set(e, i), i;
|
|
366
|
+
}
|
|
367
|
+
static createToastElement(e) {
|
|
368
|
+
const { options: t } = e, s = document.createElement("article");
|
|
369
|
+
s.className = `sod-toast sod-toast-${t.variant}`, t.className?.trim() && (s.className = `${s.className} ${t.className.trim()}`), s.dataset.toastId = e.id, s.setAttribute("role", this.resolveRole(t.variant)), t.attrs && Object.entries(t.attrs).forEach(([a, f]) => {
|
|
370
|
+
s.setAttribute(a, f);
|
|
371
|
+
});
|
|
372
|
+
const i = document.createElement("header");
|
|
373
|
+
i.className = "sod-toast-header";
|
|
374
|
+
let o = null;
|
|
375
|
+
t.title?.trim() && (o = document.createElement("strong"), o.className = "sod-toast-title", o.textContent = t.title, i.append(o));
|
|
376
|
+
let r = null;
|
|
377
|
+
t.closable && (r = document.createElement("button"), r.type = "button", r.className = "sod-toast-close", r.setAttribute("aria-label", "Close"), r.textContent = "×", r.addEventListener("click", () => {
|
|
378
|
+
this.closeRecord(e, "close-button");
|
|
379
|
+
}), i.append(r)), i.childElementCount > 0 && s.append(i);
|
|
380
|
+
const d = document.createElement("div");
|
|
381
|
+
d.className = "sod-toast-body", W(d, t.content), s.append(d);
|
|
382
|
+
let h = null;
|
|
383
|
+
if (t.showProgress && (h = document.createElement("div"), h.className = "sod-toast-progress", s.append(h)), t.pauseOnHover) {
|
|
384
|
+
const a = () => this.pauseRecord(e), f = () => this.resumeRecord(e);
|
|
385
|
+
s.addEventListener("mouseenter", a), s.addEventListener("mouseleave", f), e.cleanupListeners.push(() => {
|
|
386
|
+
s.removeEventListener("mouseenter", a), s.removeEventListener("mouseleave", f);
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
if (t.pauseOnWindowBlur) {
|
|
390
|
+
const a = () => {
|
|
391
|
+
e.paused || e.status !== "active" || (e.pausedByWindowBlur = !0, this.pauseRecord(e));
|
|
392
|
+
}, f = () => {
|
|
393
|
+
e.pausedByWindowBlur && (e.pausedByWindowBlur = !1, this.resumeRecord(e));
|
|
394
|
+
};
|
|
395
|
+
window.addEventListener("blur", a), window.addEventListener("focus", f), e.cleanupListeners.push(() => {
|
|
396
|
+
window.removeEventListener("blur", a), window.removeEventListener("focus", f);
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
e.element = s, e.bodyElement = d, e.titleElement = o, e.closeButton = r, e.progressElement = h;
|
|
400
|
+
}
|
|
401
|
+
static resetProgressAnimation(e, t) {
|
|
402
|
+
!e.progressElement || !e.options.showProgress || (e.progressElement.style.display = "block", e.progressElement.style.animation = "none", e.progressElement.style.animationPlayState = "running", e.progressElement.offsetWidth, e.progressElement.style.animation = `sod-toast-progress-countdown ${Math.max(1, t)}ms linear forwards`);
|
|
403
|
+
}
|
|
404
|
+
static hideProgress(e) {
|
|
405
|
+
e.progressElement && (e.progressElement.style.display = "none", e.progressElement.style.animation = "none");
|
|
406
|
+
}
|
|
407
|
+
static isRecordActive(e, t) {
|
|
408
|
+
return e.active.includes(t);
|
|
409
|
+
}
|
|
410
|
+
static isRecordPending(e, t) {
|
|
411
|
+
return e.pending.includes(t);
|
|
412
|
+
}
|
|
413
|
+
static mountRecord(e, t) {
|
|
414
|
+
t.status = "active", t.options.newestOnTop ? e.container.prepend(t.element) : e.container.append(t.element), e.active.push(t), this.startRecordTimer(t), t.options.onShown?.(t.handle);
|
|
415
|
+
}
|
|
416
|
+
static queueRecord(e, t) {
|
|
417
|
+
t.status = "pending", e.pending.push(t);
|
|
418
|
+
}
|
|
419
|
+
static startRecordTimer(e) {
|
|
420
|
+
if (this.clearRecordTimer(e), e.options.duration === !1) {
|
|
421
|
+
e.remainingMs = !1, e.startedAt = null, this.hideProgress(e);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
const t = Math.max(0, e.remainingMs === !1 ? e.options.duration : e.remainingMs);
|
|
425
|
+
if (t === 0) {
|
|
426
|
+
this.closeRecord(e, "timeout");
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
e.startedAt = Date.now(), e.remainingMs = t, this.resetProgressAnimation(e, t), e.timerId = window.setTimeout(() => {
|
|
430
|
+
e.timerId = null, this.closeRecord(e, "timeout");
|
|
431
|
+
}, t);
|
|
432
|
+
}
|
|
433
|
+
static clearRecordTimer(e) {
|
|
434
|
+
e.timerId !== null && (window.clearTimeout(e.timerId), e.timerId = null);
|
|
435
|
+
}
|
|
436
|
+
static pauseRecord(e) {
|
|
437
|
+
if (e.paused || e.status !== "active" || e.options.duration === !1)
|
|
438
|
+
return;
|
|
439
|
+
const t = e.startedAt ?? Date.now(), s = Math.max(0, Date.now() - t), i = e.remainingMs === !1 ? e.options.duration : e.remainingMs;
|
|
440
|
+
e.remainingMs = Math.max(0, i - s), e.startedAt = null, e.paused = !0, e.progressElement && (e.progressElement.style.animationPlayState = "paused"), this.clearRecordTimer(e);
|
|
441
|
+
}
|
|
442
|
+
static resumeRecord(e) {
|
|
443
|
+
!e.paused || e.status !== "active" || (e.paused = !1, e.progressElement && (e.progressElement.style.animationPlayState = "running"), this.startRecordTimer(e));
|
|
444
|
+
}
|
|
445
|
+
static rebuildRecordElement(e) {
|
|
446
|
+
const t = e.element, s = t.parentElement;
|
|
447
|
+
e.cleanupListeners.forEach((i) => i()), e.cleanupListeners = [], t.remove(), this.createToastElement(e), s && e.status === "active" && (e.options.newestOnTop ? s.prepend(e.element) : s.append(e.element), this.startRecordTimer(e));
|
|
448
|
+
}
|
|
449
|
+
static moveRecordToPlacement(e, t) {
|
|
450
|
+
const s = e.options.placement;
|
|
451
|
+
if (s === t)
|
|
452
|
+
return;
|
|
453
|
+
const i = this.placementState.get(s), o = this.getPlacementState(t), r = !!(i && this.removeFromArray(i.active, e)), d = !!(i && this.removeFromArray(i.pending, e));
|
|
454
|
+
if (e.options.placement = t, this.clearRecordTimer(e), d && !r) {
|
|
455
|
+
this.queueRecord(o, e), this.drainQueue(o, t), i && this.drainQueue(i, s);
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
o.active.length < e.options.maxVisible ? this.mountRecord(o, e) : this.queueRecord(o, e), i && this.drainQueue(i, s);
|
|
459
|
+
}
|
|
460
|
+
static updateRecord(e, t) {
|
|
461
|
+
if (t.title !== void 0) {
|
|
462
|
+
const i = t.title.trim();
|
|
463
|
+
if (e.options.title = i.length > 0 ? i : void 0, e.options.title)
|
|
464
|
+
if (e.titleElement)
|
|
465
|
+
e.titleElement.textContent = e.options.title;
|
|
466
|
+
else {
|
|
467
|
+
const o = e.element.querySelector(".sod-toast-header");
|
|
468
|
+
if (o) {
|
|
469
|
+
const r = document.createElement("strong");
|
|
470
|
+
r.className = "sod-toast-title", r.textContent = e.options.title, o.prepend(r), e.titleElement = r;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
else e.titleElement && (e.titleElement.remove(), e.titleElement = null);
|
|
474
|
+
}
|
|
475
|
+
t.content !== void 0 && (e.options.content = t.content, e.bodyElement.replaceChildren(), W(e.bodyElement, t.content)), t.variant !== void 0 && (e.options.variant = t.variant, e.element.classList.remove("sod-toast-default", "sod-toast-info", "sod-toast-success", "sod-toast-warning", "sod-toast-danger"), e.element.classList.add(`sod-toast-${t.variant}`), e.element.setAttribute("role", this.resolveRole(t.variant))), t.duration !== void 0 && (e.options.duration = t.duration === !1 ? !1 : Math.max(0, t.duration), e.remainingMs = e.options.duration === !1 ? !1 : e.options.duration, e.paused = !1, e.status === "active" && this.startRecordTimer(e)), t.maxVisible !== void 0 && (e.options.maxVisible = Math.max(1, t.maxVisible)), t.newestOnTop !== void 0 && (e.options.newestOnTop = t.newestOnTop);
|
|
476
|
+
let s = !1;
|
|
477
|
+
t.closable !== void 0 && t.closable !== e.options.closable && (e.options.closable = t.closable, s = !0), t.pauseOnHover !== void 0 && t.pauseOnHover !== e.options.pauseOnHover && (e.options.pauseOnHover = t.pauseOnHover, s = !0), t.pauseOnWindowBlur !== void 0 && t.pauseOnWindowBlur !== e.options.pauseOnWindowBlur && (e.options.pauseOnWindowBlur = t.pauseOnWindowBlur, s = !0), t.duplicateStrategy !== void 0 && (e.options.duplicateStrategy = t.duplicateStrategy), t.showProgress !== void 0 && t.showProgress !== e.options.showProgress && (e.options.showProgress = t.showProgress, s = !0), t.className !== void 0 && (e.options.className = t.className, s = !0), t.attrs !== void 0 && (e.options.attrs = t.attrs, s = !0), s && this.rebuildRecordElement(e), t.placement && t.placement !== e.options.placement && this.moveRecordToPlacement(e, t.placement);
|
|
478
|
+
}
|
|
479
|
+
static removeStateContainerIfEmpty(e) {
|
|
480
|
+
const t = this.placementState.get(e);
|
|
481
|
+
t && (t.active.length > 0 || t.pending.length > 0 || (t.container.remove(), this.placementState.delete(e)));
|
|
482
|
+
}
|
|
483
|
+
static drainQueue(e, t) {
|
|
484
|
+
let s = !0;
|
|
485
|
+
for (; s && e.pending.length > 0; ) {
|
|
486
|
+
const i = e.pending[0];
|
|
487
|
+
if (e.active.length >= i.options.maxVisible) {
|
|
488
|
+
s = !1;
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
e.pending.shift(), this.mountRecord(e, i);
|
|
492
|
+
}
|
|
493
|
+
this.removeStateContainerIfEmpty(t);
|
|
494
|
+
}
|
|
495
|
+
static removeFromArray(e, t) {
|
|
496
|
+
const s = e.indexOf(t);
|
|
497
|
+
return s < 0 ? !1 : (e.splice(s, 1), !0);
|
|
498
|
+
}
|
|
499
|
+
static finalizeClose(e, t) {
|
|
500
|
+
if (e.status === "closed")
|
|
501
|
+
return;
|
|
502
|
+
const s = e.options.placement, i = this.placementState.get(s);
|
|
503
|
+
this.clearRecordTimer(e), e.cleanupListeners.forEach((o) => o()), e.cleanupListeners = [], e.element.remove(), e.status = "closed", i && (this.removeFromArray(i.active, e), this.removeFromArray(i.pending, e)), this.recordById.delete(e.id), e.options.onClose?.(t, e.handle), i ? this.drainQueue(i, s) : this.removeStateContainerIfEmpty(s);
|
|
504
|
+
}
|
|
505
|
+
static closeRecord(e, t) {
|
|
506
|
+
if (e.status === "closed" || e.status === "closing")
|
|
507
|
+
return;
|
|
508
|
+
const s = e.options.placement, i = this.placementState.get(s);
|
|
509
|
+
if (!!(i && this.isRecordPending(i, e) && !this.isRecordActive(i, e))) {
|
|
510
|
+
this.finalizeClose(e, t);
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
e.status = "closing", this.clearRecordTimer(e), e.element.classList.add("is-closing");
|
|
514
|
+
let r = !1;
|
|
515
|
+
const d = () => {
|
|
516
|
+
r || (r = !0, this.finalizeClose(e, t));
|
|
517
|
+
}, h = (a) => {
|
|
518
|
+
a.target === e.element && (e.element.removeEventListener("animationend", h), d());
|
|
519
|
+
};
|
|
520
|
+
e.element.addEventListener("animationend", h), window.setTimeout(() => {
|
|
521
|
+
e.element.removeEventListener("animationend", h), d();
|
|
522
|
+
}, 220);
|
|
523
|
+
}
|
|
524
|
+
static createHandle(e) {
|
|
525
|
+
return {
|
|
526
|
+
id: e.id,
|
|
527
|
+
get element() {
|
|
528
|
+
return e.element;
|
|
529
|
+
},
|
|
530
|
+
close: (t = "programmatic") => {
|
|
531
|
+
this.closeRecord(e, t);
|
|
532
|
+
},
|
|
533
|
+
update: (t) => {
|
|
534
|
+
this.updateRecord(e, t);
|
|
535
|
+
},
|
|
536
|
+
pause: () => {
|
|
537
|
+
this.pauseRecord(e);
|
|
538
|
+
},
|
|
539
|
+
resume: () => {
|
|
540
|
+
this.resumeRecord(e);
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
static show(e) {
|
|
545
|
+
const s = e.id?.trim() || this.createAutoToastId(), i = this.normalizeOptions(e), o = this.recordById.get(s);
|
|
546
|
+
if (o) {
|
|
547
|
+
const a = i.duplicateStrategy;
|
|
548
|
+
if (a === "ignore")
|
|
549
|
+
return o.handle;
|
|
550
|
+
if (a === "stack") {
|
|
551
|
+
const f = this.createStackedToastId(s);
|
|
552
|
+
return this.show({ ...e, id: f, duplicateStrategy: "update" });
|
|
553
|
+
}
|
|
554
|
+
return this.updateRecord(o, {
|
|
555
|
+
title: e.title,
|
|
556
|
+
content: e.content,
|
|
557
|
+
variant: e.variant,
|
|
558
|
+
duration: a === "restart-timer" ? e.duration === void 0 ? o.options.duration : i.duration : e.duration === void 0 ? void 0 : i.duration,
|
|
559
|
+
placement: e.placement,
|
|
560
|
+
closable: e.closable,
|
|
561
|
+
pauseOnHover: e.pauseOnHover,
|
|
562
|
+
pauseOnWindowBlur: e.pauseOnWindowBlur,
|
|
563
|
+
duplicateStrategy: e.duplicateStrategy,
|
|
564
|
+
newestOnTop: e.newestOnTop,
|
|
565
|
+
maxVisible: e.maxVisible,
|
|
566
|
+
showProgress: e.showProgress,
|
|
567
|
+
className: e.className,
|
|
568
|
+
attrs: e.attrs
|
|
569
|
+
}), o.options.onClose = i.onClose, o.options.onShown = i.onShown, o.handle;
|
|
570
|
+
}
|
|
571
|
+
const d = {
|
|
572
|
+
id: s,
|
|
573
|
+
options: i,
|
|
574
|
+
element: document.createElement("article"),
|
|
575
|
+
status: "pending",
|
|
576
|
+
timerId: null,
|
|
577
|
+
remainingMs: i.duration,
|
|
578
|
+
startedAt: null,
|
|
579
|
+
paused: !1,
|
|
580
|
+
pausedByWindowBlur: !1,
|
|
581
|
+
closeButton: null,
|
|
582
|
+
progressElement: null,
|
|
583
|
+
bodyElement: document.createElement("div"),
|
|
584
|
+
titleElement: null,
|
|
585
|
+
cleanupListeners: [],
|
|
586
|
+
handle: void 0
|
|
587
|
+
};
|
|
588
|
+
d.handle = this.createHandle(d), this.createToastElement(d), this.recordById.set(s, d);
|
|
589
|
+
const h = this.getPlacementState(i.placement);
|
|
590
|
+
return h.active.length < i.maxVisible ? this.mountRecord(h, d) : this.queueRecord(h, d), d.handle;
|
|
591
|
+
}
|
|
592
|
+
static clear(e) {
|
|
593
|
+
(e ? [e] : Array.from(this.placementState.keys())).forEach((s) => {
|
|
594
|
+
const i = this.placementState.get(s);
|
|
595
|
+
if (!i)
|
|
596
|
+
return;
|
|
597
|
+
const o = [...i.active];
|
|
598
|
+
[...i.pending].forEach((d) => this.closeRecord(d, "container-clear")), o.forEach((d) => this.closeRecord(d, "container-clear"));
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
static configure(e) {
|
|
602
|
+
e.placement && (this.defaults.placement = e.placement), e.variant && (this.defaults.variant = e.variant), e.duration !== void 0 && (this.defaults.duration = e.duration === !1 ? 3e3 : Math.max(0, e.duration)), e.showProgress !== void 0 && (this.defaults.showProgress = e.showProgress), e.closable !== void 0 && (this.defaults.closable = e.closable), e.pauseOnHover !== void 0 && (this.defaults.pauseOnHover = e.pauseOnHover), e.pauseOnWindowBlur !== void 0 && (this.defaults.pauseOnWindowBlur = e.pauseOnWindowBlur), e.duplicateStrategy !== void 0 && (this.defaults.duplicateStrategy = e.duplicateStrategy), e.newestOnTop !== void 0 && (this.defaults.newestOnTop = e.newestOnTop), e.maxVisible !== void 0 && (this.defaults.maxVisible = Math.max(1, e.maxVisible));
|
|
603
|
+
}
|
|
604
|
+
static success(e, t = {}) {
|
|
605
|
+
return this.show({ ...t, content: e, variant: "success" });
|
|
606
|
+
}
|
|
607
|
+
static error(e, t = {}) {
|
|
608
|
+
return this.show({ ...t, content: e, variant: "danger" });
|
|
609
|
+
}
|
|
610
|
+
static info(e, t = {}) {
|
|
611
|
+
return this.show({ ...t, content: e, variant: "info" });
|
|
612
|
+
}
|
|
613
|
+
static warning(e, t = {}) {
|
|
614
|
+
return this.show({ ...t, content: e, variant: "warning" });
|
|
615
|
+
}
|
|
616
|
+
static closeAll() {
|
|
617
|
+
this.clear();
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
function q(n) {
|
|
621
|
+
return P.openModal(n);
|
|
622
|
+
}
|
|
623
|
+
function z(n) {
|
|
624
|
+
return P.openOffcanvas(n);
|
|
194
625
|
}
|
|
195
|
-
function
|
|
196
|
-
return
|
|
626
|
+
function Y(n) {
|
|
627
|
+
return V.show(n);
|
|
197
628
|
}
|
|
198
629
|
export {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
630
|
+
P as SoDialog,
|
|
631
|
+
V as SoToast,
|
|
632
|
+
q as openModal,
|
|
633
|
+
z as openOffcanvas,
|
|
634
|
+
Y as toast
|
|
202
635
|
};
|
package/dist/sodialog.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(H,W){typeof exports=="object"&&typeof module<"u"?W(exports):typeof define=="function"&&define.amd?define(["exports"],W):(H=typeof globalThis<"u"?globalThis:H||self,W(H.SoDialog={}))})(this,(function(H){"use strict";function W(t,e){if(typeof e=="string"){t.innerHTML=e;return}t.append(e)}function I(t,e="hide"){if(e==="destroy"){t.dataset.sodDestroy="true",t.open&&t.close(),t.remove();return}t.open&&t.close()}function N(t,e){const i=e??"header";return i==="panel"?t:i==="header"?t.querySelector(".sod-header"):i==="title"?t.querySelector(".sod-title"):i==="body"?t.querySelector(".sod-body"):t.querySelector(i)??t.querySelector(".sod-header")}function T(t,e){const i=N(t,e);if(!i)return;t.classList.add("sod-modal-draggable"),i.classList.add("sod-drag-handle");let s=!1,L=0,v=0,d=null,g=0,p=0,o=0;const y=document.body.style.userSelect,c=(r,m)=>{const a=t.getBoundingClientRect(),M=Math.max(0,window.innerWidth-a.width),w=Math.max(0,window.innerHeight-a.height),$=Math.min(0,window.innerWidth-a.width),l=Math.min(0,window.innerHeight-a.height);return{left:Math.min(M,Math.max($,r)),top:Math.min(w,Math.max(l,m))}},h=r=>{if(!s)return;const m=c(r.clientX-L,r.clientY-v);p=m.left,o=m.top,g===0&&(g=window.requestAnimationFrame(()=>{g=0,t.style.inset="auto",t.style.left=`${p}px`,t.style.top=`${o}px`,t.style.right="auto",t.style.bottom="auto",t.style.margin="0",t.style.transform="none"}))},f=()=>{s=!1,i.classList.remove("is-dragging"),t.classList.remove("sod-is-dragging"),t.style.willChange="",document.body.style.userSelect=y,g!==0&&(window.cancelAnimationFrame(g),g=0),d!==null&&i.hasPointerCapture&&i.hasPointerCapture(d)&&i.releasePointerCapture(d),d=null,window.removeEventListener("pointermove",h),window.removeEventListener("pointerup",f),window.removeEventListener("pointercancel",f)};i.addEventListener("pointerdown",r=>{if(r.button!==0||r.target?.closest("button, input, select, textarea, a"))return;r.preventDefault(),t.classList.add("sod-is-dragging"),t.style.animation="none",t.style.transition="none",t.style.transform="none";const a=t.getBoundingClientRect();L=r.clientX-a.left,v=r.clientY-a.top,s=!0,d=r.pointerId,i.setPointerCapture(r.pointerId),t.style.position="fixed",t.style.left=`${a.left}px`,t.style.top=`${a.top}px`,t.style.width=`${Math.round(a.width)}px`,t.style.height=`${Math.round(a.height)}px`,t.style.inset="auto",t.style.right="auto",t.style.bottom="auto",t.style.margin="0",t.style.willChange="left, top",i.classList.add("is-dragging"),document.body.style.userSelect="none",window.addEventListener("pointermove",h),window.addEventListener("pointerup",f),window.addEventListener("pointercancel",f)})}function F(t,e,i,s,L,v){const g=Math.max(1,v?.hybridSwitchRatio??1.35),p=v?.refitOnContentChange??!0,o=Math.max(120,v?.autoFitMinWidth??280),y=Math.max(100,v?.autoFitMinHeight??160),c=v?.scrollMode?v.scrollMode:v?.autoFitUseScrollbar===!1?"viewport":"body";let h=0;const f=(n,u,E)=>Math.min(E,Math.max(u,n)),r=()=>{if(h=0,!t.isConnected||!t.open)return;const n=Math.max(o,window.innerWidth-32),u=Math.max(y,window.innerHeight-32);e.style.width="auto",e.style.height="auto",e.style.maxHeight="none",s.style.maxHeight="none",s.style.overflowY="visible",s.style.overflowX="visible";const E=Math.ceil(e.scrollWidth),b=Math.ceil(e.scrollHeight),D=E>n,R=b>u;if(c==="body"){const C=f(E,o,n),x=f(b,y,u);e.style.width=`${C}px`,e.style.maxWidth=`${n}px`,e.style.height=`${x}px`,e.style.maxHeight=`${u}px`;const S=i.offsetHeight,P=L.offsetHeight,A=Math.max(64,x-S-P);R?(s.style.maxHeight=`${A}px`,s.style.overflowY="auto"):(s.style.maxHeight="none",s.style.overflowY="hidden"),s.style.overflowX=D?"auto":"hidden",t.classList.remove("sod-modal-viewport-scroll")}else if(c==="hybrid")if(b>u*g){const x=Math.max(E,o),S=Math.max(b,y);e.style.width=`${x}px`,e.style.maxWidth="none",e.style.height=`${S}px`,e.style.maxHeight="none",s.style.maxHeight="none",s.style.overflowY="visible",s.style.overflowX="visible",t.classList.add("sod-modal-viewport-scroll")}else{const x=f(E,o,n),S=f(b,y,u);e.style.width=`${x}px`,e.style.maxWidth=`${n}px`,e.style.height=`${S}px`,e.style.maxHeight=`${u}px`;const P=i.offsetHeight,A=L.offsetHeight,X=Math.max(64,S-P-A);R?(s.style.maxHeight=`${X}px`,s.style.overflowY="auto"):(s.style.maxHeight="none",s.style.overflowY="hidden"),s.style.overflowX=D?"auto":"hidden",t.classList.remove("sod-modal-viewport-scroll")}else if(c==="viewport"){const C=Math.max(E,o),x=Math.max(b,y);e.style.width=`${C}px`,e.style.maxWidth="none",e.style.height=`${x}px`,e.style.maxHeight="none",s.style.maxHeight="none",s.style.overflowY="visible",s.style.overflowX="visible",x>u?t.classList.add("sod-modal-viewport-scroll"):t.classList.remove("sod-modal-viewport-scroll")}else{const C=D?Math.max(E,o):f(E,o,n);if(D||R){const x=Math.max(b,y);e.style.width=`${C}px`,e.style.maxWidth="none",e.style.height=`${x}px`,e.style.maxHeight="none",s.style.maxHeight="none",s.style.overflowY="visible",s.style.overflowX="visible",t.classList.add("sod-modal-viewport-scroll")}else e.style.width=`${C}px`,e.style.maxWidth=`${n}px`,e.style.height="auto",e.style.maxHeight="none",s.style.maxHeight="none",s.style.overflowY="visible",s.style.overflowX="visible",t.classList.remove("sod-modal-viewport-scroll")}},m=()=>{h===0&&(h=window.requestAnimationFrame(r))},a=new ResizeObserver(()=>{m()}),M=new MutationObserver(()=>{m()}),w=()=>{m()},$=()=>{m()};t.addEventListener("sod:refit",$),a.observe(s),a.observe(i),a.observe(L),p&&(M.observe(s,{subtree:!0,childList:!0,characterData:!0,attributes:!0}),s.addEventListener("load",w,!0),s.addEventListener("error",w,!0));const l=()=>{m()};return window.addEventListener("resize",l),m(),()=>{h!==0&&(window.cancelAnimationFrame(h),h=0),a.disconnect(),M.disconnect(),window.removeEventListener("resize",l),t.removeEventListener("sod:refit",$),s.removeEventListener("load",w,!0),s.removeEventListener("error",w,!0),t.classList.remove("sod-modal-viewport-scroll"),s.style.maxHeight="",s.style.overflowY="",s.style.overflowX=""}}class O{static modalRegistry=new Map;static modalIdSeed=0;static createAutoModalId(){return this.modalIdSeed+=1,`sod-modal-${this.modalIdSeed}`}static revealExisting(e,i){if(!e.isConnected)return;const s=e.querySelector(".sod-panel");s?.classList.remove("is-closing"),document.body.append(e),e.open||(i?e.showModal():e.show()),e.dispatchEvent(new Event("sod:refit")),s?.focus()}static open(e){const i=e.kind??"modal",s="useModal"in e?e.useModal??!0:!0,L=i==="modal"?e:void 0,v=i==="modal"&&("autoFitSize"in e?e.autoFitSize!==!1:!0);let d,g=!1,p=e.confirmAction??"hide";if(i==="modal"){const l="id"in e&&e.id?.trim()?e.id.trim():void 0;if(g=!!l,d=l??this.createAutoModalId(),e.confirmAction===void 0&&g&&(p="destroy"),l){const n=this.modalRegistry.get(d);if(n&&n.isConnected){this.revealExisting(n,s);const u={dialog:n,close:()=>I(n),refit:()=>n.dispatchEvent(new Event("sod:refit")),id:d};return"onReused"in e&&e.onReused?.(u),u}}this.modalRegistry.delete(d)}const o=document.createElement("dialog");o.className=`sod-dialog sod-${i}`;const y=[];d&&(o.dataset.sodId=d,g&&(o.dataset.sodPersistent="true"));const c=document.createElement("section");if(c.className="sod-panel",c.tabIndex=-1,i==="offcanvas"){const l="placement"in e?e.placement??"end":"end",n="animation"in e?e.animation??"slide":"slide";c.classList.add(`sod-placement-${l}`),c.classList.add(`sod-anim-${n}`)}else{const l="position"in e?e.position??"center":"center",n="animation"in e?e.animation??"fade":"fade";c.classList.add(`sod-modal-pos-${l}`),c.classList.add(`sod-modal-anim-${n}`),v&&c.classList.add("sod-modal-autofit")}const h=document.createElement("header");h.className="sod-header";const f=document.createElement("h2");f.className="sod-title",f.textContent=e.title;const r=document.createElement("button");r.type="button",r.className="sod-close",r.setAttribute("aria-label","Close"),r.textContent="×",r.addEventListener("click",()=>I(o)),h.append(f,r);const m=document.createElement("div");m.className="sod-body",W(m,e.content);const a=document.createElement("footer");a.className="sod-footer";const M=document.createElement("button");M.type="button",M.className="sod-btn sod-btn-outline",M.textContent=e.cancelText??"取消",M.addEventListener("click",()=>{e.onCancel?.(),I(o)});const w=document.createElement("button");w.type="button",w.className="sod-btn sod-btn-primary",w.textContent=e.confirmText??"确认",w.addEventListener("click",()=>{e.onConfirm?.(),I(o,p)}),a.append(M,w),c.append(h,m,a),v&&y.push(F(o,c,h,m,a,L)),i==="modal"&&"draggable"in e&&e.draggable&&T(c,e.dragHandle),o.append(c),(e.closeOnBackdrop??!0)&&o.addEventListener("click",l=>{l.target===o&&I(o)}),(e.closeOnEsc??!0)||o.addEventListener("cancel",l=>{l.preventDefault()}),o.addEventListener("close",()=>{const l=o.dataset.sodPersistent==="true",n=o.dataset.sodDestroy==="true";(!l||n)&&(y.forEach(u=>u()),o.remove(),d&&this.modalRegistry.delete(d),delete o.dataset.sodDestroy)}),document.body.append(o),s?o.showModal():o.show(),o.dispatchEvent(new Event("sod:refit")),d&&this.modalRegistry.set(d,o);const $={dialog:o,close:()=>I(o),refit:()=>o.dispatchEvent(new Event("sod:refit")),id:d};return i==="modal"&&"onCreated"in e&&e.onCreated?.($),$}static openModal(e){return this.open({...e,kind:"modal"})}static openOffcanvas(e){return this.open({...e,kind:"offcanvas"})}}function Y(t){return O.openModal(t)}function k(t){return O.openOffcanvas(t)}H.SoDialog=O,H.openModal=Y,H.openOffcanvas=k,Object.defineProperty(H,Symbol.toStringTag,{value:"Module"})}));
|
|
1
|
+
(function(H,B){typeof exports=="object"&&typeof module<"u"?B(exports):typeof define=="function"&&define.amd?define(["exports"],B):(H=typeof globalThis<"u"?globalThis:H||self,B(H.SoDialog={}))})(this,(function(H){"use strict";function B(n,e){if(typeof e=="string"){n.innerHTML=e;return}n.append(e)}function I(n,e="hide"){if(e==="destroy"){n.dataset.sodDestroy="true",n.open&&n.close(),n.remove();return}n.open&&n.close()}function F(n,e){return n.action?n.action:n.role==="confirm"?e:n.role==="cancel"?"hide":"none"}function k(n){return n==="danger"?"sod-btn-danger":n==="success"?"sod-btn-success":n==="ghost"?"sod-btn-ghost":n==="link"?"sod-btn-link":n==="outline"?"sod-btn-outline":"sod-btn-primary"}function D(n,e){const t=Array.isArray(e)?e.length>0?e:["header"]:[e??"header"],s=[],i=o=>{o&&(s.includes(o)||s.push(o))};for(const o of t){if(o==="panel"){i(n);continue}if(o==="header"){i(n.querySelector(".sod-header"));continue}if(o==="title"){i(n.querySelector(".sod-title"));continue}if(o==="body"){i(n.querySelector(".sod-body"));continue}n.querySelectorAll(o).forEach(r=>{i(r)})}return s.length===0&&i(n.querySelector(".sod-header")),s}function V(n,e){const t=D(n,e);if(t.length===0)return;n.classList.add("sod-modal-draggable"),t.forEach(m=>{m.classList.add("sod-drag-handle")});let s=!1,i=0,o=0,r=null,d=null,h=0,a=0,f=0;const v=document.body.style.userSelect,E=(m,u)=>{const y=n.getBoundingClientRect(),p=Math.max(0,window.innerWidth-y.width),O=Math.max(0,window.innerHeight-y.height),T=Math.min(0,window.innerWidth-y.width),b=Math.min(0,window.innerHeight-y.height);return{left:Math.min(p,Math.max(T,m)),top:Math.min(O,Math.max(b,u))}},R=m=>{if(!s)return;const u=E(m.clientX-i,m.clientY-o);a=u.left,f=u.top,h===0&&(h=window.requestAnimationFrame(()=>{h=0,n.style.inset="auto",n.style.left=`${a}px`,n.style.top=`${f}px`,n.style.right="auto",n.style.bottom="auto",n.style.margin="0",n.style.transform="none"}))},x=()=>{s=!1,t.forEach(m=>{m.classList.remove("is-dragging")}),n.classList.remove("sod-is-dragging"),n.style.willChange="",document.body.style.userSelect=v,h!==0&&(window.cancelAnimationFrame(h),h=0),r!==null&&d!==null&&d.hasPointerCapture&&d.hasPointerCapture(r)&&d.releasePointerCapture(r),r=null,d=null,window.removeEventListener("pointermove",R),window.removeEventListener("pointerup",x),window.removeEventListener("pointercancel",x)};t.forEach(m=>{m.addEventListener("pointerdown",u=>{if(u.button!==0||u.target?.closest("button, input, select, textarea, a"))return;u.preventDefault(),n.classList.add("sod-is-dragging"),n.style.animation="none",n.style.transition="none",n.style.transform="none";const p=n.getBoundingClientRect();i=u.clientX-p.left,o=u.clientY-p.top,s=!0,r=u.pointerId,d=m,m.setPointerCapture(u.pointerId),n.style.position="fixed",n.style.left=`${p.left}px`,n.style.top=`${p.top}px`,n.style.width=`${Math.round(p.width)}px`,n.style.height=`${Math.round(p.height)}px`,n.style.inset="auto",n.style.right="auto",n.style.bottom="auto",n.style.margin="0",n.style.willChange="left, top",m.classList.add("is-dragging"),document.body.style.userSelect="none",window.addEventListener("pointermove",R),window.addEventListener("pointerup",x),window.addEventListener("pointercancel",x)})})}function q(n,e,t,s,i,o){const d=Math.max(1,o?.hybridSwitchRatio??1.35),h=o?.refitOnContentChange??!0,a=Math.max(120,o?.autoFitMinWidth??280),f=Math.max(100,o?.autoFitMinHeight??160),v=o?.scrollMode?o.scrollMode:o?.autoFitUseScrollbar===!1?"viewport":"body";let E=0;const R=(b,M,L)=>Math.min(L,Math.max(M,b)),x=()=>{if(E=0,!n.isConnected||!n.open)return;const b=Math.max(a,window.innerWidth-32),M=Math.max(f,window.innerHeight-32);e.style.width="auto",e.style.height="auto",e.style.maxHeight="none",s.style.maxHeight="none",s.style.overflowY="visible",s.style.overflowX="visible";const L=Math.ceil(e.scrollWidth),l=Math.ceil(e.scrollHeight),c=L>b,g=l>M;if(v==="body"){const w=R(L,a,b),S=R(l,f,M);e.style.width=`${w}px`,e.style.maxWidth=`${b}px`,e.style.height=`${S}px`,e.style.maxHeight=`${M}px`;const A=t.offsetHeight,P=i.offsetHeight,C=Math.max(64,S-A-P);g?(s.style.maxHeight=`${C}px`,s.style.overflowY="auto"):(s.style.maxHeight="none",s.style.overflowY="hidden"),s.style.overflowX=c?"auto":"hidden",n.classList.remove("sod-modal-viewport-scroll")}else if(v==="hybrid")if(l>M*d){const S=Math.max(L,a),A=Math.max(l,f);e.style.width=`${S}px`,e.style.maxWidth="none",e.style.height=`${A}px`,e.style.maxHeight="none",s.style.maxHeight="none",s.style.overflowY="visible",s.style.overflowX="visible",n.classList.add("sod-modal-viewport-scroll")}else{const S=R(L,a,b),A=R(l,f,M);e.style.width=`${S}px`,e.style.maxWidth=`${b}px`,e.style.height=`${A}px`,e.style.maxHeight=`${M}px`;const P=t.offsetHeight,C=i.offsetHeight,$=Math.max(64,A-P-C);g?(s.style.maxHeight=`${$}px`,s.style.overflowY="auto"):(s.style.maxHeight="none",s.style.overflowY="hidden"),s.style.overflowX=c?"auto":"hidden",n.classList.remove("sod-modal-viewport-scroll")}else if(v==="viewport"){const w=Math.max(L,a),S=Math.max(l,f);e.style.width=`${w}px`,e.style.maxWidth="none",e.style.height=`${S}px`,e.style.maxHeight="none",s.style.maxHeight="none",s.style.overflowY="visible",s.style.overflowX="visible",S>M?n.classList.add("sod-modal-viewport-scroll"):n.classList.remove("sod-modal-viewport-scroll")}else{const w=c?Math.max(L,a):R(L,a,b);if(c||g){const S=Math.max(l,f);e.style.width=`${w}px`,e.style.maxWidth="none",e.style.height=`${S}px`,e.style.maxHeight="none",s.style.maxHeight="none",s.style.overflowY="visible",s.style.overflowX="visible",n.classList.add("sod-modal-viewport-scroll")}else e.style.width=`${w}px`,e.style.maxWidth=`${b}px`,e.style.height="auto",e.style.maxHeight="none",s.style.maxHeight="none",s.style.overflowY="visible",s.style.overflowX="visible",n.classList.remove("sod-modal-viewport-scroll")}},m=()=>{E===0&&(E=window.requestAnimationFrame(x))},u=new ResizeObserver(()=>{m()}),y=new MutationObserver(()=>{m()}),p=()=>{m()},O=()=>{m()};n.addEventListener("sod:refit",O),u.observe(s),u.observe(t),u.observe(i),h&&(y.observe(s,{subtree:!0,childList:!0,characterData:!0,attributes:!0}),s.addEventListener("load",p,!0),s.addEventListener("error",p,!0));const T=()=>{m()};return window.addEventListener("resize",T),m(),()=>{E!==0&&(window.cancelAnimationFrame(E),E=0),u.disconnect(),y.disconnect(),window.removeEventListener("resize",T),n.removeEventListener("sod:refit",O),s.removeEventListener("load",p,!0),s.removeEventListener("error",p,!0),n.classList.remove("sod-modal-viewport-scroll"),s.style.maxHeight="",s.style.overflowY="",s.style.overflowX=""}}class W{static modalRegistry=new Map;static handleRegistry=new WeakMap;static modalIdSeed=0;static createAutoModalId(){return this.modalIdSeed+=1,`sod-modal-${this.modalIdSeed}`}static revealExisting(e,t){if(!e.isConnected)return{dialog:e,close:()=>I(e),refit:()=>e.dispatchEvent(new Event("sod:refit")),setFooterButtons:()=>{},updateFooterButton:()=>!1,onAction:()=>()=>{},id:e.dataset.sodId};const s=e.querySelector(".sod-panel");s?.classList.remove("is-closing"),document.body.append(e),e.open||(t?e.showModal():e.show()),e.dispatchEvent(new Event("sod:refit")),s?.focus();const i=this.handleRegistry.get(e);return i?i():{dialog:e,close:()=>I(e),refit:()=>e.dispatchEvent(new Event("sod:refit")),setFooterButtons:()=>{},updateFooterButton:()=>!1,onAction:()=>()=>{},id:e.dataset.sodId}}static open(e){const t=e.kind??"modal",s="useModal"in e?e.useModal??!0:!0,i=t==="modal"?e:void 0,o=t==="modal"&&("autoFitSize"in e?e.autoFitSize!==!1:!0);let r,d=!1,h=e.confirmAction??"hide";if(t==="modal"){const l="id"in e&&e.id?.trim()?e.id.trim():void 0;if(d=!!l,r=l??this.createAutoModalId(),e.confirmAction===void 0&&d&&(h="destroy"),l){const c=this.modalRegistry.get(r);if(c&&c.isConnected){const g=this.revealExisting(c,s);if(e.onAction){const w=g.onAction(e.onAction);c.addEventListener("close",w,{once:!0})}return"onReused"in e&&e.onReused?.(g),g}}this.modalRegistry.delete(r)}const a=document.createElement("dialog");a.className=`sod-dialog sod-${t}`;const f=[];r&&(a.dataset.sodId=r,d&&(a.dataset.sodPersistent="true"));const v=document.createElement("section");if(v.className="sod-panel",v.tabIndex=-1,t==="offcanvas"){const l="placement"in e?e.placement??"end":"end",c="animation"in e?e.animation??"slide":"slide";v.classList.add(`sod-placement-${l}`),v.classList.add(`sod-anim-${c}`)}else{const l="position"in e?e.position??"center":"center",c="animation"in e?e.animation??"fade":"fade";v.classList.add(`sod-modal-pos-${l}`),v.classList.add(`sod-modal-anim-${c}`),o&&v.classList.add("sod-modal-autofit")}const E=document.createElement("header");E.className="sod-header";const R=document.createElement("h2");R.className="sod-title",R.textContent=e.title;const x=document.createElement("button");x.type="button",x.className="sod-close",x.setAttribute("aria-label","Close"),x.textContent="×",x.addEventListener("click",()=>I(a)),E.append(R,x);const m=document.createElement("div");m.className="sod-body",B(m,e.content);const u=document.createElement("footer");u.className="sod-footer",u.dataset.align=e.footerAlign??"end";const y=new Set;e.onAction&&y.add(e.onAction);const p=l=>(y.add(l),()=>{y.delete(l)});let O=e.footerButtons?[...e.footerButtons]:[{id:"cancel",label:e.cancelText??"取消",role:"cancel",variant:"outline"},{id:"confirm",label:e.confirmText??"确认",role:"confirm",variant:"primary"}];const T=()=>({dialog:a,close:()=>I(a),refit:()=>a.dispatchEvent(new Event("sod:refit")),setFooterButtons:l=>{O=[...l],M(),a.dispatchEvent(new Event("sod:refit"))},updateFooterButton:(l,c)=>{const g=O.findIndex(w=>w.id===l);return g<0?!1:(O[g]={...O[g],...c},M(),a.dispatchEvent(new Event("sod:refit")),!0)},onAction:l=>p(l),id:r}),b=(l,c)=>{if(typeof c=="string"){l.textContent=c;return}l.append(c)},M=()=>{if(u.replaceChildren(),e.hideFooter||O.length===0){u.hidden=!0;return}u.hidden=!1;for(const l of O){const c=document.createElement("button");c.type="button",c.className=`sod-btn ${k(l.variant)}`,l.className?.trim()&&(c.className=`${c.className} ${l.className.trim()}`),l.id?.trim()&&(c.dataset.action=l.id.trim()),l.disabled&&(c.disabled=!0),l.attrs&&Object.entries(l.attrs).forEach(([g,w])=>{c.setAttribute(g,w)}),b(c,l.label),c.addEventListener("click",g=>{(async()=>{const w=T(),A={action:l.id??l.role??"custom",button:l,buttonElement:c,dialog:a,event:g,handle:w};if(await l.onClick?.(A)===!1)return;l.role==="cancel"&&e.onCancel?.(),l.role==="confirm"&&e.onConfirm?.(),y.forEach($=>{$(A)});const C=F(l,h);C==="hide"&&I(a,"hide"),C==="destroy"&&I(a,"destroy")})()}),u.append(c)}};M(),v.append(E,m,u),o&&f.push(q(a,v,E,m,u,i)),t==="modal"&&"draggable"in e&&e.draggable&&V(v,e.dragHandle),a.append(v),(e.closeOnBackdrop??!0)&&a.addEventListener("click",l=>{l.target===a&&I(a)}),(e.closeOnEsc??!0)||a.addEventListener("cancel",l=>{l.preventDefault()}),a.addEventListener("close",()=>{const l=a.dataset.sodPersistent==="true",c=a.dataset.sodDestroy==="true";(!l||c)&&(f.forEach(g=>g()),y.clear(),a.remove(),r&&this.modalRegistry.delete(r),this.handleRegistry.delete(a),delete a.dataset.sodDestroy)}),document.body.append(a),s?a.showModal():a.show(),a.dispatchEvent(new Event("sod:refit")),r&&this.modalRegistry.set(r,a),this.handleRegistry.set(a,T);const L=T();return t==="modal"&&"onCreated"in e&&e.onCreated?.(L),L}static openModal(e){return this.open({...e,kind:"modal"})}static openOffcanvas(e){return this.open({...e,kind:"offcanvas"})}}class N{static placementState=new Map;static recordById=new Map;static idSeed=0;static defaults={placement:"top-end",variant:"default",duration:3e3,showProgress:!0,closable:!0,pauseOnHover:!0,pauseOnWindowBlur:!1,duplicateStrategy:"update",newestOnTop:!0,maxVisible:3};static normalizeOptions(e){const t=e.duration===!1?!1:Math.max(0,e.duration??this.defaults.duration);return{placement:e.placement??this.defaults.placement,variant:e.variant??this.defaults.variant,duration:t,showProgress:e.showProgress??this.defaults.showProgress,closable:e.closable??this.defaults.closable,pauseOnHover:e.pauseOnHover??this.defaults.pauseOnHover,pauseOnWindowBlur:e.pauseOnWindowBlur??this.defaults.pauseOnWindowBlur,duplicateStrategy:e.duplicateStrategy??this.defaults.duplicateStrategy,newestOnTop:e.newestOnTop??this.defaults.newestOnTop,maxVisible:Math.max(1,e.maxVisible??this.defaults.maxVisible),title:e.title,content:e.content,className:e.className,attrs:e.attrs,onShown:e.onShown,onClose:e.onClose}}static createAutoToastId(){return this.idSeed+=1,`sot-toast-${this.idSeed}`}static createStackedToastId(e){let t=1,s=`${e}-${t}`;for(;this.recordById.has(s);)t+=1,s=`${e}-${t}`;return s}static resolveRole(e){return e==="danger"?"alert":"status"}static getPlacementState(e){const t=this.placementState.get(e);if(t)return t;const s=document.createElement("div");s.className=`sod-toast-layer sod-toast-layer-${e}`,s.setAttribute("aria-live","polite"),s.setAttribute("aria-atomic","false"),document.body.append(s);const i={container:s,active:[],pending:[]};return this.placementState.set(e,i),i}static createToastElement(e){const{options:t}=e,s=document.createElement("article");s.className=`sod-toast sod-toast-${t.variant}`,t.className?.trim()&&(s.className=`${s.className} ${t.className.trim()}`),s.dataset.toastId=e.id,s.setAttribute("role",this.resolveRole(t.variant)),t.attrs&&Object.entries(t.attrs).forEach(([a,f])=>{s.setAttribute(a,f)});const i=document.createElement("header");i.className="sod-toast-header";let o=null;t.title?.trim()&&(o=document.createElement("strong"),o.className="sod-toast-title",o.textContent=t.title,i.append(o));let r=null;t.closable&&(r=document.createElement("button"),r.type="button",r.className="sod-toast-close",r.setAttribute("aria-label","Close"),r.textContent="×",r.addEventListener("click",()=>{this.closeRecord(e,"close-button")}),i.append(r)),i.childElementCount>0&&s.append(i);const d=document.createElement("div");d.className="sod-toast-body",B(d,t.content),s.append(d);let h=null;if(t.showProgress&&(h=document.createElement("div"),h.className="sod-toast-progress",s.append(h)),t.pauseOnHover){const a=()=>this.pauseRecord(e),f=()=>this.resumeRecord(e);s.addEventListener("mouseenter",a),s.addEventListener("mouseleave",f),e.cleanupListeners.push(()=>{s.removeEventListener("mouseenter",a),s.removeEventListener("mouseleave",f)})}if(t.pauseOnWindowBlur){const a=()=>{e.paused||e.status!=="active"||(e.pausedByWindowBlur=!0,this.pauseRecord(e))},f=()=>{e.pausedByWindowBlur&&(e.pausedByWindowBlur=!1,this.resumeRecord(e))};window.addEventListener("blur",a),window.addEventListener("focus",f),e.cleanupListeners.push(()=>{window.removeEventListener("blur",a),window.removeEventListener("focus",f)})}e.element=s,e.bodyElement=d,e.titleElement=o,e.closeButton=r,e.progressElement=h}static resetProgressAnimation(e,t){!e.progressElement||!e.options.showProgress||(e.progressElement.style.display="block",e.progressElement.style.animation="none",e.progressElement.style.animationPlayState="running",e.progressElement.offsetWidth,e.progressElement.style.animation=`sod-toast-progress-countdown ${Math.max(1,t)}ms linear forwards`)}static hideProgress(e){e.progressElement&&(e.progressElement.style.display="none",e.progressElement.style.animation="none")}static isRecordActive(e,t){return e.active.includes(t)}static isRecordPending(e,t){return e.pending.includes(t)}static mountRecord(e,t){t.status="active",t.options.newestOnTop?e.container.prepend(t.element):e.container.append(t.element),e.active.push(t),this.startRecordTimer(t),t.options.onShown?.(t.handle)}static queueRecord(e,t){t.status="pending",e.pending.push(t)}static startRecordTimer(e){if(this.clearRecordTimer(e),e.options.duration===!1){e.remainingMs=!1,e.startedAt=null,this.hideProgress(e);return}const t=Math.max(0,e.remainingMs===!1?e.options.duration:e.remainingMs);if(t===0){this.closeRecord(e,"timeout");return}e.startedAt=Date.now(),e.remainingMs=t,this.resetProgressAnimation(e,t),e.timerId=window.setTimeout(()=>{e.timerId=null,this.closeRecord(e,"timeout")},t)}static clearRecordTimer(e){e.timerId!==null&&(window.clearTimeout(e.timerId),e.timerId=null)}static pauseRecord(e){if(e.paused||e.status!=="active"||e.options.duration===!1)return;const t=e.startedAt??Date.now(),s=Math.max(0,Date.now()-t),i=e.remainingMs===!1?e.options.duration:e.remainingMs;e.remainingMs=Math.max(0,i-s),e.startedAt=null,e.paused=!0,e.progressElement&&(e.progressElement.style.animationPlayState="paused"),this.clearRecordTimer(e)}static resumeRecord(e){!e.paused||e.status!=="active"||(e.paused=!1,e.progressElement&&(e.progressElement.style.animationPlayState="running"),this.startRecordTimer(e))}static rebuildRecordElement(e){const t=e.element,s=t.parentElement;e.cleanupListeners.forEach(i=>i()),e.cleanupListeners=[],t.remove(),this.createToastElement(e),s&&e.status==="active"&&(e.options.newestOnTop?s.prepend(e.element):s.append(e.element),this.startRecordTimer(e))}static moveRecordToPlacement(e,t){const s=e.options.placement;if(s===t)return;const i=this.placementState.get(s),o=this.getPlacementState(t),r=!!(i&&this.removeFromArray(i.active,e)),d=!!(i&&this.removeFromArray(i.pending,e));if(e.options.placement=t,this.clearRecordTimer(e),d&&!r){this.queueRecord(o,e),this.drainQueue(o,t),i&&this.drainQueue(i,s);return}o.active.length<e.options.maxVisible?this.mountRecord(o,e):this.queueRecord(o,e),i&&this.drainQueue(i,s)}static updateRecord(e,t){if(t.title!==void 0){const i=t.title.trim();if(e.options.title=i.length>0?i:void 0,e.options.title)if(e.titleElement)e.titleElement.textContent=e.options.title;else{const o=e.element.querySelector(".sod-toast-header");if(o){const r=document.createElement("strong");r.className="sod-toast-title",r.textContent=e.options.title,o.prepend(r),e.titleElement=r}}else e.titleElement&&(e.titleElement.remove(),e.titleElement=null)}t.content!==void 0&&(e.options.content=t.content,e.bodyElement.replaceChildren(),B(e.bodyElement,t.content)),t.variant!==void 0&&(e.options.variant=t.variant,e.element.classList.remove("sod-toast-default","sod-toast-info","sod-toast-success","sod-toast-warning","sod-toast-danger"),e.element.classList.add(`sod-toast-${t.variant}`),e.element.setAttribute("role",this.resolveRole(t.variant))),t.duration!==void 0&&(e.options.duration=t.duration===!1?!1:Math.max(0,t.duration),e.remainingMs=e.options.duration===!1?!1:e.options.duration,e.paused=!1,e.status==="active"&&this.startRecordTimer(e)),t.maxVisible!==void 0&&(e.options.maxVisible=Math.max(1,t.maxVisible)),t.newestOnTop!==void 0&&(e.options.newestOnTop=t.newestOnTop);let s=!1;t.closable!==void 0&&t.closable!==e.options.closable&&(e.options.closable=t.closable,s=!0),t.pauseOnHover!==void 0&&t.pauseOnHover!==e.options.pauseOnHover&&(e.options.pauseOnHover=t.pauseOnHover,s=!0),t.pauseOnWindowBlur!==void 0&&t.pauseOnWindowBlur!==e.options.pauseOnWindowBlur&&(e.options.pauseOnWindowBlur=t.pauseOnWindowBlur,s=!0),t.duplicateStrategy!==void 0&&(e.options.duplicateStrategy=t.duplicateStrategy),t.showProgress!==void 0&&t.showProgress!==e.options.showProgress&&(e.options.showProgress=t.showProgress,s=!0),t.className!==void 0&&(e.options.className=t.className,s=!0),t.attrs!==void 0&&(e.options.attrs=t.attrs,s=!0),s&&this.rebuildRecordElement(e),t.placement&&t.placement!==e.options.placement&&this.moveRecordToPlacement(e,t.placement)}static removeStateContainerIfEmpty(e){const t=this.placementState.get(e);t&&(t.active.length>0||t.pending.length>0||(t.container.remove(),this.placementState.delete(e)))}static drainQueue(e,t){let s=!0;for(;s&&e.pending.length>0;){const i=e.pending[0];if(e.active.length>=i.options.maxVisible){s=!1;continue}e.pending.shift(),this.mountRecord(e,i)}this.removeStateContainerIfEmpty(t)}static removeFromArray(e,t){const s=e.indexOf(t);return s<0?!1:(e.splice(s,1),!0)}static finalizeClose(e,t){if(e.status==="closed")return;const s=e.options.placement,i=this.placementState.get(s);this.clearRecordTimer(e),e.cleanupListeners.forEach(o=>o()),e.cleanupListeners=[],e.element.remove(),e.status="closed",i&&(this.removeFromArray(i.active,e),this.removeFromArray(i.pending,e)),this.recordById.delete(e.id),e.options.onClose?.(t,e.handle),i?this.drainQueue(i,s):this.removeStateContainerIfEmpty(s)}static closeRecord(e,t){if(e.status==="closed"||e.status==="closing")return;const s=e.options.placement,i=this.placementState.get(s);if(!!(i&&this.isRecordPending(i,e)&&!this.isRecordActive(i,e))){this.finalizeClose(e,t);return}e.status="closing",this.clearRecordTimer(e),e.element.classList.add("is-closing");let r=!1;const d=()=>{r||(r=!0,this.finalizeClose(e,t))},h=a=>{a.target===e.element&&(e.element.removeEventListener("animationend",h),d())};e.element.addEventListener("animationend",h),window.setTimeout(()=>{e.element.removeEventListener("animationend",h),d()},220)}static createHandle(e){return{id:e.id,get element(){return e.element},close:(t="programmatic")=>{this.closeRecord(e,t)},update:t=>{this.updateRecord(e,t)},pause:()=>{this.pauseRecord(e)},resume:()=>{this.resumeRecord(e)}}}static show(e){const s=e.id?.trim()||this.createAutoToastId(),i=this.normalizeOptions(e),o=this.recordById.get(s);if(o){const a=i.duplicateStrategy;if(a==="ignore")return o.handle;if(a==="stack"){const f=this.createStackedToastId(s);return this.show({...e,id:f,duplicateStrategy:"update"})}return this.updateRecord(o,{title:e.title,content:e.content,variant:e.variant,duration:a==="restart-timer"?e.duration===void 0?o.options.duration:i.duration:e.duration===void 0?void 0:i.duration,placement:e.placement,closable:e.closable,pauseOnHover:e.pauseOnHover,pauseOnWindowBlur:e.pauseOnWindowBlur,duplicateStrategy:e.duplicateStrategy,newestOnTop:e.newestOnTop,maxVisible:e.maxVisible,showProgress:e.showProgress,className:e.className,attrs:e.attrs}),o.options.onClose=i.onClose,o.options.onShown=i.onShown,o.handle}const d={id:s,options:i,element:document.createElement("article"),status:"pending",timerId:null,remainingMs:i.duration,startedAt:null,paused:!1,pausedByWindowBlur:!1,closeButton:null,progressElement:null,bodyElement:document.createElement("div"),titleElement:null,cleanupListeners:[],handle:void 0};d.handle=this.createHandle(d),this.createToastElement(d),this.recordById.set(s,d);const h=this.getPlacementState(i.placement);return h.active.length<i.maxVisible?this.mountRecord(h,d):this.queueRecord(h,d),d.handle}static clear(e){(e?[e]:Array.from(this.placementState.keys())).forEach(s=>{const i=this.placementState.get(s);if(!i)return;const o=[...i.active];[...i.pending].forEach(d=>this.closeRecord(d,"container-clear")),o.forEach(d=>this.closeRecord(d,"container-clear"))})}static configure(e){e.placement&&(this.defaults.placement=e.placement),e.variant&&(this.defaults.variant=e.variant),e.duration!==void 0&&(this.defaults.duration=e.duration===!1?3e3:Math.max(0,e.duration)),e.showProgress!==void 0&&(this.defaults.showProgress=e.showProgress),e.closable!==void 0&&(this.defaults.closable=e.closable),e.pauseOnHover!==void 0&&(this.defaults.pauseOnHover=e.pauseOnHover),e.pauseOnWindowBlur!==void 0&&(this.defaults.pauseOnWindowBlur=e.pauseOnWindowBlur),e.duplicateStrategy!==void 0&&(this.defaults.duplicateStrategy=e.duplicateStrategy),e.newestOnTop!==void 0&&(this.defaults.newestOnTop=e.newestOnTop),e.maxVisible!==void 0&&(this.defaults.maxVisible=Math.max(1,e.maxVisible))}static success(e,t={}){return this.show({...t,content:e,variant:"success"})}static error(e,t={}){return this.show({...t,content:e,variant:"danger"})}static info(e,t={}){return this.show({...t,content:e,variant:"info"})}static warning(e,t={}){return this.show({...t,content:e,variant:"warning"})}static closeAll(){this.clear()}}function z(n){return W.openModal(n)}function Y(n){return W.openOffcanvas(n)}function X(n){return N.show(n)}H.SoDialog=W,H.SoToast=N,H.openModal=z,H.openOffcanvas=Y,H.toast=X,Object.defineProperty(H,Symbol.toStringTag,{value:"Module"})}));
|
package/dist/types/lib.d.ts
CHANGED
|
@@ -4,8 +4,27 @@ export type SoOffcanvasPlacement = 'start' | 'end' | 'top' | 'bottom';
|
|
|
4
4
|
export type SoOffcanvasAnimation = 'slide' | 'fade' | 'zoom';
|
|
5
5
|
export type SoModalPosition = 'center' | 'top' | 'bottom';
|
|
6
6
|
export type SoModalAnimation = 'slide' | 'fade' | 'zoom';
|
|
7
|
-
export type
|
|
7
|
+
export type SoModalDragHandleTarget = 'header' | 'title' | 'body' | 'panel' | string;
|
|
8
|
+
export type SoModalDragHandle = SoModalDragHandleTarget | SoModalDragHandleTarget[];
|
|
8
9
|
export type SoModalScrollMode = 'body' | 'viewport' | 'none' | 'hybrid';
|
|
10
|
+
export type SoFooterButtonVariant = 'primary' | 'outline' | 'danger' | 'success' | 'ghost' | 'link';
|
|
11
|
+
export type SoFooterAlign = 'start' | 'center' | 'end' | 'between';
|
|
12
|
+
export type SoFooterButtonAction = 'none' | 'hide' | 'destroy';
|
|
13
|
+
export type SoToastPlacement = 'top-start' | 'top-center' | 'top-end' | 'bottom-start' | 'bottom-center' | 'bottom-end';
|
|
14
|
+
export type SoToastVariant = 'default' | 'info' | 'success' | 'warning' | 'danger';
|
|
15
|
+
export type SoToastCloseReason = 'timeout' | 'manual' | 'close-button' | 'container-clear' | 'programmatic';
|
|
16
|
+
export type SoToastDuplicateStrategy = 'update' | 'ignore' | 'restart-timer' | 'stack';
|
|
17
|
+
export interface SoDialogFooterButton {
|
|
18
|
+
id?: string;
|
|
19
|
+
label: string | Node;
|
|
20
|
+
role?: 'confirm' | 'cancel' | 'custom';
|
|
21
|
+
variant?: SoFooterButtonVariant;
|
|
22
|
+
className?: string;
|
|
23
|
+
action?: SoFooterButtonAction;
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
attrs?: Record<string, string>;
|
|
26
|
+
onClick?: (context: SoDialogFooterActionContext) => void | boolean | Promise<void | boolean>;
|
|
27
|
+
}
|
|
9
28
|
export interface SoDialogBaseOptions {
|
|
10
29
|
title: string;
|
|
11
30
|
content: string | Node;
|
|
@@ -16,6 +35,10 @@ export interface SoDialogBaseOptions {
|
|
|
16
35
|
closeOnEsc?: boolean;
|
|
17
36
|
onConfirm?: () => void;
|
|
18
37
|
onCancel?: () => void;
|
|
38
|
+
footerButtons?: SoDialogFooterButton[];
|
|
39
|
+
hideFooter?: boolean;
|
|
40
|
+
footerAlign?: SoFooterAlign;
|
|
41
|
+
onAction?: SoDialogActionListener;
|
|
19
42
|
}
|
|
20
43
|
export interface SoDialogModalOptions extends SoDialogBaseOptions {
|
|
21
44
|
id?: string;
|
|
@@ -45,10 +68,50 @@ export interface SoDialogHandle {
|
|
|
45
68
|
dialog: HTMLDialogElement;
|
|
46
69
|
close: () => void;
|
|
47
70
|
refit: () => void;
|
|
71
|
+
setFooterButtons: (buttons: SoDialogFooterButton[]) => void;
|
|
72
|
+
updateFooterButton: (id: string, updates: Partial<SoDialogFooterButton>) => boolean;
|
|
73
|
+
onAction: (listener: SoDialogActionListener) => () => void;
|
|
48
74
|
id?: string;
|
|
49
75
|
}
|
|
76
|
+
export interface SoDialogFooterActionContext {
|
|
77
|
+
action: string;
|
|
78
|
+
button: SoDialogFooterButton;
|
|
79
|
+
buttonElement: HTMLButtonElement;
|
|
80
|
+
dialog: HTMLDialogElement;
|
|
81
|
+
event: MouseEvent;
|
|
82
|
+
handle: SoDialogHandle;
|
|
83
|
+
}
|
|
84
|
+
export type SoDialogActionListener = (context: SoDialogFooterActionContext) => void;
|
|
85
|
+
export interface SoToastOptions {
|
|
86
|
+
id?: string;
|
|
87
|
+
title?: string;
|
|
88
|
+
content: string | Node;
|
|
89
|
+
placement?: SoToastPlacement;
|
|
90
|
+
variant?: SoToastVariant;
|
|
91
|
+
duration?: number | false;
|
|
92
|
+
showProgress?: boolean;
|
|
93
|
+
closable?: boolean;
|
|
94
|
+
pauseOnHover?: boolean;
|
|
95
|
+
pauseOnWindowBlur?: boolean;
|
|
96
|
+
duplicateStrategy?: SoToastDuplicateStrategy;
|
|
97
|
+
newestOnTop?: boolean;
|
|
98
|
+
maxVisible?: number;
|
|
99
|
+
className?: string;
|
|
100
|
+
attrs?: Record<string, string>;
|
|
101
|
+
onShown?: (handle: SoToastHandle) => void;
|
|
102
|
+
onClose?: (reason: SoToastCloseReason, handle: SoToastHandle) => void;
|
|
103
|
+
}
|
|
104
|
+
export interface SoToastHandle {
|
|
105
|
+
id: string;
|
|
106
|
+
element: HTMLElement;
|
|
107
|
+
close: (reason?: Exclude<SoToastCloseReason, 'timeout' | 'close-button'>) => void;
|
|
108
|
+
update: (patch: Partial<Pick<SoToastOptions, 'title' | 'content' | 'variant' | 'duration'>>) => void;
|
|
109
|
+
pause: () => void;
|
|
110
|
+
resume: () => void;
|
|
111
|
+
}
|
|
50
112
|
export declare class SoDialog {
|
|
51
113
|
private static modalRegistry;
|
|
114
|
+
private static handleRegistry;
|
|
52
115
|
private static modalIdSeed;
|
|
53
116
|
private static createAutoModalId;
|
|
54
117
|
private static revealExisting;
|
|
@@ -56,5 +119,45 @@ export declare class SoDialog {
|
|
|
56
119
|
static openModal(options: SoDialogModalOptions): SoDialogHandle;
|
|
57
120
|
static openOffcanvas(options: Omit<SoDialogOffcanvasOptions, 'kind'>): SoDialogHandle;
|
|
58
121
|
}
|
|
122
|
+
export declare class SoToast {
|
|
123
|
+
private static placementState;
|
|
124
|
+
private static recordById;
|
|
125
|
+
private static idSeed;
|
|
126
|
+
private static defaults;
|
|
127
|
+
private static normalizeOptions;
|
|
128
|
+
private static createAutoToastId;
|
|
129
|
+
private static createStackedToastId;
|
|
130
|
+
private static resolveRole;
|
|
131
|
+
private static getPlacementState;
|
|
132
|
+
private static createToastElement;
|
|
133
|
+
private static resetProgressAnimation;
|
|
134
|
+
private static hideProgress;
|
|
135
|
+
private static isRecordActive;
|
|
136
|
+
private static isRecordPending;
|
|
137
|
+
private static mountRecord;
|
|
138
|
+
private static queueRecord;
|
|
139
|
+
private static startRecordTimer;
|
|
140
|
+
private static clearRecordTimer;
|
|
141
|
+
private static pauseRecord;
|
|
142
|
+
private static resumeRecord;
|
|
143
|
+
private static rebuildRecordElement;
|
|
144
|
+
private static moveRecordToPlacement;
|
|
145
|
+
private static updateRecord;
|
|
146
|
+
private static removeStateContainerIfEmpty;
|
|
147
|
+
private static drainQueue;
|
|
148
|
+
private static removeFromArray;
|
|
149
|
+
private static finalizeClose;
|
|
150
|
+
private static closeRecord;
|
|
151
|
+
private static createHandle;
|
|
152
|
+
static show(options: SoToastOptions): SoToastHandle;
|
|
153
|
+
static clear(placement?: SoToastPlacement): void;
|
|
154
|
+
static configure(defaults: Partial<SoToastOptions>): void;
|
|
155
|
+
static success(content: string | Node, options?: Omit<SoToastOptions, 'content' | 'variant'>): SoToastHandle;
|
|
156
|
+
static error(content: string | Node, options?: Omit<SoToastOptions, 'content' | 'variant'>): SoToastHandle;
|
|
157
|
+
static info(content: string | Node, options?: Omit<SoToastOptions, 'content' | 'variant'>): SoToastHandle;
|
|
158
|
+
static warning(content: string | Node, options?: Omit<SoToastOptions, 'content' | 'variant'>): SoToastHandle;
|
|
159
|
+
static closeAll(): void;
|
|
160
|
+
}
|
|
59
161
|
export declare function openModal(options: SoDialogModalOptions): SoDialogHandle;
|
|
60
162
|
export declare function openOffcanvas(options: Omit<SoDialogOffcanvasOptions, 'kind'>): SoDialogHandle;
|
|
163
|
+
export declare function toast(options: SoToastOptions): SoToastHandle;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sodialog",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "A reusable HTML5 dialog-based modal and offcanvas library.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dialog",
|
|
@@ -38,6 +38,8 @@
|
|
|
38
38
|
"build": "vite build && npm run build:types",
|
|
39
39
|
"build:types": "tsc -p tsconfig.build.json",
|
|
40
40
|
"build:demo": "vite build --mode demo",
|
|
41
|
+
"release:check": "node scripts/check-release-version.mjs",
|
|
42
|
+
"docs:changelog": "node scripts/generate-changelog.mjs",
|
|
41
43
|
"preview": "vite preview",
|
|
42
44
|
"lint": "eslint .",
|
|
43
45
|
"prepublishOnly": "npm run lint && npm run build"
|