d9-toast 1.3.24 → 1.4.25
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 +152 -135
- package/dist/ToastContext.js +86 -22
- package/dist/assets/sounds/toast.m4a +0 -0
- package/dist/d9-toast.d.ts +26 -10
- package/dist/toast.css +40 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,25 +4,33 @@
|
|
|
4
4
|

|
|
5
5
|

|
|
6
6
|

|
|
7
|
-

|
|
8
8
|
[](https://rzp.io/rzp/eVnJ0oP)
|
|
9
9
|
|
|
10
|
-
A lightweight, customizable toast notification library for React applications.
|
|
10
|
+
A **lightweight, fully typed, customizable toast notification library** for React applications.
|
|
11
|
+
|
|
12
|
+
---
|
|
11
13
|
|
|
12
14
|
## ✨ Features
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
* ⚡ **Lightweight & Fast** – Minimal bundle size
|
|
17
|
+
* 🔒 **100% TypeScript Support** – Strongly typed API
|
|
18
|
+
* 🎨 **Themes** – Light, Dark & Colored
|
|
19
|
+
* 🔔 **Audio Support** – Custom toast sounds with cooldown
|
|
20
|
+
* 🎯 **Multiple Positions** – 7 flexible placements
|
|
21
|
+
* 🧩 **Action Buttons** – Custom actions per toast
|
|
22
|
+
* ⏱ **Auto / Manual Control**
|
|
23
|
+
* 🧪 **No External Dependencies**
|
|
24
|
+
* 🎭 **Tailwind Compatible**
|
|
25
|
+
* 📱 **Responsive & Animated UI**
|
|
26
|
+
|
|
27
|
+
---
|
|
22
28
|
|
|
23
29
|
## 📺 Demo
|
|
24
30
|
|
|
25
|
-
[](https://codesandbox.io/embed/cqkyzm?view=preview)
|
|
32
|
+
|
|
33
|
+
---
|
|
26
34
|
|
|
27
35
|
## 📦 Installation
|
|
28
36
|
|
|
@@ -36,220 +44,229 @@ or
|
|
|
36
44
|
yarn add d9-toast
|
|
37
45
|
```
|
|
38
46
|
|
|
47
|
+
---
|
|
48
|
+
|
|
39
49
|
## 🚀 Quick Start
|
|
40
50
|
|
|
41
51
|
### 1. Wrap your app with `ToastProvider`
|
|
42
52
|
|
|
43
53
|
```jsx
|
|
44
|
-
import React from "react";
|
|
45
54
|
import { ToastProvider } from "d9-toast";
|
|
46
|
-
import App from "./App";
|
|
47
55
|
|
|
48
|
-
function Root() {
|
|
56
|
+
export default function Root() {
|
|
49
57
|
return (
|
|
50
58
|
<ToastProvider>
|
|
51
59
|
<App />
|
|
52
60
|
</ToastProvider>
|
|
53
61
|
);
|
|
54
62
|
}
|
|
55
|
-
|
|
56
|
-
export default Root;
|
|
57
63
|
```
|
|
58
64
|
|
|
59
|
-
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
### 2. Trigger toasts anywhere
|
|
60
68
|
|
|
61
69
|
```jsx
|
|
62
|
-
import React from "react";
|
|
63
70
|
import { useToast } from "d9-toast";
|
|
64
71
|
|
|
65
72
|
function MyComponent() {
|
|
66
73
|
const { showToast } = useToast();
|
|
67
74
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
return (
|
|
76
|
+
<button
|
|
77
|
+
onClick={() =>
|
|
78
|
+
showToast({
|
|
79
|
+
message: "Saved successfully!",
|
|
80
|
+
type: "success",
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
>
|
|
84
|
+
Show Toast
|
|
85
|
+
</button>
|
|
86
|
+
);
|
|
78
87
|
}
|
|
79
88
|
```
|
|
80
89
|
|
|
90
|
+
---
|
|
91
|
+
|
|
81
92
|
## 📖 API Reference
|
|
82
93
|
|
|
83
94
|
### `useToast()`
|
|
84
95
|
|
|
85
|
-
|
|
96
|
+
```ts
|
|
97
|
+
const { showToast, removeToast, removeToastAll } = useToast();
|
|
98
|
+
```
|
|
86
99
|
|
|
87
100
|
| Method | Description |
|
|
88
101
|
| -------------------- | --------------------------------- |
|
|
89
|
-
| `showToast(options)` |
|
|
90
|
-
| `removeToast(id)` |
|
|
91
|
-
| `removeToastAll()` |
|
|
92
|
-
|
|
93
|
-
### Toast Options
|
|
94
|
-
|
|
95
|
-
| Option | Type | Default | Description |
|
|
96
|
-
| ------------------ | ------------------------- | ------------- | --------------------------------------------------------------------------------------------------------- |
|
|
97
|
-
| `message` | string \| React.ReactNode | **Required** | Toast content (supports JSX) |
|
|
98
|
-
| `type` | string | `"success"` | Toast type: `success`, `error`, `info`, `warning`, `loading`, `submit` |
|
|
99
|
-
| `position` | string | `"top-right"` | Position: `top-left`, `top-right`, `bottom-left`, `bottom-right`, `center`, `center-top`, `center-bottom` |
|
|
100
|
-
| `theme` | string | `"light"` | Theme: `light`, `dark`, `colored` |
|
|
101
|
-
| `duration` | number | `5000` | Auto-close duration in ms (0 = infinite) |
|
|
102
|
-
| `autoClose` | boolean | `true` | Whether toast auto-closes after duration |
|
|
103
|
-
| `closable` | boolean | `false` | Show close (X) button |
|
|
104
|
-
| `pauseOnHover` | boolean | `true` | Pause timer on hover |
|
|
105
|
-
| `pauseOnFocusLoss` | boolean | `true` | Pause timer when window loses focus |
|
|
106
|
-
| `progress` | boolean | `true` | Show progress bar |
|
|
107
|
-
| `title` | boolean | `true` | Show toast header with type |
|
|
108
|
-
| `actions` | Array | `[]` | Action buttons: `[{ text: string, className: string, callback: function }]` |
|
|
109
|
-
| `className` | string | `""` | Additional CSS/Tailwind classes[Use !important with Tailwind] |
|
|
110
|
-
|
|
111
|
-
## 💡 Advanced Usage
|
|
112
|
-
|
|
113
|
-
### Custom Messages with JSX
|
|
102
|
+
| `showToast(options)` | Show a toast and returns its `id` |
|
|
103
|
+
| `removeToast(id)` | Remove toast by ID |
|
|
104
|
+
| `removeToastAll()` | Clear all toasts |
|
|
114
105
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 🔧 Toast Options
|
|
109
|
+
|
|
110
|
+
### Core Options
|
|
111
|
+
|
|
112
|
+
| Option | Type | Description |
|
|
113
|
+
| ------------------ | ------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
|
|
114
|
+
| `message` | `string \| ReactNode` | **Required** content |
|
|
115
|
+
| `type` | `"success" \| "error" \| "info" \| "warning" \| "loading" \| "submit"` | Visual type |
|
|
116
|
+
| `theme` | `"light" \| "dark" \| "colored"` | Theme variant |
|
|
117
|
+
| `position` | `"top-right" \| "top-left" \| "bottom-right" \| "bottom-left" \| "center" \| "center-top" \| "center-bottom"` | Toast placement |
|
|
118
|
+
| `duration` | `number` | Auto-close duration (0 = infinite) |
|
|
119
|
+
| `autoClose` | `boolean` | Enable auto close |
|
|
120
|
+
| `closable` | `boolean` | Show close (X) button |
|
|
121
|
+
| `progress` | `boolean` | Show progress bar |
|
|
122
|
+
| `title` | `boolean` | Show header/title |
|
|
123
|
+
| `pauseOnHover` | `boolean` | Pause on hover |
|
|
124
|
+
| `pauseOnFocusLoss` | `boolean` | Pause on tab switch |
|
|
125
|
+
| `className` | `string` | Custom styles |
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
### 🔘 Actions
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
actions?: {
|
|
133
|
+
text: string;
|
|
134
|
+
className?: string;
|
|
135
|
+
callback?: (toast: { id: number }) => void;
|
|
136
|
+
}[];
|
|
125
137
|
```
|
|
126
138
|
|
|
127
|
-
|
|
139
|
+
**Example**
|
|
128
140
|
|
|
129
141
|
```jsx
|
|
130
142
|
showToast({
|
|
131
|
-
message: "File uploaded
|
|
132
|
-
type: "success",
|
|
143
|
+
message: "File uploaded",
|
|
133
144
|
actions: [
|
|
134
145
|
{
|
|
135
|
-
text: "
|
|
136
|
-
className: "!bg-gray-600 !text-white",
|
|
137
|
-
callback: () => console.log("View clicked"),
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
text: "Dismiss",
|
|
141
|
-
className: "!bg-gray-600/20 !text-white",
|
|
146
|
+
text: "Undo",
|
|
142
147
|
callback: ({ id }) => removeToast(id),
|
|
143
148
|
},
|
|
144
149
|
],
|
|
145
150
|
});
|
|
146
151
|
```
|
|
147
152
|
|
|
148
|
-
|
|
153
|
+
---
|
|
149
154
|
|
|
150
|
-
|
|
151
|
-
const { showToast, removeToast, removeToastAll } = useToast();
|
|
155
|
+
## 🔊 Audio Support (NEW)
|
|
152
156
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
### Audio Options
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
audio?: {
|
|
161
|
+
enabled?: boolean;
|
|
162
|
+
volume?: number; // 0 – 1
|
|
163
|
+
audioFile?: string;
|
|
164
|
+
cooldown?: number; // ms
|
|
165
|
+
};
|
|
166
|
+
```
|
|
159
167
|
|
|
160
|
-
|
|
161
|
-
removeToast(toastId);
|
|
168
|
+
### Example
|
|
162
169
|
|
|
163
|
-
|
|
164
|
-
|
|
170
|
+
```jsx
|
|
171
|
+
showToast({
|
|
172
|
+
message: "Message sent",
|
|
173
|
+
type: "success",
|
|
174
|
+
audio: {
|
|
175
|
+
enabled: true,
|
|
176
|
+
volume: 0.8,
|
|
177
|
+
cooldown: 500,
|
|
178
|
+
},
|
|
179
|
+
});
|
|
165
180
|
```
|
|
166
181
|
|
|
182
|
+
✔ Prevents sound spam
|
|
183
|
+
✔ Per-toast control
|
|
184
|
+
✔ Custom audio file supported
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
167
188
|
## 🎨 Styling
|
|
168
189
|
|
|
169
|
-
### Default
|
|
190
|
+
### Default Styles
|
|
170
191
|
|
|
171
|
-
```
|
|
192
|
+
```js
|
|
172
193
|
import "d9-toast/dist/toast.css";
|
|
173
194
|
```
|
|
174
195
|
|
|
175
|
-
### Custom Styling
|
|
196
|
+
### Tailwind / Custom Styling
|
|
176
197
|
|
|
177
198
|
```jsx
|
|
178
|
-
// optional Tailwind/custom styling [Use !important with Tailwind (className: "!bg-red-500")]
|
|
179
199
|
showToast({
|
|
180
|
-
message: "
|
|
200
|
+
message: "Styled Toast",
|
|
181
201
|
className:
|
|
182
|
-
"bg-gradient-to-r from-
|
|
183
|
-
type: "success",
|
|
202
|
+
"!bg-gradient-to-r from-indigo-600 to-purple-600 !text-white !rounded-xl",
|
|
184
203
|
});
|
|
185
204
|
```
|
|
186
205
|
|
|
187
|
-
|
|
206
|
+
> ⚠️ Use `!important` when overriding styles with Tailwind
|
|
188
207
|
|
|
189
|
-
|
|
190
|
-
// Light theme (default)
|
|
191
|
-
showToast({ message: "Light", theme: "light" });
|
|
208
|
+
---
|
|
192
209
|
|
|
193
|
-
|
|
194
|
-
showToast({ message: "Dark", theme: "dark" });
|
|
210
|
+
## 🧠 Advanced Usage
|
|
195
211
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
212
|
+
### Persistent Toast
|
|
213
|
+
|
|
214
|
+
```jsx
|
|
215
|
+
const id = showToast({
|
|
216
|
+
message: "Loading...",
|
|
217
|
+
type: "loading",
|
|
218
|
+
duration: 0,
|
|
201
219
|
});
|
|
220
|
+
|
|
221
|
+
// later
|
|
222
|
+
removeToast(id);
|
|
202
223
|
```
|
|
203
224
|
|
|
204
|
-
|
|
225
|
+
---
|
|
205
226
|
|
|
206
|
-
###
|
|
227
|
+
### JSX Content
|
|
207
228
|
|
|
208
|
-
```
|
|
209
|
-
|
|
229
|
+
```jsx
|
|
230
|
+
showToast({
|
|
231
|
+
message: (
|
|
232
|
+
<>
|
|
233
|
+
<strong>Custom JSX</strong>
|
|
234
|
+
<p>This supports React nodes</p>
|
|
235
|
+
</>
|
|
236
|
+
),
|
|
237
|
+
});
|
|
210
238
|
```
|
|
211
239
|
|
|
212
|
-
|
|
240
|
+
---
|
|
213
241
|
|
|
214
|
-
|
|
215
|
-
- `dist/toast.css` – Default styles
|
|
242
|
+
## 🧾 TypeScript Support
|
|
216
243
|
|
|
217
|
-
|
|
244
|
+
D9-Toast ships with **full TypeScript definitions**:
|
|
218
245
|
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
# or
|
|
222
|
-
npm run dev
|
|
246
|
+
```ts
|
|
247
|
+
import type { ToastOptions, ToastType } from "d9-toast";
|
|
223
248
|
```
|
|
224
249
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
## 📄 License
|
|
230
|
-
|
|
231
|
-
MIT © [Athul / D9 Coder]
|
|
250
|
+
✔ IntelliSense
|
|
251
|
+
✔ Strict typing
|
|
252
|
+
✔ No `any`
|
|
232
253
|
|
|
233
254
|
---
|
|
234
255
|
|
|
235
|
-
##
|
|
256
|
+
## 📄 License
|
|
236
257
|
|
|
237
|
-
|
|
238
|
-
- Built with React and modern web standards
|
|
239
|
-
- Thanks to all contributors and users
|
|
258
|
+
MIT © **Athul / D9 Coder**
|
|
240
259
|
|
|
241
260
|
---
|
|
242
261
|
|
|
243
262
|
## ❤️ Support My Work
|
|
244
263
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
[](https://rzp.io/rzp/eVnJ0oP)
|
|
264
|
+
👉 [https://rzp.io/rzp/eVnJ0oP](https://rzp.io/rzp/eVnJ0oP)
|
|
248
265
|
|
|
249
266
|
---
|
|
250
267
|
|
|
251
|
-
|
|
268
|
+
## 🔗 Links
|
|
252
269
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
270
|
+
* 🐞 [Report Issue](https://github.com/psathul073/d9-toast/issues)
|
|
271
|
+
* 💻 [Source Code](https://github.com/psathul073/d9-toast)
|
|
272
|
+
* 📦 [npm Package](https://www.npmjs.com/package/d9-toast)
|
package/dist/ToastContext.js
CHANGED
|
@@ -14,21 +14,45 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
|
|
|
14
14
|
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
15
15
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
16
16
|
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
17
|
-
import React, { createContext, useCallback, useContext, useState } from "react";
|
|
17
|
+
import React, { createContext, useCallback, useContext, useRef, useState } from "react";
|
|
18
18
|
import Toast from "./Toast";
|
|
19
|
+
import mySound from "./assets/sounds/toast.m4a";
|
|
19
20
|
import "./toast.css";
|
|
20
21
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
21
22
|
var ToastContext = /*#__PURE__*/createContext();
|
|
22
23
|
export var useToast = function useToast() {
|
|
23
24
|
return useContext(ToastContext);
|
|
24
25
|
};
|
|
26
|
+
var audioSettings = {
|
|
27
|
+
audioFile: mySound,
|
|
28
|
+
volume: 0.8,
|
|
29
|
+
enabled: true,
|
|
30
|
+
cooldown: 500
|
|
31
|
+
};
|
|
25
32
|
export var ToastProvider = function ToastProvider(_ref) {
|
|
26
|
-
var _toasts$2;
|
|
27
33
|
var children = _ref.children;
|
|
28
34
|
var _useState = useState([]),
|
|
29
35
|
_useState2 = _slicedToArray(_useState, 2),
|
|
30
36
|
toasts = _useState2[0],
|
|
31
37
|
setToasts = _useState2[1];
|
|
38
|
+
var lastSoundTimeRef = useRef(0);
|
|
39
|
+
|
|
40
|
+
// Audio player..
|
|
41
|
+
var playAudio = useCallback(function (_ref2) {
|
|
42
|
+
var audioFile = _ref2.audioFile,
|
|
43
|
+
_ref2$volume = _ref2.volume,
|
|
44
|
+
volume = _ref2$volume === void 0 ? 0.6 : _ref2$volume,
|
|
45
|
+
_ref2$enabled = _ref2.enabled,
|
|
46
|
+
enabled = _ref2$enabled === void 0 ? true : _ref2$enabled;
|
|
47
|
+
if (!enabled || !audioFile) return;
|
|
48
|
+
try {
|
|
49
|
+
var audio = new Audio(audioFile);
|
|
50
|
+
audio.volume = volume;
|
|
51
|
+
audio.play()["catch"](function () {});
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.error("Audio play error:", err);
|
|
54
|
+
}
|
|
55
|
+
}, []);
|
|
32
56
|
|
|
33
57
|
// Generate unique ID safely
|
|
34
58
|
var generateId = function generateId() {
|
|
@@ -36,57 +60,97 @@ export var ToastProvider = function ToastProvider(_ref) {
|
|
|
36
60
|
};
|
|
37
61
|
|
|
38
62
|
// Positions.
|
|
39
|
-
|
|
63
|
+
// const positions = [
|
|
40
64
|
|
|
41
65
|
// Show toast..
|
|
42
66
|
var showToast = useCallback(function (toast) {
|
|
43
|
-
var
|
|
67
|
+
var _toast$audio$enabled, _toast$audio, _toast$audio$volume, _toast$audio2, _toast$audio$audioFil, _toast$audio3, _toast$audio$cooldown, _toast$audio4;
|
|
68
|
+
var newToast = _objectSpread(_objectSpread({
|
|
44
69
|
id: generateId()
|
|
45
|
-
}, toast)
|
|
70
|
+
}, toast), {}, {
|
|
71
|
+
audio: {
|
|
72
|
+
enabled: (_toast$audio$enabled = (_toast$audio = toast.audio) === null || _toast$audio === void 0 ? void 0 : _toast$audio.enabled) !== null && _toast$audio$enabled !== void 0 ? _toast$audio$enabled : audioSettings.enabled,
|
|
73
|
+
// Toast-specific audio setting.
|
|
74
|
+
volume: (_toast$audio$volume = (_toast$audio2 = toast.audio) === null || _toast$audio2 === void 0 ? void 0 : _toast$audio2.volume) !== null && _toast$audio$volume !== void 0 ? _toast$audio$volume : audioSettings.volume,
|
|
75
|
+
// Custom volume per toast.
|
|
76
|
+
audioFile: (_toast$audio$audioFil = (_toast$audio3 = toast.audio) === null || _toast$audio3 === void 0 ? void 0 : _toast$audio3.audioFile) !== null && _toast$audio$audioFil !== void 0 ? _toast$audio$audioFil : audioSettings.audioFile,
|
|
77
|
+
// Custom sound per toast.
|
|
78
|
+
cooldown: (_toast$audio$cooldown = (_toast$audio4 = toast.audio) === null || _toast$audio4 === void 0 ? void 0 : _toast$audio4.cooldown) !== null && _toast$audio$cooldown !== void 0 ? _toast$audio$cooldown : audioSettings.cooldown // Custom cooldown im ms.
|
|
79
|
+
}
|
|
80
|
+
});
|
|
46
81
|
setToasts(function (prev) {
|
|
47
82
|
return [].concat(_toConsumableArray(prev), [newToast]);
|
|
48
83
|
});
|
|
49
|
-
|
|
84
|
+
var audio = newToast.audio,
|
|
85
|
+
type = newToast.type;
|
|
86
|
+
var now = Date.now();
|
|
87
|
+
var cooldown = Number(audio.cooldown) || audioSettings.cooldown;
|
|
88
|
+
var canPlaySound = now - lastSoundTimeRef.current >= cooldown;
|
|
89
|
+
var bypassCooldown = type === "error"; // Bypass error toast
|
|
90
|
+
|
|
91
|
+
// Play audio whenever a new toast appears.
|
|
92
|
+
if (audio.enabled && audio.audioFile && (canPlaySound || bypassCooldown)) {
|
|
93
|
+
lastSoundTimeRef.current = now;
|
|
94
|
+
playAudio({
|
|
95
|
+
audioFile: audio.audioFile,
|
|
96
|
+
volume: audio.volume
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
var shouldAutoClose = toast.autoClose !== false && toast.duration !== 0;
|
|
100
|
+
if (shouldAutoClose) {
|
|
50
101
|
setTimeout(function () {
|
|
51
102
|
return removeToast(newToast.id);
|
|
52
103
|
}, toast.duration || 5000);
|
|
53
104
|
}
|
|
54
105
|
return newToast === null || newToast === void 0 ? void 0 : newToast.id;
|
|
55
|
-
}, []);
|
|
106
|
+
}, [playAudio]);
|
|
56
107
|
|
|
57
108
|
// Remove toast
|
|
58
109
|
var removeToast = useCallback(function (id) {
|
|
59
110
|
setToasts(function (prev) {
|
|
60
|
-
|
|
111
|
+
var newToasts = prev.filter(function (t) {
|
|
61
112
|
return t.id !== id;
|
|
62
113
|
});
|
|
114
|
+
return newToasts;
|
|
63
115
|
});
|
|
64
116
|
}, []);
|
|
65
117
|
|
|
66
118
|
// Remove all toast.
|
|
67
|
-
var removeToastAll = function
|
|
119
|
+
var removeToastAll = useCallback(function () {
|
|
68
120
|
if (toasts.length > 0) {
|
|
69
121
|
setToasts([]);
|
|
70
122
|
}
|
|
71
|
-
};
|
|
123
|
+
}, [toasts.length]);
|
|
124
|
+
|
|
125
|
+
// Group toasts by there positions..
|
|
126
|
+
var groupedToasts = toasts.reduce(function (acc, toast) {
|
|
127
|
+
var position = toast.position || "top-right";
|
|
128
|
+
if (!acc[position]) {
|
|
129
|
+
acc[position] = [];
|
|
130
|
+
}
|
|
131
|
+
acc[position].push(toast);
|
|
132
|
+
return acc;
|
|
133
|
+
}, {});
|
|
72
134
|
return /*#__PURE__*/_jsxs(ToastContext.Provider, {
|
|
73
135
|
value: {
|
|
74
136
|
showToast: showToast,
|
|
75
137
|
removeToast: removeToast,
|
|
76
138
|
removeToastAll: removeToastAll
|
|
77
139
|
},
|
|
78
|
-
children: [children,
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
140
|
+
children: [children, Object.entries(groupedToasts).map(function (_ref3) {
|
|
141
|
+
var _ref4 = _slicedToArray(_ref3, 2),
|
|
142
|
+
position = _ref4[0],
|
|
143
|
+
positionToasts = _ref4[1];
|
|
144
|
+
return /*#__PURE__*/_jsx("div", {
|
|
145
|
+
className: "toastContainer ".concat(position),
|
|
146
|
+
children: positionToasts.map(function (toast) {
|
|
147
|
+
return /*#__PURE__*/_jsx(Toast, _objectSpread(_objectSpread({}, toast), {}, {
|
|
148
|
+
remove: function remove() {
|
|
149
|
+
return removeToast(toast.id);
|
|
150
|
+
}
|
|
151
|
+
}), toast.id);
|
|
152
|
+
})
|
|
153
|
+
}, position);
|
|
90
154
|
})]
|
|
91
155
|
});
|
|
92
156
|
};
|
|
Binary file
|
package/dist/d9-toast.d.ts
CHANGED
|
@@ -28,11 +28,23 @@ declare module "d9-toast" {
|
|
|
28
28
|
/** Text label for the action button */
|
|
29
29
|
text: string;
|
|
30
30
|
/** Extra custom class names */
|
|
31
|
-
className
|
|
31
|
+
className?: string;
|
|
32
32
|
/** Optional callback triggered on click */
|
|
33
33
|
callback?: (toast: { id: number }) => void;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/** Audio configuration for toast sound */
|
|
37
|
+
export interface ToastAudioOptions {
|
|
38
|
+
/** Enable or disable toast sound */
|
|
39
|
+
enabled?: boolean;
|
|
40
|
+
/** Audio volume (0 to 1) */
|
|
41
|
+
volume?: number;
|
|
42
|
+
/** Custom audio file */
|
|
43
|
+
audioFile?: string;
|
|
44
|
+
/** Cooldown in milliseconds between sounds */
|
|
45
|
+
cooldown?: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
36
48
|
/** Toast configuration options */
|
|
37
49
|
export interface ToastOptions {
|
|
38
50
|
/** Main message; can be string or any React node (you render non-strings as-is) */
|
|
@@ -45,7 +57,7 @@ declare module "d9-toast" {
|
|
|
45
57
|
actions?: ToastAction[];
|
|
46
58
|
/** Visual theme */
|
|
47
59
|
theme?: ToastTheme;
|
|
48
|
-
/**
|
|
60
|
+
/** Whether to show toast title */
|
|
49
61
|
title?: boolean;
|
|
50
62
|
/** Whether to show progress bar */
|
|
51
63
|
progress?: boolean;
|
|
@@ -61,22 +73,18 @@ declare module "d9-toast" {
|
|
|
61
73
|
position?: ToastPosition;
|
|
62
74
|
/** Whether the toast auto-closes after duration */
|
|
63
75
|
autoClose?: boolean;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
/** Toast provider props for context setup */
|
|
68
|
-
export interface ToastProviderProps {
|
|
69
|
-
/** App children to wrap with ToastProvider */
|
|
70
|
-
children: React.ReactNode;
|
|
76
|
+
/** Audio configuration for this toast */
|
|
77
|
+
audio?: ToastAudioOptions;
|
|
71
78
|
}
|
|
72
79
|
|
|
80
|
+
/** Internal toast data with generated id */
|
|
73
81
|
export interface ToastData extends ToastOptions {
|
|
74
82
|
id: number;
|
|
75
83
|
}
|
|
76
84
|
|
|
77
85
|
/** Context value shape */
|
|
78
86
|
export interface ToastContextValue {
|
|
79
|
-
/** Show a toast with given options */
|
|
87
|
+
/** Show a toast with given options and return toast id */
|
|
80
88
|
showToast: (toast: ToastOptions) => number;
|
|
81
89
|
/** Remove a toast by ID */
|
|
82
90
|
removeToast: (id: number) => void;
|
|
@@ -84,6 +92,12 @@ declare module "d9-toast" {
|
|
|
84
92
|
removeToastAll: () => void;
|
|
85
93
|
}
|
|
86
94
|
|
|
95
|
+
/** Toast provider props for context setup */
|
|
96
|
+
export interface ToastProviderProps {
|
|
97
|
+
/** App children to wrap with ToastProvider */
|
|
98
|
+
children: React.ReactNode;
|
|
99
|
+
}
|
|
100
|
+
|
|
87
101
|
/** Context provider component */
|
|
88
102
|
export const ToastProvider: React.FC<ToastProviderProps>;
|
|
89
103
|
|
|
@@ -94,5 +108,7 @@ declare module "d9-toast" {
|
|
|
94
108
|
export interface ToastProps extends ToastData {
|
|
95
109
|
remove: () => void;
|
|
96
110
|
}
|
|
111
|
+
|
|
112
|
+
/** Toast component */
|
|
97
113
|
export const Toast: React.FC<ToastProps>;
|
|
98
114
|
}
|
package/dist/toast.css
CHANGED
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
/* Loading/Submit colors */
|
|
22
22
|
--loading-color: #8736ca;
|
|
23
23
|
--loading-bg: rgba(124, 58, 237, 0.1);
|
|
24
|
+
|
|
25
|
+
--border-color: rgba(17, 24, 39, 0.1);
|
|
26
|
+
|
|
27
|
+
--line-height-base: 1.5;
|
|
28
|
+
--font-size-base: 14px;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
/* Defaults */
|
|
@@ -45,26 +50,34 @@
|
|
|
45
50
|
z-index: 999;
|
|
46
51
|
display: flex;
|
|
47
52
|
gap: 14px;
|
|
53
|
+
pointer-events: none; /* Allow clicks through empty space */
|
|
54
|
+
}
|
|
55
|
+
.toastContainer > * {
|
|
56
|
+
pointer-events: auto; /* Re-enable for toasts */
|
|
48
57
|
}
|
|
49
58
|
.toastContainer.top-right {
|
|
50
59
|
flex-direction: column;
|
|
51
60
|
top: 16px;
|
|
52
61
|
right: 16px;
|
|
62
|
+
left: auto;
|
|
53
63
|
}
|
|
54
64
|
.toastContainer.top-left {
|
|
55
65
|
flex-direction: column;
|
|
56
66
|
top: 16px;
|
|
57
67
|
left: 16px;
|
|
68
|
+
right: auto;
|
|
58
69
|
}
|
|
59
70
|
.toastContainer.bottom-right {
|
|
60
71
|
flex-direction: column-reverse;
|
|
61
72
|
bottom: 16px;
|
|
62
73
|
right: 16px;
|
|
74
|
+
left: auto;
|
|
63
75
|
}
|
|
64
76
|
.toastContainer.bottom-left {
|
|
65
77
|
flex-direction: column-reverse;
|
|
66
78
|
bottom: 16px;
|
|
67
79
|
left: 16px;
|
|
80
|
+
right: auto;
|
|
68
81
|
}
|
|
69
82
|
.toastContainer.center {
|
|
70
83
|
flex-direction: column;
|
|
@@ -76,12 +89,14 @@
|
|
|
76
89
|
flex-direction: column;
|
|
77
90
|
top: 16px;
|
|
78
91
|
left: 50%;
|
|
92
|
+
bottom: auto;
|
|
79
93
|
transform: translateX(-50%);
|
|
80
94
|
}
|
|
81
95
|
.toastContainer.center-bottom {
|
|
82
96
|
flex-direction: column-reverse;
|
|
83
97
|
bottom: 16px;
|
|
84
98
|
left: 50%;
|
|
99
|
+
top: auto;
|
|
85
100
|
transform: translateX(-50%);
|
|
86
101
|
}
|
|
87
102
|
|
|
@@ -96,16 +111,18 @@
|
|
|
96
111
|
margin: 8px;
|
|
97
112
|
border-radius: 8px;
|
|
98
113
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
|
99
|
-
font-size:
|
|
100
|
-
|
|
114
|
+
font-size: var(--font-size-base);
|
|
115
|
+
line-height: var(--line-height-base);
|
|
116
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
117
|
+
Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
|
101
118
|
transition: all 0.3s ease-in;
|
|
102
119
|
will-change: transform, opacity;
|
|
103
120
|
background-color: var(--primary-bg);
|
|
104
121
|
color: var(--primary-color);
|
|
105
122
|
backdrop-filter: blur(10px);
|
|
123
|
+
border: 1px solid var(--border-color);
|
|
106
124
|
}
|
|
107
125
|
|
|
108
|
-
|
|
109
126
|
/* Theme colors */
|
|
110
127
|
.light {
|
|
111
128
|
--primary-bg: #ffffff;
|
|
@@ -126,12 +143,14 @@
|
|
|
126
143
|
--loading-color: #6900ca;
|
|
127
144
|
--loading-bg: rgba(106, 31, 176, 0.1);
|
|
128
145
|
|
|
146
|
+
--border-color: #e5e7eb;
|
|
147
|
+
|
|
129
148
|
/* background-color: #ffffff;
|
|
130
149
|
color: #1e2939; */
|
|
131
150
|
}
|
|
132
151
|
|
|
133
152
|
.dark {
|
|
134
|
-
|
|
153
|
+
--primary-bg: #060606;
|
|
135
154
|
--primary-color: #ffffff;
|
|
136
155
|
|
|
137
156
|
--success-color: #00df5f;
|
|
@@ -149,6 +168,8 @@
|
|
|
149
168
|
--loading-color: #c586ff;
|
|
150
169
|
--loading-bg: rgba(106, 31, 176, 0.1);
|
|
151
170
|
|
|
171
|
+
--border-color: #111827;
|
|
172
|
+
|
|
152
173
|
/* background-color: #1e2939;
|
|
153
174
|
color: #ffffff; */
|
|
154
175
|
}
|
|
@@ -177,10 +198,11 @@
|
|
|
177
198
|
}
|
|
178
199
|
|
|
179
200
|
.toastHeader {
|
|
201
|
+
min-height: 24px;
|
|
180
202
|
display: flex;
|
|
181
203
|
justify-content: space-between;
|
|
182
204
|
align-items: center;
|
|
183
|
-
padding:
|
|
205
|
+
padding: 3px 6px;
|
|
184
206
|
border-radius: 6px;
|
|
185
207
|
box-shadow: inset 0 1px rgb(0 0 0 / 0.06);
|
|
186
208
|
}
|
|
@@ -188,16 +210,22 @@
|
|
|
188
210
|
.toastHeader .title {
|
|
189
211
|
display: inline-flex;
|
|
190
212
|
align-items: center;
|
|
191
|
-
gap:
|
|
213
|
+
gap: 6px;
|
|
192
214
|
font-weight: 500;
|
|
215
|
+
height: 100%;
|
|
216
|
+
}
|
|
217
|
+
.toastHeader .title p {
|
|
218
|
+
font-family: inherit;
|
|
219
|
+
font-size: 1rem;
|
|
220
|
+
line-height: var(--line-height-base);
|
|
221
|
+
text-transform: uppercase;
|
|
193
222
|
}
|
|
194
|
-
|
|
195
223
|
.close-button {
|
|
196
224
|
display: flex;
|
|
197
225
|
align-items: center;
|
|
198
226
|
justify-content: center;
|
|
199
227
|
background-color: transparent;
|
|
200
|
-
color:
|
|
228
|
+
color: currentColor;
|
|
201
229
|
cursor: pointer;
|
|
202
230
|
}
|
|
203
231
|
|
|
@@ -232,8 +260,9 @@
|
|
|
232
260
|
padding: 8px 12px;
|
|
233
261
|
font-size: 14px;
|
|
234
262
|
border-radius: 6px;
|
|
235
|
-
box-shadow:
|
|
263
|
+
box-shadow: 0px 0px 1px #0b0b0b89;
|
|
236
264
|
flex-shrink: 0;
|
|
265
|
+
font-weight: 500;
|
|
237
266
|
cursor: pointer;
|
|
238
267
|
}
|
|
239
268
|
.toastActions .action-btn:hover {
|
|
@@ -287,7 +316,7 @@
|
|
|
287
316
|
.action-btnB__loading,
|
|
288
317
|
.action-btnB__submit {
|
|
289
318
|
color: var(--loading-color);
|
|
290
|
-
|
|
319
|
+
background-color: var(--loading-bg);
|
|
291
320
|
}
|
|
292
321
|
|
|
293
322
|
.progress-container {
|
|
@@ -391,7 +420,7 @@
|
|
|
391
420
|
}
|
|
392
421
|
}
|
|
393
422
|
|
|
394
|
-
@media screen and (max-width:
|
|
423
|
+
@media screen and (max-width: 426px) {
|
|
395
424
|
.toastContainer.top-right,
|
|
396
425
|
.toastContainer.bottom-right {
|
|
397
426
|
right: 0px;
|