d9-toast 1.3.24 → 1.4.24

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
@@ -4,25 +4,33 @@
4
4
  ![npm bundle size](https://img.shields.io/bundlephobia/min/d9-toast?style=flat-square)
5
5
  ![npm downloads](https://img.shields.io/npm/dm/d9-toast?style=flat-square)
6
6
  ![License](https://img.shields.io/npm/l/d9-toast?style=flat-square)
7
- ![React](https://img.shields.io/badge/React-18+-61DAFB?style=flat-square&logo=react&logoColor=black)
7
+ ![React](https://img.shields.io/badge/React-18+-61DAFB?style=flat-square\&logo=react\&logoColor=black)
8
8
  [![Donate via Razorpay](https://img.shields.io/badge/Donate-Razorpay-blue)](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
- - **Lightweight & Customizable** – Minimal bundle size with extensive customization options
15
- - **React Native** – Built specifically for React with hooks support
16
- - **No External Dependencies** – Pure CSS included, works out of the box
17
- - **Multiple Toast Types** – Success, error, info, warning, loading, and submit states
18
- - **Responsive Design** – Modern UI with smooth animations across all devices
19
- - **Tailwind CSS Compatible** – Optional custom styling via `className` prop
20
- - **Flexible Positioning** 7 different display positions
21
- - **Theme Support** Light, dark, and colored themes
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
- [![Live Demo](https://img.shields.io/badge/Live_Demo-CodeSandbox-000000?style=for-the-badge&logo=codesandbox&logoColor=white)](https://codesandbox.io/embed/cqkyzm?view=preview&module=%2Fpublic%2Findex.html)
31
+ [![Live Demo](https://img.shields.io/badge/Live_Demo-CodeSandbox-000000?style=for-the-badge\&logo=codesandbox\&logoColor=white)](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
- ### 2. Use toast notifications anywhere
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
- const handleClick = () => {
69
- showToast({
70
- message: "Operation completed successfully!",
71
- type: "success",
72
- position: "top-right",
73
- duration: 3000,
74
- });
75
- };
76
-
77
- return <button onClick={handleClick}>Show Toast</button>;
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
- Returns an object with toast management methods:
96
+ ```ts
97
+ const { showToast, removeToast, removeToastAll } = useToast();
98
+ ```
86
99
 
87
100
  | Method | Description |
88
101
  | -------------------- | --------------------------------- |
89
- | `showToast(options)` | Displays a new toast notification |
90
- | `removeToast(id)` | Removes a specific toast by ID |
91
- | `removeToastAll()` | Removes all active toasts |
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
- ```jsx
116
- showToast({
117
- message: (
118
- <div>
119
- <strong>Custom Content</strong>
120
- <p>With formatted HTML/JSX</p>
121
- </div>
122
- ),
123
- type: "info",
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
- ### Action Buttons
139
+ **Example**
128
140
 
129
141
  ```jsx
130
142
  showToast({
131
- message: "File uploaded successfully",
132
- type: "success",
143
+ message: "File uploaded",
133
144
  actions: [
134
145
  {
135
- text: "View",
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
- ### Manual Control
153
+ ---
149
154
 
150
- ```jsx
151
- const { showToast, removeToast, removeToastAll } = useToast();
155
+ ## 🔊 Audio Support (NEW)
152
156
 
153
- // Show a persistent toast
154
- const toastId = showToast({
155
- message: "Processing...",
156
- type: "loading",
157
- duration: 0, // Infinite
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
- // Remove it later
161
- removeToast(toastId);
168
+ ### Example
162
169
 
163
- // Clear all toasts
164
- removeToastAll();
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 CSS
190
+ ### Default Styles
170
191
 
171
- ```jsx
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: "Custom styled toast",
200
+ message: "Styled Toast",
181
201
  className:
182
- "bg-gradient-to-r from-gray-800 to-gray-600 !text-white !shadow-xl !rounded-lg",
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
- ### Theme Examples
206
+ > ⚠️ Use `!important` when overriding styles with Tailwind
188
207
 
189
- ```jsx
190
- // Light theme (default)
191
- showToast({ message: "Light", theme: "light" });
208
+ ---
192
209
 
193
- // Dark theme
194
- showToast({ message: "Dark", theme: "dark" });
210
+ ## 🧠 Advanced Usage
195
211
 
196
- // Colored theme (uses type for color)
197
- showToast({
198
- message: "Colored",
199
- theme: "colored",
200
- type: "success",
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
- ## 🔧 Development
225
+ ---
205
226
 
206
- ### Build
227
+ ### JSX Content
207
228
 
208
- ```bash
209
- npm run build
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
- Outputs to `dist/` directory:
240
+ ---
213
241
 
214
- - `dist/index.js` JavaScript bundle
215
- - `dist/toast.css` – Default styles
242
+ ## 🧾 TypeScript Support
216
243
 
217
- ### Local Development
244
+ D9-Toast ships with **full TypeScript definitions**:
218
245
 
219
- ```bash
220
- npm start
221
- # or
222
- npm run dev
246
+ ```ts
247
+ import type { ToastOptions, ToastType } from "d9-toast";
223
248
  ```
224
249
 
225
- ## 🤝 Contributing
226
-
227
- Contributions are welcome! Please feel free to submit a Pull Request.
228
-
229
- ## 📄 License
230
-
231
- MIT © [Athul / D9 Coder]
250
+ IntelliSense
251
+ ✔ Strict typing
252
+ No `any`
232
253
 
233
254
  ---
234
255
 
235
- ## 🙏 Acknowledgments
256
+ ## 📄 License
236
257
 
237
- - Inspired by popular notification libraries
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
- Donate here → https://rzp.io/rzp/eVnJ0oP
246
-
247
- [![Donate via Razorpay](https://img.shields.io/badge/Donate-Razorpay-blue)](https://rzp.io/rzp/eVnJ0oP)
264
+ 👉 [https://rzp.io/rzp/eVnJ0oP](https://rzp.io/rzp/eVnJ0oP)
248
265
 
249
266
  ---
250
267
 
251
- **Quick Links:**
268
+ ## 🔗 Links
252
269
 
253
- - [Report an Issue](https://github.com/psathul073/d9-toast/issues)
254
- - [View Source](https://github.com/psathul073/d9-toast)
255
- - [npm Package](https://www.npmjs.com/package/d9-toast)
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)
@@ -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,105 @@ export var ToastProvider = function ToastProvider(_ref) {
36
60
  };
37
61
 
38
62
  // Positions.
39
- var positions = ["top-left", "top-right", "bottom-left", "bottom-right", "center", "center-top", "center-bottom"];
63
+ // const positions = [
64
+ // "top-left",
65
+ // "top-right",
66
+ // "bottom-left",
67
+ // "bottom-right",
68
+ // "center",
69
+ // "center-top",
70
+ // "center-bottom",
71
+ // ];
40
72
 
41
73
  // Show toast..
42
74
  var showToast = useCallback(function (toast) {
43
- var newToast = _objectSpread({
75
+ var _toast$audio$enabled, _toast$audio, _toast$audio$volume, _toast$audio2, _toast$audio$audioFil, _toast$audio3, _toast$audio$cooldown, _toast$audio4;
76
+ var newToast = _objectSpread(_objectSpread({
44
77
  id: generateId()
45
- }, toast);
78
+ }, toast), {}, {
79
+ audio: {
80
+ 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,
81
+ // Toast-specific audio setting.
82
+ 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,
83
+ // Custom volume per toast.
84
+ 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,
85
+ // Custom sound per toast.
86
+ 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.
87
+ }
88
+ });
46
89
  setToasts(function (prev) {
47
90
  return [].concat(_toConsumableArray(prev), [newToast]);
48
91
  });
49
- if (toast.duration !== 0 && toast.autoClose) {
92
+ var audio = newToast.audio,
93
+ type = newToast.type;
94
+ var now = Date.now();
95
+ var cooldown = Number(audio.cooldown) || audioSettings.cooldown;
96
+ var canPlaySound = now - lastSoundTimeRef.current >= cooldown;
97
+ var bypassCooldown = type === "error"; // Bypass error toast
98
+
99
+ // Play audio whenever a new toast appears.
100
+ if (audio.enabled && audio.audioFile && (canPlaySound || bypassCooldown)) {
101
+ lastSoundTimeRef.current = now;
102
+ playAudio({
103
+ audioFile: audio.audioFile,
104
+ volume: audio.volume
105
+ });
106
+ }
107
+ var shouldAutoClose = toast.autoClose !== false && toast.duration !== 0;
108
+ if (shouldAutoClose) {
50
109
  setTimeout(function () {
51
110
  return removeToast(newToast.id);
52
111
  }, toast.duration || 5000);
53
112
  }
54
113
  return newToast === null || newToast === void 0 ? void 0 : newToast.id;
55
- }, []);
114
+ }, [playAudio]);
56
115
 
57
116
  // Remove toast
58
117
  var removeToast = useCallback(function (id) {
59
118
  setToasts(function (prev) {
60
- return prev.filter(function (t) {
119
+ var newToasts = prev.filter(function (t) {
61
120
  return t.id !== id;
62
121
  });
122
+ return newToasts;
63
123
  });
64
124
  }, []);
65
125
 
66
126
  // Remove all toast.
67
- var removeToastAll = function removeToastAll() {
127
+ var removeToastAll = useCallback(function () {
68
128
  if (toasts.length > 0) {
69
129
  setToasts([]);
70
130
  }
71
- };
131
+ }, [toasts.length]);
132
+
133
+ // Group toasts by there positions..
134
+ var groupedToasts = toasts.reduce(function (acc, toast) {
135
+ var position = toast.position || "top-right";
136
+ if (!acc[position]) {
137
+ acc[position] = [];
138
+ }
139
+ acc[position].push(toast);
140
+ return acc;
141
+ }, {});
72
142
  return /*#__PURE__*/_jsxs(ToastContext.Provider, {
73
143
  value: {
74
144
  showToast: showToast,
75
145
  removeToast: removeToast,
76
146
  removeToastAll: removeToastAll
77
147
  },
78
- children: [children, /*#__PURE__*/_jsx("div", {
79
- className: "toastContainer ".concat(positions.some(function (p) {
80
- var _toasts$;
81
- return p === ((_toasts$ = toasts[0]) === null || _toasts$ === void 0 ? void 0 : _toasts$.position);
82
- }) ? (_toasts$2 = toasts[0]) === null || _toasts$2 === void 0 ? void 0 : _toasts$2.position : "top-right"),
83
- children: toasts.map(function (toast) {
84
- return /*#__PURE__*/_jsx(Toast, _objectSpread(_objectSpread({}, toast), {}, {
85
- remove: function remove() {
86
- return removeToast(toast.id);
87
- }
88
- }), toast.id);
89
- })
148
+ children: [children, Object.entries(groupedToasts).map(function (_ref3) {
149
+ var _ref4 = _slicedToArray(_ref3, 2),
150
+ position = _ref4[0],
151
+ positionToasts = _ref4[1];
152
+ return /*#__PURE__*/_jsx("div", {
153
+ className: "toastContainer ".concat(position),
154
+ children: positionToasts.map(function (toast) {
155
+ return /*#__PURE__*/_jsx(Toast, _objectSpread(_objectSpread({}, toast), {}, {
156
+ remove: function remove() {
157
+ return removeToast(toast.id);
158
+ }
159
+ }), toast.id);
160
+ })
161
+ }, position);
90
162
  })]
91
163
  });
92
164
  };
Binary file
@@ -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: string;
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
- /** Weather to show toast title */
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: smaller;
100
- font-family: Arial, Helvetica, sans-serif;
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
- --primary-bg: #1e2939;
153
+ --primary-bg: #06060606;
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: 5px;
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: 8px;
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: var(--primary-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: 0px 0px 1px #0b0b0b89;
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
- background-color: var(--loading-bg);
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: 375px) {
423
+ @media screen and (max-width: 426px) {
395
424
  .toastContainer.top-right,
396
425
  .toastContainer.bottom-right {
397
426
  right: 0px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "d9-toast",
3
- "version": "1.3.24",
3
+ "version": "1.4.24",
4
4
  "description": "Customizable toast notifications for React",
5
5
  "homepage": "https://codesandbox.io/embed/cqkyzm?view=preview",
6
6
  "repository": {