@lanxuexing/vue2toast 0.0.7 → 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 CHANGED
@@ -1,48 +1,170 @@
1
- ## vue2toast[![npm version](https://badge.fury.io/js/%40lanxuexing%2Fvue2toast.svg)](https://badge.fury.io/js/%40lanxuexing%2Fvue2toast)
1
+ <div align="center">
2
2
 
3
- ### Install
3
+ # vue2toast
4
4
 
5
- `npm i @lanxuexing/vue2toast --save`
5
+ A lightweight, high-performance Toast notification plugin for Vue 3, built with TypeScript and Vite.
6
6
 
7
+ [![NPM package](https://img.shields.io/npm/v/@lanxuexing/vue2toast.svg?style=flat-square)](https://npmjs.org/package/@lanxuexing/vue2toast)
8
+ [![GitHub Release Date](https://img.shields.io/github/release-date/lanxuexing/vue2toast.svg?style=flat-square)](https://github.com/lanxuexing/vue2toast/releases)
9
+ [![GitHub repo size](https://img.shields.io/github/repo-size/lanxuexing/vue2toast.svg?style=flat-square)](https://github.com/lanxuexing/vue2toast)
10
+ [![GitHub Stars](https://img.shields.io/github/stars/lanxuexing/vue2toast.svg?style=flat-square)](https://github.com/lanxuexing/vue2toast/stargazers)
11
+ [![NPM downloads](http://img.shields.io/npm/dm/@lanxuexing/vue2toast.svg?style=flat-square)](https://npmjs.org/package/@lanxuexing/vue2toast)
12
+ [![CI/CD](https://github.com/lanxuexing/vue2toast/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/lanxuexing/vue2toast/actions)
13
+ [![GitHub license](https://img.shields.io/github/license/lanxuexing/vue2toast.svg?style=flat-square)](https://github.com/lanxuexing/vue2toast/blob/main/LICENSE)
14
+ [![Vue 3](https://img.shields.io/badge/vue-3.x-42b883.svg?style=flat-square&logo=vue.js&logoColor=white)](https://vuejs.org)
15
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
16
+ [![Code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
17
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
7
18
 
8
- ### Settings
19
+ [中文版](./README.zh-CN.md) | English
9
20
 
10
- Name | Default | Type | Description
11
- --------------------|--------------------------|----------|---------------------------
12
- duration | 200 | Number | The duration of the toast
13
- callback | null | Number | The callback of the toast
21
+ ## 🔗 Live Demo
22
+ Check out the component in action: **[https://lanxuexing.github.io/vue2toast/](https://lanxuexing.github.io/vue2toast/)**
14
23
 
15
- ### Usage
24
+ </div>
16
25
 
17
- There are two different ways to manage a Toast.
26
+ ---
18
27
 
19
- ##### **Calling api**
28
+ ## Features
20
29
 
21
- ```javascript
22
- // import plugin
23
- import Vue2Toast from '@lanxuexing/vue2toast';
30
+ - 🚀 **Vue 3 Optimized**: Built with `createVNode` and `render` for minimal overhead.
31
+ - 📐 **TypeScript Ready**: Full type definitions included.
32
+ - 📚 **Stackable**: Multiple toasts stack automatically without overlapping.
33
+ - 📱 **Responsive**: Auto-resizing width to fit content comfortably.
34
+ - 🎨 **Modern Design**: Clean and accessible UI with smooth animations.
35
+ - 🔄 **Updateable Toasts**: Update message content programmatically (e.g., for progress bars).
36
+ - 📦 **Lightweight**: Zero dependencies, tiny bundle size.
37
+ - 🛠 **Customizable**: Control duration and styling easily.
38
+
39
+ ## 📦 Installation
40
+
41
+ ```bash
42
+ npm install @lanxuexing/vue2toast
43
+ ```
44
+
45
+ ## 🚀 Usage
46
+
47
+ ### 1. Register Plugin
48
+
49
+ Register the plugin in your main application file (`main.ts` or `main.js`).
24
50
 
25
- // register plugin on vue
26
- Vue.use(Vue2Toast)
51
+ ```typescript
52
+ import { createApp } from 'vue';
53
+ import App from './App.vue';
54
+ import Toast from '@lanxuexing/vue2toast';
55
+ import '@lanxuexing/vue2toast/style.css'; // Import styles
27
56
 
28
- // add a toast on screen
29
- this.$toast.show("Hello, Toast");
57
+ const app = createApp(App);
58
+ app.use(Toast); // Installs $toast globally and provides useToast
59
+ app.mount('#app');
60
+ ```
61
+
62
+ 3. **SSR Support**: Safe for Server-Side Rendering (Nuxt, Vite SSR).
63
+
64
+ ### 2. Usage in Components
65
+
66
+ You can access the toast instance via the `useToast` composable (Recommended) or the global `$toast` property.
30
67
 
31
- // you can manually hide the toast, or it will automatically disappear after a `duration` ms timeout.
32
- this.$toast.show("Hello, Toast", {
33
- duration: 500
34
- });
68
+ **Composition API (Recommended):**
35
69
 
36
- // you can add callback functions after toast display is complete
37
- this.$toast.show("Hello, Toast", function() {
38
- // do anything
39
- });
70
+ ```typescript
71
+ <script setup lang="ts">
72
+ import { useToast } from '@lanxuexing/vue2toast';
40
73
 
74
+ // Best practice: Typesafe & Clean
75
+ const toast = useToast();
76
+
77
+ const showToast = () => {
78
+ toast('Hello World');
79
+ };
80
+
81
+ const showLongToast = () => {
82
+ toast('This stays for 5 seconds', {
83
+ duration: 5000,
84
+ position: 'top',
85
+ style: { fontWeight: 'bold' }
86
+ });
87
+ };
88
+ </script>
41
89
  ```
42
90
 
43
- ### Run example:
91
+ **Options API:**
92
+
93
+ ```javascript
94
+ export default {
95
+ methods: {
96
+ showToast() {
97
+ // Fully typed via module augmentation
98
+ this.$toast('Hello World');
99
+ }
100
+ }
101
+ }
102
+ ```
44
103
 
104
+ ### 3. Updateable Toasts
105
+
106
+ You can update a toast message while it's still visible. This is perfect for loading states or countdowns.
107
+
108
+ ```typescript
109
+ const showDynamic = () => {
110
+ // Set duration to 0 to keep it open indefinitely (until closed manually)
111
+ const instance = toast('Loading... 0%', { duration: 0 });
112
+
113
+ let progress = 0;
114
+ const timer = setInterval(() => {
115
+ progress += 10;
116
+ instance.update(`Loading... ${progress}%`); // Update text
117
+
118
+ if (progress >= 100) {
119
+ clearInterval(timer);
120
+ instance.close(); // Close programmatically
121
+ toast('Done!');
122
+ }
123
+ }, 300);
124
+ };
45
125
  ```
46
- cd ./vue2toast
47
- npm install
126
+
127
+ ### 4. Manual Close (Persistent Toast)
128
+
129
+ Set `duration` to `0` to keep the toast open indefinitely until you call the `close()` method on the returned instance.
130
+
131
+ ```typescript
132
+ const showPersist = () => {
133
+ const instance = toast('I will not close automatically...', { duration: 0 });
134
+
135
+ // Close manually after some action
136
+ setTimeout(() => {
137
+ instance.close();
138
+ }, 5000);
139
+ };
48
140
  ```
141
+
142
+ ### 5. SSR & Best Practices
143
+
144
+ - **SSR Safe**: The plugin automatically detects the environment and returns a no-op instance on the server, preventing hydration mismatches or node errors.
145
+ - **Context Inheritance**: Toasts inherit the `appContext` of your application, meaning they can access global plugins (like `i18n`, `router`, `pinia`) and provided values.
146
+
147
+ ## ⚙️ Configuration
148
+
149
+ | Option | Type | Default | Description |
150
+ | :--- | :--- | :--- | :--- |
151
+ | `duration` | `number` | `3000` | Duration in ms. Set to `0` to persist indefinitely. |
152
+ | `pauseOnHover` | `boolean` | `true` | Pauses timer when hovering over the toast. |
153
+ | `position` | `'top' \| 'bottom' \| 'center'` | `'top'` | Vertical position of the toast. |
154
+ | `zIndex` | `number` | `9999` | Z-Index of the toast container. |
155
+ | `className` | `string` | `''` | Custom CSS class name for the toast content. |
156
+ | `style` | `CSSProperties` | `{}` | Custom inline styles (Vue CSS object). |
157
+ | `useHtml` | `boolean` | `false` | **Warning**: Enables HTML rendering (XSS Risk). |
158
+
159
+ ## 🛠 Development
160
+
161
+ This repository is powered by Vite.
162
+
163
+ - **Node.js**: >= 18.0.0 (Required for Vite 6+ / Tailwind 4)
164
+ - **Dev Server**: `npm run dev`
165
+ - **Build Lib**: `npm run build`
166
+ - **Build Demo**: `npm run build:demo`
167
+
168
+ ---
169
+
170
+ Built with ❤️ for the Vue Community.
@@ -0,0 +1,168 @@
1
+ <div align="center">
2
+
3
+ # vue2toast
4
+
5
+ 一个轻量、高性能的 Vue 3 Toast 提示插件,基于 TypeScript 和 Vite 构建。
6
+
7
+ [![NPM package](https://img.shields.io/npm/v/@lanxuexing/vue2toast.svg?style=flat-square)](https://npmjs.org/package/@lanxuexing/vue2toast)
8
+ [![GitHub Release Date](https://img.shields.io/github/release-date/lanxuexing/vue2toast.svg?style=flat-square)](https://github.com/lanxuexing/vue2toast/releases)
9
+ [![GitHub repo size](https://img.shields.io/github/repo-size/lanxuexing/vue2toast.svg?style=flat-square)](https://github.com/lanxuexing/vue2toast)
10
+ [![GitHub Stars](https://img.shields.io/github/stars/lanxuexing/vue2toast.svg?style=flat-square)](https://github.com/lanxuexing/vue2toast/stargazers)
11
+ [![NPM downloads](http://img.shields.io/npm/dm/@lanxuexing/vue2toast.svg?style=flat-square)](https://npmjs.org/package/@lanxuexing/vue2toast)
12
+ [![CI/CD](https://github.com/lanxuexing/vue2toast/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/lanxuexing/vue2toast/actions)
13
+ [![GitHub license](https://img.shields.io/github/license/lanxuexing/vue2toast.svg?style=flat-square)](https://github.com/lanxuexing/vue2toast/blob/main/LICENSE)
14
+ [![Vue 3](https://img.shields.io/badge/vue-3.x-42b883.svg?style=flat-square&logo=vue.js&logoColor=white)](https://vuejs.org)
15
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
16
+ [![Code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
17
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
18
+
19
+ [中文版](./README.zh-CN.md) | [English](./README.md)
20
+
21
+ ## 🔗 在线演示
22
+ 查看组件效果: **[https://lanxuexing.github.io/vue2toast/](https://lanxuexing.github.io/vue2toast/)**
23
+
24
+ </div>
25
+
26
+ ---
27
+
28
+ ## ✨ 特性
29
+
30
+ - 🚀 **Vue 3 优化**: 使用 `createVNode` 和 `render` 函数构建,性能极致。
31
+ - 📐 **TypeScript 支持**: 内置完整的类型定义 (d.ts)。
32
+ - 📚 **堆叠显示**: 支持多个 Toast 自动垂直堆叠,不重叠。
33
+ - 📱 **响应式**: 宽度随内容自动调整,适应长文本。
34
+ - 🎨 **现代设计**: 简洁美观的 UI,流畅的动画。
35
+ - 🔄 **支持更新**: 可编程更新 Toast 内容 (适用于进度条、倒计时等)。
36
+ - 📦 **轻量级**: 零依赖,体积极小。
37
+ - 🛠 **易定制**: 轻松控制时长和样式。
38
+
39
+ ## 📦 安装
40
+
41
+ ```bash
42
+ npm install @lanxuexing/vue2toast
43
+ ```
44
+
45
+ ## 🚀 使用方法
46
+
47
+ ### 1. 注册插件
48
+
49
+ 在你的主入口文件 (`main.ts` 或 `main.js`) 中注册插件。
50
+
51
+ ```typescript
52
+ import { createApp } from 'vue';
53
+ import App from './App.vue';
54
+ import Toast from '@lanxuexing/vue2toast';
55
+ import '@lanxuexing/vue2toast/style.css'; // 记得引入样式文件
56
+
57
+ const app = createApp(App);
58
+ app.use(Toast); // 全局注册 $toast 并提供 useToast
59
+ app.mount('#app');
60
+ ```
61
+
62
+ ### 2. 在组件中使用
63
+
64
+ 推荐使用 `useToast` 组合式函数,也可以继续使用全局 `$toast`。
65
+
66
+ **Composition API (推荐):**
67
+
68
+ ```typescript
69
+ <script setup lang="ts">
70
+ import { useToast } from '@lanxuexing/vue2toast';
71
+
72
+ // 最佳实践:类型安全且简洁
73
+ const toast = useToast();
74
+
75
+ const showToast = () => {
76
+ toast('Hello World');
77
+ };
78
+
79
+ const showLongToast = () => {
80
+ toast('这条消息会显示 5 秒', {
81
+ duration: 5000,
82
+ position: 'top',
83
+ style: { fontWeight: 'bold' }
84
+ });
85
+ };
86
+ </script>
87
+ ```
88
+
89
+ **Options API:**
90
+
91
+ ```javascript
92
+ export default {
93
+ methods: {
94
+ showToast() {
95
+ // 这里的 this.$toast 现在有完善的类型提示
96
+ this.$toast('Hello World');
97
+ }
98
+ }
99
+ }
100
+ ```
101
+
102
+ ### 3. 可更新的 Toast
103
+
104
+ 你可以在 Toast 显示期间更新其内容,这非常适合加载状态或倒计时场景。
105
+
106
+ ```typescript
107
+ const showDynamic = () => {
108
+ // 设置 duration 为 0,使其一直显示,直到手动关闭
109
+ const instance = toast('加载中... 0%', { duration: 0 });
110
+
111
+ let progress = 0;
112
+ const timer = setInterval(() => {
113
+ progress += 10;
114
+ instance.update(`加载中... ${progress}%`); // 更新内容
115
+
116
+ if (progress >= 100) {
117
+ clearInterval(timer);
118
+ instance.close(); // 手动关闭
119
+ toast('加载完成!');
120
+ }
121
+ }, 300);
122
+ };
123
+ ```
124
+
125
+ ### 4. 手动关闭 (持久化 Toast)
126
+
127
+ 将 `duration` 设置为 `0`,Toast 将不会自动消失,直到你调用返回实例的 `close()` 方法。
128
+
129
+ ```typescript
130
+ const showPersist = () => {
131
+ const instance = toast('我不会自动消失...', { duration: 0 });
132
+
133
+ // 模拟异步操作后关闭
134
+ setTimeout(() => {
135
+ instance.close();
136
+ }, 5000);
137
+ };
138
+ ```
139
+
140
+ ### 5. SSR 与最佳实践
141
+
142
+ - **SSR 安全**: 插件会自动检测环境,在服务端返回空实例,避免水合不匹配或 Node 报错。
143
+ - **上下文继承**: Toast 会自动继承应用的 `appContext`,这意味着你可以在 Toast 组件内部正常访问全局插件 (如 `i18n`, `router`, `pinia`)。
144
+
145
+ ## ⚙️ 配置选项
146
+
147
+ | 选项名 | 类型 | 默认值 | 描述 |
148
+ | :--- | :--- | :--- | :--- |
149
+ | `duration` | `number` | `3000` | 显示时长 (ms)。设置为 `0` 则永久显示。 |
150
+ | `pauseOnHover` | `boolean` | `true` | 鼠标悬停时是否暂停倒计时。 |
151
+ | `position` | `'top' \| 'bottom' \| 'center'` | `'top'` | Toast 的垂直显示位置。 |
152
+ | `zIndex` | `number` | `9999` | Toast 容器的层级 (z-index)。 |
153
+ | `className` | `string` | `''` | 自定义 CSS 类名。 |
154
+ | `style` | `CSSProperties` | `{}` | 自定义内联样式对象 (Vue CSS)。 |
155
+ | `useHtml` | `boolean` | `false` | **警告**: 是否解析 HTML (注意 XSS 风险)。 |
156
+
157
+ ## 🛠 本地开发
158
+
159
+ 本项目使用 Vite 构建。
160
+
161
+ - **Node.js**: >= 18.0.0 (Vite 6+ / Tailwind 4 需要)
162
+ - **启动开发服务器**: `npm run dev`
163
+ - **构建库**: `npm run build`
164
+ - **构建 Demo**: `npm run build:demo`
165
+
166
+ ---
167
+
168
+ Built with ❤️ for the Vue Community.
@@ -0,0 +1,64 @@
1
+ import { App } from 'vue';
2
+ import { CSSProperties } from 'vue';
3
+
4
+ export declare type ShowToast = (message: string, options?: ToastOptions | (() => void)) => ToastInstance;
5
+
6
+ declare const Toast: {
7
+ install(app: App, options?: ToastOptions): void;
8
+ };
9
+ export default Toast;
10
+
11
+ export declare interface ToastInstance {
12
+ close: () => void;
13
+ update: (message: string) => void;
14
+ }
15
+
16
+ export declare interface ToastOptions {
17
+ /**
18
+ * Duration in milliseconds before the toast automatically closes.
19
+ * Set to 0 to disable auto-close.
20
+ * @default 3000
21
+ */
22
+ duration?: number;
23
+ /**
24
+ * Whether to pause the auto-close timer when mouse hovers over the toast.
25
+ * @default true
26
+ */
27
+ pauseOnHover?: boolean;
28
+ /**
29
+ * Custom CSS class name(s) to apply to the toast element.
30
+ */
31
+ className?: string | object | string[];
32
+ /**
33
+ * Custom inline styles to apply to the toast element.
34
+ */
35
+ style?: CSSProperties;
36
+ /**
37
+ * Z-index of the toast container.
38
+ * @default 9999
39
+ */
40
+ zIndex?: number;
41
+ /**
42
+ * Position of the toast on the screen.
43
+ * @default 'center'
44
+ */
45
+ position?: 'top' | 'bottom' | 'center';
46
+ /**
47
+ * Whether to interpret the message property as HTML content.
48
+ * ⚠️ Be careful with XSS vulnerabilities when enabling this.
49
+ * @default false
50
+ */
51
+ useHtml?: boolean;
52
+ [key: string]: any;
53
+ }
54
+
55
+ export declare const useToast: () => ShowToast;
56
+
57
+ export { }
58
+
59
+
60
+ declare module '@vue/runtime-core' {
61
+ interface ComponentCustomProperties {
62
+ $toast: ShowToast;
63
+ }
64
+ }
@@ -0,0 +1 @@
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)}
@@ -0,0 +1,166 @@
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
+ key: 1,
4
+ class: "message"
5
+ }, L = /* @__PURE__ */ T({
6
+ __name: "Toast",
7
+ props: {
8
+ message: {
9
+ type: String,
10
+ required: !0
11
+ },
12
+ useHtml: {
13
+ type: Boolean,
14
+ default: !1
15
+ },
16
+ customClass: {
17
+ type: [String, Object, Array],
18
+ default: ""
19
+ },
20
+ customStyle: {
21
+ type: Object,
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"
59
+ }
60
+ },
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));
120
+ }
121
+ }), q = /* @__PURE__ */ b(D, [["__scopeId", "data-v-39f2ff69"]]), I = Symbol("Toast"), F = {
122
+ install(o, i = {}) {
123
+ let n = {
124
+ duration: 3e3,
125
+ pauseOnHover: !0,
126
+ zIndex: 9999,
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.
129
+ useHtml: !1
130
+ };
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
153
+ });
154
+ };
155
+ o.config.globalProperties.$toast = u, o.provide(I, u);
156
+ }
157
+ }, G = () => {
158
+ const o = w(I);
159
+ if (!o)
160
+ throw new Error("Toast plugin not installed");
161
+ return o;
162
+ };
163
+ export {
164
+ F as default,
165
+ G as useToast
166
+ };
@@ -0,0 +1 @@
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"}})}));