@rosadorito/vue-toast 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,311 @@
1
+ # Vue Toast
2
+
3
+ A lightweight, customizable toast notification library for Vue 3.
4
+
5
+ ## Features
6
+
7
+ - ๐ŸŽจ **Multiple toast types**: Success, Error, Warning, Info, and Default
8
+ - ๐Ÿ“ **Flexible positioning**: 6 different positions (top/bottom-left/center/right)
9
+ - โฑ๏ธ **Auto-dismiss**: Configurable duration with auto-removal
10
+ - ๐ŸŽฏ **Programmatic API**: Use via composable or global plugin
11
+ - โ™ฟ **Accessible**: ARIA labels and proper semantic markup
12
+ - ๐Ÿ“ฑ **Responsive**: Works on mobile and desktop
13
+ - ๐ŸŽจ **Customizable**: Style with CSS custom properties
14
+ - ๐Ÿงช **TypeScript**: Full TypeScript support
15
+ - ๐ŸŒณ **Tree-shakable**: Only import what you need
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install vue-toast
21
+ # or
22
+ yarn add vue-toast
23
+ # or
24
+ pnpm add vue-toast
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ### As a Plugin (Global)
30
+
31
+ ```javascript
32
+ import { createApp } from 'vue'
33
+ import App from './App.vue'
34
+ import VueToast from 'vue-toast'
35
+
36
+ const app = createApp(App)
37
+ app.use(VueToast)
38
+ app.mount('#app')
39
+ ```
40
+
41
+ Now you can use it anywhere in your components:
42
+
43
+ ```vue
44
+ <template>
45
+ <button @click="showToast">Show Toast</button>
46
+ </template>
47
+
48
+ <script setup>
49
+ const showToast = () => {
50
+ // Using global $toast
51
+ this.$toast.success('Operation completed successfully!')
52
+
53
+ // Or with options
54
+ this.$toast.error('Something went wrong!', {
55
+ duration: 3000,
56
+ position: 'top-center',
57
+ })
58
+ }
59
+ </script>
60
+ ```
61
+
62
+ ### Using Composables (Recommended)
63
+
64
+ ```vue
65
+ <template>
66
+ <div>
67
+ <button @click="showSuccess">Success</button>
68
+ <button @click="showError">Error</button>
69
+
70
+ <!-- Render toasts -->
71
+ <div v-for="(toasts, position) in groupedToasts" :key="position">
72
+ <VueToast
73
+ v-for="(toast, index) in toasts"
74
+ :key="toast.id"
75
+ :toast="toast"
76
+ :index="index"
77
+ :total="toasts.length"
78
+ @close="removeToast(toast.id)"
79
+ />
80
+ </div>
81
+ </div>
82
+ </template>
83
+
84
+ <script setup>
85
+ import { VueToast, useToast } from 'vue-toast'
86
+
87
+ const {
88
+ success,
89
+ error,
90
+ warning,
91
+ info,
92
+ addToast,
93
+ removeToast,
94
+ groupedToasts
95
+ } = useToast()
96
+
97
+ const showSuccess = () => {
98
+ success('Operation completed!', {
99
+ duration: 3000,
100
+ position: 'bottom-right',
101
+ })
102
+ }
103
+
104
+ const showError = () => {
105
+ error('Something went wrong!', {
106
+ duration: 5000,
107
+ dismissible: false,
108
+ })
109
+ }
110
+ </script>
111
+ ```
112
+
113
+ ## API Reference
114
+
115
+ ### Toast Options
116
+
117
+ | Option | Type | Default | Description |
118
+ |--------|------|---------|-------------|
119
+ | `message` | `string` | **Required** | The message to display |
120
+ | `type` | `'success' \| 'error' \| 'warning' \| 'info' \| 'default'` | `'default'` | Toast type |
121
+ | `duration` | `number` | `5000` | Duration in milliseconds (0 for no auto-dismiss) |
122
+ | `position` | `ToastPosition` | `'top-right'` | Position on screen |
123
+ | `dismissible` | `boolean` | `true` | Whether to show close button |
124
+ | `id` | `string` | Auto-generated | Unique identifier |
125
+ | `onClose` | `() => void` | - | Callback when toast closes |
126
+ | `onClick` | `() => void` | - | Callback when toast is clicked |
127
+
128
+ ### Toast Positions
129
+
130
+ ```typescript
131
+ type ToastPosition =
132
+ | 'top-left'
133
+ | 'top-center'
134
+ | 'top-right'
135
+ | 'bottom-left'
136
+ | 'bottom-center'
137
+ | 'bottom-right'
138
+ ```
139
+
140
+ ### useToast() Composables
141
+
142
+ ```typescript
143
+ const {
144
+ // State
145
+ toasts, // Array of all toasts
146
+ groupedToasts, // Toasts grouped by position
147
+
148
+ // Methods
149
+ addToast, // Add a toast with custom options
150
+ removeToast, // Remove a toast by id
151
+ clearToasts, // Remove all toasts
152
+
153
+ // Convenience methods
154
+ success, // Add success toast
155
+ error, // Add error toast
156
+ warning, // Add warning toast
157
+ info, // Add info toast
158
+ } = useToast(defaultPosition?: ToastPosition)
159
+ ```
160
+
161
+ ### Global Plugin API
162
+
163
+ When installed as a plugin, `$toast` is available on Vue instances:
164
+
165
+ ```typescript
166
+ // In Options API
167
+ this.$toast.success('Message')
168
+
169
+ // In Composition API setup()
170
+ import { getCurrentInstance } from 'vue'
171
+
172
+ const instance = getCurrentInstance()
173
+ instance?.proxy?.$toast.success('Message')
174
+ ```
175
+
176
+ Methods available on `$toast`:
177
+ - `success(message, options?)`
178
+ - `error(message, options?)`
179
+ - `warning(message, options?)`
180
+ - `info(message, options?)`
181
+ - `add(options)`
182
+
183
+ ## Styling
184
+
185
+ ### CSS Custom Properties
186
+
187
+ You can customize the appearance using CSS custom properties:
188
+
189
+ ```css
190
+ :root {
191
+ --vue-toast-border-radius: 6px;
192
+ --vue-toast-padding: 12px 16px;
193
+ --vue-toast-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
194
+ --vue-toast-font-size: 14px;
195
+ --vue-toast-line-height: 1.4;
196
+ --vue-toast-box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
197
+ }
198
+
199
+ /* Type-specific colors */
200
+ .vue-toast--success {
201
+ --vue-toast-border-color: #10b981;
202
+ --vue-toast-bg-color: #f0fdf4;
203
+ --vue-toast-text-color: #065f46;
204
+ }
205
+
206
+ .vue-toast--error {
207
+ --vue-toast-border-color: #ef4444;
208
+ --vue-toast-bg-color: #fef2f2;
209
+ --vue-toast-text-color: #991b1b;
210
+ }
211
+ ```
212
+
213
+ ### Overriding Styles
214
+
215
+ You can override the default styles by targeting the component classes:
216
+
217
+ ```css
218
+ .vue-toast {
219
+ /* Your custom styles */
220
+ }
221
+
222
+ .vue-toast__close {
223
+ /* Custom close button styles */
224
+ }
225
+ ```
226
+
227
+ ## TypeScript
228
+
229
+ Full TypeScript support is included. Import types as needed:
230
+
231
+ ```typescript
232
+ import type { ToastOptions, ToastPosition, ToastType } from 'vue-toast'
233
+ ```
234
+
235
+ ## Examples
236
+
237
+ ### Multiple Toasts with Different Positions
238
+
239
+ ```vue
240
+ <template>
241
+ <div>
242
+ <button @click="addTopLeft">Top Left</button>
243
+ <button @click="addBottomCenter">Bottom Center</button>
244
+
245
+ <div v-for="(toasts, position) in groupedToasts" :key="position">
246
+ <VueToast
247
+ v-for="(toast, index) in toasts"
248
+ :key="toast.id"
249
+ :toast="toast"
250
+ :index="index"
251
+ :total="toasts.length"
252
+ @close="removeToast(toast.id)"
253
+ />
254
+ </div>
255
+ </div>
256
+ </template>
257
+
258
+ <script setup>
259
+ import { useToast } from 'vue-toast'
260
+
261
+ const { addToast, removeToast, groupedToasts } = useToast()
262
+
263
+ const addTopLeft = () => {
264
+ addToast({
265
+ message: 'Top left notification',
266
+ type: 'info',
267
+ position: 'top-left',
268
+ duration: 3000,
269
+ })
270
+ }
271
+
272
+ const addBottomCenter = () => {
273
+ addToast({
274
+ message: 'Bottom center warning',
275
+ type: 'warning',
276
+ position: 'bottom-center',
277
+ duration: 5000,
278
+ })
279
+ }
280
+ </script>
281
+ ```
282
+
283
+ ### Toast with Callbacks
284
+
285
+ ```javascript
286
+ const showToastWithCallback = () => {
287
+ addToast({
288
+ message: 'Click me!',
289
+ type: 'success',
290
+ onClick: () => {
291
+ console.log('Toast clicked!')
292
+ // Navigate or perform action
293
+ },
294
+ onClose: () => {
295
+ console.log('Toast closed')
296
+ // Cleanup or tracking
297
+ },
298
+ })
299
+ }
300
+ ```
301
+
302
+ ## Browser Support
303
+
304
+ - Chrome 60+
305
+ - Firefox 60+
306
+ - Safari 12+
307
+ - Edge 79+
308
+
309
+ ## License
310
+
311
+ MIT
@@ -0,0 +1,10 @@
1
+ import { ToastComponentProps } from '../../types';
2
+ declare const _default: import('vue').DefineComponent<ToastComponentProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
3
+ close: (id?: string | undefined) => any;
4
+ click: () => any;
5
+ }, string, import('vue').PublicProps, Readonly<ToastComponentProps> & Readonly<{
6
+ onClose?: ((id?: string | undefined) => any) | undefined;
7
+ onClick?: (() => any) | undefined;
8
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
9
+ export default _default;
10
+ //# sourceMappingURL=Toast.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Toast.vue.d.ts","sourceRoot":"","sources":["../../../src/components/Toast/Toast.vue"],"names":[],"mappings":"AAyCA;AAgQA,OAAO,KAAK,EAAE,mBAAmB,EAAa,MAAM,SAAS,CAAA;;;;;;;;AAyJ7D,wBAQG"}
@@ -0,0 +1,4 @@
1
+ import { default as Toast } from './Toast.vue';
2
+ export { Toast };
3
+ export default Toast;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Toast/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,aAAa,CAAA;AAE/B,OAAO,EAAE,KAAK,EAAE,CAAA;AAChB,eAAe,KAAK,CAAA"}
@@ -0,0 +1,20 @@
1
+ import { Ref } from 'vue';
2
+ import { ToastOptions, ToastPosition } from '../types';
3
+ interface ToastInstance extends ToastOptions {
4
+ id: string;
5
+ timer?: ReturnType<typeof setTimeout>;
6
+ }
7
+ export declare function useToast(defaultPosition?: ToastPosition): {
8
+ toasts: Ref<ToastInstance[], ToastInstance[]>;
9
+ groupedToasts: import('vue').ComputedRef<Record<string, ToastInstance[]>>;
10
+ addToast: (options: ToastOptions) => string;
11
+ removeToast: (id: string) => void;
12
+ clearToasts: () => void;
13
+ success: (message: string, options?: Omit<ToastOptions, "message" | "type">) => string;
14
+ error: (message: string, options?: Omit<ToastOptions, "message" | "type">) => string;
15
+ warning: (message: string, options?: Omit<ToastOptions, "message" | "type">) => string;
16
+ info: (message: string, options?: Omit<ToastOptions, "message" | "type">) => string;
17
+ };
18
+ export type UseToastReturn = ReturnType<typeof useToast>;
19
+ export {};
20
+ //# sourceMappingURL=useToast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useToast.d.ts","sourceRoot":"","sources":["../../src/composables/useToast.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,KAAK,GAAG,EAAE,MAAM,KAAK,CAAA;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE1D,UAAU,aAAc,SAAQ,YAAY;IAC1C,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA;CACtC;AAED,wBAAgB,QAAQ,CAAC,eAAe,GAAE,aAA2B;;;wBAKxC,YAAY;sBAqBd,MAAM;;uBA6BL,MAAM,YAAW,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,MAAM,CAAC;qBAQzD,MAAM,YAAW,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,MAAM,CAAC;uBAQrD,MAAM,YAAW,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,MAAM,CAAC;oBAQ1D,MAAM,YAAW,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,MAAM,CAAC;EAqC/E;AAED,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAA"}
@@ -0,0 +1,13 @@
1
+ import { App } from 'vue';
2
+ import { default as Toast } from './components/Toast';
3
+ import { useToast } from './composables/useToast';
4
+ import { ToastOptions, ToastPosition, ToastType } from './types';
5
+ export { Toast, useToast };
6
+ export type { ToastOptions, ToastPosition, ToastType };
7
+ declare const VueToast: {
8
+ install: (app: App, pluginOptions?: {
9
+ defaultPosition?: ToastPosition;
10
+ }) => void;
11
+ };
12
+ export default VueToast;
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,KAAK,CAAA;AAC9B,OAAO,KAAK,MAAM,oBAAoB,CAAA;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAErE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAA;AAC1B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,CAAA;AAEtD,QAAA,MAAM,QAAQ;mBACG,GAAG,kBAAkB;QAAE,eAAe,CAAC,EAAE,aAAa,CAAA;KAAE;CA0BxE,CAAA;AAED,eAAe,QAAQ,CAAA"}
@@ -0,0 +1,18 @@
1
+ export type ToastType = 'success' | 'error' | 'warning' | 'info' | 'default';
2
+ export type ToastPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
3
+ export interface ToastOptions {
4
+ id?: string;
5
+ type?: ToastType;
6
+ message: string;
7
+ duration?: number;
8
+ position?: ToastPosition;
9
+ dismissible?: boolean;
10
+ onClose?: () => void;
11
+ onClick?: () => void;
12
+ }
13
+ export interface ToastComponentProps {
14
+ toast: ToastOptions;
15
+ index: number;
16
+ total: number;
17
+ }
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAA;AAE5E,MAAM,MAAM,aAAa,GACrB,UAAU,GACV,YAAY,GACZ,WAAW,GACX,aAAa,GACb,eAAe,GACf,cAAc,CAAA;AAElB,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,aAAa,CAAA;IACxB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,YAAY,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd"}
@@ -0,0 +1 @@
1
+ .vue-toast[data-v-38db861e]{position:relative;display:flex;align-items:center;justify-content:space-between;min-width:300px;max-width:500px;padding:12px 16px;margin-bottom:8px;border-radius:6px;box-shadow:0 4px 12px #00000026;background-color:#fff;color:#333;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:14px;line-height:1.4;animation:toast-slide-in-38db861e .3s ease-out;transition:transform .2s ease,opacity .2s ease;z-index:calc(1000 + var(--toast-index));cursor:pointer}.vue-toast[data-v-38db861e]:hover{transform:translateY(-1px);box-shadow:0 6px 16px #0003}.vue-toast--success[data-v-38db861e]{border-left:4px solid #10b981;background-color:#f0fdf4;color:#065f46}.vue-toast--error[data-v-38db861e]{border-left:4px solid #ef4444;background-color:#fef2f2;color:#991b1b}.vue-toast--warning[data-v-38db861e]{border-left:4px solid #f59e0b;background-color:#fffbeb;color:#92400e}.vue-toast--info[data-v-38db861e]{border-left:4px solid #3b82f6;background-color:#eff6ff;color:#1e40af}.vue-toast--default[data-v-38db861e]{border-left:4px solid #6b7280;background-color:#f9fafb;color:#374151}.vue-toast__content[data-v-38db861e]{flex:1;margin-right:8px}.vue-toast__message[data-v-38db861e]{word-break:break-word}.vue-toast__close[data-v-38db861e]{flex-shrink:0;background:none;border:none;padding:4px;margin-left:8px;cursor:pointer;color:inherit;opacity:.7;border-radius:4px;transition:opacity .2s ease,background-color .2s ease}.vue-toast__close[data-v-38db861e]:hover{opacity:1;background-color:#0000001a}.vue-toast__close[data-v-38db861e]:focus{outline:2px solid currentColor;outline-offset:2px}.vue-toast__close-icon[data-v-38db861e]{display:block}.vue-toast--topleft[data-v-38db861e]{position:fixed;top:20px;left:20px}.vue-toast--topcenter[data-v-38db861e]{position:fixed;top:20px;left:50%;transform:translate(-50%)}.vue-toast--topright[data-v-38db861e]{position:fixed;top:20px;right:20px}.vue-toast--bottomleft[data-v-38db861e]{position:fixed;bottom:20px;left:20px}.vue-toast--bottomcenter[data-v-38db861e]{position:fixed;bottom:20px;left:50%;transform:translate(-50%)}.vue-toast--bottomright[data-v-38db861e]{position:fixed;bottom:20px;right:20px}@keyframes toast-slide-in-38db861e{0%{opacity:0;transform:translateY(-20px)}to{opacity:1;transform:translateY(0)}}@media(max-width:640px){.vue-toast[data-v-38db861e]{min-width:calc(100vw - 40px);max-width:calc(100vw - 40px);margin-left:20px;margin-right:20px}.vue-toast--topleft[data-v-38db861e],.vue-toast--topcenter[data-v-38db861e],.vue-toast--topright[data-v-38db861e]{top:10px}.vue-toast--bottomleft[data-v-38db861e],.vue-toast--bottomcenter[data-v-38db861e],.vue-toast--bottomright[data-v-38db861e]{bottom:10px}}
@@ -0,0 +1,233 @@
1
+ import { defineComponent, computed, openBlock, createElementBlock, normalizeStyle, normalizeClass, createElementVNode, toDisplayString, withModifiers, createCommentVNode, ref, onUnmounted } from "vue";
2
+ const _hoisted_1 = ["aria-label"];
3
+ const _hoisted_2 = { class: "vue-toast__content" };
4
+ const _hoisted_3 = { class: "vue-toast__message" };
5
+ const _sfc_main = /* @__PURE__ */ defineComponent({
6
+ __name: "Toast",
7
+ props: {
8
+ toast: {},
9
+ index: {},
10
+ total: {}
11
+ },
12
+ emits: ["close", "click"],
13
+ setup(__props, { emit: __emit }) {
14
+ const props = __props;
15
+ const emit = __emit;
16
+ const positionClass = computed(() => {
17
+ const position = props.toast.position || "top-right";
18
+ return position.replace("-", "");
19
+ });
20
+ const toastStyle = computed(() => ({
21
+ "--toast-index": props.index,
22
+ "--toast-total": props.total
23
+ }));
24
+ const ariaLabel = computed(() => {
25
+ const type = props.toast.type || "default";
26
+ const typeLabels = {
27
+ success: "Success notification",
28
+ error: "Error notification",
29
+ warning: "Warning notification",
30
+ info: "Information notification",
31
+ default: "Notification"
32
+ };
33
+ return typeLabels[type];
34
+ });
35
+ const handleClose = () => {
36
+ emit("close", props.toast.id);
37
+ };
38
+ const handleClick = () => {
39
+ if (props.toast.onClick) {
40
+ props.toast.onClick();
41
+ }
42
+ emit("click");
43
+ };
44
+ return (_ctx, _cache) => {
45
+ return openBlock(), createElementBlock("div", {
46
+ class: normalizeClass([
47
+ "vue-toast",
48
+ `vue-toast--${__props.toast.type || "default"}`,
49
+ `vue-toast--${positionClass.value}`,
50
+ { "vue-toast--dismissible": __props.toast.dismissible }
51
+ ]),
52
+ style: normalizeStyle(toastStyle.value),
53
+ onClick: handleClick,
54
+ role: "alert",
55
+ "aria-live": "polite",
56
+ "aria-label": ariaLabel.value
57
+ }, [
58
+ createElementVNode("div", _hoisted_2, [
59
+ createElementVNode("span", _hoisted_3, toDisplayString(__props.toast.message), 1)
60
+ ]),
61
+ __props.toast.dismissible ? (openBlock(), createElementBlock("button", {
62
+ key: 0,
63
+ class: "vue-toast__close",
64
+ onClick: withModifiers(handleClose, ["stop"]),
65
+ "aria-label": "Close notification"
66
+ }, [..._cache[0] || (_cache[0] = [
67
+ createElementVNode("svg", {
68
+ class: "vue-toast__close-icon",
69
+ viewBox: "0 0 24 24",
70
+ width: "16",
71
+ height: "16",
72
+ fill: "none",
73
+ stroke: "currentColor",
74
+ "stroke-width": "2",
75
+ "stroke-linecap": "round",
76
+ "stroke-linejoin": "round"
77
+ }, [
78
+ createElementVNode("line", {
79
+ x1: "18",
80
+ y1: "6",
81
+ x2: "6",
82
+ y2: "18"
83
+ }),
84
+ createElementVNode("line", {
85
+ x1: "6",
86
+ y1: "6",
87
+ x2: "18",
88
+ y2: "18"
89
+ })
90
+ ], -1)
91
+ ])])) : createCommentVNode("", true)
92
+ ], 14, _hoisted_1);
93
+ };
94
+ }
95
+ });
96
+ const _export_sfc = (sfc, props) => {
97
+ const target = sfc.__vccOpts || sfc;
98
+ for (const [key, val] of props) {
99
+ target[key] = val;
100
+ }
101
+ return target;
102
+ };
103
+ const Toast = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-38db861e"]]);
104
+ function useToast(defaultPosition = "top-right") {
105
+ const toasts = ref([]);
106
+ const generateId = () => `toast-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
107
+ const addToast = (options) => {
108
+ const id = options.id || generateId();
109
+ const toast = {
110
+ ...options,
111
+ id,
112
+ position: options.position || defaultPosition,
113
+ duration: options.duration ?? 5e3,
114
+ dismissible: options.dismissible ?? true
115
+ };
116
+ toasts.value.push(toast);
117
+ if (toast.duration && toast.duration > 0) {
118
+ toast.timer = setTimeout(() => {
119
+ removeToast(id);
120
+ }, toast.duration);
121
+ }
122
+ return id;
123
+ };
124
+ const removeToast = (id) => {
125
+ const index = toasts.value.findIndex((t) => t.id === id);
126
+ if (index === -1) return;
127
+ const toast = toasts.value[index];
128
+ if (toast.timer) {
129
+ clearTimeout(toast.timer);
130
+ }
131
+ if (toast.onClose) {
132
+ toast.onClose();
133
+ }
134
+ toasts.value.splice(index, 1);
135
+ };
136
+ const clearToasts = () => {
137
+ toasts.value.forEach((toast) => {
138
+ if (toast.timer) {
139
+ clearTimeout(toast.timer);
140
+ }
141
+ if (toast.onClose) {
142
+ toast.onClose();
143
+ }
144
+ });
145
+ toasts.value = [];
146
+ };
147
+ const success = (message, options = {}) => {
148
+ return addToast({
149
+ ...options,
150
+ message,
151
+ type: "success"
152
+ });
153
+ };
154
+ const error = (message, options = {}) => {
155
+ return addToast({
156
+ ...options,
157
+ message,
158
+ type: "error"
159
+ });
160
+ };
161
+ const warning = (message, options = {}) => {
162
+ return addToast({
163
+ ...options,
164
+ message,
165
+ type: "warning"
166
+ });
167
+ };
168
+ const info = (message, options = {}) => {
169
+ return addToast({
170
+ ...options,
171
+ message,
172
+ type: "info"
173
+ });
174
+ };
175
+ const groupedToasts = computed(() => {
176
+ const groups = {};
177
+ toasts.value.forEach((toast) => {
178
+ const position = toast.position || defaultPosition;
179
+ if (!groups[position]) {
180
+ groups[position] = [];
181
+ }
182
+ groups[position].push(toast);
183
+ });
184
+ return groups;
185
+ });
186
+ onUnmounted(() => {
187
+ clearToasts();
188
+ });
189
+ return {
190
+ toasts,
191
+ groupedToasts,
192
+ addToast,
193
+ removeToast,
194
+ clearToasts,
195
+ success,
196
+ error,
197
+ warning,
198
+ info
199
+ };
200
+ }
201
+ const VueToast = {
202
+ install: (app, pluginOptions) => {
203
+ app.component("VueToast", Toast);
204
+ app.config.globalProperties.$toast = {
205
+ success: (message, options) => {
206
+ const { success } = useToast((options == null ? void 0 : options.position) || (pluginOptions == null ? void 0 : pluginOptions.defaultPosition));
207
+ return success(message, options);
208
+ },
209
+ error: (message, options) => {
210
+ const { error } = useToast((options == null ? void 0 : options.position) || (pluginOptions == null ? void 0 : pluginOptions.defaultPosition));
211
+ return error(message, options);
212
+ },
213
+ warning: (message, options) => {
214
+ const { warning } = useToast((options == null ? void 0 : options.position) || (pluginOptions == null ? void 0 : pluginOptions.defaultPosition));
215
+ return warning(message, options);
216
+ },
217
+ info: (message, options) => {
218
+ const { info } = useToast((options == null ? void 0 : options.position) || (pluginOptions == null ? void 0 : pluginOptions.defaultPosition));
219
+ return info(message, options);
220
+ },
221
+ add: (options) => {
222
+ const { addToast } = useToast(options.position);
223
+ return addToast(options);
224
+ }
225
+ };
226
+ }
227
+ };
228
+ export {
229
+ Toast,
230
+ VueToast as default,
231
+ useToast
232
+ };
233
+ //# sourceMappingURL=vue-toast.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vue-toast.es.js","sources":["../src/components/Toast/Toast.vue","../src/composables/useToast.ts","../src/index.ts"],"sourcesContent":["<template>\n <div\n :class=\"[\n 'vue-toast',\n `vue-toast--${toast.type || 'default'}`,\n `vue-toast--${positionClass}`,\n { 'vue-toast--dismissible': toast.dismissible }\n ]\"\n :style=\"toastStyle\"\n @click=\"handleClick\"\n role=\"alert\"\n aria-live=\"polite\"\n :aria-label=\"ariaLabel\"\n >\n <div class=\"vue-toast__content\">\n <span class=\"vue-toast__message\">{{ toast.message }}</span>\n </div>\n \n <button\n v-if=\"toast.dismissible\"\n class=\"vue-toast__close\"\n @click.stop=\"handleClose\"\n aria-label=\"Close notification\"\n >\n <svg\n class=\"vue-toast__close-icon\"\n viewBox=\"0 0 24 24\"\n width=\"16\"\n height=\"16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { ToastComponentProps, ToastType } from '@/types'\n\nconst props = defineProps<ToastComponentProps>()\n\nconst emit = defineEmits<{\n close: [id?: string]\n click: []\n}>()\n\nconst positionClass = computed(() => {\n const position = props.toast.position || 'top-right'\n return position.replace('-', '')\n})\n\nconst toastStyle = computed(() => ({\n '--toast-index': props.index,\n '--toast-total': props.total,\n}))\n\nconst ariaLabel = computed(() => {\n const type = props.toast.type || 'default'\n const typeLabels: Record<ToastType, string> = {\n success: 'Success notification',\n error: 'Error notification',\n warning: 'Warning notification',\n info: 'Information notification',\n default: 'Notification',\n }\n return typeLabels[type]\n})\n\nconst handleClose = () => {\n emit('close', props.toast.id)\n}\n\nconst handleClick = () => {\n if (props.toast.onClick) {\n props.toast.onClick()\n }\n emit('click')\n}\n</script>\n\n<style scoped>\n.vue-toast {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-width: 300px;\n max-width: 500px;\n padding: 12px 16px;\n margin-bottom: 8px;\n border-radius: 6px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n background-color: white;\n color: #333;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n line-height: 1.4;\n animation: toast-slide-in 0.3s ease-out;\n transition: transform 0.2s ease, opacity 0.2s ease;\n z-index: calc(1000 + var(--toast-index));\n cursor: pointer;\n}\n\n.vue-toast:hover {\n transform: translateY(-1px);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);\n}\n\n.vue-toast--success {\n border-left: 4px solid #10b981;\n background-color: #f0fdf4;\n color: #065f46;\n}\n\n.vue-toast--error {\n border-left: 4px solid #ef4444;\n background-color: #fef2f2;\n color: #991b1b;\n}\n\n.vue-toast--warning {\n border-left: 4px solid #f59e0b;\n background-color: #fffbeb;\n color: #92400e;\n}\n\n.vue-toast--info {\n border-left: 4px solid #3b82f6;\n background-color: #eff6ff;\n color: #1e40af;\n}\n\n.vue-toast--default {\n border-left: 4px solid #6b7280;\n background-color: #f9fafb;\n color: #374151;\n}\n\n.vue-toast__content {\n flex: 1;\n margin-right: 8px;\n}\n\n.vue-toast__message {\n word-break: break-word;\n}\n\n.vue-toast__close {\n flex-shrink: 0;\n background: none;\n border: none;\n padding: 4px;\n margin-left: 8px;\n cursor: pointer;\n color: inherit;\n opacity: 0.7;\n border-radius: 4px;\n transition: opacity 0.2s ease, background-color 0.2s ease;\n}\n\n.vue-toast__close:hover {\n opacity: 1;\n background-color: rgba(0, 0, 0, 0.1);\n}\n\n.vue-toast__close:focus {\n outline: 2px solid currentColor;\n outline-offset: 2px;\n}\n\n.vue-toast__close-icon {\n display: block;\n}\n\n/* Position classes */\n.vue-toast--topleft {\n position: fixed;\n top: 20px;\n left: 20px;\n}\n\n.vue-toast--topcenter {\n position: fixed;\n top: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.vue-toast--topright {\n position: fixed;\n top: 20px;\n right: 20px;\n}\n\n.vue-toast--bottomleft {\n position: fixed;\n bottom: 20px;\n left: 20px;\n}\n\n.vue-toast--bottomcenter {\n position: fixed;\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.vue-toast--bottomright {\n position: fixed;\n bottom: 20px;\n right: 20px;\n}\n\n/* Animation */\n@keyframes toast-slide-in {\n from {\n opacity: 0;\n transform: translateY(-20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Responsive */\n@media (max-width: 640px) {\n .vue-toast {\n min-width: calc(100vw - 40px);\n max-width: calc(100vw - 40px);\n margin-left: 20px;\n margin-right: 20px;\n }\n \n .vue-toast--topleft,\n .vue-toast--topcenter,\n .vue-toast--topright {\n top: 10px;\n }\n \n .vue-toast--bottomleft,\n .vue-toast--bottomcenter,\n .vue-toast--bottomright {\n bottom: 10px;\n }\n}\n</style>","import { ref, computed, onUnmounted, type Ref } from 'vue'\nimport type { ToastOptions, ToastPosition } from '@/types'\n\ninterface ToastInstance extends ToastOptions {\n id: string\n timer?: ReturnType<typeof setTimeout>\n}\n\nexport function useToast(defaultPosition: ToastPosition = 'top-right') {\n const toasts: Ref<ToastInstance[]> = ref([])\n\n const generateId = () => `toast-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`\n\n const addToast = (options: ToastOptions) => {\n const id = options.id || generateId()\n const toast: ToastInstance = {\n ...options,\n id,\n position: options.position || defaultPosition,\n duration: options.duration ?? 5000,\n dismissible: options.dismissible ?? true,\n }\n\n toasts.value.push(toast)\n\n if (toast.duration && toast.duration > 0) {\n toast.timer = setTimeout(() => {\n removeToast(id)\n }, toast.duration)\n }\n\n return id\n }\n\n const removeToast = (id: string) => {\n const index = toasts.value.findIndex(t => t.id === id)\n if (index === -1) return\n\n const toast = toasts.value[index]\n \n if (toast.timer) {\n clearTimeout(toast.timer)\n }\n\n if (toast.onClose) {\n toast.onClose()\n }\n\n toasts.value.splice(index, 1)\n }\n\n const clearToasts = () => {\n toasts.value.forEach(toast => {\n if (toast.timer) {\n clearTimeout(toast.timer)\n }\n if (toast.onClose) {\n toast.onClose()\n }\n })\n toasts.value = []\n }\n\n const success = (message: string, options: Omit<ToastOptions, 'message' | 'type'> = {}) => {\n return addToast({\n ...options,\n message,\n type: 'success',\n })\n }\n\n const error = (message: string, options: Omit<ToastOptions, 'message' | 'type'> = {}) => {\n return addToast({\n ...options,\n message,\n type: 'error',\n })\n }\n\n const warning = (message: string, options: Omit<ToastOptions, 'message' | 'type'> = {}) => {\n return addToast({\n ...options,\n message,\n type: 'warning',\n })\n }\n\n const info = (message: string, options: Omit<ToastOptions, 'message' | 'type'> = {}) => {\n return addToast({\n ...options,\n message,\n type: 'info',\n })\n }\n\n const groupedToasts = computed(() => {\n const groups: Record<string, ToastInstance[]> = {}\n \n toasts.value.forEach(toast => {\n const position = toast.position || defaultPosition\n if (!groups[position]) {\n groups[position] = []\n }\n groups[position].push(toast)\n })\n\n return groups\n })\n\n onUnmounted(() => {\n clearToasts()\n })\n\n return {\n toasts,\n groupedToasts,\n addToast,\n removeToast,\n clearToasts,\n success,\n error,\n warning,\n info,\n }\n}\n\nexport type UseToastReturn = ReturnType<typeof useToast>","import { type App } from 'vue'\nimport Toast from './components/Toast'\nimport { useToast } from './composables/useToast'\nimport type { ToastOptions, ToastPosition, ToastType } from './types'\n\nexport { Toast, useToast }\nexport type { ToastOptions, ToastPosition, ToastType }\n\nconst VueToast = {\n install: (app: App, pluginOptions?: { defaultPosition?: ToastPosition }) => {\n app.component('VueToast', Toast)\n \n app.config.globalProperties.$toast = {\n success: (message: string, options?: Omit<ToastOptions, 'message' | 'type'>) => {\n const { success } = useToast(options?.position || pluginOptions?.defaultPosition)\n return success(message, options)\n },\n error: (message: string, options?: Omit<ToastOptions, 'message' | 'type'>) => {\n const { error } = useToast(options?.position || pluginOptions?.defaultPosition)\n return error(message, options)\n },\n warning: (message: string, options?: Omit<ToastOptions, 'message' | 'type'>) => {\n const { warning } = useToast(options?.position || pluginOptions?.defaultPosition)\n return warning(message, options)\n },\n info: (message: string, options?: Omit<ToastOptions, 'message' | 'type'>) => {\n const { info } = useToast(options?.position || pluginOptions?.defaultPosition)\n return info(message, options)\n },\n add: (options: ToastOptions) => {\n const { addToast } = useToast(options.position)\n return addToast(options)\n },\n }\n },\n}\n\nexport default VueToast"],"names":["_createElementBlock","_normalizeClass","_createElementVNode","_toDisplayString"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vue")):"function"==typeof define&&define.amd?define(["exports","vue"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).VueToast={},e.Vue)}(this,function(e,t){"use strict";const o=["aria-label"],s={class:"vue-toast__content"},i={class:"vue-toast__message"},n=((e,t)=>{const o=e.__vccOpts||e;for(const[s,i]of t)o[s]=i;return o})(t.defineComponent({__name:"Toast",props:{toast:{},index:{},total:{}},emits:["close","click"],setup(e,{emit:n}){const a=e,l=n,r=t.computed(()=>(a.toast.position||"top-right").replace("-","")),u=t.computed(()=>({"--toast-index":a.index,"--toast-total":a.total})),c=t.computed(()=>({success:"Success notification",error:"Error notification",warning:"Warning notification",info:"Information notification",default:"Notification"}[a.toast.type||"default"])),d=()=>{l("close",a.toast.id)},p=()=>{a.toast.onClick&&a.toast.onClick(),l("click")};return(n,a)=>(t.openBlock(),t.createElementBlock("div",{class:t.normalizeClass(["vue-toast",`vue-toast--${e.toast.type||"default"}`,`vue-toast--${r.value}`,{"vue-toast--dismissible":e.toast.dismissible}]),style:t.normalizeStyle(u.value),onClick:p,role:"alert","aria-live":"polite","aria-label":c.value},[t.createElementVNode("div",s,[t.createElementVNode("span",i,t.toDisplayString(e.toast.message),1)]),e.toast.dismissible?(t.openBlock(),t.createElementBlock("button",{key:0,class:"vue-toast__close",onClick:t.withModifiers(d,["stop"]),"aria-label":"Close notification"},[...a[0]||(a[0]=[t.createElementVNode("svg",{class:"vue-toast__close-icon",viewBox:"0 0 24 24",width:"16",height:"16",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[t.createElementVNode("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),t.createElementVNode("line",{x1:"6",y1:"6",x2:"18",y2:"18"})],-1)])])):t.createCommentVNode("",!0)],14,o))}}),[["__scopeId","data-v-38db861e"]]);function a(e="top-right"){const o=t.ref([]),s=t=>{const s=t.id||`toast-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,n={...t,id:s,position:t.position||e,duration:t.duration??5e3,dismissible:t.dismissible??!0};return o.value.push(n),n.duration&&n.duration>0&&(n.timer=setTimeout(()=>{i(s)},n.duration)),s},i=e=>{const t=o.value.findIndex(t=>t.id===e);if(-1===t)return;const s=o.value[t];s.timer&&clearTimeout(s.timer),s.onClose&&s.onClose(),o.value.splice(t,1)},n=()=>{o.value.forEach(e=>{e.timer&&clearTimeout(e.timer),e.onClose&&e.onClose()}),o.value=[]},a=t.computed(()=>{const t={};return o.value.forEach(o=>{const s=o.position||e;t[s]||(t[s]=[]),t[s].push(o)}),t});return t.onUnmounted(()=>{n()}),{toasts:o,groupedToasts:a,addToast:s,removeToast:i,clearToasts:n,success:(e,t={})=>s({...t,message:e,type:"success"}),error:(e,t={})=>s({...t,message:e,type:"error"}),warning:(e,t={})=>s({...t,message:e,type:"warning"}),info:(e,t={})=>s({...t,message:e,type:"info"})}}const l={install:(e,t)=>{e.component("VueToast",n),e.config.globalProperties.$toast={success:(e,o)=>{const{success:s}=a((null==o?void 0:o.position)||(null==t?void 0:t.defaultPosition));return s(e,o)},error:(e,o)=>{const{error:s}=a((null==o?void 0:o.position)||(null==t?void 0:t.defaultPosition));return s(e,o)},warning:(e,o)=>{const{warning:s}=a((null==o?void 0:o.position)||(null==t?void 0:t.defaultPosition));return s(e,o)},info:(e,o)=>{const{info:s}=a((null==o?void 0:o.position)||(null==t?void 0:t.defaultPosition));return s(e,o)},add:e=>{const{addToast:t}=a(e.position);return t(e)}}}};e.Toast=n,e.default=l,e.useToast=a,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
2
+ //# sourceMappingURL=vue-toast.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vue-toast.umd.js","sources":["../src/components/Toast/Toast.vue","../src/composables/useToast.ts","../src/index.ts"],"sourcesContent":["<template>\n <div\n :class=\"[\n 'vue-toast',\n `vue-toast--${toast.type || 'default'}`,\n `vue-toast--${positionClass}`,\n { 'vue-toast--dismissible': toast.dismissible }\n ]\"\n :style=\"toastStyle\"\n @click=\"handleClick\"\n role=\"alert\"\n aria-live=\"polite\"\n :aria-label=\"ariaLabel\"\n >\n <div class=\"vue-toast__content\">\n <span class=\"vue-toast__message\">{{ toast.message }}</span>\n </div>\n \n <button\n v-if=\"toast.dismissible\"\n class=\"vue-toast__close\"\n @click.stop=\"handleClose\"\n aria-label=\"Close notification\"\n >\n <svg\n class=\"vue-toast__close-icon\"\n viewBox=\"0 0 24 24\"\n width=\"16\"\n height=\"16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { ToastComponentProps, ToastType } from '@/types'\n\nconst props = defineProps<ToastComponentProps>()\n\nconst emit = defineEmits<{\n close: [id?: string]\n click: []\n}>()\n\nconst positionClass = computed(() => {\n const position = props.toast.position || 'top-right'\n return position.replace('-', '')\n})\n\nconst toastStyle = computed(() => ({\n '--toast-index': props.index,\n '--toast-total': props.total,\n}))\n\nconst ariaLabel = computed(() => {\n const type = props.toast.type || 'default'\n const typeLabels: Record<ToastType, string> = {\n success: 'Success notification',\n error: 'Error notification',\n warning: 'Warning notification',\n info: 'Information notification',\n default: 'Notification',\n }\n return typeLabels[type]\n})\n\nconst handleClose = () => {\n emit('close', props.toast.id)\n}\n\nconst handleClick = () => {\n if (props.toast.onClick) {\n props.toast.onClick()\n }\n emit('click')\n}\n</script>\n\n<style scoped>\n.vue-toast {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-width: 300px;\n max-width: 500px;\n padding: 12px 16px;\n margin-bottom: 8px;\n border-radius: 6px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n background-color: white;\n color: #333;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n line-height: 1.4;\n animation: toast-slide-in 0.3s ease-out;\n transition: transform 0.2s ease, opacity 0.2s ease;\n z-index: calc(1000 + var(--toast-index));\n cursor: pointer;\n}\n\n.vue-toast:hover {\n transform: translateY(-1px);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);\n}\n\n.vue-toast--success {\n border-left: 4px solid #10b981;\n background-color: #f0fdf4;\n color: #065f46;\n}\n\n.vue-toast--error {\n border-left: 4px solid #ef4444;\n background-color: #fef2f2;\n color: #991b1b;\n}\n\n.vue-toast--warning {\n border-left: 4px solid #f59e0b;\n background-color: #fffbeb;\n color: #92400e;\n}\n\n.vue-toast--info {\n border-left: 4px solid #3b82f6;\n background-color: #eff6ff;\n color: #1e40af;\n}\n\n.vue-toast--default {\n border-left: 4px solid #6b7280;\n background-color: #f9fafb;\n color: #374151;\n}\n\n.vue-toast__content {\n flex: 1;\n margin-right: 8px;\n}\n\n.vue-toast__message {\n word-break: break-word;\n}\n\n.vue-toast__close {\n flex-shrink: 0;\n background: none;\n border: none;\n padding: 4px;\n margin-left: 8px;\n cursor: pointer;\n color: inherit;\n opacity: 0.7;\n border-radius: 4px;\n transition: opacity 0.2s ease, background-color 0.2s ease;\n}\n\n.vue-toast__close:hover {\n opacity: 1;\n background-color: rgba(0, 0, 0, 0.1);\n}\n\n.vue-toast__close:focus {\n outline: 2px solid currentColor;\n outline-offset: 2px;\n}\n\n.vue-toast__close-icon {\n display: block;\n}\n\n/* Position classes */\n.vue-toast--topleft {\n position: fixed;\n top: 20px;\n left: 20px;\n}\n\n.vue-toast--topcenter {\n position: fixed;\n top: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.vue-toast--topright {\n position: fixed;\n top: 20px;\n right: 20px;\n}\n\n.vue-toast--bottomleft {\n position: fixed;\n bottom: 20px;\n left: 20px;\n}\n\n.vue-toast--bottomcenter {\n position: fixed;\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.vue-toast--bottomright {\n position: fixed;\n bottom: 20px;\n right: 20px;\n}\n\n/* Animation */\n@keyframes toast-slide-in {\n from {\n opacity: 0;\n transform: translateY(-20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Responsive */\n@media (max-width: 640px) {\n .vue-toast {\n min-width: calc(100vw - 40px);\n max-width: calc(100vw - 40px);\n margin-left: 20px;\n margin-right: 20px;\n }\n \n .vue-toast--topleft,\n .vue-toast--topcenter,\n .vue-toast--topright {\n top: 10px;\n }\n \n .vue-toast--bottomleft,\n .vue-toast--bottomcenter,\n .vue-toast--bottomright {\n bottom: 10px;\n }\n}\n</style>","import { ref, computed, onUnmounted, type Ref } from 'vue'\nimport type { ToastOptions, ToastPosition } from '@/types'\n\ninterface ToastInstance extends ToastOptions {\n id: string\n timer?: ReturnType<typeof setTimeout>\n}\n\nexport function useToast(defaultPosition: ToastPosition = 'top-right') {\n const toasts: Ref<ToastInstance[]> = ref([])\n\n const generateId = () => `toast-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`\n\n const addToast = (options: ToastOptions) => {\n const id = options.id || generateId()\n const toast: ToastInstance = {\n ...options,\n id,\n position: options.position || defaultPosition,\n duration: options.duration ?? 5000,\n dismissible: options.dismissible ?? true,\n }\n\n toasts.value.push(toast)\n\n if (toast.duration && toast.duration > 0) {\n toast.timer = setTimeout(() => {\n removeToast(id)\n }, toast.duration)\n }\n\n return id\n }\n\n const removeToast = (id: string) => {\n const index = toasts.value.findIndex(t => t.id === id)\n if (index === -1) return\n\n const toast = toasts.value[index]\n \n if (toast.timer) {\n clearTimeout(toast.timer)\n }\n\n if (toast.onClose) {\n toast.onClose()\n }\n\n toasts.value.splice(index, 1)\n }\n\n const clearToasts = () => {\n toasts.value.forEach(toast => {\n if (toast.timer) {\n clearTimeout(toast.timer)\n }\n if (toast.onClose) {\n toast.onClose()\n }\n })\n toasts.value = []\n }\n\n const success = (message: string, options: Omit<ToastOptions, 'message' | 'type'> = {}) => {\n return addToast({\n ...options,\n message,\n type: 'success',\n })\n }\n\n const error = (message: string, options: Omit<ToastOptions, 'message' | 'type'> = {}) => {\n return addToast({\n ...options,\n message,\n type: 'error',\n })\n }\n\n const warning = (message: string, options: Omit<ToastOptions, 'message' | 'type'> = {}) => {\n return addToast({\n ...options,\n message,\n type: 'warning',\n })\n }\n\n const info = (message: string, options: Omit<ToastOptions, 'message' | 'type'> = {}) => {\n return addToast({\n ...options,\n message,\n type: 'info',\n })\n }\n\n const groupedToasts = computed(() => {\n const groups: Record<string, ToastInstance[]> = {}\n \n toasts.value.forEach(toast => {\n const position = toast.position || defaultPosition\n if (!groups[position]) {\n groups[position] = []\n }\n groups[position].push(toast)\n })\n\n return groups\n })\n\n onUnmounted(() => {\n clearToasts()\n })\n\n return {\n toasts,\n groupedToasts,\n addToast,\n removeToast,\n clearToasts,\n success,\n error,\n warning,\n info,\n }\n}\n\nexport type UseToastReturn = ReturnType<typeof useToast>","import { type App } from 'vue'\nimport Toast from './components/Toast'\nimport { useToast } from './composables/useToast'\nimport type { ToastOptions, ToastPosition, ToastType } from './types'\n\nexport { Toast, useToast }\nexport type { ToastOptions, ToastPosition, ToastType }\n\nconst VueToast = {\n install: (app: App, pluginOptions?: { defaultPosition?: ToastPosition }) => {\n app.component('VueToast', Toast)\n \n app.config.globalProperties.$toast = {\n success: (message: string, options?: Omit<ToastOptions, 'message' | 'type'>) => {\n const { success } = useToast(options?.position || pluginOptions?.defaultPosition)\n return success(message, options)\n },\n error: (message: string, options?: Omit<ToastOptions, 'message' | 'type'>) => {\n const { error } = useToast(options?.position || pluginOptions?.defaultPosition)\n return error(message, options)\n },\n warning: (message: string, options?: Omit<ToastOptions, 'message' | 'type'>) => {\n const { warning } = useToast(options?.position || pluginOptions?.defaultPosition)\n return warning(message, options)\n },\n info: (message: string, options?: Omit<ToastOptions, 'message' | 'type'>) => {\n const { info } = useToast(options?.position || pluginOptions?.defaultPosition)\n return info(message, options)\n },\n add: (options: ToastOptions) => {\n const { addToast } = useToast(options.position)\n return addToast(options)\n },\n }\n },\n}\n\nexport default VueToast"],"names":["props","__props","emit","__emit","positionClass","computed","toast","position","replace","toastStyle","index","total","ariaLabel","success","error","warning","info","default","type","handleClose","id","handleClick","onClick","_createElementBlock","class","_normalizeClass","value","dismissible","style","role","_createElementVNode","_hoisted_2","_hoisted_3","_toDisplayString","message","viewBox","width","height","fill","stroke","x1","y1","x2","y2","useToast","defaultPosition","toasts","ref","addToast","options","Date","now","Math","random","toString","substr","duration","push","timer","setTimeout","removeToast","findIndex","t","clearTimeout","onClose","splice","clearToasts","forEach","groupedToasts","groups","onUnmounted","VueToast","install","app","pluginOptions","component","Toast","config","globalProperties","$toast","add"],"mappings":"uhBA8CA,MAAMA,EAAQC,EAERC,EAAOC,EAKPC,EAAgBC,EAAAA,SAAS,KACZL,EAAMM,MAAMC,UAAY,aACzBC,QAAQ,IAAK,KAGzBC,EAAaJ,EAAAA,SAAS,KAAA,CAC1B,gBAAiBL,EAAMU,MACvB,gBAAiBV,EAAMW,SAGnBC,EAAYP,EAAAA,SAAS,KAEqB,CAC5CQ,QAAS,uBACTC,MAAO,qBACPC,QAAS,uBACTC,KAAM,2BACNC,QAAS,gBANEjB,EAAMM,MAAMY,MAAQ,aAW7BC,EAAc,KAClBjB,EAAK,QAASF,EAAMM,MAAMc,KAGtBC,EAAc,KACdrB,EAAMM,MAAMgB,SACdtB,EAAMM,MAAMgB,UAEdpB,EAAK,sCAlFLqB,EAAAA,mBAsCM,MAAA,CArCHC,MAAKC,EAAAA,eAAA,aAA2C,cAAAxB,EAAAK,MAAMY,MAAI,0BAAqCd,EAAAsB,QAAmD,CAAA,yBAAAzB,EAAAK,MAAMqB,eAMxJC,uBAAOnB,EAAAiB,OACPJ,QAAOD,EACRQ,KAAK,QACL,YAAU,SACT,aAAYjB,EAAAc,QAEbI,EAAAA,mBAEM,MAFNC,EAEM,CADJD,EAAAA,mBAA2D,OAA3DE,EAA2DC,EAAAA,gBAAvBhC,EAAAK,MAAM4B,SAAO,KAI3CjC,EAAAK,MAAMqB,2BADdJ,EAAAA,mBAoBS,SAAA,OAlBPC,MAAM,mBACLF,wBAAYH,EAAW,CAAA,SACxB,aAAW,uCAEXW,EAAAA,mBAaM,MAAA,CAZJN,MAAM,wBACNW,QAAQ,YACRC,MAAM,KACNC,OAAO,KACPC,KAAK,OACLC,OAAO,eACP,eAAa,IACb,iBAAe,QACf,kBAAgB,UAEhBT,EAAAA,mBAA2C,OAAA,CAArCU,GAAG,KAAKC,GAAG,IAAIC,GAAG,IAAIC,GAAG,OAC/Bb,EAAAA,mBAA2C,OAAA,CAArCU,GAAG,IAAIC,GAAG,IAAIC,GAAG,KAAKC,GAAG,2FC5BhC,SAASC,EAASC,EAAiC,aACxD,MAAMC,EAA+BC,EAAAA,IAAI,IAInCC,EAAYC,IAChB,MAAM7B,EAAK6B,EAAQ7B,IAHI,SAAS8B,KAAKC,SAASC,KAAKC,SAASC,SAAS,IAAIC,OAAO,EAAG,KAI7EjD,EAAuB,IACxB2C,EACH7B,KACAb,SAAU0C,EAAQ1C,UAAYsC,EAC9BW,SAAUP,EAAQO,UAAY,IAC9B7B,YAAasB,EAAQtB,cAAe,GAWtC,OARAmB,EAAOpB,MAAM+B,KAAKnD,GAEdA,EAAMkD,UAAYlD,EAAMkD,SAAW,IACrClD,EAAMoD,MAAQC,WAAW,KACvBC,EAAYxC,IACXd,EAAMkD,WAGJpC,GAGHwC,EAAexC,IACnB,MAAMV,EAAQoC,EAAOpB,MAAMmC,UAAUC,GAAKA,EAAE1C,KAAOA,GACnD,IAAc,IAAVV,EAAc,OAElB,MAAMJ,EAAQwC,EAAOpB,MAAMhB,GAEvBJ,EAAMoD,OACRK,aAAazD,EAAMoD,OAGjBpD,EAAM0D,SACR1D,EAAM0D,UAGRlB,EAAOpB,MAAMuC,OAAOvD,EAAO,IAGvBwD,EAAc,KAClBpB,EAAOpB,MAAMyC,QAAQ7D,IACfA,EAAMoD,OACRK,aAAazD,EAAMoD,OAEjBpD,EAAM0D,SACR1D,EAAM0D,YAGVlB,EAAOpB,MAAQ,IAmCX0C,EAAgB/D,EAAAA,SAAS,KAC7B,MAAMgE,EAA0C,CAAA,EAUhD,OARAvB,EAAOpB,MAAMyC,QAAQ7D,IACnB,MAAMC,EAAWD,EAAMC,UAAYsC,EAC9BwB,EAAO9D,KACV8D,EAAO9D,GAAY,IAErB8D,EAAO9D,GAAUkD,KAAKnD,KAGjB+D,IAOT,OAJAC,EAAAA,YAAY,KACVJ,MAGK,CACLpB,SACAsB,gBACApB,WACAY,cACAM,cACArD,QAxDc,CAACqB,EAAiBe,EAAkD,CAAA,IAC3ED,EAAS,IACXC,EACHf,UACAhB,KAAM,YAqDRJ,MAjDY,CAACoB,EAAiBe,EAAkD,CAAA,IACzED,EAAS,IACXC,EACHf,UACAhB,KAAM,UA8CRH,QA1Cc,CAACmB,EAAiBe,EAAkD,CAAA,IAC3ED,EAAS,IACXC,EACHf,UACAhB,KAAM,YAuCRF,KAnCW,CAACkB,EAAiBe,EAAkD,CAAA,IACxED,EAAS,IACXC,EACHf,UACAhB,KAAM,SAiCZ,CCpHA,MAAMqD,EAAW,CACfC,QAAS,CAACC,EAAUC,KAClBD,EAAIE,UAAU,WAAYC,GAE1BH,EAAII,OAAOC,iBAAiBC,OAAS,CACnClE,QAAS,CAACqB,EAAiBe,KACzB,MAAMpC,QAAEA,GAAY+B,GAAS,MAAAK,OAAA,EAAAA,EAAS1C,kBAAYmE,WAAe7B,kBACjE,OAAOhC,EAAQqB,EAASe,IAE1BnC,MAAO,CAACoB,EAAiBe,KACvB,MAAMnC,MAAEA,GAAU8B,GAAS,MAAAK,OAAA,EAAAA,EAAS1C,kBAAYmE,WAAe7B,kBAC/D,OAAO/B,EAAMoB,EAASe,IAExBlC,QAAS,CAACmB,EAAiBe,KACzB,MAAMlC,QAAEA,GAAY6B,GAAS,MAAAK,OAAA,EAAAA,EAAS1C,kBAAYmE,WAAe7B,kBACjE,OAAO9B,EAAQmB,EAASe,IAE1BjC,KAAM,CAACkB,EAAiBe,KACtB,MAAMjC,KAAEA,GAAS4B,GAAS,MAAAK,OAAA,EAAAA,EAAS1C,kBAAYmE,WAAe7B,kBAC9D,OAAO7B,EAAKkB,EAASe,IAEvB+B,IAAM/B,IACJ,MAAMD,SAAEA,GAAaJ,EAASK,EAAQ1C,UACtC,OAAOyC,EAASC"}
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "@rosadorito/vue-toast",
3
+ "version": "0.0.1",
4
+ "description": "A lightweight, customizable toast notification library for Vue 3",
5
+ "type": "module",
6
+ "main": "./dist/vue-toast.umd.js",
7
+ "module": "./dist/vue-toast.es.js",
8
+ "types": "./dist/index.d.ts",
9
+ "private": false,
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/vue-toast.es.js",
14
+ "require": "./dist/vue-toast.umd.js"
15
+ },
16
+ "./style.css": "./dist/style.css",
17
+ "./dist/*": "./dist/*"
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "scripts": {
23
+ "dev": "vite --config examples/vite.config.js",
24
+ "build": "vue-tsc --noEmit && vite build",
25
+ "preview": "vite preview --config examples/vite.config.js",
26
+ "test": "vitest",
27
+ "test:ui": "vitest --ui",
28
+ "test:coverage": "vitest --coverage",
29
+ "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
30
+ "type-check": "vue-tsc --noEmit",
31
+ "prepublishOnly": "npm run build",
32
+ "build:examples": "vite build --config examples/vite.config.js"
33
+ },
34
+ "keywords": [
35
+ "vue",
36
+ "vue3",
37
+ "toast",
38
+ "notification",
39
+ "component-library",
40
+ "ui",
41
+ "alert"
42
+ ],
43
+ "author": "",
44
+ "license": "MIT",
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "git+https://github.com/yourusername/vue-toast.git"
48
+ },
49
+ "bugs": {
50
+ "url": "https://github.com/yourusername/vue-toast/issues"
51
+ },
52
+ "homepage": "https://github.com/yourusername/vue-toast#readme",
53
+ "packageManager": "pnpm@10.30.1",
54
+ "dependencies": {
55
+ "vue": "^3.5.32"
56
+ },
57
+ "peerDependencies": {
58
+ "vue": "^3.5.0"
59
+ },
60
+ "devDependencies": {
61
+ "@types/node": "^22.10.6",
62
+ "@vitejs/plugin-vue": "^5.2.1",
63
+ "@vue/eslint-config-typescript": "^14.2.0",
64
+ "@vue/test-utils": "^2.4.6",
65
+ "@vue/tsconfig": "^0.6.0",
66
+ "eslint": "^9.17.0",
67
+ "eslint-plugin-vue": "^9.30.0",
68
+ "jsdom": "^26.0.0",
69
+ "terser": "^5.46.1",
70
+ "typescript": "^5.7.3",
71
+ "vite": "^6.0.11",
72
+ "vite-plugin-dts": "^4.3.0",
73
+ "vitest": "^2.1.8",
74
+ "vue-tsc": "^2.1.10"
75
+ },
76
+ "sideEffects": false
77
+ }