d9-toast 1.1.16 → 1.1.18

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
@@ -10,11 +10,15 @@ Customizable toast notifications for React.
10
10
  * Pure CSS included — no additional setup required.
11
11
  * Easy to import and use in any React project.
12
12
  * Supports multiple types: success, error, info, warning, loading, submit.
13
- * Fully responsive and modern UI.
13
+ * Fully responsive and modern UI and smooth animation.
14
14
  * Users can optionally add Tailwind CSS classes via `className` for custom styling.
15
15
 
16
16
  ---
17
17
 
18
+ ## Demo
19
+
20
+ [Click Here](https://codesandbox.io/embed/cqkyzm?view=preview&module=%2Fpublic%2Findex.html)
21
+
18
22
  ## Installation
19
23
 
20
24
  ```bash
@@ -40,7 +44,7 @@ import App from "./App";
40
44
 
41
45
  function Root() {
42
46
  return (
43
- <ToastProvider position="top-right">
47
+ <ToastProvider>
44
48
  <App />
45
49
  </ToastProvider>
46
50
  );
@@ -57,16 +61,17 @@ import { useToast } from "d9-toast";
57
61
 
58
62
  function App() {
59
63
 
60
- const { showToast, removeToast } = useToast();
64
+ const { showToast, removeToast, removeToastAll } = useToast();
61
65
 
62
66
  const Toast = () => {
63
67
  showToast({
64
68
  message: "Hello World!",
65
69
  type: "success", // success | error | info | warning | loading | submit
70
+ position: "top-right",
66
71
  duration: 3000,
67
72
  actions: [
68
- { text: "Save", callback: () => console.log("Save clicked") },
69
- { text: "Undo", callback: () => console.log("Undo clicked") },
73
+ { text: "Toast ID", callback: (toastId) => console.log(toastId) },
74
+ { text: "Submit", callback: () => console.log("Submit clicked") },
70
75
  ],
71
76
  className: "bg-green-500 text-white shadow-lg", // optional Tailwind/custom styling
72
77
  });
@@ -78,26 +83,21 @@ function App() {
78
83
  export default App;
79
84
  ```
80
85
 
81
- ### 3. ToastProvider Props
82
-
83
- | Prop | Type | Default | Description |
84
- | ------------------ | ------- | ----------- | ------------------------------------------------------------------------------- |
85
- | `position` | string | `top-right` | Position of all toasts (`top-left`, `top-right`, `bottom-left`, `bottom-right`, `center`, `center-top`, `center-bottom` ) |
86
-
87
-
88
- ### 4. Toast Options
86
+ ### 3. Toast Options
89
87
 
90
88
  | Option | Type | Default | Description |
91
89
  | ---------- | ------- | ------- | -------------------------------------------------------------------------- |
92
- | `message` | string | - | The message to display |
90
+ | `message` | string | - | Main message text of the toast |
93
91
  | `type` | string | `info` | Type of toast (`success`, `error`, `info`, `warning`, `loading`, `submit`) |
94
92
  | `duration` | number | 5000 | Auto-close duration in ms (0 for infinite) |
93
+ | `position` | string | `top-right` | Position of all toasts (`top-left`, `top-right`, `bottom-left`, `bottom-right`, `center`, `center-top`, `center-bottom` ) |
95
94
  | `theme` | string | `light` | Default theme for all toasts (`light` or `dark`) |
96
- | `pauseOnHover` | boolean | `true` | Pause toast timer on hover |
97
- | `pauseOnFocusLoss` | boolean | `true` | Pause toast timer when window loses focus |
95
+ | `pauseOnHover` | boolean | `true` | Pause timer when hovered |
96
+ | `pauseOnFocusLoss` | boolean | `true` | Pause timer when window/tab loses focus |
98
97
  | `actions` | array | [] | Array of action objects `{ text: string, callback: function }` |
99
- | `closable` | boolean | true | Show close button |
100
- | `progress` | boolean | true | Show progress bar |
98
+ | `closable` | boolean | true | Allow manual close via X button
99
+ | `autoClose` | boolean | true | Whether the toast auto-closes after duration button |
100
+ | `progress` | boolean | true | Whether to show progress bar |
101
101
  | `className` | string| " " | Optional extra CSS/Tailwind classes to customize the toast bar |
102
102
 
103
103
  ---
package/dist/Toast.js CHANGED
@@ -15,6 +15,8 @@ var Toast = function Toast(_ref) {
15
15
  type = _ref$type === void 0 ? "info" : _ref$type,
16
16
  _ref$theme = _ref.theme,
17
17
  theme = _ref$theme === void 0 ? "light" : _ref$theme,
18
+ _ref$position = _ref.position,
19
+ position = _ref$position === void 0 ? "top-right" : _ref$position,
18
20
  _ref$className = _ref.className,
19
21
  className = _ref$className === void 0 ? "" : _ref$className,
20
22
  _ref$duration = _ref.duration,
@@ -22,9 +24,10 @@ var Toast = function Toast(_ref) {
22
24
  _ref$actions = _ref.actions,
23
25
  actions = _ref$actions === void 0 ? [] : _ref$actions,
24
26
  remove = _ref.remove,
25
- position = _ref.position,
26
27
  _ref$progress = _ref.progress,
27
28
  progress = _ref$progress === void 0 ? true : _ref$progress,
29
+ _ref$autoClose = _ref.autoClose,
30
+ autoClose = _ref$autoClose === void 0 ? true : _ref$autoClose,
28
31
  _ref$closable = _ref.closable,
29
32
  closable = _ref$closable === void 0 ? true : _ref$closable,
30
33
  _ref$pauseOnHover = _ref.pauseOnHover,
@@ -42,13 +45,23 @@ var Toast = function Toast(_ref) {
42
45
  _useState4 = _slicedToArray(_useState3, 2),
43
46
  isPaused = _useState4[0],
44
47
  setPaused = _useState4[1]; // For timer pause
48
+ var _useState5 = useState(false),
49
+ _useState6 = _slicedToArray(_useState5, 2),
50
+ exiting = _useState6[0],
51
+ setExiting = _useState6[1];
52
+
53
+ // Styles [Animation]
54
+ // entry animation [based on position]
55
+ var enterAnim = "".concat(position.startsWith("top") && "upToDown" || position.startsWith("bottom") && "downToUp" || position.endsWith("top") && "upToDown" || position.endsWith("bottom") && "downToUp" || "centerEnter", " 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards");
56
+
57
+ // exit animation [reverse direction]
58
+ var exitAnim = "".concat(position.startsWith("top") && "downToUpExit" || position.startsWith("bottom") && "upToDownExit" || position.endsWith("top") && "downToUpExit" || position.endsWith("bottom") && "upToDownExit" || "centerExit", " 0.25s cubic-bezier(0.39, 0.575, 0.565, 1) forwards");
45
59
 
46
60
  // Start auto-close timer.
47
61
  useEffect(function () {
48
- if (duration !== 0) {
62
+ if (duration !== 0 && autoClose) {
49
63
  startTimer();
50
64
  }
51
-
52
65
  // pause/resume when window focus changes.
53
66
  var handleBlur = function handleBlur() {
54
67
  return pauseOnFocusLoss && pauseTimer();
@@ -67,11 +80,12 @@ var Toast = function Toast(_ref) {
67
80
  window.removeEventListener("focus", handleFocus);
68
81
  }
69
82
  };
70
- }, [duration, pauseOnFocusLoss]);
83
+ }, [duration, autoClose, pauseOnFocusLoss]);
71
84
 
72
85
  // --- Helpers Fun ---
73
86
  // for start
74
87
  var startTimer = function startTimer() {
88
+ if (!autoClose) return;
75
89
  intervalRef.current = setInterval(function () {
76
90
  // time to passed...
77
91
  var elapsed = Date.now() - start.current;
@@ -83,14 +97,14 @@ var Toast = function Toast(_ref) {
83
97
  // stop timer...
84
98
  clearInterval(intervalRef.current);
85
99
  // remove toast.
86
- remove();
100
+ triggerExit();
87
101
  }
88
102
  }, 100);
89
103
  };
90
104
 
91
105
  // for pause
92
106
  var pauseTimer = function pauseTimer() {
93
- if (isPaused) return;
107
+ if (isPaused && !autoClose) return;
94
108
  clearInterval(intervalRef.current);
95
109
  remaining.current = remaining.current - (Date.now() - start.current);
96
110
  setPaused(true);
@@ -98,18 +112,23 @@ var Toast = function Toast(_ref) {
98
112
 
99
113
  // for resume
100
114
  var resumeTimer = function resumeTimer() {
101
- if (!isPaused) return;
115
+ if (!isPaused && !autoClose) return;
102
116
  start.current = Date.now();
103
117
  setPaused(false);
104
118
  startTimer();
105
119
  };
106
120
 
107
- // Styles
108
- var animation = "".concat(position.startsWith("top") && "upToDown" || position.startsWith("bottom") && "downToUp" || position.endsWith("top") && "upToDown" || position.endsWith("bottom") && "downToUp", " 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)");
121
+ // for exit
122
+ var triggerExit = function triggerExit() {
123
+ setExiting(true);
124
+ setTimeout(function () {
125
+ return remove();
126
+ }, 250); // Set and match exit animation duration.
127
+ };
109
128
  return /*#__PURE__*/_jsx(_Fragment, {
110
129
  children: /*#__PURE__*/_jsxs("div", {
111
130
  style: {
112
- animation: animation
131
+ animation: exiting ? exitAnim : enterAnim
113
132
  },
114
133
  className: "toast ".concat(theme, " ").concat(className),
115
134
  onMouseEnter: pauseOnHover ? pauseTimer : undefined,
@@ -124,7 +143,9 @@ var Toast = function Toast(_ref) {
124
143
  children: type.toUpperCase()
125
144
  })]
126
145
  }), closable && /*#__PURE__*/_jsx("button", {
127
- onClick: remove,
146
+ onClick: function onClick() {
147
+ return triggerExit();
148
+ },
128
149
  children: /*#__PURE__*/_jsx(Icons, {
129
150
  name: "X"
130
151
  })
@@ -150,7 +171,7 @@ var Toast = function Toast(_ref) {
150
171
  }, idx);
151
172
  }
152
173
  })
153
- }), progress && duration !== 0 && /*#__PURE__*/_jsx("div", {
174
+ }), progress && duration !== 0 && autoClose && /*#__PURE__*/_jsx("div", {
154
175
  className: "progress-container ".concat(type),
155
176
  children: /*#__PURE__*/_jsx("div", {
156
177
  className: "toast-progress ".concat(type),
@@ -23,9 +23,8 @@ export var useToast = function useToast() {
23
23
  return useContext(ToastContext);
24
24
  };
25
25
  export var ToastProvider = function ToastProvider(_ref) {
26
- var children = _ref.children,
27
- _ref$position = _ref.position,
28
- position = _ref$position === void 0 ? "top-right" : _ref$position;
26
+ var _toasts$2;
27
+ var children = _ref.children;
29
28
  var _useState = useState([]),
30
29
  _useState2 = _slicedToArray(_useState, 2),
31
30
  toasts = _useState2[0],
@@ -39,7 +38,7 @@ export var ToastProvider = function ToastProvider(_ref) {
39
38
  // Positions.
40
39
  var positions = ["top-left", "top-right", "bottom-left", "bottom-right", "center", "center-top", "center-bottom"];
41
40
 
42
- // Show toast
41
+ // Show toast..
43
42
  var showToast = useCallback(function (toast) {
44
43
  var newToast = _objectSpread({
45
44
  id: generateId()
@@ -47,7 +46,7 @@ export var ToastProvider = function ToastProvider(_ref) {
47
46
  setToasts(function (prev) {
48
47
  return [].concat(_toConsumableArray(prev), [newToast]);
49
48
  });
50
- if (toast.duration !== 0) {
49
+ if (toast.duration !== 0 && toast.autoClose) {
51
50
  setTimeout(function () {
52
51
  return removeToast(newToast.id);
53
52
  }, toast.duration || 5000);
@@ -62,18 +61,26 @@ export var ToastProvider = function ToastProvider(_ref) {
62
61
  });
63
62
  });
64
63
  }, []);
64
+
65
+ // Remove all toast.
66
+ var removeToastAll = function removeToastAll() {
67
+ if (toasts.length > 0) {
68
+ setToasts([]);
69
+ }
70
+ };
65
71
  return /*#__PURE__*/_jsxs(ToastContext.Provider, {
66
72
  value: {
67
73
  showToast: showToast,
68
- removeToast: removeToast
74
+ removeToast: removeToast,
75
+ removeToastAll: removeToastAll
69
76
  },
70
77
  children: [children, /*#__PURE__*/_jsx("div", {
71
78
  className: "toastContainer ".concat(positions.some(function (p) {
72
- return p === position;
73
- }) ? position : "top-right"),
79
+ var _toasts$;
80
+ return p === ((_toasts$ = toasts[0]) === null || _toasts$ === void 0 ? void 0 : _toasts$.position);
81
+ }) ? (_toasts$2 = toasts[0]) === null || _toasts$2 === void 0 ? void 0 : _toasts$2.position : "top-right"),
74
82
  children: toasts.map(function (toast) {
75
83
  return /*#__PURE__*/_jsx(Toast, _objectSpread(_objectSpread({}, toast), {}, {
76
- position: position,
77
84
  remove: function remove() {
78
85
  return removeToast(toast.id);
79
86
  }
@@ -1,6 +1,7 @@
1
1
  declare module "d9-toast" {
2
2
  import React from "react";
3
3
 
4
+ /** Toast type (icon + header color) */
4
5
  export type ToastType =
5
6
  | "success"
6
7
  | "error"
@@ -9,40 +10,74 @@ declare module "d9-toast" {
9
10
  | "loading"
10
11
  | "submit";
11
12
 
13
+ /** Theme variants */
14
+ export type ToastTheme = "light" | "dark";
15
+
16
+ /** Available toast positions */
17
+ export type ToastPosition =
18
+ | "top-right"
19
+ | "top-left"
20
+ | "bottom-right"
21
+ | "bottom-left"
22
+ | "center"
23
+ | "center-top"
24
+ | "center-bottom";
25
+
26
+ /** Single button/action displayed inside a toast */
12
27
  export interface ToastAction {
28
+ /** Text label for the action button */
13
29
  text: string;
30
+ /** Optional callback triggered on click */
14
31
  callback?: (toast: { id: number }) => void;
15
32
  }
16
33
 
34
+ /** Toast configuration options */
17
35
  export interface ToastOptions {
36
+ /** Main message text of the toast */
18
37
  message: string;
38
+ /** Visual type (color/icon) */
19
39
  type?: ToastType;
40
+ /** Duration in ms before auto-close (0 = persistent) */
20
41
  duration?: number;
42
+ /** Optional buttons shown inside the toast */
21
43
  actions?: ToastAction[];
22
- theme?: "light" | "dark";
44
+ /** Visual theme */
45
+ theme?: ToastTheme;
46
+ /** Whether to show progress bar */
23
47
  progress?: boolean;
48
+ /** Allow manual close via X button */
24
49
  closable?: boolean;
50
+ /** Pause timer when hovered */
25
51
  pauseOnHover?: boolean;
52
+ /** Pause timer when window/tab loses focus */
26
53
  pauseOnFocusLoss?: boolean;
27
- className?: string;
54
+ /** Extra custom class names */
55
+ className?: string;
56
+ /** Where to place the toast on screen */
57
+ position?: ToastPosition;
58
+ /** Whether the toast auto-closes after duration */
59
+ autoClose?: boolean;
28
60
  }
29
61
 
62
+ /** Toast provider props for context setup */
30
63
  export interface ToastProviderProps {
64
+ /** App children to wrap with ToastProvider */
31
65
  children: React.ReactNode;
32
- position?:
33
- | "top-right"
34
- | "top-left"
35
- | "bottom-right"
36
- | "bottom-left"
37
- | "center"
38
- | "center-top"
39
- | "center-bottom";
40
66
  }
41
67
 
42
- export const ToastProvider: React.FC<ToastProviderProps>;
43
-
44
- export const useToast: () => {
68
+ /** Context value shape */
69
+ export interface ToastContextValue {
70
+ /** Show a toast with given options */
45
71
  showToast: (toast: ToastOptions) => void;
72
+ /** Remove a toast by ID */
46
73
  removeToast: (id: number) => void;
47
- };
74
+ /** Remove all active toasts */
75
+ removeToastAll: () => void;
76
+ }
77
+
78
+ /** Context provider component */
79
+ export const ToastProvider: React.FC<ToastProviderProps>;
80
+
81
+ /** Hook to trigger and manage toasts */
82
+ export const useToast: () => ToastContextValue;
48
83
  }
package/dist/toast.css CHANGED
@@ -1,5 +1,5 @@
1
1
  /* Defaults */
2
- button,
2
+ .toastContainer button,
3
3
  p,
4
4
  span {
5
5
  font: inherit;
@@ -43,11 +43,13 @@ span {
43
43
  transform: translate(-50%, -50%);
44
44
  }
45
45
  .toastContainer.center-top {
46
+ flex-direction: column;
46
47
  top: 16px;
47
48
  left: 50%;
48
49
  transform: translateX(-50%);
49
50
  }
50
51
  .toastContainer.center-bottom {
52
+ flex-direction: column-reverse;
51
53
  bottom: 16px;
52
54
  left: 50%;
53
55
  transform: translateX(-50%);
@@ -244,25 +246,71 @@ span {
244
246
  background-color: oklab(54.13400000000001% 0.09644 -0.22706);
245
247
  }
246
248
 
249
+ /* Enter animate keyframes */
250
+ @keyframes upToDown {
251
+ from {
252
+ opacity: 0;
253
+ transform: translateY(-60px) scale(0.6);
254
+ }
255
+ to {
256
+ opacity: 1;
257
+ transform: translateY(0) scale(1);
258
+ }
259
+ }
260
+
247
261
  @keyframes downToUp {
248
262
  from {
249
- transform: translateY(100%);
250
263
  opacity: 0;
264
+ transform: translateY(60px) scale(0.6);
251
265
  }
252
266
  to {
253
- transform: translateY(0);
254
267
  opacity: 1;
268
+ transform: translateY(0) scale(1);
255
269
  }
256
270
  }
257
271
 
258
- @keyframes upToDown {
272
+ /* Exit animate keyframes */
273
+ @keyframes upToDownExit {
274
+ from {
275
+ opacity: 1;
276
+ transform: translateY(0) scale(1);
277
+ }
278
+ to {
279
+ opacity: 0;
280
+ transform: translateY(60px) scale(0.6);
281
+ }
282
+ }
283
+
284
+ @keyframes downToUpExit {
285
+ from {
286
+ opacity: 1;
287
+ transform: translateY(0) scale(1);
288
+ }
289
+ to {
290
+ opacity: 0;
291
+ transform: translateY(-60px) scale(0.6);
292
+ }
293
+ }
294
+
295
+ @keyframes centerEnter {
259
296
  from {
260
- transform: translateY(-100%);
261
297
  opacity: 0;
298
+ transform: scale(0.6);
262
299
  }
263
300
  to {
264
- transform: translateY(0);
265
301
  opacity: 1;
302
+ transform: scale(1);
303
+ }
304
+ }
305
+
306
+ @keyframes centerExit {
307
+ from {
308
+ opacity: 1;
309
+ transform: scale(1);
310
+ }
311
+ to {
312
+ opacity: 0;
313
+ transform: scale(0.6);
266
314
  }
267
315
  }
268
316
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "d9-toast",
3
- "version": "1.1.16",
3
+ "version": "1.1.18",
4
4
  "description": "Customizable toast notifications for React",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",