@lanxuexing/vue2toast 1.0.0 → 1.0.2
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 +4 -1
- package/README.zh-CN.md +4 -1
- package/dist/vue2toast.css +1 -1
- package/dist/vue2toast.es.js +134 -102
- package/dist/vue2toast.umd.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -29,6 +29,8 @@ Check out the component in action: **[https://lanxuexing.github.io/vue2toast/](h
|
|
|
29
29
|
|
|
30
30
|
- 🚀 **Vue 3 Optimized**: Built with `createVNode` and `render` for minimal overhead.
|
|
31
31
|
- 📐 **TypeScript Ready**: Full type definitions included.
|
|
32
|
+
- 📚 **Stackable**: Multiple toasts stack automatically without overlapping.
|
|
33
|
+
- 📱 **Responsive**: Auto-resizing width to fit content comfortably.
|
|
32
34
|
- 🎨 **Modern Design**: Clean and accessible UI with smooth animations.
|
|
33
35
|
- 🔄 **Updateable Toasts**: Update message content programmatically (e.g., for progress bars).
|
|
34
36
|
- 📦 **Lightweight**: Zero dependencies, tiny bundle size.
|
|
@@ -148,7 +150,7 @@ const showPersist = () => {
|
|
|
148
150
|
| :--- | :--- | :--- | :--- |
|
|
149
151
|
| `duration` | `number` | `3000` | Duration in ms. Set to `0` to persist indefinitely. |
|
|
150
152
|
| `pauseOnHover` | `boolean` | `true` | Pauses timer when hovering over the toast. |
|
|
151
|
-
| `position` | `'top' \| 'bottom' \| 'center'` | `'
|
|
153
|
+
| `position` | `'top' \| 'bottom' \| 'center'` | `'top'` | Vertical position of the toast. |
|
|
152
154
|
| `zIndex` | `number` | `9999` | Z-Index of the toast container. |
|
|
153
155
|
| `className` | `string` | `''` | Custom CSS class name for the toast content. |
|
|
154
156
|
| `style` | `CSSProperties` | `{}` | Custom inline styles (Vue CSS object). |
|
|
@@ -158,6 +160,7 @@ const showPersist = () => {
|
|
|
158
160
|
|
|
159
161
|
This repository is powered by Vite.
|
|
160
162
|
|
|
163
|
+
- **Node.js**: >= 18.0.0 (Required for Vite 6+ / Tailwind 4)
|
|
161
164
|
- **Dev Server**: `npm run dev`
|
|
162
165
|
- **Build Lib**: `npm run build`
|
|
163
166
|
- **Build Demo**: `npm run build:demo`
|
package/README.zh-CN.md
CHANGED
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
|
|
30
30
|
- 🚀 **Vue 3 优化**: 使用 `createVNode` 和 `render` 函数构建,性能极致。
|
|
31
31
|
- 📐 **TypeScript 支持**: 内置完整的类型定义 (d.ts)。
|
|
32
|
+
- 📚 **堆叠显示**: 支持多个 Toast 自动垂直堆叠,不重叠。
|
|
33
|
+
- 📱 **响应式**: 宽度随内容自动调整,适应长文本。
|
|
32
34
|
- 🎨 **现代设计**: 简洁美观的 UI,流畅的动画。
|
|
33
35
|
- 🔄 **支持更新**: 可编程更新 Toast 内容 (适用于进度条、倒计时等)。
|
|
34
36
|
- 📦 **轻量级**: 零依赖,体积极小。
|
|
@@ -146,7 +148,7 @@ const showPersist = () => {
|
|
|
146
148
|
| :--- | :--- | :--- | :--- |
|
|
147
149
|
| `duration` | `number` | `3000` | 显示时长 (ms)。设置为 `0` 则永久显示。 |
|
|
148
150
|
| `pauseOnHover` | `boolean` | `true` | 鼠标悬停时是否暂停倒计时。 |
|
|
149
|
-
| `position` | `'top' \| 'bottom' \| 'center'` | `'
|
|
151
|
+
| `position` | `'top' \| 'bottom' \| 'center'` | `'top'` | Toast 的垂直显示位置。 |
|
|
150
152
|
| `zIndex` | `number` | `9999` | Toast 容器的层级 (z-index)。 |
|
|
151
153
|
| `className` | `string` | `''` | 自定义 CSS 类名。 |
|
|
152
154
|
| `style` | `CSSProperties` | `{}` | 自定义内联样式对象 (Vue CSS)。 |
|
|
@@ -156,6 +158,7 @@ const showPersist = () => {
|
|
|
156
158
|
|
|
157
159
|
本项目使用 Vite 构建。
|
|
158
160
|
|
|
161
|
+
- **Node.js**: >= 18.0.0 (Vite 6+ / Tailwind 4 需要)
|
|
159
162
|
- **启动开发服务器**: `npm run dev`
|
|
160
163
|
- **构建库**: `npm run build`
|
|
161
164
|
- **构建 Demo**: `npm run build:demo`
|
package/dist/vue2toast.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.toast
|
|
1
|
+
.toast[data-v-c8a446fe]{display:flex;align-items:center;justify-content:center;min-width:200px;max-width:400px;padding:12px 24px;background-color:#000c;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border-radius:8px;color:#fff;pointer-events:auto;box-shadow:0 4px 12px #00000026;cursor:default;font-size:14px;line-height:1.5;text-align:center;word-break:break-word}.toast[data-v-c8a446fe]:hover{transform:translateY(-1px);box-shadow:0 6px 16px #0003}.toast .message[data-v-c8a446fe]{color:#fff}.toast-container[data-v-39f2ff69]{position:fixed;left:0;right:0;display:flex;justify-content:center;pointer-events:none;padding:20px}.toast-container.is-top[data-v-39f2ff69]{top:0;align-items:flex-start}.toast-container.is-bottom[data-v-39f2ff69]{bottom:0;align-items:flex-end}.toast-container.is-center[data-v-39f2ff69]{top:50%;transform:translateY(-50%);align-items:center}.toast-list[data-v-39f2ff69]{display:flex;flex-direction:column;align-items:center;gap:10px}.toast-list-enter-active[data-v-39f2ff69],.toast-list-leave-active[data-v-39f2ff69]{transition:all .3s ease}.toast-list-enter-from[data-v-39f2ff69],.toast-list-leave-to[data-v-39f2ff69]{opacity:0;transform:translateY(-20px)}
|
package/dist/vue2toast.es.js
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
const
|
|
1
|
+
import { defineComponent as T, createElementBlock as f, openBlock as d, normalizeStyle as x, normalizeClass as C, toDisplayString as O, ref as h, createVNode as $, TransitionGroup as H, withCtx as S, Fragment as k, renderList as z, createBlock as _, inject as w, render as j } from "vue";
|
|
2
|
+
const B = ["innerHTML"], E = {
|
|
3
3
|
key: 1,
|
|
4
4
|
class: "message"
|
|
5
|
-
},
|
|
5
|
+
}, L = /* @__PURE__ */ T({
|
|
6
6
|
__name: "Toast",
|
|
7
7
|
props: {
|
|
8
|
-
|
|
9
|
-
type: Number,
|
|
10
|
-
default: 9999
|
|
11
|
-
},
|
|
12
|
-
position: {
|
|
8
|
+
message: {
|
|
13
9
|
type: String,
|
|
14
|
-
|
|
15
|
-
// 'top' | 'bottom' | 'center'
|
|
10
|
+
required: !0
|
|
16
11
|
},
|
|
17
12
|
useHtml: {
|
|
18
13
|
type: Boolean,
|
|
@@ -25,110 +20,147 @@ const w = ["innerHTML"], B = {
|
|
|
25
20
|
customStyle: {
|
|
26
21
|
type: Object,
|
|
27
22
|
default: () => ({})
|
|
23
|
+
},
|
|
24
|
+
type: {
|
|
25
|
+
type: String,
|
|
26
|
+
default: "info"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
emits: ["mouseenter", "mouseleave", "close"],
|
|
30
|
+
setup(o) {
|
|
31
|
+
return (i, n) => (d(), f("div", {
|
|
32
|
+
class: C(["toast", o.customClass]),
|
|
33
|
+
style: x(o.customStyle),
|
|
34
|
+
onMouseenter: n[0] || (n[0] = (s) => i.$emit("mouseenter")),
|
|
35
|
+
onMouseleave: n[1] || (n[1] = (s) => i.$emit("mouseleave"))
|
|
36
|
+
}, [
|
|
37
|
+
o.useHtml ? (d(), f("div", {
|
|
38
|
+
key: 0,
|
|
39
|
+
innerHTML: o.message,
|
|
40
|
+
class: "message-html"
|
|
41
|
+
}, null, 8, B)) : (d(), f("span", E, O(o.message), 1))
|
|
42
|
+
], 38));
|
|
43
|
+
}
|
|
44
|
+
}), b = (o, i) => {
|
|
45
|
+
const n = o.__vccOpts || o;
|
|
46
|
+
for (const [s, u] of i)
|
|
47
|
+
n[s] = u;
|
|
48
|
+
return n;
|
|
49
|
+
}, N = /* @__PURE__ */ b(L, [["__scopeId", "data-v-c8a446fe"]]), D = /* @__PURE__ */ T({
|
|
50
|
+
__name: "ToastContainer",
|
|
51
|
+
props: {
|
|
52
|
+
zIndex: {
|
|
53
|
+
type: Number,
|
|
54
|
+
default: 9999
|
|
55
|
+
},
|
|
56
|
+
position: {
|
|
57
|
+
type: String,
|
|
58
|
+
default: "top"
|
|
28
59
|
}
|
|
29
60
|
},
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
})
|
|
61
|
+
setup(o, { expose: i }) {
|
|
62
|
+
const n = o, s = h([]);
|
|
63
|
+
let u = 0;
|
|
64
|
+
const y = (t, r) => {
|
|
65
|
+
const e = `toast-${Date.now()}-${u++}`, l = {
|
|
66
|
+
id: e,
|
|
67
|
+
message: t,
|
|
68
|
+
options: r
|
|
69
|
+
};
|
|
70
|
+
return n.position.includes("bottom") ? s.value.unshift(l) : s.value.push(l), r.duration > 0 && c(l), {
|
|
71
|
+
close: () => a(e),
|
|
72
|
+
update: (m) => {
|
|
73
|
+
const g = s.value.find((M) => M.id === e);
|
|
74
|
+
g && (g.message = m);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}, a = (t) => {
|
|
78
|
+
const r = s.value.findIndex((e) => e.id === t);
|
|
79
|
+
if (r !== -1) {
|
|
80
|
+
const e = s.value[r];
|
|
81
|
+
e.timer && clearTimeout(e.timer), s.value.splice(r, 1), e.options.onClose && e.options.onClose();
|
|
82
|
+
}
|
|
83
|
+
}, c = (t) => {
|
|
84
|
+
t.timer = setTimeout(() => {
|
|
85
|
+
a(t.id);
|
|
86
|
+
}, t.options.duration);
|
|
87
|
+
}, v = (t) => {
|
|
88
|
+
t.timer && (clearTimeout(t.timer), t.timer = null);
|
|
89
|
+
}, p = (t) => {
|
|
90
|
+
t.options.duration > 0 && c(t);
|
|
91
|
+
};
|
|
92
|
+
return i({
|
|
93
|
+
add: y,
|
|
94
|
+
remove: a
|
|
95
|
+
}), (t, r) => (d(), f("div", {
|
|
96
|
+
class: C(["toast-container", [`is-${o.position}`]]),
|
|
97
|
+
style: x({ zIndex: o.zIndex })
|
|
98
|
+
}, [
|
|
99
|
+
$(H, {
|
|
100
|
+
name: "toast-list",
|
|
101
|
+
tag: "div",
|
|
102
|
+
class: "toast-list"
|
|
103
|
+
}, {
|
|
104
|
+
default: S(() => [
|
|
105
|
+
(d(!0), f(k, null, z(s.value, (e) => (d(), _(N, {
|
|
106
|
+
key: e.id,
|
|
107
|
+
message: e.message,
|
|
108
|
+
type: e.options.type,
|
|
109
|
+
"use-html": e.options.useHtml,
|
|
110
|
+
"custom-class": e.options.className,
|
|
111
|
+
"custom-style": e.options.style,
|
|
112
|
+
onClose: (l) => a(e.id),
|
|
113
|
+
onMouseenter: (l) => e.options.pauseOnHover && v(e),
|
|
114
|
+
onMouseleave: (l) => e.options.pauseOnHover && p(e)
|
|
115
|
+
}, null, 8, ["message", "type", "use-html", "custom-class", "custom-style", "onClose", "onMouseenter", "onMouseleave"]))), 128))
|
|
116
|
+
]),
|
|
117
|
+
_: 1
|
|
118
|
+
})
|
|
119
|
+
], 6));
|
|
59
120
|
}
|
|
60
|
-
}),
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
s[n] = a;
|
|
64
|
-
return s;
|
|
65
|
-
}, L = /* @__PURE__ */ V(E, [["__scopeId", "data-v-00a26138"]]), H = Symbol("Toast"), A = {
|
|
66
|
-
install(e, c = {}) {
|
|
67
|
-
let s = {
|
|
121
|
+
}), q = /* @__PURE__ */ b(D, [["__scopeId", "data-v-39f2ff69"]]), I = Symbol("Toast"), F = {
|
|
122
|
+
install(o, i = {}) {
|
|
123
|
+
let n = {
|
|
68
124
|
duration: 3e3,
|
|
69
125
|
pauseOnHover: !0,
|
|
70
126
|
zIndex: 9999,
|
|
71
|
-
position: "
|
|
127
|
+
position: "top",
|
|
128
|
+
// Changed default to top as it's more standard for stacks, but center is fine too. Let's stick to center to match old default if possible, but stack usually implies top/bottom. Let's use 'top' as default for modern feel.
|
|
72
129
|
useHtml: !1
|
|
73
130
|
};
|
|
74
|
-
Object.assign(
|
|
75
|
-
const
|
|
76
|
-
var
|
|
77
|
-
let
|
|
78
|
-
if (typeof
|
|
79
|
-
return {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
zIndex: t.zIndex,
|
|
97
|
-
position: t.position,
|
|
98
|
-
useHtml: t.useHtml,
|
|
99
|
-
customClass: t.className,
|
|
100
|
-
customStyle: t.style,
|
|
101
|
-
onMouseenter: () => {
|
|
102
|
-
t.pauseOnHover && v();
|
|
103
|
-
},
|
|
104
|
-
onMouseleave: () => {
|
|
105
|
-
t.pauseOnHover && p();
|
|
106
|
-
}
|
|
131
|
+
Object.assign(n, i);
|
|
132
|
+
const s = /* @__PURE__ */ new Map(), u = (y, a) => {
|
|
133
|
+
var e;
|
|
134
|
+
let c = { ...n }, v = null;
|
|
135
|
+
if (typeof a == "object" ? Object.assign(c, a) : typeof a == "function" && (v = a), typeof document > "u")
|
|
136
|
+
return { close: () => {
|
|
137
|
+
}, update: () => {
|
|
138
|
+
} };
|
|
139
|
+
const p = c.position || "top";
|
|
140
|
+
let t = s.get(p);
|
|
141
|
+
if (!t) {
|
|
142
|
+
const l = document.createElement("div");
|
|
143
|
+
document.body.appendChild(l);
|
|
144
|
+
const m = $(q, {
|
|
145
|
+
position: p,
|
|
146
|
+
zIndex: c.zIndex
|
|
147
|
+
});
|
|
148
|
+
m.appContext = o._context, j(m, l), t = (e = m.component) == null ? void 0 : e.exposed, s.set(p, t);
|
|
149
|
+
}
|
|
150
|
+
return t.add(y, {
|
|
151
|
+
...c,
|
|
152
|
+
onClose: v
|
|
107
153
|
});
|
|
108
|
-
d.appContext = e._context, C(d, o);
|
|
109
|
-
const i = (T = d.component) == null ? void 0 : T.exposed;
|
|
110
|
-
i && (i.message.value = a, i.visible.value = !0);
|
|
111
|
-
const y = () => {
|
|
112
|
-
i && (i.visible.value = !1), v(), setTimeout(() => {
|
|
113
|
-
o && o.parentNode && (C(null, o), o.parentNode.removeChild(o)), r && r();
|
|
114
|
-
}, 300);
|
|
115
|
-
};
|
|
116
|
-
return p(), {
|
|
117
|
-
close: y,
|
|
118
|
-
update: (O) => {
|
|
119
|
-
i && (i.message.value = O);
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
154
|
};
|
|
123
|
-
|
|
155
|
+
o.config.globalProperties.$toast = u, o.provide(I, u);
|
|
124
156
|
}
|
|
125
|
-
},
|
|
126
|
-
const
|
|
127
|
-
if (!
|
|
157
|
+
}, G = () => {
|
|
158
|
+
const o = w(I);
|
|
159
|
+
if (!o)
|
|
128
160
|
throw new Error("Toast plugin not installed");
|
|
129
|
-
return
|
|
161
|
+
return o;
|
|
130
162
|
};
|
|
131
163
|
export {
|
|
132
|
-
|
|
133
|
-
|
|
164
|
+
F as default,
|
|
165
|
+
G as useToast
|
|
134
166
|
};
|
package/dist/vue2toast.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(c,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(c=typeof globalThis<"u"?globalThis:c||self,e(c.vue2toast={},c.Vue))})(this,(function(c,e){"use strict";const x=["innerHTML"],b={key:1,class:"message"},B=e.defineComponent({__name:"Toast",props:{message:{type:String,required:!0},useHtml:{type:Boolean,default:!1},customClass:{type:[String,Object,Array],default:""},customStyle:{type:Object,default:()=>({})},type:{type:String,default:"info"}},emits:["mouseenter","mouseleave","close"],setup(n){return(r,a)=>(e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["toast",n.customClass]),style:e.normalizeStyle(n.customStyle),onMouseenter:a[0]||(a[0]=s=>r.$emit("mouseenter")),onMouseleave:a[1]||(a[1]=s=>r.$emit("mouseleave"))},[n.useHtml?(e.openBlock(),e.createElementBlock("div",{key:0,innerHTML:n.message,class:"message-html"},null,8,x)):(e.openBlock(),e.createElementBlock("span",b,e.toDisplayString(n.message),1))],38))}}),T=(n,r)=>{const a=n.__vccOpts||n;for(const[s,p]of r)a[s]=p;return a},M=T(B,[["__scopeId","data-v-c8a446fe"]]),$=T(e.defineComponent({__name:"ToastContainer",props:{zIndex:{type:Number,default:9999},position:{type:String,default:"top"}},setup(n,{expose:r}){const a=n,s=e.ref([]);let p=0;const g=(o,u)=>{const t=`toast-${Date.now()}-${p++}`,i={id:t,message:o,options:u};return a.position.includes("bottom")?s.value.unshift(i):s.value.push(i),u.duration>0&&d(i),{close:()=>l(t),update:f=>{const C=s.value.find(_=>_.id===t);C&&(C.message=f)}}},l=o=>{const u=s.value.findIndex(t=>t.id===o);if(u!==-1){const t=s.value[u];t.timer&&clearTimeout(t.timer),s.value.splice(u,1),t.options.onClose&&t.options.onClose()}},d=o=>{o.timer=setTimeout(()=>{l(o.id)},o.options.duration)},y=o=>{o.timer&&(clearTimeout(o.timer),o.timer=null)},m=o=>{o.options.duration>0&&d(o)};return r({add:g,remove:l}),(o,u)=>(e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["toast-container",[`is-${n.position}`]]),style:e.normalizeStyle({zIndex:n.zIndex})},[e.createVNode(e.TransitionGroup,{name:"toast-list",tag:"div",class:"toast-list"},{default:e.withCtx(()=>[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(s.value,t=>(e.openBlock(),e.createBlock(M,{key:t.id,message:t.message,type:t.options.type,"use-html":t.options.useHtml,"custom-class":t.options.className,"custom-style":t.options.style,onClose:i=>l(t.id),onMouseenter:i=>t.options.pauseOnHover&&y(t),onMouseleave:i=>t.options.pauseOnHover&&m(t)},null,8,["message","type","use-html","custom-class","custom-style","onClose","onMouseenter","onMouseleave"]))),128))]),_:1})],6))}}),[["__scopeId","data-v-39f2ff69"]]),k=Symbol("Toast"),h={install(n,r={}){let a={duration:3e3,pauseOnHover:!0,zIndex:9999,position:"top",useHtml:!1};Object.assign(a,r);const s=new Map,p=(g,l)=>{var t;let d={...a},y=null;if(typeof l=="object"?Object.assign(d,l):typeof l=="function"&&(y=l),typeof document>"u")return{close:()=>{},update:()=>{}};const m=d.position||"top";let o=s.get(m);if(!o){const i=document.createElement("div");document.body.appendChild(i);const f=e.createVNode($,{position:m,zIndex:d.zIndex});f.appContext=n._context,e.render(f,i),o=(t=f.component)==null?void 0:t.exposed,s.set(m,o)}return o.add(g,{...d,onClose:y})};n.config.globalProperties.$toast=p,n.provide(k,p)}},S=()=>{const n=e.inject(k);if(!n)throw new Error("Toast plugin not installed");return n};c.default=h,c.useToast=S,Object.defineProperties(c,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lanxuexing/vue2toast",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "A lightweight, high-performance Toast notification plugin for Vue 3, built with TypeScript.",
|
|
5
5
|
"main": "dist/vue2toast.umd.js",
|
|
6
6
|
"module": "dist/vue2toast.es.js",
|
|
@@ -72,6 +72,6 @@
|
|
|
72
72
|
},
|
|
73
73
|
"homepage": "https://github.com/lanxuexing/vue2toast#readme",
|
|
74
74
|
"engines": {
|
|
75
|
-
"node": ">=
|
|
75
|
+
"node": ">=18.0.0"
|
|
76
76
|
}
|
|
77
77
|
}
|