sodialog 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -0
- package/dist/sodialog.css +1 -0
- package/dist/sodialog.es.js +202 -0
- package/dist/sodialog.umd.js +1 -0
- package/dist/types/lib.d.ts +60 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# SoDialog
|
|
2
|
+
|
|
3
|
+
基于 HTML5 `dialog` 的可复用弹窗库,支持 **Modal** 与 **Offcanvas**,并通过 JavaScript 动态创建 HTML 元素。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install sodialog
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 使用
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { openModal, openOffcanvas } from 'sodialog'
|
|
15
|
+
import 'sodialog/style.css'
|
|
16
|
+
|
|
17
|
+
openModal({
|
|
18
|
+
id: 'order-delete',
|
|
19
|
+
title: '提示',
|
|
20
|
+
position: 'center',
|
|
21
|
+
animation: 'fade',
|
|
22
|
+
useModal: true,
|
|
23
|
+
draggable: true,
|
|
24
|
+
dragHandle: 'header',
|
|
25
|
+
autoFitSize: true,
|
|
26
|
+
content: '<p>这是 Modal</p>',
|
|
27
|
+
confirmText: '确定',
|
|
28
|
+
cancelText: '取消',
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
openOffcanvas({
|
|
32
|
+
title: '侧边栏',
|
|
33
|
+
placement: 'end',
|
|
34
|
+
animation: 'slide',
|
|
35
|
+
content: '<p>这是 Offcanvas</p>',
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## API
|
|
40
|
+
|
|
41
|
+
### `openModal(options)`
|
|
42
|
+
|
|
43
|
+
- `title: string`
|
|
44
|
+
- `content: string | Node`
|
|
45
|
+
- `id?: string`(默认自动生成。传入后同 ID Modal 不重复创建,再次调用会唤起已有实例)
|
|
46
|
+
- `onCreated?: (handle) => void`(仅新建时触发,可读取自动生成的 `handle.id`)
|
|
47
|
+
- `onReused?: (handle) => void`(仅复用已有同 ID 实例时触发)
|
|
48
|
+
- `handle.refit(): void`(手动触发一次尺寸重算)
|
|
49
|
+
- `position?: 'center' | 'top' | 'bottom'` (默认 `center`)
|
|
50
|
+
- `animation?: 'slide' | 'fade' | 'zoom'` (默认 `fade`)
|
|
51
|
+
- `useModal?: boolean` (默认 `true`,`true` 使用 `showModal()`,`false` 使用 `show()`)
|
|
52
|
+
- `draggable?: boolean` (默认 `false`)
|
|
53
|
+
- `dragHandle?: 'header' | 'title' | 'body' | 'panel' | string` (默认 `header`,也可传 CSS 选择器)
|
|
54
|
+
- `autoFitSize?: boolean` (默认 `true`,会根据 body 内容变化自动扩/缩尺寸,例如图片加载完成后)
|
|
55
|
+
- `scrollMode?: 'body' | 'hybrid' | 'viewport' | 'none'` (默认 `body`)
|
|
56
|
+
- `hybridSwitchRatio?: number` (默认 `1.35`,仅 `scrollMode: 'hybrid'` 时生效,最小值 `1`)
|
|
57
|
+
- `autoFitUseScrollbar?: boolean` (兼容旧参数。`false` 等价于 `scrollMode: 'viewport'`)
|
|
58
|
+
- `refitOnContentChange?: boolean` (默认 `true`,内容变化/图片加载后自动触发尺寸重算)
|
|
59
|
+
- `autoFitMinWidth?: number` (默认 `280`)
|
|
60
|
+
- `autoFitMinHeight?: number` (默认 `160`)
|
|
61
|
+
- `confirmText?: string`
|
|
62
|
+
- `cancelText?: string`
|
|
63
|
+
- `confirmAction?: 'hide' | 'destroy'`(默认 `hide`;显式传入 `id` 时默认 `destroy`)
|
|
64
|
+
- `closeOnBackdrop?: boolean` (默认 `true`)
|
|
65
|
+
- `closeOnEsc?: boolean` (默认 `true`)
|
|
66
|
+
- `onConfirm?: () => void`
|
|
67
|
+
- `onCancel?: () => void`
|
|
68
|
+
|
|
69
|
+
说明:
|
|
70
|
+
|
|
71
|
+
- `hybrid` 表示先使用 body 内滚动;当内容高度远超可视区阈值时自动切到外层 viewport 滚动
|
|
72
|
+
- `取消/关闭` 语义是 `dialog.close()`(隐藏)
|
|
73
|
+
- `confirmAction: 'destroy'` 语义是 `dialog.remove()`(销毁)
|
|
74
|
+
|
|
75
|
+
### `openOffcanvas(options)`
|
|
76
|
+
|
|
77
|
+
在 `openModal` 参数基础上新增:
|
|
78
|
+
|
|
79
|
+
- `placement?: 'start' | 'end' | 'top' | 'bottom'` (默认 `end`)
|
|
80
|
+
- `animation?: 'slide' | 'fade' | 'zoom'` (默认 `slide`)
|
|
81
|
+
|
|
82
|
+
示例(类似 Bootstrap Offcanvas 多位置):
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
openOffcanvas({ title: 'Left', placement: 'start', animation: 'slide', content: '<p>Left</p>' })
|
|
86
|
+
openOffcanvas({ title: 'Right', placement: 'end', animation: 'slide', content: '<p>Right</p>' })
|
|
87
|
+
openOffcanvas({ title: 'Top', placement: 'top', animation: 'fade', content: '<p>Top</p>' })
|
|
88
|
+
openOffcanvas({ title: 'Bottom', placement: 'bottom', animation: 'zoom', content: '<p>Bottom</p>' })
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### `SoDialog.open(options)`
|
|
92
|
+
|
|
93
|
+
通用入口,`options.kind` 可为 `modal` 或 `offcanvas`。
|
|
94
|
+
|
|
95
|
+
## 开发
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npm run dev
|
|
99
|
+
npm run lint
|
|
100
|
+
npm run build
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Demo 中已包含:
|
|
104
|
+
|
|
105
|
+
- 预设默认值:`center`、`zoom`、`medium`、`showModal`、不可拖动、自动适配
|
|
106
|
+
- `Modal ID` 留空自动生成,输入后可复用唤醒同 ID
|
|
107
|
+
- Modal 内切换不同尺寸图片,验证 `autoFitSize` 自动扩缩
|
|
108
|
+
- 包含超大图(`xlarge`)、超长单词、超宽表格的溢出测试
|
|
109
|
+
- Modal 内容按钮打开子窗口(支持 ID 复用唤起)
|
|
110
|
+
- 子窗口包含多种表单元素(input/select/checkbox/textarea)演示
|
|
111
|
+
- 新增 Markdown 编辑器子窗口(工具栏插入、实时预览)
|
|
112
|
+
- 编辑器支持“仅编辑 / 编辑 + 预览”模式切换
|
|
113
|
+
|
|
114
|
+
## 发布到 NPM
|
|
115
|
+
|
|
116
|
+
1. 登录:`npm login`
|
|
117
|
+
2. 检查包名可用性
|
|
118
|
+
3. 发布:`npm publish --access public`
|
|
119
|
+
|
|
120
|
+
> 当前样式均使用 `sod-` 前缀命名,避免污染全局 `body/:root/*`。
|
|
@@ -0,0 +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)}}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
function A(t, e) {
|
|
2
|
+
if (typeof e == "string") {
|
|
3
|
+
t.innerHTML = e;
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
t.append(e);
|
|
7
|
+
}
|
|
8
|
+
function I(t, e = "hide") {
|
|
9
|
+
if (e === "destroy") {
|
|
10
|
+
t.dataset.sodDestroy = "true", t.open && t.close(), t.remove();
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
t.open && t.close();
|
|
14
|
+
}
|
|
15
|
+
function N(t, e) {
|
|
16
|
+
const i = e ?? "header";
|
|
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");
|
|
18
|
+
}
|
|
19
|
+
function F(t, e) {
|
|
20
|
+
const i = N(t, e);
|
|
21
|
+
if (!i)
|
|
22
|
+
return;
|
|
23
|
+
t.classList.add("sod-modal-draggable"), i.classList.add("sod-drag-handle");
|
|
24
|
+
let s = !1, H = 0, v = 0, d = null, g = 0, L = 0, o = 0;
|
|
25
|
+
const x = document.body.style.userSelect, c = (r, m) => {
|
|
26
|
+
const a = t.getBoundingClientRect(), M = Math.max(0, window.innerWidth - a.width), w = Math.max(0, window.innerHeight - a.height), p = Math.min(0, window.innerWidth - a.width), l = Math.min(0, window.innerHeight - a.height);
|
|
27
|
+
return {
|
|
28
|
+
left: Math.min(M, Math.max(p, r)),
|
|
29
|
+
top: Math.min(w, Math.max(l, m))
|
|
30
|
+
};
|
|
31
|
+
}, h = (r) => {
|
|
32
|
+
if (!s)
|
|
33
|
+
return;
|
|
34
|
+
const m = c(r.clientX - H, r.clientY - v);
|
|
35
|
+
L = m.left, o = m.top, g === 0 && (g = window.requestAnimationFrame(() => {
|
|
36
|
+
g = 0, t.style.inset = "auto", t.style.left = `${L}px`, t.style.top = `${o}px`, t.style.right = "auto", t.style.bottom = "auto", t.style.margin = "0", t.style.transform = "none";
|
|
37
|
+
}));
|
|
38
|
+
}, u = () => {
|
|
39
|
+
s = !1, i.classList.remove("is-dragging"), t.classList.remove("sod-is-dragging"), t.style.willChange = "", document.body.style.userSelect = x, 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", u), window.removeEventListener("pointercancel", u);
|
|
40
|
+
};
|
|
41
|
+
i.addEventListener("pointerdown", (r) => {
|
|
42
|
+
if (r.button !== 0 || r.target?.closest("button, input, select, textarea, a"))
|
|
43
|
+
return;
|
|
44
|
+
r.preventDefault(), t.classList.add("sod-is-dragging"), t.style.animation = "none", t.style.transition = "none", t.style.transform = "none";
|
|
45
|
+
const a = t.getBoundingClientRect();
|
|
46
|
+
H = 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", u), window.addEventListener("pointercancel", u);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function Y(t, e, i, s, H, v) {
|
|
50
|
+
const g = Math.max(1, v?.hybridSwitchRatio ?? 1.35), L = v?.refitOnContentChange ?? !0, o = Math.max(120, v?.autoFitMinWidth ?? 280), x = Math.max(100, v?.autoFitMinHeight ?? 160), c = v?.scrollMode ? v.scrollMode : v?.autoFitUseScrollbar === !1 ? "viewport" : "body";
|
|
51
|
+
let h = 0;
|
|
52
|
+
const u = (n, f, E) => Math.min(E, Math.max(f, n)), r = () => {
|
|
53
|
+
if (h = 0, !t.isConnected || !t.open)
|
|
54
|
+
return;
|
|
55
|
+
const n = Math.max(o, window.innerWidth - 32), f = Math.max(x, window.innerHeight - 32);
|
|
56
|
+
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 E = Math.ceil(e.scrollWidth), $ = Math.ceil(e.scrollHeight), W = E > n, S = $ > f;
|
|
58
|
+
if (c === "body") {
|
|
59
|
+
const b = u(E, o, n), y = u($, x, f);
|
|
60
|
+
e.style.width = `${b}px`, e.style.maxWidth = `${n}px`, e.style.height = `${y}px`, e.style.maxHeight = `${f}px`;
|
|
61
|
+
const C = i.offsetHeight, R = H.offsetHeight, D = Math.max(64, y - C - R);
|
|
62
|
+
S ? (s.style.maxHeight = `${D}px`, s.style.overflowY = "auto") : (s.style.maxHeight = "none", s.style.overflowY = "hidden"), s.style.overflowX = W ? "auto" : "hidden", t.classList.remove("sod-modal-viewport-scroll");
|
|
63
|
+
} else if (c === "hybrid")
|
|
64
|
+
if ($ > f * g) {
|
|
65
|
+
const y = Math.max(E, o), C = Math.max($, x);
|
|
66
|
+
e.style.width = `${y}px`, e.style.maxWidth = "none", e.style.height = `${C}px`, e.style.maxHeight = "none", s.style.maxHeight = "none", s.style.overflowY = "visible", s.style.overflowX = "visible", t.classList.add("sod-modal-viewport-scroll");
|
|
67
|
+
} else {
|
|
68
|
+
const y = u(E, o, n), C = u($, x, f);
|
|
69
|
+
e.style.width = `${y}px`, e.style.maxWidth = `${n}px`, e.style.height = `${C}px`, e.style.maxHeight = `${f}px`;
|
|
70
|
+
const R = i.offsetHeight, D = H.offsetHeight, P = Math.max(64, C - R - D);
|
|
71
|
+
S ? (s.style.maxHeight = `${P}px`, s.style.overflowY = "auto") : (s.style.maxHeight = "none", s.style.overflowY = "hidden"), s.style.overflowX = W ? "auto" : "hidden", t.classList.remove("sod-modal-viewport-scroll");
|
|
72
|
+
}
|
|
73
|
+
else if (c === "viewport") {
|
|
74
|
+
const b = Math.max(E, o), y = Math.max($, x);
|
|
75
|
+
e.style.width = `${b}px`, e.style.maxWidth = "none", e.style.height = `${y}px`, e.style.maxHeight = "none", s.style.maxHeight = "none", s.style.overflowY = "visible", s.style.overflowX = "visible", y > f ? t.classList.add("sod-modal-viewport-scroll") : t.classList.remove("sod-modal-viewport-scroll");
|
|
76
|
+
} else {
|
|
77
|
+
const b = W ? Math.max(E, o) : u(E, o, n);
|
|
78
|
+
if (W || S) {
|
|
79
|
+
const y = Math.max($, x);
|
|
80
|
+
e.style.width = `${b}px`, e.style.maxWidth = "none", e.style.height = `${y}px`, e.style.maxHeight = "none", s.style.maxHeight = "none", s.style.overflowY = "visible", s.style.overflowX = "visible", t.classList.add("sod-modal-viewport-scroll");
|
|
81
|
+
} else
|
|
82
|
+
e.style.width = `${b}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");
|
|
83
|
+
}
|
|
84
|
+
}, m = () => {
|
|
85
|
+
h === 0 && (h = window.requestAnimationFrame(r));
|
|
86
|
+
}, a = new ResizeObserver(() => {
|
|
87
|
+
m();
|
|
88
|
+
}), M = new MutationObserver(() => {
|
|
89
|
+
m();
|
|
90
|
+
}), w = () => {
|
|
91
|
+
m();
|
|
92
|
+
}, p = () => {
|
|
93
|
+
m();
|
|
94
|
+
};
|
|
95
|
+
t.addEventListener("sod:refit", p), a.observe(s), a.observe(i), a.observe(H), L && (M.observe(s, {
|
|
96
|
+
subtree: !0,
|
|
97
|
+
childList: !0,
|
|
98
|
+
characterData: !0,
|
|
99
|
+
attributes: !0
|
|
100
|
+
}), s.addEventListener("load", w, !0), s.addEventListener("error", w, !0));
|
|
101
|
+
const l = () => {
|
|
102
|
+
m();
|
|
103
|
+
};
|
|
104
|
+
return window.addEventListener("resize", l), m(), () => {
|
|
105
|
+
h !== 0 && (window.cancelAnimationFrame(h), h = 0), a.disconnect(), M.disconnect(), window.removeEventListener("resize", l), t.removeEventListener("sod:refit", p), 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 = "";
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
class O {
|
|
109
|
+
static modalRegistry = /* @__PURE__ */ new Map();
|
|
110
|
+
static modalIdSeed = 0;
|
|
111
|
+
static createAutoModalId() {
|
|
112
|
+
return this.modalIdSeed += 1, `sod-modal-${this.modalIdSeed}`;
|
|
113
|
+
}
|
|
114
|
+
static revealExisting(e, i) {
|
|
115
|
+
if (!e.isConnected)
|
|
116
|
+
return;
|
|
117
|
+
const s = e.querySelector(".sod-panel");
|
|
118
|
+
s?.classList.remove("is-closing"), document.body.append(e), e.open || (i ? e.showModal() : e.show()), e.dispatchEvent(new Event("sod:refit")), s?.focus();
|
|
119
|
+
}
|
|
120
|
+
static open(e) {
|
|
121
|
+
const i = e.kind ?? "modal", s = "useModal" in e ? e.useModal ?? !0 : !0, H = i === "modal" ? e : void 0, v = i === "modal" && ("autoFitSize" in e ? e.autoFitSize !== !1 : !0);
|
|
122
|
+
let d, g = !1, L = e.confirmAction ?? "hide";
|
|
123
|
+
if (i === "modal") {
|
|
124
|
+
const l = "id" in e && e.id?.trim() ? e.id.trim() : void 0;
|
|
125
|
+
if (g = !!l, d = l ?? this.createAutoModalId(), e.confirmAction === void 0 && g && (L = "destroy"), l) {
|
|
126
|
+
const n = this.modalRegistry.get(d);
|
|
127
|
+
if (n && n.isConnected) {
|
|
128
|
+
this.revealExisting(n, s);
|
|
129
|
+
const f = {
|
|
130
|
+
dialog: n,
|
|
131
|
+
close: () => I(n),
|
|
132
|
+
refit: () => n.dispatchEvent(new Event("sod:refit")),
|
|
133
|
+
id: d
|
|
134
|
+
};
|
|
135
|
+
return "onReused" in e && e.onReused?.(f), f;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
this.modalRegistry.delete(d);
|
|
139
|
+
}
|
|
140
|
+
const o = document.createElement("dialog");
|
|
141
|
+
o.className = `sod-dialog sod-${i}`;
|
|
142
|
+
const x = [];
|
|
143
|
+
d && (o.dataset.sodId = d, g && (o.dataset.sodPersistent = "true"));
|
|
144
|
+
const c = document.createElement("section");
|
|
145
|
+
if (c.className = "sod-panel", c.tabIndex = -1, i === "offcanvas") {
|
|
146
|
+
const l = "placement" in e ? e.placement ?? "end" : "end", n = "animation" in e ? e.animation ?? "slide" : "slide";
|
|
147
|
+
c.classList.add(`sod-placement-${l}`), c.classList.add(`sod-anim-${n}`);
|
|
148
|
+
} else {
|
|
149
|
+
const l = "position" in e ? e.position ?? "center" : "center", n = "animation" in e ? e.animation ?? "fade" : "fade";
|
|
150
|
+
c.classList.add(`sod-modal-pos-${l}`), c.classList.add(`sod-modal-anim-${n}`), v && c.classList.add("sod-modal-autofit");
|
|
151
|
+
}
|
|
152
|
+
const h = document.createElement("header");
|
|
153
|
+
h.className = "sod-header";
|
|
154
|
+
const u = document.createElement("h2");
|
|
155
|
+
u.className = "sod-title", u.textContent = e.title;
|
|
156
|
+
const r = document.createElement("button");
|
|
157
|
+
r.type = "button", r.className = "sod-close", r.setAttribute("aria-label", "Close"), r.textContent = "×", r.addEventListener("click", () => I(o)), h.append(u, r);
|
|
158
|
+
const m = document.createElement("div");
|
|
159
|
+
m.className = "sod-body", A(m, e.content);
|
|
160
|
+
const a = document.createElement("footer");
|
|
161
|
+
a.className = "sod-footer";
|
|
162
|
+
const M = document.createElement("button");
|
|
163
|
+
M.type = "button", M.className = "sod-btn sod-btn-outline", M.textContent = e.cancelText ?? "取消", M.addEventListener("click", () => {
|
|
164
|
+
e.onCancel?.(), I(o);
|
|
165
|
+
});
|
|
166
|
+
const w = document.createElement("button");
|
|
167
|
+
w.type = "button", w.className = "sod-btn sod-btn-primary", w.textContent = e.confirmText ?? "确认", w.addEventListener("click", () => {
|
|
168
|
+
e.onConfirm?.(), I(o, L);
|
|
169
|
+
}), a.append(M, w), c.append(h, m, a), v && x.push(Y(o, c, h, m, a, H)), i === "modal" && "draggable" in e && e.draggable && F(c, e.dragHandle), o.append(c), (e.closeOnBackdrop ?? !0) && o.addEventListener("click", (l) => {
|
|
170
|
+
l.target === o && I(o);
|
|
171
|
+
}), (e.closeOnEsc ?? !0) || o.addEventListener("cancel", (l) => {
|
|
172
|
+
l.preventDefault();
|
|
173
|
+
}), o.addEventListener("close", () => {
|
|
174
|
+
const l = o.dataset.sodPersistent === "true", n = o.dataset.sodDestroy === "true";
|
|
175
|
+
(!l || n) && (x.forEach((f) => f()), o.remove(), d && this.modalRegistry.delete(d), delete o.dataset.sodDestroy);
|
|
176
|
+
}), document.body.append(o), s ? o.showModal() : o.show(), o.dispatchEvent(new Event("sod:refit")), d && this.modalRegistry.set(d, o);
|
|
177
|
+
const p = {
|
|
178
|
+
dialog: o,
|
|
179
|
+
close: () => I(o),
|
|
180
|
+
refit: () => o.dispatchEvent(new Event("sod:refit")),
|
|
181
|
+
id: d
|
|
182
|
+
};
|
|
183
|
+
return i === "modal" && "onCreated" in e && e.onCreated?.(p), p;
|
|
184
|
+
}
|
|
185
|
+
static openModal(e) {
|
|
186
|
+
return this.open({ ...e, kind: "modal" });
|
|
187
|
+
}
|
|
188
|
+
static openOffcanvas(e) {
|
|
189
|
+
return this.open({ ...e, kind: "offcanvas" });
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function k(t) {
|
|
193
|
+
return O.openModal(t);
|
|
194
|
+
}
|
|
195
|
+
function T(t) {
|
|
196
|
+
return O.openOffcanvas(t);
|
|
197
|
+
}
|
|
198
|
+
export {
|
|
199
|
+
O as SoDialog,
|
|
200
|
+
k as openModal,
|
|
201
|
+
T as openOffcanvas
|
|
202
|
+
};
|
|
@@ -0,0 +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"})}));
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import './sodialog.css';
|
|
2
|
+
export type SoPanelKind = 'modal' | 'offcanvas';
|
|
3
|
+
export type SoOffcanvasPlacement = 'start' | 'end' | 'top' | 'bottom';
|
|
4
|
+
export type SoOffcanvasAnimation = 'slide' | 'fade' | 'zoom';
|
|
5
|
+
export type SoModalPosition = 'center' | 'top' | 'bottom';
|
|
6
|
+
export type SoModalAnimation = 'slide' | 'fade' | 'zoom';
|
|
7
|
+
export type SoModalDragHandle = 'header' | 'title' | 'body' | 'panel' | string;
|
|
8
|
+
export type SoModalScrollMode = 'body' | 'viewport' | 'none' | 'hybrid';
|
|
9
|
+
export interface SoDialogBaseOptions {
|
|
10
|
+
title: string;
|
|
11
|
+
content: string | Node;
|
|
12
|
+
confirmText?: string;
|
|
13
|
+
cancelText?: string;
|
|
14
|
+
confirmAction?: 'hide' | 'destroy';
|
|
15
|
+
closeOnBackdrop?: boolean;
|
|
16
|
+
closeOnEsc?: boolean;
|
|
17
|
+
onConfirm?: () => void;
|
|
18
|
+
onCancel?: () => void;
|
|
19
|
+
}
|
|
20
|
+
export interface SoDialogModalOptions extends SoDialogBaseOptions {
|
|
21
|
+
id?: string;
|
|
22
|
+
kind?: 'modal';
|
|
23
|
+
position?: SoModalPosition;
|
|
24
|
+
animation?: SoModalAnimation;
|
|
25
|
+
useModal?: boolean;
|
|
26
|
+
draggable?: boolean;
|
|
27
|
+
dragHandle?: SoModalDragHandle;
|
|
28
|
+
autoFitSize?: boolean;
|
|
29
|
+
scrollMode?: SoModalScrollMode;
|
|
30
|
+
hybridSwitchRatio?: number;
|
|
31
|
+
autoFitUseScrollbar?: boolean;
|
|
32
|
+
refitOnContentChange?: boolean;
|
|
33
|
+
autoFitMinWidth?: number;
|
|
34
|
+
autoFitMinHeight?: number;
|
|
35
|
+
onCreated?: (handle: SoDialogHandle) => void;
|
|
36
|
+
onReused?: (handle: SoDialogHandle) => void;
|
|
37
|
+
}
|
|
38
|
+
export interface SoDialogOffcanvasOptions extends SoDialogBaseOptions {
|
|
39
|
+
kind: 'offcanvas';
|
|
40
|
+
placement?: SoOffcanvasPlacement;
|
|
41
|
+
animation?: SoOffcanvasAnimation;
|
|
42
|
+
}
|
|
43
|
+
export type SoDialogOptions = SoDialogModalOptions | SoDialogOffcanvasOptions;
|
|
44
|
+
export interface SoDialogHandle {
|
|
45
|
+
dialog: HTMLDialogElement;
|
|
46
|
+
close: () => void;
|
|
47
|
+
refit: () => void;
|
|
48
|
+
id?: string;
|
|
49
|
+
}
|
|
50
|
+
export declare class SoDialog {
|
|
51
|
+
private static modalRegistry;
|
|
52
|
+
private static modalIdSeed;
|
|
53
|
+
private static createAutoModalId;
|
|
54
|
+
private static revealExisting;
|
|
55
|
+
static open(options: SoDialogOptions): SoDialogHandle;
|
|
56
|
+
static openModal(options: SoDialogModalOptions): SoDialogHandle;
|
|
57
|
+
static openOffcanvas(options: Omit<SoDialogOffcanvasOptions, 'kind'>): SoDialogHandle;
|
|
58
|
+
}
|
|
59
|
+
export declare function openModal(options: SoDialogModalOptions): SoDialogHandle;
|
|
60
|
+
export declare function openOffcanvas(options: Omit<SoDialogOffcanvasOptions, 'kind'>): SoDialogHandle;
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sodialog",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "A reusable HTML5 dialog-based modal and offcanvas library.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"dialog",
|
|
7
|
+
"modal",
|
|
8
|
+
"offcanvas",
|
|
9
|
+
"typescript",
|
|
10
|
+
"html5"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "./dist/sodialog.es.js",
|
|
15
|
+
"module": "./dist/sodialog.es.js",
|
|
16
|
+
"types": "./dist/types/lib.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/types/lib.d.ts",
|
|
20
|
+
"import": "./dist/sodialog.es.js",
|
|
21
|
+
"default": "./dist/sodialog.es.js"
|
|
22
|
+
},
|
|
23
|
+
"./style.css": "./dist/sodialog.css"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"dev": "vite",
|
|
30
|
+
"build": "vite build && npm run build:types",
|
|
31
|
+
"build:types": "tsc -p tsconfig.build.json",
|
|
32
|
+
"build:demo": "vite build --mode demo",
|
|
33
|
+
"preview": "vite preview",
|
|
34
|
+
"lint": "eslint .",
|
|
35
|
+
"prepublishOnly": "npm run lint && npm run build"
|
|
36
|
+
},
|
|
37
|
+
"sideEffects": [
|
|
38
|
+
"**/*.css"
|
|
39
|
+
],
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@eslint/js": "^10.0.1",
|
|
42
|
+
"eslint": "^10.0.2",
|
|
43
|
+
"typescript": "~5.9.3",
|
|
44
|
+
"typescript-eslint": "^8.56.1",
|
|
45
|
+
"vite": "^7.3.1"
|
|
46
|
+
}
|
|
47
|
+
}
|