toastflux 1.0.0 → 1.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/LICENSE +21 -0
- package/package.json +10 -2
- package/packages/react/dist/index.js +108 -30
- package/packages/react/dist/index.js.map +1 -1
- package/packages/react/dist/index.mjs +108 -30
- package/packages/react/dist/index.mjs.map +1 -1
- package/packages/styles/toast.css +202 -174
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rahul Bairwa
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toastflux",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "A lightweight, beautiful, and fully customizable toast notification library for React & Next.js with modern UI, themes, actions, and progress support.",
|
|
5
5
|
"author": "Rahul",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
@@ -36,6 +36,14 @@
|
|
|
36
36
|
"sideEffects": [
|
|
37
37
|
"*.css"
|
|
38
38
|
],
|
|
39
|
+
"homepage": "https://github.com/Rahul-Bairwa/toastflux",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "https://github.com/Rahul-Bairwa/toastflux.git"
|
|
43
|
+
},
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/Rahul-Bairwa/toastflux/issues"
|
|
46
|
+
},
|
|
39
47
|
"peerDependencies": {
|
|
40
48
|
"react": ">=16.8.0",
|
|
41
49
|
"react-dom": ">=16.8.0"
|
|
@@ -25,6 +25,9 @@ __export(index_exports, {
|
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(index_exports);
|
|
27
27
|
|
|
28
|
+
// packages/react/src/Toaster.tsx
|
|
29
|
+
var import_react3 = require("react");
|
|
30
|
+
|
|
28
31
|
// packages/react/src/useToast.ts
|
|
29
32
|
var import_react = require("react");
|
|
30
33
|
|
|
@@ -120,29 +123,34 @@ var icons = {
|
|
|
120
123
|
] }),
|
|
121
124
|
default: null
|
|
122
125
|
};
|
|
123
|
-
|
|
126
|
+
var MAX_STACK_VISIBLE = 3;
|
|
127
|
+
var PEEK_OFFSET = 10;
|
|
128
|
+
var SCALE_STEP = 0.05;
|
|
129
|
+
var OPACITY_STEP = 0.15;
|
|
130
|
+
function ToastItem({ toast: toast2, index, total, isExpanded, isBottom }) {
|
|
124
131
|
var _a;
|
|
125
132
|
const duration = (_a = toast2.duration) != null ? _a : 3e3;
|
|
126
133
|
const [offset, setOffset] = (0, import_react2.useState)(0);
|
|
127
134
|
const [isDragging, setIsDragging] = (0, import_react2.useState)(false);
|
|
128
|
-
const [
|
|
135
|
+
const [isItemHovered, setIsItemHovered] = (0, import_react2.useState)(false);
|
|
129
136
|
const dragStartX = (0, import_react2.useRef)(null);
|
|
130
137
|
const remainingTime = (0, import_react2.useRef)(duration);
|
|
131
138
|
const startTime = (0, import_react2.useRef)(Date.now());
|
|
139
|
+
const isPaused = isExpanded || isItemHovered || isDragging;
|
|
132
140
|
(0, import_react2.useEffect)(() => {
|
|
133
141
|
if (duration === Infinity || duration <= 0) return;
|
|
134
|
-
if (
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}, [isHovered, isDragging, duration, toast2.id]);
|
|
142
|
+
if (isPaused) return;
|
|
143
|
+
startTime.current = Date.now();
|
|
144
|
+
const timer = setTimeout(() => {
|
|
145
|
+
toast.dismiss(toast2.id);
|
|
146
|
+
}, remainingTime.current);
|
|
147
|
+
return () => {
|
|
148
|
+
clearTimeout(timer);
|
|
149
|
+
remainingTime.current -= Date.now() - startTime.current;
|
|
150
|
+
};
|
|
151
|
+
}, [isPaused, duration, toast2.id]);
|
|
145
152
|
const handlePointerDown = (e) => {
|
|
153
|
+
if (!isExpanded && index !== 0) return;
|
|
146
154
|
if (e.target.closest("button")) return;
|
|
147
155
|
dragStartX.current = e.clientX;
|
|
148
156
|
setIsDragging(true);
|
|
@@ -166,23 +174,52 @@ function ToastItem({ toast: toast2 }) {
|
|
|
166
174
|
setOffset(0);
|
|
167
175
|
}
|
|
168
176
|
};
|
|
177
|
+
const stackDepth = index;
|
|
178
|
+
const isHidden = stackDepth >= MAX_STACK_VISIBLE;
|
|
179
|
+
const scale = 1 - stackDepth * SCALE_STEP;
|
|
180
|
+
const peekY = stackDepth * PEEK_OFFSET * (isBottom ? -1 : 1);
|
|
181
|
+
const opacity = isHidden ? 0 : 1 - stackDepth * OPACITY_STEP;
|
|
182
|
+
let containerStyle;
|
|
183
|
+
if (!isExpanded) {
|
|
184
|
+
containerStyle = {
|
|
185
|
+
position: "absolute",
|
|
186
|
+
top: isBottom ? void 0 : 0,
|
|
187
|
+
bottom: isBottom ? 0 : void 0,
|
|
188
|
+
left: 0,
|
|
189
|
+
right: 0,
|
|
190
|
+
transform: `translateY(${peekY}px) scale(${scale})${offset ? ` translateX(${offset}px)` : ""}`,
|
|
191
|
+
opacity,
|
|
192
|
+
zIndex: total - stackDepth,
|
|
193
|
+
visibility: isHidden ? "hidden" : "visible",
|
|
194
|
+
pointerEvents: index === 0 ? "auto" : "none",
|
|
195
|
+
transformOrigin: isBottom ? "bottom center" : "top center"
|
|
196
|
+
};
|
|
197
|
+
} else {
|
|
198
|
+
containerStyle = {
|
|
199
|
+
position: "relative",
|
|
200
|
+
transform: offset ? `translateX(${offset}px)` : void 0,
|
|
201
|
+
opacity: 1,
|
|
202
|
+
zIndex: total - stackDepth,
|
|
203
|
+
pointerEvents: "auto"
|
|
204
|
+
};
|
|
205
|
+
}
|
|
169
206
|
const dynamicStyle = {
|
|
170
207
|
...toast2.style,
|
|
171
|
-
|
|
172
|
-
transition: isDragging ? "
|
|
208
|
+
...containerStyle,
|
|
209
|
+
transition: isDragging ? "opacity 0.3s ease, visibility 0.3s ease" : "transform 0.35s cubic-bezier(0.34, 1.15, 0.64, 1), opacity 0.3s ease, visibility 0.3s ease",
|
|
173
210
|
touchAction: "none"
|
|
174
211
|
};
|
|
175
212
|
if (toast2.render) {
|
|
176
213
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
177
214
|
"div",
|
|
178
215
|
{
|
|
179
|
-
style:
|
|
216
|
+
style: dynamicStyle,
|
|
180
217
|
onPointerDown: handlePointerDown,
|
|
181
218
|
onPointerMove: handlePointerMove,
|
|
182
219
|
onPointerUp: handlePointerUp,
|
|
183
220
|
onPointerCancel: handlePointerUp,
|
|
184
|
-
onMouseEnter: () =>
|
|
185
|
-
onMouseLeave: () =>
|
|
221
|
+
onMouseEnter: () => setIsItemHovered(true),
|
|
222
|
+
onMouseLeave: () => setIsItemHovered(false),
|
|
186
223
|
children: toast2.render()
|
|
187
224
|
}
|
|
188
225
|
);
|
|
@@ -198,23 +235,23 @@ function ToastItem({ toast: toast2 }) {
|
|
|
198
235
|
onPointerMove: handlePointerMove,
|
|
199
236
|
onPointerUp: handlePointerUp,
|
|
200
237
|
onPointerCancel: handlePointerUp,
|
|
201
|
-
onMouseEnter: () =>
|
|
202
|
-
onMouseLeave: () =>
|
|
238
|
+
onMouseEnter: () => setIsItemHovered(true),
|
|
239
|
+
onMouseLeave: () => setIsItemHovered(false),
|
|
203
240
|
children: [
|
|
204
|
-
Icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
241
|
+
Icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
242
|
+
"span",
|
|
243
|
+
{
|
|
244
|
+
className: "tf-icon",
|
|
245
|
+
style: { alignSelf: "flex-start", marginTop: "2px", color: toast2.iconColor },
|
|
246
|
+
children: Icon
|
|
247
|
+
}
|
|
248
|
+
),
|
|
205
249
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "tf-message", style: { flex: 1, display: "flex", flexDirection: "column" }, children: [
|
|
206
250
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: toast2.message }),
|
|
207
251
|
toast2.description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tf-description", children: toast2.description }),
|
|
208
252
|
toast2.progress !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tf-progress-bg", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tf-progress-fill", style: { width: `${toast2.progress}%` } }) })
|
|
209
253
|
] }),
|
|
210
|
-
toast2.action && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
211
|
-
"button",
|
|
212
|
-
{
|
|
213
|
-
onClick: toast2.action.onClick,
|
|
214
|
-
className: "tf-action-btn",
|
|
215
|
-
children: toast2.action.label
|
|
216
|
-
}
|
|
217
|
-
),
|
|
254
|
+
toast2.action && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: toast2.action.onClick, className: "tf-action-btn", children: toast2.action.label }),
|
|
218
255
|
toast2.dismissible && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
219
256
|
"button",
|
|
220
257
|
{
|
|
@@ -233,6 +270,7 @@ function ToastItem({ toast: toast2 }) {
|
|
|
233
270
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
234
271
|
function Toaster({ theme = "dark" } = {}) {
|
|
235
272
|
const toasts = useToastStore();
|
|
273
|
+
const [hoveredPos, setHoveredPos] = (0, import_react3.useState)(null);
|
|
236
274
|
if (typeof window === "undefined") return null;
|
|
237
275
|
const positions = [
|
|
238
276
|
"top-left",
|
|
@@ -248,7 +286,47 @@ function Toaster({ theme = "dark" } = {}) {
|
|
|
248
286
|
}, {});
|
|
249
287
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: positions.map((pos) => {
|
|
250
288
|
if (!groupedToasts[pos].length) return null;
|
|
251
|
-
|
|
289
|
+
const isBottom = pos.startsWith("bottom");
|
|
290
|
+
const posToasts = groupedToasts[pos];
|
|
291
|
+
const isExpanded = hoveredPos === pos;
|
|
292
|
+
const count = posToasts.length;
|
|
293
|
+
const PEEK_OFFSET2 = 10;
|
|
294
|
+
const MAX_VISIBLE_STACK = 3;
|
|
295
|
+
const visibleStack = Math.min(count - 1, MAX_VISIBLE_STACK - 1);
|
|
296
|
+
const collapsedExtraHeight = isExpanded ? 0 : visibleStack * PEEK_OFFSET2;
|
|
297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
298
|
+
"div",
|
|
299
|
+
{
|
|
300
|
+
className: `tf-toast-container tf-${pos} tf-theme-${theme}`,
|
|
301
|
+
style: { pointerEvents: "auto" },
|
|
302
|
+
onMouseEnter: () => setHoveredPos(pos),
|
|
303
|
+
onMouseLeave: () => setHoveredPos(null),
|
|
304
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
305
|
+
"div",
|
|
306
|
+
{
|
|
307
|
+
className: `tf-stack-wrapper ${isExpanded ? "tf-stack-expanded" : "tf-stack-collapsed"}`,
|
|
308
|
+
style: !isExpanded ? {
|
|
309
|
+
position: "relative",
|
|
310
|
+
// Extra padding at bottom (top positions) or top (bottom positions) for peeking
|
|
311
|
+
paddingBottom: !isBottom ? collapsedExtraHeight : 0,
|
|
312
|
+
paddingTop: isBottom ? collapsedExtraHeight : 0
|
|
313
|
+
} : { display: "flex", flexDirection: "column", gap: "10px" },
|
|
314
|
+
children: posToasts.map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
315
|
+
ToastItem,
|
|
316
|
+
{
|
|
317
|
+
toast: t,
|
|
318
|
+
index: i,
|
|
319
|
+
total: count,
|
|
320
|
+
isExpanded,
|
|
321
|
+
isBottom
|
|
322
|
+
},
|
|
323
|
+
t.id
|
|
324
|
+
))
|
|
325
|
+
}
|
|
326
|
+
)
|
|
327
|
+
},
|
|
328
|
+
pos
|
|
329
|
+
);
|
|
252
330
|
}) });
|
|
253
331
|
}
|
|
254
332
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/useToast.ts","../../core/src/store.ts","../../core/src/toast.ts","../src/ToastItem.tsx","../src/Toaster.tsx"],"sourcesContent":["export { Toaster } from \"./Toaster\";\r\nexport { toast } from \"../../core/src\";\r\n","import { useEffect, useState } from \"react\";\r\nimport { toastStore } from \"../../core/src\";\r\n\r\nexport function useToastStore() {\r\n const [toasts, setToasts] = useState(toastStore.getToasts());\r\n\r\n useEffect(() => {\r\n return toastStore.subscribe(() => {\r\n setToasts([...toastStore.getToasts()]);\r\n });\r\n }, []);\r\n\r\n return toasts;\r\n}\r\n","import { Toast } from \"./types\";\r\n\r\ntype Listener = () => void;\r\n\r\nclass ToastStore {\r\n private toasts: Toast[] = [];\r\n private listeners: Listener[] = [];\r\n\r\n subscribe(listener: Listener) {\r\n this.listeners.push(listener);\r\n return () => {\r\n this.listeners = this.listeners.filter((l) => l !== listener);\r\n };\r\n }\r\n\r\n getToasts() {\r\n return this.toasts;\r\n }\r\n\r\n add(toast: Toast) {\r\n this.toasts = [toast, ...this.toasts];\r\n this.emit();\r\n }\r\n\r\n remove(id: string) {\r\n this.toasts = this.toasts.filter((t) => t.id !== id);\r\n this.emit();\r\n }\r\n\r\n private emit() {\r\n this.listeners.forEach((l) => l());\r\n }\r\n}\r\n\r\nexport const toastStore = new ToastStore();\r\n","import { toastStore } from \"./store\";\nimport { Toast, ToastType } from \"./types\";\n\nexport type ToastOptions = Partial<Omit<Toast, \"id\" | \"type\" | \"createdAt\">>;\n\nfunction createToast(message: string | undefined, type: ToastType, options?: ToastOptions) {\n const id = crypto.randomUUID();\n\n toastStore.add({\n id,\n message,\n type,\n createdAt: Date.now(),\n ...options,\n });\n\n return id;\n}\n\nconst toastFn = (msg: string | undefined, type: ToastType = \"default\", options?: ToastOptions) => createToast(msg, type, options);\n\ntoastFn.success = (msg: string, options?: ToastOptions) => createToast(msg, \"success\", options);\ntoastFn.error = (msg: string, options?: ToastOptions) => createToast(msg, \"error\", options);\ntoastFn.info = (msg: string, options?: ToastOptions) => createToast(msg, \"info\", options);\ntoastFn.warning = (msg: string, options?: ToastOptions) => createToast(msg, \"warning\", options);\ntoastFn.loading = (msg: string, options?: ToastOptions) => createToast(msg, \"loading\", options);\ntoastFn.default = (msg: string, options?: ToastOptions) => createToast(msg, \"default\", options);\ntoastFn.custom = (options: ToastOptions) => createToast(options.message, \"default\", options);\n\ntoastFn.dismiss = (id: string) => toastStore.remove(id);\n\nexport const toast = toastFn;\n","import React, { useRef, useState, useEffect } from \"react\";\nimport { Toast, toast as toastLib } from \"../../core/src\";\n\nconst icons = {\n success: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 48 48\">\n <rect width=\"48\" height=\"48\" fill=\"none\" />\n <g fill=\"none\" stroke=\"currentColor\" strokeLinejoin=\"round\" strokeWidth=\"4\">\n <path d=\"M24 44a19.94 19.94 0 0 0 14.142-5.858A19.94 19.94 0 0 0 44 24a19.94 19.94 0 0 0-5.858-14.142A19.94 19.94 0 0 0 24 4A19.94 19.94 0 0 0 9.858 9.858A19.94 19.94 0 0 0 4 24a19.94 19.94 0 0 0 5.858 14.142A19.94 19.94 0 0 0 24 44Z\" />\n <path strokeLinecap=\"round\" d=\"m16 24l6 6l12-12\" />\n </g>\n </svg>\n ),\n info: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\">\n <rect width=\"24\" height=\"24\" fill=\"none\" />\n <path fill=\"currentColor\" d=\"M12.002 1.999c5.523 0 10.001 4.478 10.001 10.002c0 5.523-4.478 10.001-10.001 10.001C6.478 22.002 2 17.524 2 12.001C2 6.477 6.478 1.999 12.002 1.999m0 1.5a8.502 8.502 0 1 0 0 17.003a8.502 8.502 0 0 0 0-17.003M12 10.5a.75.75 0 0 1 .75.75v5a.75.75 0 0 1-1.5 0v-5a.75.75 0 0 1 .75-.75M12 9a1 1 0 1 0 0-2a1 1 0 0 0 0 2\" />\n </svg>\n ),\n warning: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 256 256\">\n <rect width=\"256\" height=\"256\" fill=\"none\" />\n <path fill=\"currentColor\" d=\"M236.8 188.09L149.35 36.22a24.76 24.76 0 0 0-42.7 0L19.2 188.09a23.51 23.51 0 0 0 0 23.72A24.35 24.35 0 0 0 40.55 224h174.9a24.35 24.35 0 0 0 21.33-12.19a23.51 23.51 0 0 0 .02-23.72m-13.87 15.71a8.5 8.5 0 0 1-7.48 4.2H40.55a8.5 8.5 0 0 1-7.48-4.2a7.59 7.59 0 0 1 0-7.72l87.45-151.87a8.75 8.75 0 0 1 15 0l87.45 151.87a7.59 7.59 0 0 1-.04 7.72M120 144v-40a8 8 0 0 1 16 0v40a8 8 0 0 1-16 0m20 36a12 12 0 1 1-12-12a12 12 0 0 1 12 12\" />\n </svg>\n ),\n error: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 16 16\">\n <rect width=\"16\" height=\"16\" fill=\"none\" />\n <path fill=\"currentColor\" d=\"M8 1C4.14 1 1 4.14 1 8s3.14 7 7 7s7-3.14 7-7s-3.14-7-7-7m0 13c-3.309 0-6-2.691-6-6s2.691-6 6-6s6 2.691 6 6s-2.691 6-6 6m2.854-8.146L8.708 8l2.146 2.146a.5.5 0 0 1-.708.707L8 8.707l-2.146 2.146a.5.5 0 0 1-.708 0a.5.5 0 0 1 0-.707L7.292 8L5.146 5.854a.5.5 0 0 1 .707-.707l2.146 2.146l2.146-2.146a.5.5 0 0 1 .707.707z\" />\n </svg>\n ),\n loading: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\">\n <rect width=\"24\" height=\"24\" fill=\"none\" />\n <path fill=\"none\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M12 3c4.97 0 9 4.03 9 9\">\n <animateTransform attributeName=\"transform\" dur=\"1.5s\" repeatCount=\"indefinite\" type=\"rotate\" values=\"0 12 12;360 12 12\" />\n </path>\n </svg>\n ),\n default: null,\n};\n\nexport function ToastItem({ toast }: { toast: Toast }) {\n const duration = toast.duration ?? 3000;\n const [offset, setOffset] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const dragStartX = useRef<number | null>(null);\n\n const remainingTime = useRef(duration);\n const startTime = useRef(Date.now());\n\n useEffect(() => {\n if (duration === Infinity || duration <= 0) return;\n\n if (!isHovered && !isDragging) {\n startTime.current = Date.now();\n const timer = setTimeout(() => {\n toastLib.dismiss(toast.id);\n }, remainingTime.current);\n\n return () => {\n clearTimeout(timer);\n remainingTime.current -= Date.now() - startTime.current;\n };\n }\n }, [isHovered, isDragging, duration, toast.id]);\n\n const handlePointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n if ((e.target as HTMLElement).closest('button')) return;\n dragStartX.current = e.clientX;\n setIsDragging(true);\n e.currentTarget.setPointerCapture(e.pointerId);\n };\n\n const handlePointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!isDragging || dragStartX.current === null) return;\n const deltaX = e.clientX - dragStartX.current;\n \n const pos = toast.position || \"top-right\";\n if (pos.includes(\"right\") && deltaX < 0) return;\n if (pos.includes(\"left\") && deltaX > 0) return;\n\n setOffset(deltaX);\n };\n\n const handlePointerUp = () => {\n if (!isDragging) return;\n setIsDragging(false);\n dragStartX.current = null;\n \n // Dismiss if swiped more than 50px\n if (Math.abs(offset) > 50) {\n toastLib.dismiss(toast.id);\n } else {\n setOffset(0);\n }\n };\n\n const dynamicStyle = {\n ...toast.style,\n transform: offset ? `translateX(${offset}px)` : undefined,\n transition: isDragging ? \"none\" : \"transform 0.2s ease\",\n touchAction: 'none' as const\n };\n\n if (toast.render) {\n return (\n <div \n style={{ transform: dynamicStyle.transform, transition: dynamicStyle.transition, touchAction: 'none' }}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {toast.render()}\n </div>\n );\n }\n\n const defaultIcon = icons[toast.type as keyof typeof icons] || null;\n const Icon = toast.icon !== undefined ? toast.icon : defaultIcon;\n\n return (\n <div \n className={`tf-toast tf-toast-${toast.type} ${toast.className || \"\"}`}\n style={dynamicStyle}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {Icon && <span className=\"tf-icon\" style={{ alignSelf: 'flex-start', marginTop: '2px', color: toast.iconColor }}>{Icon}</span>}\n <div className=\"tf-message\" style={{ flex: 1, display: 'flex', flexDirection: 'column' }}>\n <span>{toast.message}</span>\n {toast.description && <span className=\"tf-description\">{toast.description}</span>}\n {toast.progress !== undefined && (\n <div className=\"tf-progress-bg\">\n <div className=\"tf-progress-fill\" style={{ width: `${toast.progress}%` }} />\n </div>\n )}\n </div>\n\n {toast.action && (\n <button \n onClick={toast.action.onClick}\n className=\"tf-action-btn\"\n >\n {toast.action.label}\n </button>\n )}\n\n {toast.dismissible && (\n <button \n title=\"Dismiss\"\n onClick={() => toastLib.dismiss(toast.id)}\n className=\"tf-close-btn\"\n >\n ✖\n </button>\n )}\n </div>\n );\n}\n","\"use client\";\r\n\r\nimport React from \"react\";\r\nimport { useToastStore } from \"./useToast\";\r\nimport { ToastItem } from \"./ToastItem\";\r\n\r\nexport function Toaster({ theme = \"dark\" }: { theme?: \"light\" | \"dark\" } = {}) {\r\n const toasts = useToastStore();\r\n\r\n if (typeof window === \"undefined\") return null;\r\n\r\n const positions = [\r\n \"top-left\",\r\n \"top-center\",\r\n \"top-right\",\r\n \"bottom-left\",\r\n \"bottom-center\",\r\n \"bottom-right\",\r\n ];\r\n\r\n const groupedToasts = positions.reduce((acc, pos) => {\r\n acc[pos] = toasts.filter((t: any) => (t.position || \"top-right\") === pos);\r\n return acc;\r\n }, {} as Record<string, typeof toasts>);\r\n\r\n return (\r\n <>\r\n {positions.map((pos) => {\r\n if (!groupedToasts[pos].length) return null;\r\n\r\n return (\r\n <div key={pos} className={`tf-toast-container tf-${pos} tf-theme-${theme}`}>\r\n {groupedToasts[pos].map((t: any) => (\r\n <ToastItem key={t.id} toast={t} />\r\n ))}\r\n </div>\r\n );\r\n })}\r\n </>\r\n );\r\n}\r\n"],"mappings":"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","names":["toast","import_react","toast","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Toaster.tsx","../src/useToast.ts","../../core/src/store.ts","../../core/src/toast.ts","../src/ToastItem.tsx"],"sourcesContent":["export { Toaster } from \"./Toaster\";\r\nexport { toast } from \"@toastflux/core\";\r\n","\"use client\";\n\nimport React, { useState } from \"react\";\nimport { useToastStore } from \"./useToast\";\nimport { ToastItem } from \"./ToastItem\";\n\nexport function Toaster({ theme = \"dark\" }: { theme?: \"light\" | \"dark\" } = {}) {\n const toasts = useToastStore();\n const [hoveredPos, setHoveredPos] = useState<string | null>(null);\n\n if (typeof window === \"undefined\") return null;\n\n const positions = [\n \"top-left\",\n \"top-center\",\n \"top-right\",\n \"bottom-left\",\n \"bottom-center\",\n \"bottom-right\",\n ];\n\n const groupedToasts = positions.reduce((acc, pos) => {\n acc[pos] = toasts.filter((t: any) => (t.position || \"top-right\") === pos);\n return acc;\n }, {} as Record<string, typeof toasts>);\n\n return (\n <>\n {positions.map((pos) => {\n if (!groupedToasts[pos].length) return null;\n\n const isBottom = pos.startsWith(\"bottom\");\n const posToasts = groupedToasts[pos];\n const isExpanded = hoveredPos === pos;\n const count = posToasts.length;\n\n // How much extra space to show \"peeking\" toasts behind\n // Each subsequent toast peeks 10px further away\n const PEEK_OFFSET = 10;\n const MAX_VISIBLE_STACK = 3;\n const visibleStack = Math.min(count - 1, MAX_VISIBLE_STACK - 1);\n\n // collapsed container height accounts for peeking\n const collapsedExtraHeight = isExpanded ? 0 : visibleStack * PEEK_OFFSET;\n\n return (\n <div\n key={pos}\n className={`tf-toast-container tf-${pos} tf-theme-${theme}`}\n style={{ pointerEvents: \"auto\" }}\n onMouseEnter={() => setHoveredPos(pos)}\n onMouseLeave={() => setHoveredPos(null)}\n >\n {/* Stack wrapper: relative container so absolute toasts position correctly */}\n <div\n className={`tf-stack-wrapper ${isExpanded ? \"tf-stack-expanded\" : \"tf-stack-collapsed\"}`}\n style={\n !isExpanded\n ? {\n position: \"relative\",\n // Extra padding at bottom (top positions) or top (bottom positions) for peeking\n paddingBottom: !isBottom ? collapsedExtraHeight : 0,\n paddingTop: isBottom ? collapsedExtraHeight : 0,\n }\n : { display: \"flex\", flexDirection: \"column\", gap: \"10px\" }\n }\n >\n {posToasts.map((t: any, i: number) => (\n <ToastItem\n key={t.id}\n toast={t}\n index={i}\n total={count}\n isExpanded={isExpanded}\n isBottom={isBottom}\n />\n ))}\n </div>\n </div>\n );\n })}\n </>\n );\n}\n","\"use client\";\r\n\r\nimport { useEffect, useState } from \"react\";\r\nimport { toastStore } from \"@toastflux/core\";\r\n\r\nexport function useToastStore() {\r\n const [toasts, setToasts] = useState(toastStore.getToasts());\r\n\r\n useEffect(() => {\r\n return toastStore.subscribe(() => {\r\n setToasts([...toastStore.getToasts()]);\r\n });\r\n }, []);\r\n\r\n return toasts;\r\n}\r\n","import { Toast } from \"./types\";\r\n\r\ntype Listener = () => void;\r\n\r\nclass ToastStore {\r\n private toasts: Toast[] = [];\r\n private listeners: Listener[] = [];\r\n\r\n subscribe(listener: Listener) {\r\n this.listeners.push(listener);\r\n return () => {\r\n this.listeners = this.listeners.filter((l) => l !== listener);\r\n };\r\n }\r\n\r\n getToasts() {\r\n return this.toasts;\r\n }\r\n\r\n add(toast: Toast) {\r\n this.toasts = [toast, ...this.toasts];\r\n this.emit();\r\n }\r\n\r\n remove(id: string) {\r\n this.toasts = this.toasts.filter((t) => t.id !== id);\r\n this.emit();\r\n }\r\n\r\n private emit() {\r\n this.listeners.forEach((l) => l());\r\n }\r\n}\r\n\r\nexport const toastStore = new ToastStore();\r\n","import { toastStore } from \"./store\";\nimport { Toast, ToastType } from \"./types\";\n\nexport type ToastOptions = Partial<Omit<Toast, \"id\" | \"type\" | \"createdAt\">>;\n\nfunction createToast(message: string | undefined, type: ToastType, options?: ToastOptions) {\n const id = crypto.randomUUID();\n\n toastStore.add({\n id,\n message,\n type,\n createdAt: Date.now(),\n ...options,\n });\n\n return id;\n}\n\nconst toastFn = (msg: string | undefined, type: ToastType = \"default\", options?: ToastOptions) => createToast(msg, type, options);\n\ntoastFn.success = (msg: string, options?: ToastOptions) => createToast(msg, \"success\", options);\ntoastFn.error = (msg: string, options?: ToastOptions) => createToast(msg, \"error\", options);\ntoastFn.info = (msg: string, options?: ToastOptions) => createToast(msg, \"info\", options);\ntoastFn.warning = (msg: string, options?: ToastOptions) => createToast(msg, \"warning\", options);\ntoastFn.loading = (msg: string, options?: ToastOptions) => createToast(msg, \"loading\", options);\ntoastFn.default = (msg: string, options?: ToastOptions) => createToast(msg, \"default\", options);\ntoastFn.custom = (options: ToastOptions) => createToast(options.message, \"default\", options);\n\ntoastFn.dismiss = (id: string) => toastStore.remove(id);\n\nexport const toast = toastFn;\n","\"use client\";\n\nimport React, { useRef, useState, useEffect } from \"react\";\nimport { Toast, toast as toastLib } from \"@toastflux/core\";\n\nconst icons = {\n success: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 48 48\">\n <rect width=\"48\" height=\"48\" fill=\"none\" />\n <g fill=\"none\" stroke=\"currentColor\" strokeLinejoin=\"round\" strokeWidth=\"4\">\n <path d=\"M24 44a19.94 19.94 0 0 0 14.142-5.858A19.94 19.94 0 0 0 44 24a19.94 19.94 0 0 0-5.858-14.142A19.94 19.94 0 0 0 24 4A19.94 19.94 0 0 0 9.858 9.858A19.94 19.94 0 0 0 4 24a19.94 19.94 0 0 0 5.858 14.142A19.94 19.94 0 0 0 24 44Z\" />\n <path strokeLinecap=\"round\" d=\"m16 24l6 6l12-12\" />\n </g>\n </svg>\n ),\n info: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\">\n <rect width=\"24\" height=\"24\" fill=\"none\" />\n <path fill=\"currentColor\" d=\"M12.002 1.999c5.523 0 10.001 4.478 10.001 10.002c0 5.523-4.478 10.001-10.001 10.001C6.478 22.002 2 17.524 2 12.001C2 6.477 6.478 1.999 12.002 1.999m0 1.5a8.502 8.502 0 1 0 0 17.003a8.502 8.502 0 0 0 0-17.003M12 10.5a.75.75 0 0 1 .75.75v5a.75.75 0 0 1-1.5 0v-5a.75.75 0 0 1 .75-.75M12 9a1 1 0 1 0 0-2a1 1 0 0 0 0 2\" />\n </svg>\n ),\n warning: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 256 256\">\n <rect width=\"256\" height=\"256\" fill=\"none\" />\n <path fill=\"currentColor\" d=\"M236.8 188.09L149.35 36.22a24.76 24.76 0 0 0-42.7 0L19.2 188.09a23.51 23.51 0 0 0 0 23.72A24.35 24.35 0 0 0 40.55 224h174.9a24.35 24.35 0 0 0 21.33-12.19a23.51 23.51 0 0 0 .02-23.72m-13.87 15.71a8.5 8.5 0 0 1-7.48 4.2H40.55a8.5 8.5 0 0 1-7.48-4.2a7.59 7.59 0 0 1 0-7.72l87.45-151.87a8.75 8.75 0 0 1 15 0l87.45 151.87a7.59 7.59 0 0 1-.04 7.72M120 144v-40a8 8 0 0 1 16 0v40a8 8 0 0 1-16 0m20 36a12 12 0 1 1-12-12a12 12 0 0 1 12 12\" />\n </svg>\n ),\n error: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 16 16\">\n <rect width=\"16\" height=\"16\" fill=\"none\" />\n <path fill=\"currentColor\" d=\"M8 1C4.14 1 1 4.14 1 8s3.14 7 7 7s7-3.14 7-7s-3.14-7-7-7m0 13c-3.309 0-6-2.691-6-6s2.691-6 6-6s6 2.691 6 6s-2.691 6-6 6m2.854-8.146L8.708 8l2.146 2.146a.5.5 0 0 1-.708.707L8 8.707l-2.146 2.146a.5.5 0 0 1-.708 0a.5.5 0 0 1 0-.707L7.292 8L5.146 5.854a.5.5 0 0 1 .707-.707l2.146 2.146l2.146-2.146a.5.5 0 0 1 .707.707z\" />\n </svg>\n ),\n loading: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\">\n <rect width=\"24\" height=\"24\" fill=\"none\" />\n <path fill=\"none\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M12 3c4.97 0 9 4.03 9 9\">\n <animateTransform attributeName=\"transform\" dur=\"1.5s\" repeatCount=\"indefinite\" type=\"rotate\" values=\"0 12 12;360 12 12\" />\n </path>\n </svg>\n ),\n default: null,\n};\n\ninterface ToastItemProps {\n toast: Toast;\n index: number;\n total: number;\n isExpanded: boolean;\n isBottom: boolean;\n}\n\nconst MAX_STACK_VISIBLE = 3;\nconst PEEK_OFFSET = 10;\nconst SCALE_STEP = 0.05;\nconst OPACITY_STEP = 0.15;\n\nexport function ToastItem({ toast, index, total, isExpanded, isBottom }: ToastItemProps) {\n const duration = toast.duration ?? 3000;\n const [offset, setOffset] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n const [isItemHovered, setIsItemHovered] = useState(false);\n const dragStartX = useRef<number | null>(null);\n\n const remainingTime = useRef(duration);\n const startTime = useRef(Date.now());\n\n const isPaused = isExpanded || isItemHovered || isDragging;\n\n useEffect(() => {\n if (duration === Infinity || duration <= 0) return;\n if (isPaused) return;\n\n startTime.current = Date.now();\n const timer = setTimeout(() => {\n toastLib.dismiss(toast.id);\n }, remainingTime.current);\n\n return () => {\n clearTimeout(timer);\n remainingTime.current -= Date.now() - startTime.current;\n };\n }, [isPaused, duration, toast.id]);\n\n const handlePointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!isExpanded && index !== 0) return;\n if ((e.target as HTMLElement).closest('button')) return;\n dragStartX.current = e.clientX;\n setIsDragging(true);\n e.currentTarget.setPointerCapture(e.pointerId);\n };\n\n const handlePointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!isDragging || dragStartX.current === null) return;\n const deltaX = e.clientX - dragStartX.current;\n\n const pos = toast.position || \"top-right\";\n if (pos.includes(\"right\") && deltaX < 0) return;\n if (pos.includes(\"left\") && deltaX > 0) return;\n\n setOffset(deltaX);\n };\n\n const handlePointerUp = () => {\n if (!isDragging) return;\n setIsDragging(false);\n dragStartX.current = null;\n\n if (Math.abs(offset) > 50) {\n toastLib.dismiss(toast.id);\n } else {\n setOffset(0);\n }\n };\n\n const stackDepth = index;\n const isHidden = stackDepth >= MAX_STACK_VISIBLE;\n const scale = 1 - stackDepth * SCALE_STEP;\n const peekY = stackDepth * PEEK_OFFSET * (isBottom ? -1 : 1);\n const opacity = isHidden ? 0 : 1 - stackDepth * OPACITY_STEP;\n\n let containerStyle: React.CSSProperties;\n\n if (!isExpanded) {\n containerStyle = {\n position: \"absolute\",\n top: isBottom ? undefined : 0,\n bottom: isBottom ? 0 : undefined,\n left: 0,\n right: 0,\n transform: `translateY(${peekY}px) scale(${scale})${offset ? ` translateX(${offset}px)` : \"\"}`,\n opacity,\n zIndex: total - stackDepth,\n visibility: isHidden ? \"hidden\" : \"visible\",\n pointerEvents: index === 0 ? \"auto\" : \"none\",\n transformOrigin: isBottom ? \"bottom center\" : \"top center\",\n };\n } else {\n containerStyle = {\n position: \"relative\",\n transform: offset ? `translateX(${offset}px)` : undefined,\n opacity: 1,\n zIndex: total - stackDepth,\n pointerEvents: \"auto\",\n };\n }\n\n const dynamicStyle: React.CSSProperties = {\n ...toast.style,\n ...containerStyle,\n transition: isDragging\n ? \"opacity 0.3s ease, visibility 0.3s ease\"\n : \"transform 0.35s cubic-bezier(0.34, 1.15, 0.64, 1), opacity 0.3s ease, visibility 0.3s ease\",\n touchAction: \"none\",\n };\n\n if (toast.render) {\n return (\n <div\n style={dynamicStyle}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onMouseEnter={() => setIsItemHovered(true)}\n onMouseLeave={() => setIsItemHovered(false)}\n >\n {toast.render()}\n </div>\n );\n }\n\n const defaultIcon = icons[toast.type as keyof typeof icons] || null;\n const Icon = toast.icon !== undefined ? toast.icon : defaultIcon;\n\n return (\n <div\n className={`tf-toast tf-toast-${toast.type} ${toast.className || \"\"}`}\n style={dynamicStyle}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onMouseEnter={() => setIsItemHovered(true)}\n onMouseLeave={() => setIsItemHovered(false)}\n >\n {Icon && (\n <span\n className=\"tf-icon\"\n style={{ alignSelf: \"flex-start\", marginTop: \"2px\", color: toast.iconColor }}\n >\n {Icon}\n </span>\n )}\n <div className=\"tf-message\" style={{ flex: 1, display: \"flex\", flexDirection: \"column\" }}>\n <span>{toast.message}</span>\n {toast.description && (\n <span className=\"tf-description\">{toast.description}</span>\n )}\n {toast.progress !== undefined && (\n <div className=\"tf-progress-bg\">\n <div className=\"tf-progress-fill\" style={{ width: `${toast.progress}%` }} />\n </div>\n )}\n </div>\n\n {toast.action && (\n <button onClick={toast.action.onClick} className=\"tf-action-btn\">\n {toast.action.label}\n </button>\n )}\n\n {toast.dismissible && (\n <button\n title=\"Dismiss\"\n onClick={() => toastLib.dismiss(toast.id)}\n className=\"tf-close-btn\"\n >\n ✖\n </button>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["import_react","toast","import_react","toast","import_jsx_runtime","PEEK_OFFSET"]}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// packages/react/src/Toaster.tsx
|
|
2
|
+
import { useState as useState3 } from "react";
|
|
3
|
+
|
|
1
4
|
// packages/react/src/useToast.ts
|
|
2
5
|
import { useEffect, useState } from "react";
|
|
3
6
|
|
|
@@ -93,29 +96,34 @@ var icons = {
|
|
|
93
96
|
] }),
|
|
94
97
|
default: null
|
|
95
98
|
};
|
|
96
|
-
|
|
99
|
+
var MAX_STACK_VISIBLE = 3;
|
|
100
|
+
var PEEK_OFFSET = 10;
|
|
101
|
+
var SCALE_STEP = 0.05;
|
|
102
|
+
var OPACITY_STEP = 0.15;
|
|
103
|
+
function ToastItem({ toast: toast2, index, total, isExpanded, isBottom }) {
|
|
97
104
|
var _a;
|
|
98
105
|
const duration = (_a = toast2.duration) != null ? _a : 3e3;
|
|
99
106
|
const [offset, setOffset] = useState2(0);
|
|
100
107
|
const [isDragging, setIsDragging] = useState2(false);
|
|
101
|
-
const [
|
|
108
|
+
const [isItemHovered, setIsItemHovered] = useState2(false);
|
|
102
109
|
const dragStartX = useRef(null);
|
|
103
110
|
const remainingTime = useRef(duration);
|
|
104
111
|
const startTime = useRef(Date.now());
|
|
112
|
+
const isPaused = isExpanded || isItemHovered || isDragging;
|
|
105
113
|
useEffect2(() => {
|
|
106
114
|
if (duration === Infinity || duration <= 0) return;
|
|
107
|
-
if (
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}, [isHovered, isDragging, duration, toast2.id]);
|
|
115
|
+
if (isPaused) return;
|
|
116
|
+
startTime.current = Date.now();
|
|
117
|
+
const timer = setTimeout(() => {
|
|
118
|
+
toast.dismiss(toast2.id);
|
|
119
|
+
}, remainingTime.current);
|
|
120
|
+
return () => {
|
|
121
|
+
clearTimeout(timer);
|
|
122
|
+
remainingTime.current -= Date.now() - startTime.current;
|
|
123
|
+
};
|
|
124
|
+
}, [isPaused, duration, toast2.id]);
|
|
118
125
|
const handlePointerDown = (e) => {
|
|
126
|
+
if (!isExpanded && index !== 0) return;
|
|
119
127
|
if (e.target.closest("button")) return;
|
|
120
128
|
dragStartX.current = e.clientX;
|
|
121
129
|
setIsDragging(true);
|
|
@@ -139,23 +147,52 @@ function ToastItem({ toast: toast2 }) {
|
|
|
139
147
|
setOffset(0);
|
|
140
148
|
}
|
|
141
149
|
};
|
|
150
|
+
const stackDepth = index;
|
|
151
|
+
const isHidden = stackDepth >= MAX_STACK_VISIBLE;
|
|
152
|
+
const scale = 1 - stackDepth * SCALE_STEP;
|
|
153
|
+
const peekY = stackDepth * PEEK_OFFSET * (isBottom ? -1 : 1);
|
|
154
|
+
const opacity = isHidden ? 0 : 1 - stackDepth * OPACITY_STEP;
|
|
155
|
+
let containerStyle;
|
|
156
|
+
if (!isExpanded) {
|
|
157
|
+
containerStyle = {
|
|
158
|
+
position: "absolute",
|
|
159
|
+
top: isBottom ? void 0 : 0,
|
|
160
|
+
bottom: isBottom ? 0 : void 0,
|
|
161
|
+
left: 0,
|
|
162
|
+
right: 0,
|
|
163
|
+
transform: `translateY(${peekY}px) scale(${scale})${offset ? ` translateX(${offset}px)` : ""}`,
|
|
164
|
+
opacity,
|
|
165
|
+
zIndex: total - stackDepth,
|
|
166
|
+
visibility: isHidden ? "hidden" : "visible",
|
|
167
|
+
pointerEvents: index === 0 ? "auto" : "none",
|
|
168
|
+
transformOrigin: isBottom ? "bottom center" : "top center"
|
|
169
|
+
};
|
|
170
|
+
} else {
|
|
171
|
+
containerStyle = {
|
|
172
|
+
position: "relative",
|
|
173
|
+
transform: offset ? `translateX(${offset}px)` : void 0,
|
|
174
|
+
opacity: 1,
|
|
175
|
+
zIndex: total - stackDepth,
|
|
176
|
+
pointerEvents: "auto"
|
|
177
|
+
};
|
|
178
|
+
}
|
|
142
179
|
const dynamicStyle = {
|
|
143
180
|
...toast2.style,
|
|
144
|
-
|
|
145
|
-
transition: isDragging ? "
|
|
181
|
+
...containerStyle,
|
|
182
|
+
transition: isDragging ? "opacity 0.3s ease, visibility 0.3s ease" : "transform 0.35s cubic-bezier(0.34, 1.15, 0.64, 1), opacity 0.3s ease, visibility 0.3s ease",
|
|
146
183
|
touchAction: "none"
|
|
147
184
|
};
|
|
148
185
|
if (toast2.render) {
|
|
149
186
|
return /* @__PURE__ */ jsx(
|
|
150
187
|
"div",
|
|
151
188
|
{
|
|
152
|
-
style:
|
|
189
|
+
style: dynamicStyle,
|
|
153
190
|
onPointerDown: handlePointerDown,
|
|
154
191
|
onPointerMove: handlePointerMove,
|
|
155
192
|
onPointerUp: handlePointerUp,
|
|
156
193
|
onPointerCancel: handlePointerUp,
|
|
157
|
-
onMouseEnter: () =>
|
|
158
|
-
onMouseLeave: () =>
|
|
194
|
+
onMouseEnter: () => setIsItemHovered(true),
|
|
195
|
+
onMouseLeave: () => setIsItemHovered(false),
|
|
159
196
|
children: toast2.render()
|
|
160
197
|
}
|
|
161
198
|
);
|
|
@@ -171,23 +208,23 @@ function ToastItem({ toast: toast2 }) {
|
|
|
171
208
|
onPointerMove: handlePointerMove,
|
|
172
209
|
onPointerUp: handlePointerUp,
|
|
173
210
|
onPointerCancel: handlePointerUp,
|
|
174
|
-
onMouseEnter: () =>
|
|
175
|
-
onMouseLeave: () =>
|
|
211
|
+
onMouseEnter: () => setIsItemHovered(true),
|
|
212
|
+
onMouseLeave: () => setIsItemHovered(false),
|
|
176
213
|
children: [
|
|
177
|
-
Icon && /* @__PURE__ */ jsx(
|
|
214
|
+
Icon && /* @__PURE__ */ jsx(
|
|
215
|
+
"span",
|
|
216
|
+
{
|
|
217
|
+
className: "tf-icon",
|
|
218
|
+
style: { alignSelf: "flex-start", marginTop: "2px", color: toast2.iconColor },
|
|
219
|
+
children: Icon
|
|
220
|
+
}
|
|
221
|
+
),
|
|
178
222
|
/* @__PURE__ */ jsxs("div", { className: "tf-message", style: { flex: 1, display: "flex", flexDirection: "column" }, children: [
|
|
179
223
|
/* @__PURE__ */ jsx("span", { children: toast2.message }),
|
|
180
224
|
toast2.description && /* @__PURE__ */ jsx("span", { className: "tf-description", children: toast2.description }),
|
|
181
225
|
toast2.progress !== void 0 && /* @__PURE__ */ jsx("div", { className: "tf-progress-bg", children: /* @__PURE__ */ jsx("div", { className: "tf-progress-fill", style: { width: `${toast2.progress}%` } }) })
|
|
182
226
|
] }),
|
|
183
|
-
toast2.action && /* @__PURE__ */ jsx(
|
|
184
|
-
"button",
|
|
185
|
-
{
|
|
186
|
-
onClick: toast2.action.onClick,
|
|
187
|
-
className: "tf-action-btn",
|
|
188
|
-
children: toast2.action.label
|
|
189
|
-
}
|
|
190
|
-
),
|
|
227
|
+
toast2.action && /* @__PURE__ */ jsx("button", { onClick: toast2.action.onClick, className: "tf-action-btn", children: toast2.action.label }),
|
|
191
228
|
toast2.dismissible && /* @__PURE__ */ jsx(
|
|
192
229
|
"button",
|
|
193
230
|
{
|
|
@@ -206,6 +243,7 @@ function ToastItem({ toast: toast2 }) {
|
|
|
206
243
|
import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
|
|
207
244
|
function Toaster({ theme = "dark" } = {}) {
|
|
208
245
|
const toasts = useToastStore();
|
|
246
|
+
const [hoveredPos, setHoveredPos] = useState3(null);
|
|
209
247
|
if (typeof window === "undefined") return null;
|
|
210
248
|
const positions = [
|
|
211
249
|
"top-left",
|
|
@@ -221,7 +259,47 @@ function Toaster({ theme = "dark" } = {}) {
|
|
|
221
259
|
}, {});
|
|
222
260
|
return /* @__PURE__ */ jsx2(Fragment, { children: positions.map((pos) => {
|
|
223
261
|
if (!groupedToasts[pos].length) return null;
|
|
224
|
-
|
|
262
|
+
const isBottom = pos.startsWith("bottom");
|
|
263
|
+
const posToasts = groupedToasts[pos];
|
|
264
|
+
const isExpanded = hoveredPos === pos;
|
|
265
|
+
const count = posToasts.length;
|
|
266
|
+
const PEEK_OFFSET2 = 10;
|
|
267
|
+
const MAX_VISIBLE_STACK = 3;
|
|
268
|
+
const visibleStack = Math.min(count - 1, MAX_VISIBLE_STACK - 1);
|
|
269
|
+
const collapsedExtraHeight = isExpanded ? 0 : visibleStack * PEEK_OFFSET2;
|
|
270
|
+
return /* @__PURE__ */ jsx2(
|
|
271
|
+
"div",
|
|
272
|
+
{
|
|
273
|
+
className: `tf-toast-container tf-${pos} tf-theme-${theme}`,
|
|
274
|
+
style: { pointerEvents: "auto" },
|
|
275
|
+
onMouseEnter: () => setHoveredPos(pos),
|
|
276
|
+
onMouseLeave: () => setHoveredPos(null),
|
|
277
|
+
children: /* @__PURE__ */ jsx2(
|
|
278
|
+
"div",
|
|
279
|
+
{
|
|
280
|
+
className: `tf-stack-wrapper ${isExpanded ? "tf-stack-expanded" : "tf-stack-collapsed"}`,
|
|
281
|
+
style: !isExpanded ? {
|
|
282
|
+
position: "relative",
|
|
283
|
+
// Extra padding at bottom (top positions) or top (bottom positions) for peeking
|
|
284
|
+
paddingBottom: !isBottom ? collapsedExtraHeight : 0,
|
|
285
|
+
paddingTop: isBottom ? collapsedExtraHeight : 0
|
|
286
|
+
} : { display: "flex", flexDirection: "column", gap: "10px" },
|
|
287
|
+
children: posToasts.map((t, i) => /* @__PURE__ */ jsx2(
|
|
288
|
+
ToastItem,
|
|
289
|
+
{
|
|
290
|
+
toast: t,
|
|
291
|
+
index: i,
|
|
292
|
+
total: count,
|
|
293
|
+
isExpanded,
|
|
294
|
+
isBottom
|
|
295
|
+
},
|
|
296
|
+
t.id
|
|
297
|
+
))
|
|
298
|
+
}
|
|
299
|
+
)
|
|
300
|
+
},
|
|
301
|
+
pos
|
|
302
|
+
);
|
|
225
303
|
}) });
|
|
226
304
|
}
|
|
227
305
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/useToast.ts","../../core/src/store.ts","../../core/src/toast.ts","../src/ToastItem.tsx","../src/Toaster.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\r\nimport { toastStore } from \"../../core/src\";\r\n\r\nexport function useToastStore() {\r\n const [toasts, setToasts] = useState(toastStore.getToasts());\r\n\r\n useEffect(() => {\r\n return toastStore.subscribe(() => {\r\n setToasts([...toastStore.getToasts()]);\r\n });\r\n }, []);\r\n\r\n return toasts;\r\n}\r\n","import { Toast } from \"./types\";\r\n\r\ntype Listener = () => void;\r\n\r\nclass ToastStore {\r\n private toasts: Toast[] = [];\r\n private listeners: Listener[] = [];\r\n\r\n subscribe(listener: Listener) {\r\n this.listeners.push(listener);\r\n return () => {\r\n this.listeners = this.listeners.filter((l) => l !== listener);\r\n };\r\n }\r\n\r\n getToasts() {\r\n return this.toasts;\r\n }\r\n\r\n add(toast: Toast) {\r\n this.toasts = [toast, ...this.toasts];\r\n this.emit();\r\n }\r\n\r\n remove(id: string) {\r\n this.toasts = this.toasts.filter((t) => t.id !== id);\r\n this.emit();\r\n }\r\n\r\n private emit() {\r\n this.listeners.forEach((l) => l());\r\n }\r\n}\r\n\r\nexport const toastStore = new ToastStore();\r\n","import { toastStore } from \"./store\";\nimport { Toast, ToastType } from \"./types\";\n\nexport type ToastOptions = Partial<Omit<Toast, \"id\" | \"type\" | \"createdAt\">>;\n\nfunction createToast(message: string | undefined, type: ToastType, options?: ToastOptions) {\n const id = crypto.randomUUID();\n\n toastStore.add({\n id,\n message,\n type,\n createdAt: Date.now(),\n ...options,\n });\n\n return id;\n}\n\nconst toastFn = (msg: string | undefined, type: ToastType = \"default\", options?: ToastOptions) => createToast(msg, type, options);\n\ntoastFn.success = (msg: string, options?: ToastOptions) => createToast(msg, \"success\", options);\ntoastFn.error = (msg: string, options?: ToastOptions) => createToast(msg, \"error\", options);\ntoastFn.info = (msg: string, options?: ToastOptions) => createToast(msg, \"info\", options);\ntoastFn.warning = (msg: string, options?: ToastOptions) => createToast(msg, \"warning\", options);\ntoastFn.loading = (msg: string, options?: ToastOptions) => createToast(msg, \"loading\", options);\ntoastFn.default = (msg: string, options?: ToastOptions) => createToast(msg, \"default\", options);\ntoastFn.custom = (options: ToastOptions) => createToast(options.message, \"default\", options);\n\ntoastFn.dismiss = (id: string) => toastStore.remove(id);\n\nexport const toast = toastFn;\n","import React, { useRef, useState, useEffect } from \"react\";\nimport { Toast, toast as toastLib } from \"../../core/src\";\n\nconst icons = {\n success: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 48 48\">\n <rect width=\"48\" height=\"48\" fill=\"none\" />\n <g fill=\"none\" stroke=\"currentColor\" strokeLinejoin=\"round\" strokeWidth=\"4\">\n <path d=\"M24 44a19.94 19.94 0 0 0 14.142-5.858A19.94 19.94 0 0 0 44 24a19.94 19.94 0 0 0-5.858-14.142A19.94 19.94 0 0 0 24 4A19.94 19.94 0 0 0 9.858 9.858A19.94 19.94 0 0 0 4 24a19.94 19.94 0 0 0 5.858 14.142A19.94 19.94 0 0 0 24 44Z\" />\n <path strokeLinecap=\"round\" d=\"m16 24l6 6l12-12\" />\n </g>\n </svg>\n ),\n info: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\">\n <rect width=\"24\" height=\"24\" fill=\"none\" />\n <path fill=\"currentColor\" d=\"M12.002 1.999c5.523 0 10.001 4.478 10.001 10.002c0 5.523-4.478 10.001-10.001 10.001C6.478 22.002 2 17.524 2 12.001C2 6.477 6.478 1.999 12.002 1.999m0 1.5a8.502 8.502 0 1 0 0 17.003a8.502 8.502 0 0 0 0-17.003M12 10.5a.75.75 0 0 1 .75.75v5a.75.75 0 0 1-1.5 0v-5a.75.75 0 0 1 .75-.75M12 9a1 1 0 1 0 0-2a1 1 0 0 0 0 2\" />\n </svg>\n ),\n warning: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 256 256\">\n <rect width=\"256\" height=\"256\" fill=\"none\" />\n <path fill=\"currentColor\" d=\"M236.8 188.09L149.35 36.22a24.76 24.76 0 0 0-42.7 0L19.2 188.09a23.51 23.51 0 0 0 0 23.72A24.35 24.35 0 0 0 40.55 224h174.9a24.35 24.35 0 0 0 21.33-12.19a23.51 23.51 0 0 0 .02-23.72m-13.87 15.71a8.5 8.5 0 0 1-7.48 4.2H40.55a8.5 8.5 0 0 1-7.48-4.2a7.59 7.59 0 0 1 0-7.72l87.45-151.87a8.75 8.75 0 0 1 15 0l87.45 151.87a7.59 7.59 0 0 1-.04 7.72M120 144v-40a8 8 0 0 1 16 0v40a8 8 0 0 1-16 0m20 36a12 12 0 1 1-12-12a12 12 0 0 1 12 12\" />\n </svg>\n ),\n error: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 16 16\">\n <rect width=\"16\" height=\"16\" fill=\"none\" />\n <path fill=\"currentColor\" d=\"M8 1C4.14 1 1 4.14 1 8s3.14 7 7 7s7-3.14 7-7s-3.14-7-7-7m0 13c-3.309 0-6-2.691-6-6s2.691-6 6-6s6 2.691 6 6s-2.691 6-6 6m2.854-8.146L8.708 8l2.146 2.146a.5.5 0 0 1-.708.707L8 8.707l-2.146 2.146a.5.5 0 0 1-.708 0a.5.5 0 0 1 0-.707L7.292 8L5.146 5.854a.5.5 0 0 1 .707-.707l2.146 2.146l2.146-2.146a.5.5 0 0 1 .707.707z\" />\n </svg>\n ),\n loading: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\">\n <rect width=\"24\" height=\"24\" fill=\"none\" />\n <path fill=\"none\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M12 3c4.97 0 9 4.03 9 9\">\n <animateTransform attributeName=\"transform\" dur=\"1.5s\" repeatCount=\"indefinite\" type=\"rotate\" values=\"0 12 12;360 12 12\" />\n </path>\n </svg>\n ),\n default: null,\n};\n\nexport function ToastItem({ toast }: { toast: Toast }) {\n const duration = toast.duration ?? 3000;\n const [offset, setOffset] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const dragStartX = useRef<number | null>(null);\n\n const remainingTime = useRef(duration);\n const startTime = useRef(Date.now());\n\n useEffect(() => {\n if (duration === Infinity || duration <= 0) return;\n\n if (!isHovered && !isDragging) {\n startTime.current = Date.now();\n const timer = setTimeout(() => {\n toastLib.dismiss(toast.id);\n }, remainingTime.current);\n\n return () => {\n clearTimeout(timer);\n remainingTime.current -= Date.now() - startTime.current;\n };\n }\n }, [isHovered, isDragging, duration, toast.id]);\n\n const handlePointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n if ((e.target as HTMLElement).closest('button')) return;\n dragStartX.current = e.clientX;\n setIsDragging(true);\n e.currentTarget.setPointerCapture(e.pointerId);\n };\n\n const handlePointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!isDragging || dragStartX.current === null) return;\n const deltaX = e.clientX - dragStartX.current;\n \n const pos = toast.position || \"top-right\";\n if (pos.includes(\"right\") && deltaX < 0) return;\n if (pos.includes(\"left\") && deltaX > 0) return;\n\n setOffset(deltaX);\n };\n\n const handlePointerUp = () => {\n if (!isDragging) return;\n setIsDragging(false);\n dragStartX.current = null;\n \n // Dismiss if swiped more than 50px\n if (Math.abs(offset) > 50) {\n toastLib.dismiss(toast.id);\n } else {\n setOffset(0);\n }\n };\n\n const dynamicStyle = {\n ...toast.style,\n transform: offset ? `translateX(${offset}px)` : undefined,\n transition: isDragging ? \"none\" : \"transform 0.2s ease\",\n touchAction: 'none' as const\n };\n\n if (toast.render) {\n return (\n <div \n style={{ transform: dynamicStyle.transform, transition: dynamicStyle.transition, touchAction: 'none' }}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {toast.render()}\n </div>\n );\n }\n\n const defaultIcon = icons[toast.type as keyof typeof icons] || null;\n const Icon = toast.icon !== undefined ? toast.icon : defaultIcon;\n\n return (\n <div \n className={`tf-toast tf-toast-${toast.type} ${toast.className || \"\"}`}\n style={dynamicStyle}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {Icon && <span className=\"tf-icon\" style={{ alignSelf: 'flex-start', marginTop: '2px', color: toast.iconColor }}>{Icon}</span>}\n <div className=\"tf-message\" style={{ flex: 1, display: 'flex', flexDirection: 'column' }}>\n <span>{toast.message}</span>\n {toast.description && <span className=\"tf-description\">{toast.description}</span>}\n {toast.progress !== undefined && (\n <div className=\"tf-progress-bg\">\n <div className=\"tf-progress-fill\" style={{ width: `${toast.progress}%` }} />\n </div>\n )}\n </div>\n\n {toast.action && (\n <button \n onClick={toast.action.onClick}\n className=\"tf-action-btn\"\n >\n {toast.action.label}\n </button>\n )}\n\n {toast.dismissible && (\n <button \n title=\"Dismiss\"\n onClick={() => toastLib.dismiss(toast.id)}\n className=\"tf-close-btn\"\n >\n ✖\n </button>\n )}\n </div>\n );\n}\n","\"use client\";\r\n\r\nimport React from \"react\";\r\nimport { useToastStore } from \"./useToast\";\r\nimport { ToastItem } from \"./ToastItem\";\r\n\r\nexport function Toaster({ theme = \"dark\" }: { theme?: \"light\" | \"dark\" } = {}) {\r\n const toasts = useToastStore();\r\n\r\n if (typeof window === \"undefined\") return null;\r\n\r\n const positions = [\r\n \"top-left\",\r\n \"top-center\",\r\n \"top-right\",\r\n \"bottom-left\",\r\n \"bottom-center\",\r\n \"bottom-right\",\r\n ];\r\n\r\n const groupedToasts = positions.reduce((acc, pos) => {\r\n acc[pos] = toasts.filter((t: any) => (t.position || \"top-right\") === pos);\r\n return acc;\r\n }, {} as Record<string, typeof toasts>);\r\n\r\n return (\r\n <>\r\n {positions.map((pos) => {\r\n if (!groupedToasts[pos].length) return null;\r\n\r\n return (\r\n <div key={pos} className={`tf-toast-container tf-${pos} tf-theme-${theme}`}>\r\n {groupedToasts[pos].map((t: any) => (\r\n <ToastItem key={t.id} toast={t} />\r\n ))}\r\n </div>\r\n );\r\n })}\r\n </>\r\n );\r\n}\r\n"],"mappings":"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","names":["toast","useState","useEffect","toast","useState","useEffect","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../src/Toaster.tsx","../src/useToast.ts","../../core/src/store.ts","../../core/src/toast.ts","../src/ToastItem.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { useState } from \"react\";\nimport { useToastStore } from \"./useToast\";\nimport { ToastItem } from \"./ToastItem\";\n\nexport function Toaster({ theme = \"dark\" }: { theme?: \"light\" | \"dark\" } = {}) {\n const toasts = useToastStore();\n const [hoveredPos, setHoveredPos] = useState<string | null>(null);\n\n if (typeof window === \"undefined\") return null;\n\n const positions = [\n \"top-left\",\n \"top-center\",\n \"top-right\",\n \"bottom-left\",\n \"bottom-center\",\n \"bottom-right\",\n ];\n\n const groupedToasts = positions.reduce((acc, pos) => {\n acc[pos] = toasts.filter((t: any) => (t.position || \"top-right\") === pos);\n return acc;\n }, {} as Record<string, typeof toasts>);\n\n return (\n <>\n {positions.map((pos) => {\n if (!groupedToasts[pos].length) return null;\n\n const isBottom = pos.startsWith(\"bottom\");\n const posToasts = groupedToasts[pos];\n const isExpanded = hoveredPos === pos;\n const count = posToasts.length;\n\n // How much extra space to show \"peeking\" toasts behind\n // Each subsequent toast peeks 10px further away\n const PEEK_OFFSET = 10;\n const MAX_VISIBLE_STACK = 3;\n const visibleStack = Math.min(count - 1, MAX_VISIBLE_STACK - 1);\n\n // collapsed container height accounts for peeking\n const collapsedExtraHeight = isExpanded ? 0 : visibleStack * PEEK_OFFSET;\n\n return (\n <div\n key={pos}\n className={`tf-toast-container tf-${pos} tf-theme-${theme}`}\n style={{ pointerEvents: \"auto\" }}\n onMouseEnter={() => setHoveredPos(pos)}\n onMouseLeave={() => setHoveredPos(null)}\n >\n {/* Stack wrapper: relative container so absolute toasts position correctly */}\n <div\n className={`tf-stack-wrapper ${isExpanded ? \"tf-stack-expanded\" : \"tf-stack-collapsed\"}`}\n style={\n !isExpanded\n ? {\n position: \"relative\",\n // Extra padding at bottom (top positions) or top (bottom positions) for peeking\n paddingBottom: !isBottom ? collapsedExtraHeight : 0,\n paddingTop: isBottom ? collapsedExtraHeight : 0,\n }\n : { display: \"flex\", flexDirection: \"column\", gap: \"10px\" }\n }\n >\n {posToasts.map((t: any, i: number) => (\n <ToastItem\n key={t.id}\n toast={t}\n index={i}\n total={count}\n isExpanded={isExpanded}\n isBottom={isBottom}\n />\n ))}\n </div>\n </div>\n );\n })}\n </>\n );\n}\n","\"use client\";\r\n\r\nimport { useEffect, useState } from \"react\";\r\nimport { toastStore } from \"@toastflux/core\";\r\n\r\nexport function useToastStore() {\r\n const [toasts, setToasts] = useState(toastStore.getToasts());\r\n\r\n useEffect(() => {\r\n return toastStore.subscribe(() => {\r\n setToasts([...toastStore.getToasts()]);\r\n });\r\n }, []);\r\n\r\n return toasts;\r\n}\r\n","import { Toast } from \"./types\";\r\n\r\ntype Listener = () => void;\r\n\r\nclass ToastStore {\r\n private toasts: Toast[] = [];\r\n private listeners: Listener[] = [];\r\n\r\n subscribe(listener: Listener) {\r\n this.listeners.push(listener);\r\n return () => {\r\n this.listeners = this.listeners.filter((l) => l !== listener);\r\n };\r\n }\r\n\r\n getToasts() {\r\n return this.toasts;\r\n }\r\n\r\n add(toast: Toast) {\r\n this.toasts = [toast, ...this.toasts];\r\n this.emit();\r\n }\r\n\r\n remove(id: string) {\r\n this.toasts = this.toasts.filter((t) => t.id !== id);\r\n this.emit();\r\n }\r\n\r\n private emit() {\r\n this.listeners.forEach((l) => l());\r\n }\r\n}\r\n\r\nexport const toastStore = new ToastStore();\r\n","import { toastStore } from \"./store\";\nimport { Toast, ToastType } from \"./types\";\n\nexport type ToastOptions = Partial<Omit<Toast, \"id\" | \"type\" | \"createdAt\">>;\n\nfunction createToast(message: string | undefined, type: ToastType, options?: ToastOptions) {\n const id = crypto.randomUUID();\n\n toastStore.add({\n id,\n message,\n type,\n createdAt: Date.now(),\n ...options,\n });\n\n return id;\n}\n\nconst toastFn = (msg: string | undefined, type: ToastType = \"default\", options?: ToastOptions) => createToast(msg, type, options);\n\ntoastFn.success = (msg: string, options?: ToastOptions) => createToast(msg, \"success\", options);\ntoastFn.error = (msg: string, options?: ToastOptions) => createToast(msg, \"error\", options);\ntoastFn.info = (msg: string, options?: ToastOptions) => createToast(msg, \"info\", options);\ntoastFn.warning = (msg: string, options?: ToastOptions) => createToast(msg, \"warning\", options);\ntoastFn.loading = (msg: string, options?: ToastOptions) => createToast(msg, \"loading\", options);\ntoastFn.default = (msg: string, options?: ToastOptions) => createToast(msg, \"default\", options);\ntoastFn.custom = (options: ToastOptions) => createToast(options.message, \"default\", options);\n\ntoastFn.dismiss = (id: string) => toastStore.remove(id);\n\nexport const toast = toastFn;\n","\"use client\";\n\nimport React, { useRef, useState, useEffect } from \"react\";\nimport { Toast, toast as toastLib } from \"@toastflux/core\";\n\nconst icons = {\n success: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 48 48\">\n <rect width=\"48\" height=\"48\" fill=\"none\" />\n <g fill=\"none\" stroke=\"currentColor\" strokeLinejoin=\"round\" strokeWidth=\"4\">\n <path d=\"M24 44a19.94 19.94 0 0 0 14.142-5.858A19.94 19.94 0 0 0 44 24a19.94 19.94 0 0 0-5.858-14.142A19.94 19.94 0 0 0 24 4A19.94 19.94 0 0 0 9.858 9.858A19.94 19.94 0 0 0 4 24a19.94 19.94 0 0 0 5.858 14.142A19.94 19.94 0 0 0 24 44Z\" />\n <path strokeLinecap=\"round\" d=\"m16 24l6 6l12-12\" />\n </g>\n </svg>\n ),\n info: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\">\n <rect width=\"24\" height=\"24\" fill=\"none\" />\n <path fill=\"currentColor\" d=\"M12.002 1.999c5.523 0 10.001 4.478 10.001 10.002c0 5.523-4.478 10.001-10.001 10.001C6.478 22.002 2 17.524 2 12.001C2 6.477 6.478 1.999 12.002 1.999m0 1.5a8.502 8.502 0 1 0 0 17.003a8.502 8.502 0 0 0 0-17.003M12 10.5a.75.75 0 0 1 .75.75v5a.75.75 0 0 1-1.5 0v-5a.75.75 0 0 1 .75-.75M12 9a1 1 0 1 0 0-2a1 1 0 0 0 0 2\" />\n </svg>\n ),\n warning: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 256 256\">\n <rect width=\"256\" height=\"256\" fill=\"none\" />\n <path fill=\"currentColor\" d=\"M236.8 188.09L149.35 36.22a24.76 24.76 0 0 0-42.7 0L19.2 188.09a23.51 23.51 0 0 0 0 23.72A24.35 24.35 0 0 0 40.55 224h174.9a24.35 24.35 0 0 0 21.33-12.19a23.51 23.51 0 0 0 .02-23.72m-13.87 15.71a8.5 8.5 0 0 1-7.48 4.2H40.55a8.5 8.5 0 0 1-7.48-4.2a7.59 7.59 0 0 1 0-7.72l87.45-151.87a8.75 8.75 0 0 1 15 0l87.45 151.87a7.59 7.59 0 0 1-.04 7.72M120 144v-40a8 8 0 0 1 16 0v40a8 8 0 0 1-16 0m20 36a12 12 0 1 1-12-12a12 12 0 0 1 12 12\" />\n </svg>\n ),\n error: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 16 16\">\n <rect width=\"16\" height=\"16\" fill=\"none\" />\n <path fill=\"currentColor\" d=\"M8 1C4.14 1 1 4.14 1 8s3.14 7 7 7s7-3.14 7-7s-3.14-7-7-7m0 13c-3.309 0-6-2.691-6-6s2.691-6 6-6s6 2.691 6 6s-2.691 6-6 6m2.854-8.146L8.708 8l2.146 2.146a.5.5 0 0 1-.708.707L8 8.707l-2.146 2.146a.5.5 0 0 1-.708 0a.5.5 0 0 1 0-.707L7.292 8L5.146 5.854a.5.5 0 0 1 .707-.707l2.146 2.146l2.146-2.146a.5.5 0 0 1 .707.707z\" />\n </svg>\n ),\n loading: (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\">\n <rect width=\"24\" height=\"24\" fill=\"none\" />\n <path fill=\"none\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M12 3c4.97 0 9 4.03 9 9\">\n <animateTransform attributeName=\"transform\" dur=\"1.5s\" repeatCount=\"indefinite\" type=\"rotate\" values=\"0 12 12;360 12 12\" />\n </path>\n </svg>\n ),\n default: null,\n};\n\ninterface ToastItemProps {\n toast: Toast;\n index: number;\n total: number;\n isExpanded: boolean;\n isBottom: boolean;\n}\n\nconst MAX_STACK_VISIBLE = 3;\nconst PEEK_OFFSET = 10;\nconst SCALE_STEP = 0.05;\nconst OPACITY_STEP = 0.15;\n\nexport function ToastItem({ toast, index, total, isExpanded, isBottom }: ToastItemProps) {\n const duration = toast.duration ?? 3000;\n const [offset, setOffset] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n const [isItemHovered, setIsItemHovered] = useState(false);\n const dragStartX = useRef<number | null>(null);\n\n const remainingTime = useRef(duration);\n const startTime = useRef(Date.now());\n\n const isPaused = isExpanded || isItemHovered || isDragging;\n\n useEffect(() => {\n if (duration === Infinity || duration <= 0) return;\n if (isPaused) return;\n\n startTime.current = Date.now();\n const timer = setTimeout(() => {\n toastLib.dismiss(toast.id);\n }, remainingTime.current);\n\n return () => {\n clearTimeout(timer);\n remainingTime.current -= Date.now() - startTime.current;\n };\n }, [isPaused, duration, toast.id]);\n\n const handlePointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!isExpanded && index !== 0) return;\n if ((e.target as HTMLElement).closest('button')) return;\n dragStartX.current = e.clientX;\n setIsDragging(true);\n e.currentTarget.setPointerCapture(e.pointerId);\n };\n\n const handlePointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!isDragging || dragStartX.current === null) return;\n const deltaX = e.clientX - dragStartX.current;\n\n const pos = toast.position || \"top-right\";\n if (pos.includes(\"right\") && deltaX < 0) return;\n if (pos.includes(\"left\") && deltaX > 0) return;\n\n setOffset(deltaX);\n };\n\n const handlePointerUp = () => {\n if (!isDragging) return;\n setIsDragging(false);\n dragStartX.current = null;\n\n if (Math.abs(offset) > 50) {\n toastLib.dismiss(toast.id);\n } else {\n setOffset(0);\n }\n };\n\n const stackDepth = index;\n const isHidden = stackDepth >= MAX_STACK_VISIBLE;\n const scale = 1 - stackDepth * SCALE_STEP;\n const peekY = stackDepth * PEEK_OFFSET * (isBottom ? -1 : 1);\n const opacity = isHidden ? 0 : 1 - stackDepth * OPACITY_STEP;\n\n let containerStyle: React.CSSProperties;\n\n if (!isExpanded) {\n containerStyle = {\n position: \"absolute\",\n top: isBottom ? undefined : 0,\n bottom: isBottom ? 0 : undefined,\n left: 0,\n right: 0,\n transform: `translateY(${peekY}px) scale(${scale})${offset ? ` translateX(${offset}px)` : \"\"}`,\n opacity,\n zIndex: total - stackDepth,\n visibility: isHidden ? \"hidden\" : \"visible\",\n pointerEvents: index === 0 ? \"auto\" : \"none\",\n transformOrigin: isBottom ? \"bottom center\" : \"top center\",\n };\n } else {\n containerStyle = {\n position: \"relative\",\n transform: offset ? `translateX(${offset}px)` : undefined,\n opacity: 1,\n zIndex: total - stackDepth,\n pointerEvents: \"auto\",\n };\n }\n\n const dynamicStyle: React.CSSProperties = {\n ...toast.style,\n ...containerStyle,\n transition: isDragging\n ? \"opacity 0.3s ease, visibility 0.3s ease\"\n : \"transform 0.35s cubic-bezier(0.34, 1.15, 0.64, 1), opacity 0.3s ease, visibility 0.3s ease\",\n touchAction: \"none\",\n };\n\n if (toast.render) {\n return (\n <div\n style={dynamicStyle}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onMouseEnter={() => setIsItemHovered(true)}\n onMouseLeave={() => setIsItemHovered(false)}\n >\n {toast.render()}\n </div>\n );\n }\n\n const defaultIcon = icons[toast.type as keyof typeof icons] || null;\n const Icon = toast.icon !== undefined ? toast.icon : defaultIcon;\n\n return (\n <div\n className={`tf-toast tf-toast-${toast.type} ${toast.className || \"\"}`}\n style={dynamicStyle}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onMouseEnter={() => setIsItemHovered(true)}\n onMouseLeave={() => setIsItemHovered(false)}\n >\n {Icon && (\n <span\n className=\"tf-icon\"\n style={{ alignSelf: \"flex-start\", marginTop: \"2px\", color: toast.iconColor }}\n >\n {Icon}\n </span>\n )}\n <div className=\"tf-message\" style={{ flex: 1, display: \"flex\", flexDirection: \"column\" }}>\n <span>{toast.message}</span>\n {toast.description && (\n <span className=\"tf-description\">{toast.description}</span>\n )}\n {toast.progress !== undefined && (\n <div className=\"tf-progress-bg\">\n <div className=\"tf-progress-fill\" style={{ width: `${toast.progress}%` }} />\n </div>\n )}\n </div>\n\n {toast.action && (\n <button onClick={toast.action.onClick} className=\"tf-action-btn\">\n {toast.action.label}\n </button>\n )}\n\n {toast.dismissible && (\n <button\n title=\"Dismiss\"\n onClick={() => toastLib.dismiss(toast.id)}\n className=\"tf-close-btn\"\n >\n ✖\n </button>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["useState","toast","useState","useEffect","toast","useState","useEffect","jsx","useState","PEEK_OFFSET"]}
|
|
@@ -1,174 +1,202 @@
|
|
|
1
|
-
.tf-toast-container {
|
|
2
|
-
position: fixed;
|
|
3
|
-
z-index:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
.tf-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
.tf-bottom-
|
|
31
|
-
bottom: 20px;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
.tf-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
font-size:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/*
|
|
124
|
-
.tf-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/*
|
|
138
|
-
.tf-
|
|
139
|
-
background:
|
|
140
|
-
border:
|
|
141
|
-
color: #
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
color: #
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
1
|
+
.tf-toast-container {
|
|
2
|
+
position: fixed;
|
|
3
|
+
z-index: 99999;
|
|
4
|
+
pointer-events: auto;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/* ---- Position placements ---- */
|
|
8
|
+
.tf-top-left {
|
|
9
|
+
top: 20px;
|
|
10
|
+
left: 20px;
|
|
11
|
+
}
|
|
12
|
+
.tf-top-center {
|
|
13
|
+
top: 20px;
|
|
14
|
+
left: 50%;
|
|
15
|
+
transform: translateX(-50%);
|
|
16
|
+
}
|
|
17
|
+
.tf-top-right {
|
|
18
|
+
top: 20px;
|
|
19
|
+
right: 20px;
|
|
20
|
+
}
|
|
21
|
+
.tf-bottom-left {
|
|
22
|
+
bottom: 20px;
|
|
23
|
+
left: 20px;
|
|
24
|
+
}
|
|
25
|
+
.tf-bottom-center {
|
|
26
|
+
bottom: 20px;
|
|
27
|
+
left: 50%;
|
|
28
|
+
transform: translateX(-50%);
|
|
29
|
+
}
|
|
30
|
+
.tf-bottom-right {
|
|
31
|
+
bottom: 20px;
|
|
32
|
+
right: 20px;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.tf-stack-collapsed {
|
|
36
|
+
position: relative;
|
|
37
|
+
display: block;
|
|
38
|
+
width: 320px;
|
|
39
|
+
min-height: 46px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.tf-stack-expanded {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-direction: column;
|
|
45
|
+
gap: 10px;
|
|
46
|
+
width: 320px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.tf-top-left .tf-stack-collapsed,
|
|
50
|
+
.tf-bottom-left .tf-stack-collapsed,
|
|
51
|
+
.tf-top-left .tf-stack-expanded,
|
|
52
|
+
.tf-bottom-left .tf-stack-expanded {
|
|
53
|
+
align-items: flex-start;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.tf-top-center .tf-stack-collapsed,
|
|
57
|
+
.tf-bottom-center .tf-stack-collapsed,
|
|
58
|
+
.tf-top-center .tf-stack-expanded,
|
|
59
|
+
.tf-bottom-center .tf-stack-expanded {
|
|
60
|
+
align-items: center;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.tf-top-right .tf-stack-collapsed,
|
|
64
|
+
.tf-bottom-right .tf-stack-collapsed,
|
|
65
|
+
.tf-top-right .tf-stack-expanded,
|
|
66
|
+
.tf-bottom-right .tf-stack-expanded {
|
|
67
|
+
align-items: flex-end;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* ---- Toast base ---- */
|
|
71
|
+
.tf-toast {
|
|
72
|
+
display: flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
gap: 12px;
|
|
75
|
+
padding: 12px 16px;
|
|
76
|
+
background: #0f0f0f;
|
|
77
|
+
border: 1px solid #2a2a2a;
|
|
78
|
+
border-radius: 8px;
|
|
79
|
+
color: #f1f1f1;
|
|
80
|
+
font-size: 14px;
|
|
81
|
+
font-family: var(
|
|
82
|
+
--tf-font-family,
|
|
83
|
+
system-ui,
|
|
84
|
+
-apple-system,
|
|
85
|
+
BlinkMacSystemFont,
|
|
86
|
+
"Segoe UI",
|
|
87
|
+
Roboto,
|
|
88
|
+
"Helvetica Neue",
|
|
89
|
+
Arial,
|
|
90
|
+
sans-serif
|
|
91
|
+
);
|
|
92
|
+
font-weight: 500;
|
|
93
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
|
94
|
+
min-width: 320px;
|
|
95
|
+
width: 320px;
|
|
96
|
+
box-sizing: border-box;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* New toast entry animation */
|
|
100
|
+
.tf-stack-collapsed > .tf-toast:first-child,
|
|
101
|
+
.tf-stack-expanded > .tf-toast {
|
|
102
|
+
animation: tf-fadeIn 0.22s ease-out;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.tf-icon {
|
|
106
|
+
display: flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
justify-content: center;
|
|
109
|
+
color: #f1f1f1;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.tf-message {
|
|
113
|
+
text-align: left;
|
|
114
|
+
flex: 1;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.tf-description {
|
|
118
|
+
font-size: 13px;
|
|
119
|
+
color: rgba(241, 241, 241, 0.7);
|
|
120
|
+
margin-top: -5px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* Progress Bar */
|
|
124
|
+
.tf-progress-bg {
|
|
125
|
+
margin-top: 10px;
|
|
126
|
+
height: 4px;
|
|
127
|
+
background: rgba(255, 255, 255, 0.1);
|
|
128
|
+
border-radius: 2px;
|
|
129
|
+
overflow: hidden;
|
|
130
|
+
}
|
|
131
|
+
.tf-progress-fill {
|
|
132
|
+
height: 100%;
|
|
133
|
+
background: #ffffff;
|
|
134
|
+
transition: width 0.2s;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Action Button */
|
|
138
|
+
.tf-action-btn {
|
|
139
|
+
background: rgba(255, 255, 255, 0.1);
|
|
140
|
+
border: none;
|
|
141
|
+
color: #ffffff;
|
|
142
|
+
padding: 6px 12px;
|
|
143
|
+
border-radius: 4px;
|
|
144
|
+
cursor: pointer;
|
|
145
|
+
margin-left: 8px;
|
|
146
|
+
font-size: 12px;
|
|
147
|
+
font-weight: 600;
|
|
148
|
+
white-space: nowrap;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* Close Button */
|
|
152
|
+
.tf-close-btn {
|
|
153
|
+
background: transparent;
|
|
154
|
+
border: none;
|
|
155
|
+
color: #888888;
|
|
156
|
+
cursor: pointer;
|
|
157
|
+
padding: 4px 4px 4px 8px;
|
|
158
|
+
font-size: 14px;
|
|
159
|
+
align-self: flex-start;
|
|
160
|
+
}
|
|
161
|
+
.tf-close-btn:hover {
|
|
162
|
+
color: #ffffff;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* ---- LIGHT THEME ---- */
|
|
166
|
+
.tf-theme-light .tf-toast {
|
|
167
|
+
background: #ffffff;
|
|
168
|
+
border: 1px solid #e5e5e5;
|
|
169
|
+
color: #171717;
|
|
170
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
|
171
|
+
}
|
|
172
|
+
.tf-theme-light .tf-icon {
|
|
173
|
+
color: #171717;
|
|
174
|
+
}
|
|
175
|
+
.tf-theme-light .tf-progress-bg {
|
|
176
|
+
background: rgba(0, 0, 0, 0.1);
|
|
177
|
+
}
|
|
178
|
+
.tf-theme-light .tf-progress-fill {
|
|
179
|
+
background: #171717;
|
|
180
|
+
}
|
|
181
|
+
.tf-theme-light .tf-action-btn {
|
|
182
|
+
background: rgba(0, 0, 0, 0.06);
|
|
183
|
+
color: #171717;
|
|
184
|
+
}
|
|
185
|
+
.tf-theme-light .tf-close-btn:hover {
|
|
186
|
+
color: #000000;
|
|
187
|
+
}
|
|
188
|
+
.tf-theme-light .tf-description {
|
|
189
|
+
color: rgba(23, 23, 23, 0.7);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* ---- Animations ---- */
|
|
193
|
+
@keyframes tf-fadeIn {
|
|
194
|
+
from {
|
|
195
|
+
opacity: 0;
|
|
196
|
+
transform: translateY(-8px) scale(0.96);
|
|
197
|
+
}
|
|
198
|
+
to {
|
|
199
|
+
opacity: 1;
|
|
200
|
+
transform: translateY(0) scale(1);
|
|
201
|
+
}
|
|
202
|
+
}
|