toastywave 0.1.0
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/README.md +345 -0
- package/dist/index.cjs.js +2 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +130 -0
- package/dist/index.esm.js +2 -0
- package/dist/index.esm.js.map +1 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Toastwave Contributors
|
|
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/README.md
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# Toastywave
|
|
2
|
+
|
|
3
|
+
Lightweight React toast notifications with zero CSS dependencies.
|
|
4
|
+
|
|
5
|
+
- **~3KB** gzipped
|
|
6
|
+
- **Deduplication** — identical messages won't stack
|
|
7
|
+
- **Countdown timer** with configurable text, pause-on-hover, and "click to stop"
|
|
8
|
+
- **Action presets** — built-in "undo", "retry" or custom actions
|
|
9
|
+
- **Custom icons** — use any React icon library (Hero Icons, Lucide, etc.)
|
|
10
|
+
- **Theming** — dark, light, or fully custom theme objects
|
|
11
|
+
- **Container scoping** — render at window level or inside any element
|
|
12
|
+
- **Promise toasts** — loading → success/error transitions
|
|
13
|
+
- **TypeScript** — full type definitions included
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
bun add toastywave
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```jsx
|
|
24
|
+
import { toast, Toaster } from 'toastywave';
|
|
25
|
+
|
|
26
|
+
function App() {
|
|
27
|
+
return (
|
|
28
|
+
<div>
|
|
29
|
+
<Toaster position="bottom-right" theme="dark" />
|
|
30
|
+
<button onClick={() => toast.success('Saved!')}>
|
|
31
|
+
Save
|
|
32
|
+
</button>
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## API Reference
|
|
39
|
+
|
|
40
|
+
### `toast(message, options?)`
|
|
41
|
+
|
|
42
|
+
Show a toast notification. Returns a numeric toast ID.
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
toast('Hello world');
|
|
46
|
+
toast('Custom duration', { duration: 8000 });
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
#### Shorthand Methods
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
toast.success('Changes saved');
|
|
53
|
+
toast.error('Something went wrong');
|
|
54
|
+
toast.warning('Are you sure?');
|
|
55
|
+
toast.info('New version available');
|
|
56
|
+
toast.loading('Uploading...'); // duration: Infinity
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
#### Options
|
|
60
|
+
|
|
61
|
+
| Option | Type | Default | Description |
|
|
62
|
+
|---|---|---|---|
|
|
63
|
+
| `type` | `string` | `"default"` | `"default"` `"success"` `"error"` `"warning"` `"info"` `"loading"` |
|
|
64
|
+
| `description` | `string` | — | Secondary text below the title |
|
|
65
|
+
| `duration` | `number` | `5000` | Auto-dismiss in ms. Use `Infinity` to persist. |
|
|
66
|
+
| `action` | `string \| object` | — | Preset name, preset config, or custom action |
|
|
67
|
+
| `icon` | `ReactNode` | — | Custom icon element (overrides default type icon) |
|
|
68
|
+
| `dedupeKey` | `string` | `${type}::${message}` | Custom key for deduplication |
|
|
69
|
+
| `showCountdown` | `boolean` | `true` | Show/hide the countdown footer |
|
|
70
|
+
| `countdownText` | `string` | `"This message will close in {seconds} second{s}."` | Countdown template |
|
|
71
|
+
| `pausedText` | `string` | `"Timer paused"` | Text when hovering (timer paused) |
|
|
72
|
+
| `stopText` | `string` | `"Click to stop."` | Clickable text to permanently stop timer |
|
|
73
|
+
|
|
74
|
+
### Action Buttons
|
|
75
|
+
|
|
76
|
+
Actions support three formats: preset name, preset with callback, or custom action.
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
// Using preset name (no callback)
|
|
80
|
+
toast.success('Deleted', { action: 'undo' });
|
|
81
|
+
|
|
82
|
+
// Using preset with callback
|
|
83
|
+
toast.success('Message archived', {
|
|
84
|
+
action: {
|
|
85
|
+
preset: 'undo',
|
|
86
|
+
onAction: () => {
|
|
87
|
+
restoreMessage();
|
|
88
|
+
toast.info('Message restored');
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Custom action
|
|
94
|
+
toast.error('Upload failed', {
|
|
95
|
+
action: {
|
|
96
|
+
label: 'Retry',
|
|
97
|
+
onClick: () => retryUpload(),
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### Registering Custom Presets
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
import { registerActionPreset } from 'toastywave';
|
|
106
|
+
|
|
107
|
+
registerActionPreset('retry', (onRetry) => ({
|
|
108
|
+
label: 'Retry',
|
|
109
|
+
onClick: onRetry,
|
|
110
|
+
}));
|
|
111
|
+
|
|
112
|
+
// Now use it anywhere
|
|
113
|
+
toast.error('Request failed', {
|
|
114
|
+
action: { preset: 'retry', onAction: () => fetchData() },
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Custom Icons
|
|
119
|
+
|
|
120
|
+
Use any React icon library by passing the `icon` prop:
|
|
121
|
+
|
|
122
|
+
```jsx
|
|
123
|
+
import { RocketLaunchIcon } from '@heroicons/react/24/outline';
|
|
124
|
+
|
|
125
|
+
// Override default icon with Hero Icons
|
|
126
|
+
toast('Launching soon!', {
|
|
127
|
+
icon: <RocketLaunchIcon style={{ width: 20, height: 20, color: '#f472b6' }} />,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Works with any toast type
|
|
131
|
+
toast.success('Deployed!', {
|
|
132
|
+
icon: <RocketLaunchIcon style={{ width: 20, height: 20, color: '#4ade80' }} />,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Or use Lucide, FontAwesome, custom SVGs, etc.
|
|
136
|
+
toast.info('Syncing...', {
|
|
137
|
+
icon: <CloudIcon className="w-5 h-5 text-blue-400" />,
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Promise Toasts
|
|
142
|
+
|
|
143
|
+
```js
|
|
144
|
+
toast.promise(
|
|
145
|
+
fetch('/api/deploy'),
|
|
146
|
+
{
|
|
147
|
+
loading: 'Deploying...',
|
|
148
|
+
success: 'Deployed successfully!',
|
|
149
|
+
error: 'Deploy failed',
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Dismissing
|
|
155
|
+
|
|
156
|
+
```js
|
|
157
|
+
const id = toast('Persistent message', { duration: Infinity });
|
|
158
|
+
|
|
159
|
+
// Later...
|
|
160
|
+
toast.dismiss(id);
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Custom Countdown Text
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
// Custom text
|
|
167
|
+
toast.success('Saved', {
|
|
168
|
+
countdownText: 'Auto-closing in {seconds}s',
|
|
169
|
+
stopText: 'Keep open',
|
|
170
|
+
pausedText: 'Paused',
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Hide countdown entirely
|
|
174
|
+
toast.info('Clean notification', {
|
|
175
|
+
showCountdown: false,
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Deduplication
|
|
180
|
+
|
|
181
|
+
Identical toasts (same type + message) are automatically deduplicated:
|
|
182
|
+
|
|
183
|
+
```js
|
|
184
|
+
toast.success('Saved'); // shown
|
|
185
|
+
toast.success('Saved'); // ignored (already active)
|
|
186
|
+
toast.success('Saved'); // ignored
|
|
187
|
+
|
|
188
|
+
// Custom dedup key
|
|
189
|
+
toast.info('Update', { dedupeKey: 'update-check' });
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## `<Toaster />` Component
|
|
195
|
+
|
|
196
|
+
Place once in your app layout.
|
|
197
|
+
|
|
198
|
+
```jsx
|
|
199
|
+
<Toaster
|
|
200
|
+
position="bottom-right"
|
|
201
|
+
theme="dark"
|
|
202
|
+
/>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
#### Props
|
|
206
|
+
|
|
207
|
+
| Prop | Type | Default | Description |
|
|
208
|
+
|---|---|---|---|
|
|
209
|
+
| `position` | `string` | `"bottom-right"` | `"top-left"` `"top-center"` `"top-right"` `"bottom-left"` `"bottom-center"` `"bottom-right"` |
|
|
210
|
+
| `theme` | `string \| object` | `"dark"` | `"dark"`, `"light"`, or a custom theme object |
|
|
211
|
+
| `container` | `RefObject` | — | Ref to a container element for scoped rendering |
|
|
212
|
+
|
|
213
|
+
### Container Scoping
|
|
214
|
+
|
|
215
|
+
Render toasts inside a specific element instead of the window:
|
|
216
|
+
|
|
217
|
+
```jsx
|
|
218
|
+
function Panel() {
|
|
219
|
+
const containerRef = useRef(null);
|
|
220
|
+
|
|
221
|
+
return (
|
|
222
|
+
<div ref={containerRef} style={{ position: 'relative', overflow: 'hidden' }}>
|
|
223
|
+
<Toaster position="top-center" container={containerRef} theme="light" />
|
|
224
|
+
<button onClick={() => toast.success('Scoped!')}>
|
|
225
|
+
Toast inside panel
|
|
226
|
+
</button>
|
|
227
|
+
</div>
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
> **Note:** The container must have `position: relative` (or `absolute`/`fixed`).
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Theming
|
|
237
|
+
|
|
238
|
+
### Built-in Themes
|
|
239
|
+
|
|
240
|
+
```jsx
|
|
241
|
+
<Toaster theme="dark" />
|
|
242
|
+
<Toaster theme="light" />
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Custom Theme
|
|
246
|
+
|
|
247
|
+
Pass an object with any subset of theme tokens. Missing tokens fall back to the dark theme.
|
|
248
|
+
|
|
249
|
+
```jsx
|
|
250
|
+
const customTheme = {
|
|
251
|
+
toastBg: 'rgba(15, 10, 40, 0.96)',
|
|
252
|
+
toastBorder: 'rgba(120, 80, 255, 0.15)',
|
|
253
|
+
toastShadow: '0 16px 48px rgba(60, 20, 180, 0.25)',
|
|
254
|
+
title: '#e8e0ff',
|
|
255
|
+
// ... other tokens
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
<Toaster theme={customTheme} />
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Theme Token Reference
|
|
262
|
+
|
|
263
|
+
| Token | Description |
|
|
264
|
+
|---|---|
|
|
265
|
+
| `toastBg` | Toast card background |
|
|
266
|
+
| `toastBorder` | Toast card border |
|
|
267
|
+
| `toastShadow` | Toast card box-shadow |
|
|
268
|
+
| `title` | Title text color |
|
|
269
|
+
| `desc` | Description text color |
|
|
270
|
+
| `footerBg` | Countdown footer background |
|
|
271
|
+
| `footerBorder` | Countdown footer top border |
|
|
272
|
+
| `footerText` | Countdown text color |
|
|
273
|
+
| `footerLink` | "Click to stop" link color |
|
|
274
|
+
| `progressTrack` | Progress bar track background |
|
|
275
|
+
| `closeBtnColor` | Close button default color |
|
|
276
|
+
| `closeBtnHover` | Close button hover color |
|
|
277
|
+
| `closeBtnHoverBg` | Close button hover background |
|
|
278
|
+
| `actionBg` | Action button background |
|
|
279
|
+
| `actionBorder` | Action button border |
|
|
280
|
+
| `actionHoverBg` | Action button hover background |
|
|
281
|
+
| `actionHoverBorder` | Action button hover border |
|
|
282
|
+
| `actionText` | Action button text color |
|
|
283
|
+
| `backdrop` | CSS backdrop-filter value |
|
|
284
|
+
|
|
285
|
+
### Utilities
|
|
286
|
+
|
|
287
|
+
```js
|
|
288
|
+
import { darkTheme, lightTheme, resolveTheme } from 'toastywave';
|
|
289
|
+
|
|
290
|
+
// Extend the dark theme
|
|
291
|
+
const custom = resolveTheme({
|
|
292
|
+
...darkTheme,
|
|
293
|
+
toastBg: '#1a1a2e',
|
|
294
|
+
title: '#eee',
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## Development
|
|
301
|
+
|
|
302
|
+
### Running the Playground
|
|
303
|
+
|
|
304
|
+
The repo includes a comprehensive playground that showcases all features.
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
# Install dependencies
|
|
308
|
+
bun install
|
|
309
|
+
|
|
310
|
+
# Build library and start playground
|
|
311
|
+
bun run dev
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Then open **http://localhost:5173** in your browser.
|
|
315
|
+
|
|
316
|
+
The playground demonstrates:
|
|
317
|
+
- All toast types (default, success, error, warning, info, loading)
|
|
318
|
+
- Action presets (undo, retry) and custom actions
|
|
319
|
+
- Promise toasts
|
|
320
|
+
- Countdown timer options
|
|
321
|
+
- Position anchoring (6 positions)
|
|
322
|
+
- Theme switching (dark, light, custom)
|
|
323
|
+
- Deduplication
|
|
324
|
+
- Container scoping
|
|
325
|
+
- Programmatic dismissal
|
|
326
|
+
|
|
327
|
+
### Scripts
|
|
328
|
+
|
|
329
|
+
| Script | Description |
|
|
330
|
+
|---|---|
|
|
331
|
+
| `bun run dev` | Build library and start playground |
|
|
332
|
+
| `bun run build` | Build the library |
|
|
333
|
+
| `bun run watch` | Watch mode for library development |
|
|
334
|
+
| `bun run playground` | Start playground only (requires build) |
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Browser Support
|
|
339
|
+
|
|
340
|
+
Works in all modern browsers (Chrome, Firefox, Safari, Edge).
|
|
341
|
+
Requires `backdrop-filter` support for the glass effect (gracefully degrades).
|
|
342
|
+
|
|
343
|
+
## License
|
|
344
|
+
|
|
345
|
+
MIT
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("react/jsx-runtime");function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function n(e,t,r){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t);if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),r.push.apply(r,n)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach(function(t){n(e,t,r[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))})}return e}function a(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var n,o,i,a,s=[],c=!0,u=!1;try{if(i=(r=r.call(e)).next,0===t);else for(;!(c=(n=i.call(r)).done)&&(s.push(n.value),s.length!==t);c=!0);}catch(e){u=!0,o=e}finally{try{if(!c&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(u)throw o}}return s}}(e,t)||c(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function s(e){return function(e){if(Array.isArray(e))return r(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||c(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function c(e,t){if(e){if("string"==typeof e)return r(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?r(e,t):void 0}}var u=0,l=null,d=new Map,f=function(e){return d.delete(e)},p={undo:function(e){return{label:"Undo",onClick:e}}},g=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=t.dedupeKey||"".concat(t.type||"default","::").concat(e);if(d.has(r))return d.get(r);var n=++u,o=function(e){if(!e)return null;if("string"==typeof e){var t=p[e];return t?t(function(){}):null}if(e.preset){var r=p[e.preset];return r?r(e.onAction||function(){}):null}return e}(t.action),a=i(i({id:n,message:e,type:"default",duration:5e3,showCountdown:!0,countdownText:"This message will close in {seconds} second{s}.",pausedText:"Timer paused",stopText:"Click to stop."},t),{},{action:o,dedupeKey:r,createdAt:Date.now()});return d.set(r,n),l&&l(a),n};g.success=function(e,t){return g(e,i(i({},t),{},{type:"success"}))},g.error=function(e,t){return g(e,i(i({},t),{},{type:"error"}))},g.warning=function(e,t){return g(e,i(i({},t),{},{type:"warning"}))},g.info=function(e,t){return g(e,i(i({},t),{},{type:"info"}))},g.loading=function(e,t){return g(e,i(i({},t),{},{type:"loading",duration:1/0}))},g.promise=function(e,t,r){var n=g(t.loading,i(i({},r),{},{type:"loading",duration:1/0}));return e.then(function(){l&&l({id:n,message:t.success,type:"success",duration:5e3,showCountdown:!0,countdownText:(null==r?void 0:r.countdownText)||"This message will close in {seconds} second{s}.",pausedText:(null==r?void 0:r.pausedText)||"Timer paused",stopText:(null==r?void 0:r.stopText)||"Click to stop.",createdAt:Date.now(),replace:!0,dedupeKey:"p-ok-".concat(n)})}).catch(function(){l&&l({id:n,message:t.error,type:"error",duration:5e3,showCountdown:!0,countdownText:(null==r?void 0:r.countdownText)||"This message will close in {seconds} second{s}.",pausedText:(null==r?void 0:r.pausedText)||"Timer paused",stopText:(null==r?void 0:r.stopText)||"Click to stop.",createdAt:Date.now(),replace:!0,dedupeKey:"p-err-".concat(n)})}),n},g.dismiss=function(e){l&&l({id:e,_dismiss:!0})};var x={toastBg:"rgba(30,30,32,.95)",toastBorder:"rgba(255,255,255,.08)",toastShadow:"0 16px 48px rgba(0,0,0,.5),0 2px 8px rgba(0,0,0,.3),inset 0 1px 0 rgba(255,255,255,.04)",title:"#f0f0f0",desc:"rgba(255,255,255,.5)",footerBg:"rgba(0,0,0,.15)",footerBorder:"rgba(255,255,255,.06)",footerText:"rgba(255,255,255,.35)",footerLink:"rgba(255,255,255,.6)",progressTrack:"rgba(255,255,255,.04)",closeBtnColor:"rgba(255,255,255,.3)",closeBtnHover:"rgba(255,255,255,.7)",closeBtnHoverBg:"rgba(255,255,255,.06)",actionBg:"rgba(255,255,255,.08)",actionBorder:"rgba(255,255,255,.15)",actionHoverBg:"rgba(255,255,255,.14)",actionHoverBorder:"rgba(255,255,255,.25)",actionText:"#f0f0f0",backdrop:"blur(16px) saturate(1.4)"},b={toastBg:"rgba(255,255,255,.97)",toastBorder:"rgba(0,0,0,.08)",toastShadow:"0 16px 48px rgba(0,0,0,.08),0 4px 12px rgba(0,0,0,.05),0 1px 3px rgba(0,0,0,.06)",title:"#1a1a1a",desc:"rgba(0,0,0,.5)",footerBg:"rgba(0,0,0,.025)",footerBorder:"rgba(0,0,0,.06)",footerText:"rgba(0,0,0,.35)",footerLink:"rgba(0,0,0,.6)",progressTrack:"rgba(0,0,0,.05)",closeBtnColor:"rgba(0,0,0,.25)",closeBtnHover:"rgba(0,0,0,.6)",closeBtnHoverBg:"rgba(0,0,0,.05)",actionBg:"rgba(0,0,0,.05)",actionBorder:"rgba(0,0,0,.12)",actionHoverBg:"rgba(0,0,0,.1)",actionHoverBorder:"rgba(0,0,0,.2)",actionText:"#1a1a1a",backdrop:"blur(16px) saturate(1.2)"},h={dark:x,light:b},y=function(e){return e?"string"==typeof e?h[e]||x:i(i({},x),e):x},v=function(){return t.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",children:[t.jsx("circle",{cx:"10",cy:"10",r:"9",stroke:"#4ade80",strokeWidth:"1.5",opacity:".3"}),t.jsx("path",{d:"M6.5 10.5l2 2 5-5",stroke:"#4ade80",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})]})},m=function(){return t.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",children:[t.jsx("circle",{cx:"10",cy:"10",r:"9",stroke:"#f87171",strokeWidth:"1.5",opacity:".3"}),t.jsx("path",{d:"M10 6v5",stroke:"#f87171",strokeWidth:"1.5",strokeLinecap:"round"}),t.jsx("circle",{cx:"10",cy:"13.5",r:".75",fill:"#f87171"})]})},k=function(){return t.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",children:[t.jsx("path",{d:"M10 2.5L1.5 17h17L10 2.5z",stroke:"#fbbf24",strokeWidth:"1.3",strokeLinejoin:"round",opacity:".35"}),t.jsx("path",{d:"M10 8v4",stroke:"#fbbf24",strokeWidth:"1.5",strokeLinecap:"round"}),t.jsx("circle",{cx:"10",cy:"14.5",r:".75",fill:"#fbbf24"})]})},j=function(){return t.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",children:[t.jsx("circle",{cx:"10",cy:"10",r:"9",stroke:"#60a5fa",strokeWidth:"1.5",opacity:".3"}),t.jsx("path",{d:"M10 9v5",stroke:"#60a5fa",strokeWidth:"1.5",strokeLinecap:"round"}),t.jsx("circle",{cx:"10",cy:"6.5",r:".75",fill:"#60a5fa"})]})},w=function(){return t.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",style:{animation:"toastywave-spin .7s linear infinite"},children:[t.jsx("circle",{cx:"10",cy:"10",r:"8",stroke:"currentColor",strokeWidth:"1.8",opacity:".15"}),t.jsx("path",{d:"M10 2a8 8 0 018 8",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",opacity:".5"})]})},T=function(){return t.jsx("svg",{width:"14",height:"14",viewBox:"0 0 14 14",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",children:t.jsx("path",{d:"M3.5 3.5l7 7M10.5 3.5l-7 7"})})},B={success:t.jsx(v,{}),error:t.jsx(m,{}),warning:t.jsx(k,{}),info:t.jsx(j,{}),loading:t.jsx(w,{})},S={success:"#4ade80",error:"#f87171",warning:"#fbbf24",info:"#60a5fa",loading:"#a78bfa",default:"#888"};function C(r){var n=r.data,o=r.onDismiss,i=r.position,s=r.theme,c=a(e.useState("enter"),2),u=c[0],l=c[1],d=a(e.useState(!1),2),f=d[0],p=d[1],g=a(e.useState(n.duration),2),x=g[0],b=g[1],h=e.useRef(null),y=e.useRef(Date.now()),v=i.startsWith("top"),m=n.duration!==1/0,k=m&&!1!==n.showCountdown,j=s;e.useEffect(function(){if(m&&!f){y.current=Date.now();var e=y.current+x;return h.current=setInterval(function(){var t=e-Date.now();t<=0?(clearInterval(h.current),l("exit"),setTimeout(function(){return o(n.id,n.dedupeKey)},320)):b(t)},50),function(){return clearInterval(h.current)}}h.current&&clearInterval(h.current)},[f,m]),e.useEffect(function(){n.duration!==1/0&&b(n.duration)},[n.type,n.duration,n.createdAt]),e.useEffect(function(){var e=requestAnimationFrame(function(){return l("visible")});return function(){return cancelAnimationFrame(e)}},[]);var w,C,O=function(){l("exit"),setTimeout(function(){return o(n.id,n.dedupeKey)},320)},M=m?Math.max(0,x/n.duration):1,W=Math.ceil(x/1e3),A=v?-24:24,L={enter:"translateY(".concat(A,"px) scale(.95)"),visible:"translateY(0) scale(1)",exit:"translateY(".concat(A,"px) scale(.95)")};return t.jsxs("div",{onMouseEnter:function(){return!f&&p(!0)},onMouseLeave:function(){return p(!1)},style:{width:420,maxWidth:"calc(100vw - 32px)",background:j.toastBg,backdropFilter:j.backdrop,WebkitBackdropFilter:j.backdrop,border:"1px solid ".concat(j.toastBorder),borderRadius:12,overflow:"hidden",transform:L[u],opacity:"visible"===u?1:0,transition:"all .32s cubic-bezier(.16,1,.3,1)",boxShadow:j.toastShadow},children:[t.jsxs("div",{style:{padding:"14px 16px",display:"flex",alignItems:"flex-start",gap:12},children:[(n.icon||"default"!==n.type)&&t.jsx("div",{style:{flexShrink:0,marginTop:1,color:j.title},children:n.icon||B[n.type]}),t.jsxs("div",{style:{flex:1,minWidth:0},children:[t.jsx("div",{style:{fontSize:14,fontWeight:600,color:j.title,lineHeight:1.4},children:n.message}),n.description&&t.jsx("div",{style:{fontSize:13,color:j.desc,marginTop:4,lineHeight:1.45},children:n.description}),n.action&&t.jsx("button",{onClick:function(e){e.stopPropagation(),n.action.onClick&&n.action.onClick(),O()},onMouseEnter:function(e){e.currentTarget.style.background=j.actionHoverBg,e.currentTarget.style.borderColor=j.actionHoverBorder},onMouseLeave:function(e){e.currentTarget.style.background=j.actionBg,e.currentTarget.style.borderColor=j.actionBorder},style:{marginTop:10,padding:"6px 14px",fontSize:13,fontWeight:600,fontFamily:"inherit",borderRadius:6,border:"1px solid ".concat(j.actionBorder),background:j.actionBg,color:j.actionText,cursor:"pointer",transition:"all .15s ease"},children:n.action.label})]}),t.jsx("button",{onClick:function(e){e.stopPropagation(),O()},onMouseEnter:function(e){e.currentTarget.style.color=j.closeBtnHover,e.currentTarget.style.background=j.closeBtnHoverBg},onMouseLeave:function(e){e.currentTarget.style.color=j.closeBtnColor,e.currentTarget.style.background="transparent"},style:{flexShrink:0,width:28,height:28,border:"none",background:"transparent",color:j.closeBtnColor,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",borderRadius:6,transition:"all .15s ease",padding:0},children:t.jsx(T,{})})]}),k&&t.jsx("div",{style:{borderTop:"1px solid ".concat(j.footerBorder),padding:"8px 16px",background:j.footerBg,display:"flex",alignItems:"center"},children:t.jsx("div",{style:{fontSize:12,color:j.footerText},children:f?n.pausedText:t.jsxs(t.Fragment,{children:[(w=n.countdownText,C=W,w.replace(/\{seconds\}/g,String(C)).replace(/\{s\}/g,1!==C?"s":""))," ",t.jsx("span",{onClick:function(e){e.stopPropagation(),p(!0)},style:{color:j.footerLink,fontWeight:600,cursor:"pointer",textDecoration:"underline",textUnderlineOffset:2},children:n.stopText})]})})}),m&&!f&&t.jsx("div",{style:{height:2,background:j.progressTrack,position:"relative"},children:t.jsx("div",{style:{position:"absolute",left:0,top:0,height:"100%",width:"".concat(100*M,"%"),background:S[n.type]||S.default,transition:"width .1s linear",borderRadius:"0 1px 1px 0"}})})]})}exports.Toaster=function(r){var n=r.position,o=void 0===n?"bottom-right":n,c=r.theme,u=void 0===c?"dark":c,d=r.container,p=a(e.useState([]),2),g=p[0],x=p[1],b=y(u);e.useEffect(function(){return l=function(e){e._dismiss?x(function(t){var r=t.find(function(t){return t.id===e.id});return r&&f(r.dedupeKey),t.filter(function(t){return t.id!==e.id})}):x(function(t){if(e.replace){var r=t.find(function(t){return t.id===e.id});return r&&f(r.dedupeKey),t.map(function(t){return t.id===e.id?i({},e):t})}return[].concat(s(t),[e])})},function(){l=null}},[]);var h=e.useCallback(function(e,t){f(t),x(function(t){return t.filter(function(t){return t.id!==e})})},[]),v=a(o.split("-"),2),m=v[0],k=v[1],j="center"===k;return t.jsxs("div",{style:i(i({position:d?"absolute":"fixed",zIndex:99999,display:"flex",flexDirection:"top"===m?"column":"column-reverse",alignItems:j?"center":"left"===k?"flex-start":"flex-end",gap:10,padding:d?12:20,pointerEvents:"none"},"top"===m?{top:0}:{bottom:0}),j?{left:0,right:0}:"left"===k?{left:0}:{right:0}),children:[t.jsx("style",{children:"@keyframes toastywave-spin{to{transform:rotate(360deg)}}"}),g.map(function(e){return t.jsx("div",{style:{pointerEvents:"auto"},children:t.jsx(C,{data:e,onDismiss:h,position:o,theme:b})},e.id)})]})},exports.darkTheme=x,exports.default=g,exports.lightTheme=b,exports.registerActionPreset=function(e,t){p[e]=t},exports.resolveTheme=y,exports.toast=g;
|
|
2
|
+
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/index.jsx"],"sourcesContent":["import { useState, useEffect, useCallback, useRef, createContext, useContext } from \"react\";\n\n/* ═══════════════════════════════════════════════════════════════\n TOASTYWAVE - Lightweight React Toast Notification System\n ═══════════════════════════════════════════════════════════════ */\n\n// ── Internal State ──────────────────────────────────────────────\n\nlet _id = 0;\nlet _addToast = null;\nlet _active = new Map();\n\nconst _unreg = (k) => _active.delete(k);\n\n// ── Public API ──────────────────────────────────────────────────\n\n// ── Action Presets ───────────────────────────────────────────────\n\nconst actionPresets = {\n undo: (onUndo) => ({\n label: \"Undo\",\n onClick: onUndo,\n }),\n};\n\n/**\n * Register a custom action preset.\n * @param {string} name - Preset name\n * @param {Function} factory - Factory function (onAction) => { label, onClick }\n */\nconst registerActionPreset = (name, factory) => {\n actionPresets[name] = factory;\n};\n\n/**\n * Resolve action from preset string or custom object.\n * @param {string|Object} action - \"undo\", { preset: \"undo\", onAction }, or { label, onClick }\n * @returns {Object|null} Resolved action object\n */\nconst resolveAction = (action) => {\n if (!action) return null;\n if (typeof action === \"string\") {\n // Preset name only (e.g., \"undo\") - return preset with no-op\n const factory = actionPresets[action];\n return factory ? factory(() => {}) : null;\n }\n if (action.preset) {\n // Preset with callback (e.g., { preset: \"undo\", onAction: () => {...} })\n const factory = actionPresets[action.preset];\n return factory ? factory(action.onAction || (() => {})) : null;\n }\n // Custom action object { label, onClick }\n return action;\n};\n\n/**\n * Show a toast notification.\n *\n * @param {string} message - The toast title/message\n * @param {Object} [opts] - Options\n * @param {string} [opts.type=\"default\"] - Toast type: \"default\"|\"success\"|\"error\"|\"warning\"|\"info\"|\"loading\"\n * @param {string} [opts.description] - Secondary text below the message\n * @param {number} [opts.duration=5000] - Auto-dismiss duration in ms. Use Infinity to persist.\n * @param {string|Object} [opts.action] - Action button: preset name (\"undo\"), preset config ({ preset: \"undo\", onAction }), or custom ({ label, onClick })\n * @param {React.ReactNode} [opts.icon] - Custom icon element. Overrides the default type icon.\n * @param {string} [opts.dedupeKey] - Custom dedup key. Defaults to `${type}::${message}`\n * @param {string} [opts.countdownText] - Custom countdown text. Use `{seconds}` as placeholder.\n * @param {string} [opts.pausedText] - Custom text shown when timer is paused.\n * @param {string} [opts.stopText] - Custom \"Click to stop\" text.\n * @param {boolean} [opts.showCountdown=true] - Whether to show the countdown footer.\n * @returns {number} Toast ID\n */\nconst toast = (message, opts = {}) => {\n const dk = opts.dedupeKey || `${opts.type || \"default\"}::${message}`;\n if (_active.has(dk)) return _active.get(dk);\n const id = ++_id;\n const resolvedAction = resolveAction(opts.action);\n const t = {\n id,\n message,\n type: \"default\",\n duration: 5000,\n showCountdown: true,\n countdownText: \"This message will close in {seconds} second{s}.\",\n pausedText: \"Timer paused\",\n stopText: \"Click to stop.\",\n ...opts,\n action: resolvedAction,\n dedupeKey: dk,\n createdAt: Date.now(),\n };\n _active.set(dk, id);\n if (_addToast) _addToast(t);\n return id;\n};\n\ntoast.success = (m, o) => toast(m, { ...o, type: \"success\" });\ntoast.error = (m, o) => toast(m, { ...o, type: \"error\" });\ntoast.warning = (m, o) => toast(m, { ...o, type: \"warning\" });\ntoast.info = (m, o) => toast(m, { ...o, type: \"info\" });\ntoast.loading = (m, o) => toast(m, { ...o, type: \"loading\", duration: Infinity });\n\n/**\n * Show a promise-based toast that transitions from loading → success/error.\n *\n * @param {Promise} promise\n * @param {Object} msgs - { loading, success, error }\n * @param {Object} [opts] - Same options as toast()\n * @returns {number} Toast ID\n */\ntoast.promise = (promise, msgs, o) => {\n const id = toast(msgs.loading, { ...o, type: \"loading\", duration: Infinity });\n promise\n .then(() => {\n if (_addToast)\n _addToast({\n id, message: msgs.success, type: \"success\", duration: 5000,\n showCountdown: true,\n countdownText: o?.countdownText || \"This message will close in {seconds} second{s}.\",\n pausedText: o?.pausedText || \"Timer paused\",\n stopText: o?.stopText || \"Click to stop.\",\n createdAt: Date.now(), replace: true, dedupeKey: `p-ok-${id}`,\n });\n })\n .catch(() => {\n if (_addToast)\n _addToast({\n id, message: msgs.error, type: \"error\", duration: 5000,\n showCountdown: true,\n countdownText: o?.countdownText || \"This message will close in {seconds} second{s}.\",\n pausedText: o?.pausedText || \"Timer paused\",\n stopText: o?.stopText || \"Click to stop.\",\n createdAt: Date.now(), replace: true, dedupeKey: `p-err-${id}`,\n });\n });\n return id;\n};\n\n/**\n * Programmatically dismiss a toast by ID.\n * @param {number} id\n */\ntoast.dismiss = (id) => {\n if (_addToast) _addToast({ id, _dismiss: true });\n};\n\n// ── Default Themes ──────────────────────────────────────────────\n\nconst darkTheme = {\n toastBg: \"rgba(30,30,32,.95)\",\n toastBorder: \"rgba(255,255,255,.08)\",\n toastShadow: \"0 16px 48px rgba(0,0,0,.5),0 2px 8px rgba(0,0,0,.3),inset 0 1px 0 rgba(255,255,255,.04)\",\n title: \"#f0f0f0\",\n desc: \"rgba(255,255,255,.5)\",\n footerBg: \"rgba(0,0,0,.15)\",\n footerBorder: \"rgba(255,255,255,.06)\",\n footerText: \"rgba(255,255,255,.35)\",\n footerLink: \"rgba(255,255,255,.6)\",\n progressTrack: \"rgba(255,255,255,.04)\",\n closeBtnColor: \"rgba(255,255,255,.3)\",\n closeBtnHover: \"rgba(255,255,255,.7)\",\n closeBtnHoverBg: \"rgba(255,255,255,.06)\",\n actionBg: \"rgba(255,255,255,.08)\",\n actionBorder: \"rgba(255,255,255,.15)\",\n actionHoverBg: \"rgba(255,255,255,.14)\",\n actionHoverBorder: \"rgba(255,255,255,.25)\",\n actionText: \"#f0f0f0\",\n backdrop: \"blur(16px) saturate(1.4)\",\n};\n\nconst lightTheme = {\n toastBg: \"rgba(255,255,255,.97)\",\n toastBorder: \"rgba(0,0,0,.08)\",\n toastShadow: \"0 16px 48px rgba(0,0,0,.08),0 4px 12px rgba(0,0,0,.05),0 1px 3px rgba(0,0,0,.06)\",\n title: \"#1a1a1a\",\n desc: \"rgba(0,0,0,.5)\",\n footerBg: \"rgba(0,0,0,.025)\",\n footerBorder: \"rgba(0,0,0,.06)\",\n footerText: \"rgba(0,0,0,.35)\",\n footerLink: \"rgba(0,0,0,.6)\",\n progressTrack: \"rgba(0,0,0,.05)\",\n closeBtnColor: \"rgba(0,0,0,.25)\",\n closeBtnHover: \"rgba(0,0,0,.6)\",\n closeBtnHoverBg: \"rgba(0,0,0,.05)\",\n actionBg: \"rgba(0,0,0,.05)\",\n actionBorder: \"rgba(0,0,0,.12)\",\n actionHoverBg: \"rgba(0,0,0,.1)\",\n actionHoverBorder: \"rgba(0,0,0,.2)\",\n actionText: \"#1a1a1a\",\n backdrop: \"blur(16px) saturate(1.2)\",\n};\n\nconst builtInThemes = { dark: darkTheme, light: lightTheme };\n\n/**\n * Resolve a theme by name or merge a custom theme object on top of the dark base.\n * @param {\"dark\"|\"light\"|Object} themeOrName\n * @returns {Object} Resolved theme tokens\n */\nconst resolveTheme = (themeOrName) => {\n if (!themeOrName) return darkTheme;\n if (typeof themeOrName === \"string\") return builtInThemes[themeOrName] || darkTheme;\n return { ...darkTheme, ...themeOrName };\n};\n\n// ── SVG Icons ───────────────────────────────────────────────────\n\nconst CheckIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <circle cx=\"10\" cy=\"10\" r=\"9\" stroke=\"#4ade80\" strokeWidth=\"1.5\" opacity=\".3\" />\n <path d=\"M6.5 10.5l2 2 5-5\" stroke=\"#4ade80\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n);\nconst ErrorIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <circle cx=\"10\" cy=\"10\" r=\"9\" stroke=\"#f87171\" strokeWidth=\"1.5\" opacity=\".3\" />\n <path d=\"M10 6v5\" stroke=\"#f87171\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n <circle cx=\"10\" cy=\"13.5\" r=\".75\" fill=\"#f87171\" />\n </svg>\n);\nconst WarningIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M10 2.5L1.5 17h17L10 2.5z\" stroke=\"#fbbf24\" strokeWidth=\"1.3\" strokeLinejoin=\"round\" opacity=\".35\" />\n <path d=\"M10 8v4\" stroke=\"#fbbf24\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n <circle cx=\"10\" cy=\"14.5\" r=\".75\" fill=\"#fbbf24\" />\n </svg>\n);\nconst InfoIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <circle cx=\"10\" cy=\"10\" r=\"9\" stroke=\"#60a5fa\" strokeWidth=\"1.5\" opacity=\".3\" />\n <path d=\"M10 9v5\" stroke=\"#60a5fa\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n <circle cx=\"10\" cy=\"6.5\" r=\".75\" fill=\"#60a5fa\" />\n </svg>\n);\nconst LoadingIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" style={{ animation: \"toastywave-spin .7s linear infinite\" }}>\n <circle cx=\"10\" cy=\"10\" r=\"8\" stroke=\"currentColor\" strokeWidth=\"1.8\" opacity=\".15\" />\n <path d=\"M10 2a8 8 0 018 8\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" opacity=\".5\" />\n </svg>\n);\nconst CloseIcon = () => (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\">\n <path d=\"M3.5 3.5l7 7M10.5 3.5l-7 7\" />\n </svg>\n);\n\nconst iconMap = {\n success: <CheckIcon />,\n error: <ErrorIcon />,\n warning: <WarningIcon />,\n info: <InfoIcon />,\n loading: <LoadingIcon />,\n};\n\nconst accentMap = {\n success: \"#4ade80\",\n error: \"#f87171\",\n warning: \"#fbbf24\",\n info: \"#60a5fa\",\n loading: \"#a78bfa\",\n default: \"#888\",\n};\n\n// ── Countdown Text Formatter ────────────────────────────────────\n\nconst formatCountdown = (template, seconds) => {\n return template\n .replace(/\\{seconds\\}/g, String(seconds))\n .replace(/\\{s\\}/g, seconds !== 1 ? \"s\" : \"\");\n};\n\n// ── Toast Item ──────────────────────────────────────────────────\n\nfunction ToastItem({ data, onDismiss, position, theme }) {\n const [phase, setPhase] = useState(\"enter\");\n const [paused, setPaused] = useState(false);\n const [remain, setRemain] = useState(data.duration);\n const ivRef = useRef(null);\n const startRef = useRef(Date.now());\n const isTop = position.startsWith(\"top\");\n const hasDur = data.duration !== Infinity;\n const showFooter = hasDur && data.showCountdown !== false;\n const th = theme;\n\n useEffect(() => {\n if (!hasDur || paused) {\n if (ivRef.current) clearInterval(ivRef.current);\n return;\n }\n startRef.current = Date.now();\n const end = startRef.current + remain;\n ivRef.current = setInterval(() => {\n const left = end - Date.now();\n if (left <= 0) {\n clearInterval(ivRef.current);\n setPhase(\"exit\");\n setTimeout(() => onDismiss(data.id, data.dedupeKey), 320);\n } else {\n setRemain(left);\n }\n }, 50);\n return () => clearInterval(ivRef.current);\n }, [paused, hasDur]);\n\n useEffect(() => {\n if (data.duration !== Infinity) setRemain(data.duration);\n }, [data.type, data.duration, data.createdAt]);\n\n useEffect(() => {\n const r = requestAnimationFrame(() => setPhase(\"visible\"));\n return () => cancelAnimationFrame(r);\n }, []);\n\n const dismiss = () => {\n setPhase(\"exit\");\n setTimeout(() => onDismiss(data.id, data.dedupeKey), 320);\n };\n\n const stopTimer = (e) => {\n e.stopPropagation();\n setPaused(true);\n };\n\n const progress = hasDur ? Math.max(0, remain / data.duration) : 1;\n const secs = Math.ceil(remain / 1000);\n const enterY = isTop ? -24 : 24;\n const tf = {\n enter: `translateY(${enterY}px) scale(.95)`,\n visible: \"translateY(0) scale(1)\",\n exit: `translateY(${enterY}px) scale(.95)`,\n };\n\n return (\n <div\n onMouseEnter={() => !paused && setPaused(true)}\n onMouseLeave={() => setPaused(false)}\n style={{\n width: 420,\n maxWidth: \"calc(100vw - 32px)\",\n background: th.toastBg,\n backdropFilter: th.backdrop,\n WebkitBackdropFilter: th.backdrop,\n border: `1px solid ${th.toastBorder}`,\n borderRadius: 12,\n overflow: \"hidden\",\n transform: tf[phase],\n opacity: phase === \"visible\" ? 1 : 0,\n transition: \"all .32s cubic-bezier(.16,1,.3,1)\",\n boxShadow: th.toastShadow,\n }}\n >\n {/* Content */}\n <div style={{ padding: \"14px 16px\", display: \"flex\", alignItems: \"flex-start\", gap: 12 }}>\n {(data.icon || data.type !== \"default\") && (\n <div style={{ flexShrink: 0, marginTop: 1, color: th.title }}>\n {data.icon || iconMap[data.type]}\n </div>\n )}\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ fontSize: 14, fontWeight: 600, color: th.title, lineHeight: 1.4 }}>\n {data.message}\n </div>\n {data.description && (\n <div style={{ fontSize: 13, color: th.desc, marginTop: 4, lineHeight: 1.45 }}>\n {data.description}\n </div>\n )}\n {data.action && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n if (data.action.onClick) data.action.onClick();\n dismiss();\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = th.actionHoverBg;\n e.currentTarget.style.borderColor = th.actionHoverBorder;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = th.actionBg;\n e.currentTarget.style.borderColor = th.actionBorder;\n }}\n style={{\n marginTop: 10,\n padding: \"6px 14px\",\n fontSize: 13,\n fontWeight: 600,\n fontFamily: \"inherit\",\n borderRadius: 6,\n border: `1px solid ${th.actionBorder}`,\n background: th.actionBg,\n color: th.actionText,\n cursor: \"pointer\",\n transition: \"all .15s ease\",\n }}\n >\n {data.action.label}\n </button>\n )}\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n dismiss();\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.color = th.closeBtnHover;\n e.currentTarget.style.background = th.closeBtnHoverBg;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.color = th.closeBtnColor;\n e.currentTarget.style.background = \"transparent\";\n }}\n style={{\n flexShrink: 0,\n width: 28,\n height: 28,\n border: \"none\",\n background: \"transparent\",\n color: th.closeBtnColor,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n borderRadius: 6,\n transition: \"all .15s ease\",\n padding: 0,\n }}\n >\n <CloseIcon />\n </button>\n </div>\n\n {/* Countdown footer */}\n {showFooter && (\n <div\n style={{\n borderTop: `1px solid ${th.footerBorder}`,\n padding: \"8px 16px\",\n background: th.footerBg,\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <div style={{ fontSize: 12, color: th.footerText }}>\n {paused ? (\n data.pausedText\n ) : (\n <>\n {formatCountdown(data.countdownText, secs)}{\" \"}\n <span\n onClick={stopTimer}\n style={{\n color: th.footerLink,\n fontWeight: 600,\n cursor: \"pointer\",\n textDecoration: \"underline\",\n textUnderlineOffset: 2,\n }}\n >\n {data.stopText}\n </span>\n </>\n )}\n </div>\n </div>\n )}\n\n {/* Progress bar */}\n {hasDur && !paused && (\n <div style={{ height: 2, background: th.progressTrack, position: \"relative\" }}>\n <div\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n height: \"100%\",\n width: `${progress * 100}%`,\n background: accentMap[data.type] || accentMap.default,\n transition: \"width .1s linear\",\n borderRadius: \"0 1px 1px 0\",\n }}\n />\n </div>\n )}\n </div>\n );\n}\n\n// ── Toaster Component ───────────────────────────────────────────\n\n/**\n * Toaster container component. Place once in your app.\n *\n * @param {Object} props\n * @param {\"top-left\"|\"top-center\"|\"top-right\"|\"bottom-left\"|\"bottom-center\"|\"bottom-right\"} [props.position=\"bottom-right\"]\n * @param {\"dark\"|\"light\"|Object} [props.theme=\"dark\"] - Built-in theme name or custom theme object\n * @param {React.RefObject} [props.container] - Optional ref to scope toasts inside a container (uses absolute positioning)\n */\nfunction Toaster({ position = \"bottom-right\", theme = \"dark\", container }) {\n const [toasts, setToasts] = useState([]);\n const resolvedThemeObj = resolveTheme(theme);\n\n useEffect(() => {\n _addToast = (t) => {\n if (t._dismiss) {\n setToasts((p) => {\n const f = p.find((x) => x.id === t.id);\n if (f) _unreg(f.dedupeKey);\n return p.filter((x) => x.id !== t.id);\n });\n return;\n }\n setToasts((p) => {\n if (t.replace) {\n const o = p.find((x) => x.id === t.id);\n if (o) _unreg(o.dedupeKey);\n return p.map((x) => (x.id === t.id ? { ...t } : x));\n }\n return [...p, t];\n });\n };\n return () => {\n _addToast = null;\n };\n }, []);\n\n const dismiss = useCallback((id, dk) => {\n _unreg(dk);\n setToasts((p) => p.filter((x) => x.id !== id));\n }, []);\n\n const [vPos, hPos] = position.split(\"-\");\n const isCenter = hPos === \"center\";\n\n return (\n <div\n style={{\n position: container ? \"absolute\" : \"fixed\",\n zIndex: 99999,\n display: \"flex\",\n flexDirection: vPos === \"top\" ? \"column\" : \"column-reverse\",\n alignItems: isCenter ? \"center\" : hPos === \"left\" ? \"flex-start\" : \"flex-end\",\n gap: 10,\n padding: container ? 12 : 20,\n pointerEvents: \"none\",\n ...(vPos === \"top\" ? { top: 0 } : { bottom: 0 }),\n ...(isCenter ? { left: 0, right: 0 } : hPos === \"left\" ? { left: 0 } : { right: 0 }),\n }}\n >\n <style>{`@keyframes toastywave-spin{to{transform:rotate(360deg)}}`}</style>\n {toasts.map((t) => (\n <div key={t.id} style={{ pointerEvents: \"auto\" }}>\n <ToastItem data={t} onDismiss={dismiss} position={position} theme={resolvedThemeObj} />\n </div>\n ))}\n </div>\n );\n}\n\n// ── Exports ─────────────────────────────────────────────────────\n\nexport { toast, Toaster, darkTheme, lightTheme, resolveTheme, registerActionPreset };\nexport default toast;\n"],"names":["_id","_addToast","_active","Map","_unreg","k","actionPresets","undo","onUndo","label","onClick","toast","message","opts","arguments","length","undefined","dk","dedupeKey","concat","type","has","get","id","resolvedAction","action","factory","preset","onAction","resolveAction","t","_objectSpread","duration","showCountdown","countdownText","pausedText","stopText","createdAt","Date","now","set","success","m","o","error","warning","info","loading","Infinity","promise","msgs","then","replace","dismiss","_dismiss","darkTheme","toastBg","toastBorder","toastShadow","title","desc","footerBg","footerBorder","footerText","footerLink","progressTrack","closeBtnColor","closeBtnHover","closeBtnHoverBg","actionBg","actionBorder","actionHoverBg","actionHoverBorder","actionText","backdrop","lightTheme","builtInThemes","dark","light","resolveTheme","themeOrName","CheckIcon","_jsxs","width","height","viewBox","fill","children","_jsx","cx","cy","r","stroke","strokeWidth","opacity","d","strokeLinecap","strokeLinejoin","ErrorIcon","WarningIcon","InfoIcon","LoadingIcon","style","animation","CloseIcon","iconMap","accentMap","default","ToastItem","_ref","data","onDismiss","position","theme","_useState2","_slicedToArray","useState","phase","setPhase","_useState4","paused","setPaused","_useState6","remain","setRemain","ivRef","useRef","startRef","isTop","startsWith","hasDur","showFooter","th","useEffect","current","end","setInterval","left","clearInterval","setTimeout","requestAnimationFrame","cancelAnimationFrame","template","seconds","progress","Math","max","secs","ceil","enterY","tf","enter","visible","exit","onMouseEnter","onMouseLeave","maxWidth","background","backdropFilter","WebkitBackdropFilter","border","borderRadius","overflow","transform","transition","boxShadow","padding","display","alignItems","gap","icon","flexShrink","marginTop","color","flex","minWidth","fontSize","fontWeight","lineHeight","description","e","stopPropagation","currentTarget","borderColor","fontFamily","cursor","justifyContent","borderTop","_Fragment","String","textDecoration","textUnderlineOffset","top","_ref2","_ref2$position","_ref2$theme","container","_useState8","toasts","setToasts","resolvedThemeObj","p","f","find","x","filter","map","_toConsumableArray","useCallback","_position$split2","split","vPos","hPos","isCenter","zIndex","flexDirection","pointerEvents","bottom","right","name"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { FC, RefObject, ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
// ── Theme ───────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
export interface ToastTheme {
|
|
6
|
+
toastBg?: string;
|
|
7
|
+
toastBorder?: string;
|
|
8
|
+
toastShadow?: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
desc?: string;
|
|
11
|
+
footerBg?: string;
|
|
12
|
+
footerBorder?: string;
|
|
13
|
+
footerText?: string;
|
|
14
|
+
footerLink?: string;
|
|
15
|
+
progressTrack?: string;
|
|
16
|
+
closeBtnColor?: string;
|
|
17
|
+
closeBtnHover?: string;
|
|
18
|
+
closeBtnHoverBg?: string;
|
|
19
|
+
actionBg?: string;
|
|
20
|
+
actionBorder?: string;
|
|
21
|
+
actionHoverBg?: string;
|
|
22
|
+
actionHoverBorder?: string;
|
|
23
|
+
actionText?: string;
|
|
24
|
+
backdrop?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ── Toast Options ───────────────────────────────────────────────
|
|
28
|
+
|
|
29
|
+
/** Custom action button configuration */
|
|
30
|
+
export interface ToastAction {
|
|
31
|
+
/** Button label text */
|
|
32
|
+
label: string;
|
|
33
|
+
/** Callback when button is clicked */
|
|
34
|
+
onClick: () => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Preset action with callback */
|
|
38
|
+
export interface ToastActionPreset {
|
|
39
|
+
/** Preset name (e.g., "undo") */
|
|
40
|
+
preset: string;
|
|
41
|
+
/** Callback when the action is triggered */
|
|
42
|
+
onAction?: () => void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Action can be a preset name, preset config, or custom action */
|
|
46
|
+
export type ToastActionInput = string | ToastActionPreset | ToastAction;
|
|
47
|
+
|
|
48
|
+
/** Factory function for creating action presets */
|
|
49
|
+
export type ActionPresetFactory = (onAction: () => void) => ToastAction;
|
|
50
|
+
|
|
51
|
+
export interface ToastOptions {
|
|
52
|
+
/** Toast type */
|
|
53
|
+
type?: "default" | "success" | "error" | "warning" | "info" | "loading";
|
|
54
|
+
/** Secondary description text */
|
|
55
|
+
description?: string;
|
|
56
|
+
/** Auto-dismiss in ms. Use Infinity to persist. Default: 5000 */
|
|
57
|
+
duration?: number;
|
|
58
|
+
/** Action button: preset name ("undo"), preset config ({ preset: "undo", onAction }), or custom ({ label, onClick }) */
|
|
59
|
+
action?: ToastActionInput;
|
|
60
|
+
/** Custom icon element. Overrides the default type icon. Use with any icon library (Hero Icons, Lucide, etc.) */
|
|
61
|
+
icon?: ReactNode;
|
|
62
|
+
/** Custom dedup key. Defaults to `${type}::${message}` */
|
|
63
|
+
dedupeKey?: string;
|
|
64
|
+
/** Countdown text template. Use {seconds} and {s} as placeholders. */
|
|
65
|
+
countdownText?: string;
|
|
66
|
+
/** Text shown when timer is paused on hover. */
|
|
67
|
+
pausedText?: string;
|
|
68
|
+
/** "Click to stop" link text. */
|
|
69
|
+
stopText?: string;
|
|
70
|
+
/** Whether to show countdown footer. Default: true */
|
|
71
|
+
showCountdown?: boolean;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface PromiseMessages {
|
|
75
|
+
loading: string;
|
|
76
|
+
success: string;
|
|
77
|
+
error: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ── toast() API ─────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
export interface ToastAPI {
|
|
83
|
+
(message: string, opts?: ToastOptions): number;
|
|
84
|
+
success(message: string, opts?: Omit<ToastOptions, "type">): number;
|
|
85
|
+
error(message: string, opts?: Omit<ToastOptions, "type">): number;
|
|
86
|
+
warning(message: string, opts?: Omit<ToastOptions, "type">): number;
|
|
87
|
+
info(message: string, opts?: Omit<ToastOptions, "type">): number;
|
|
88
|
+
loading(message: string, opts?: Omit<ToastOptions, "type">): number;
|
|
89
|
+
promise(promise: Promise<any>, msgs: PromiseMessages, opts?: ToastOptions): number;
|
|
90
|
+
dismiss(id: number): void;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export declare const toast: ToastAPI;
|
|
94
|
+
export default toast;
|
|
95
|
+
|
|
96
|
+
// ── Toaster Component ───────────────────────────────────────────
|
|
97
|
+
|
|
98
|
+
export type ToastPosition =
|
|
99
|
+
| "top-left"
|
|
100
|
+
| "top-center"
|
|
101
|
+
| "top-right"
|
|
102
|
+
| "bottom-left"
|
|
103
|
+
| "bottom-center"
|
|
104
|
+
| "bottom-right";
|
|
105
|
+
|
|
106
|
+
export interface ToasterProps {
|
|
107
|
+
/** Position of toast stack. Default: "bottom-right" */
|
|
108
|
+
position?: ToastPosition;
|
|
109
|
+
/** "dark" | "light" | custom ToastTheme object */
|
|
110
|
+
theme?: "dark" | "light" | ToastTheme;
|
|
111
|
+
/** Ref to a container element for scoped rendering */
|
|
112
|
+
container?: RefObject<HTMLElement>;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export declare const Toaster: FC<ToasterProps>;
|
|
116
|
+
|
|
117
|
+
// ── Built-in Themes ─────────────────────────────────────────────
|
|
118
|
+
|
|
119
|
+
export declare const darkTheme: ToastTheme;
|
|
120
|
+
export declare const lightTheme: ToastTheme;
|
|
121
|
+
export declare function resolveTheme(themeOrName: "dark" | "light" | ToastTheme): ToastTheme;
|
|
122
|
+
|
|
123
|
+
// ── Action Presets ───────────────────────────────────────────────
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Register a custom action preset.
|
|
127
|
+
* @param name - Preset name (e.g., "retry", "dismiss")
|
|
128
|
+
* @param factory - Factory function that takes onAction callback and returns { label, onClick }
|
|
129
|
+
*/
|
|
130
|
+
export declare function registerActionPreset(name: string, factory: ActionPresetFactory): void;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{useState as t,useEffect as e,useCallback as r,useRef as n}from"react";import{jsxs as o,jsx as i,Fragment as a}from"react/jsx-runtime";function c(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r<e;r++)n[r]=t[r];return n}function s(t,e,r){return(e=function(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var r=t[Symbol.toPrimitive];if(void 0!==r){var n=r.call(t,e);if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:e+""}(e))in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function l(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function u(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{};e%2?l(Object(r),!0).forEach(function(e){s(t,e,r[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):l(Object(r)).forEach(function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(r,e))})}return t}function d(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,c=[],s=!0,l=!1;try{if(i=(r=r.call(t)).next,0===e);else for(;!(s=(n=i.call(r)).done)&&(c.push(n.value),c.length!==e);s=!0);}catch(t){l=!0,o=t}finally{try{if(!s&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(l)throw o}}return c}}(t,e)||p(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function f(t){return function(t){if(Array.isArray(t))return c(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||p(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function p(t,e){if(t){if("string"==typeof t)return c(t,e);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?c(t,e):void 0}}var g=0,b=null,h=new Map,y=function(t){return h.delete(t)},v={undo:function(t){return{label:"Undo",onClick:t}}},x=function(t,e){v[t]=e},m=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=e.dedupeKey||"".concat(e.type||"default","::").concat(t);if(h.has(r))return h.get(r);var n=++g,o=function(t){if(!t)return null;if("string"==typeof t){var e=v[t];return e?e(function(){}):null}if(t.preset){var r=v[t.preset];return r?r(t.onAction||function(){}):null}return t}(e.action),i=u(u({id:n,message:t,type:"default",duration:5e3,showCountdown:!0,countdownText:"This message will close in {seconds} second{s}.",pausedText:"Timer paused",stopText:"Click to stop."},e),{},{action:o,dedupeKey:r,createdAt:Date.now()});return h.set(r,n),b&&b(i),n};m.success=function(t,e){return m(t,u(u({},e),{},{type:"success"}))},m.error=function(t,e){return m(t,u(u({},e),{},{type:"error"}))},m.warning=function(t,e){return m(t,u(u({},e),{},{type:"warning"}))},m.info=function(t,e){return m(t,u(u({},e),{},{type:"info"}))},m.loading=function(t,e){return m(t,u(u({},e),{},{type:"loading",duration:1/0}))},m.promise=function(t,e,r){var n=m(e.loading,u(u({},r),{},{type:"loading",duration:1/0}));return t.then(function(){b&&b({id:n,message:e.success,type:"success",duration:5e3,showCountdown:!0,countdownText:(null==r?void 0:r.countdownText)||"This message will close in {seconds} second{s}.",pausedText:(null==r?void 0:r.pausedText)||"Timer paused",stopText:(null==r?void 0:r.stopText)||"Click to stop.",createdAt:Date.now(),replace:!0,dedupeKey:"p-ok-".concat(n)})}).catch(function(){b&&b({id:n,message:e.error,type:"error",duration:5e3,showCountdown:!0,countdownText:(null==r?void 0:r.countdownText)||"This message will close in {seconds} second{s}.",pausedText:(null==r?void 0:r.pausedText)||"Timer paused",stopText:(null==r?void 0:r.stopText)||"Click to stop.",createdAt:Date.now(),replace:!0,dedupeKey:"p-err-".concat(n)})}),n},m.dismiss=function(t){b&&b({id:t,_dismiss:!0})};var k={toastBg:"rgba(30,30,32,.95)",toastBorder:"rgba(255,255,255,.08)",toastShadow:"0 16px 48px rgba(0,0,0,.5),0 2px 8px rgba(0,0,0,.3),inset 0 1px 0 rgba(255,255,255,.04)",title:"#f0f0f0",desc:"rgba(255,255,255,.5)",footerBg:"rgba(0,0,0,.15)",footerBorder:"rgba(255,255,255,.06)",footerText:"rgba(255,255,255,.35)",footerLink:"rgba(255,255,255,.6)",progressTrack:"rgba(255,255,255,.04)",closeBtnColor:"rgba(255,255,255,.3)",closeBtnHover:"rgba(255,255,255,.7)",closeBtnHoverBg:"rgba(255,255,255,.06)",actionBg:"rgba(255,255,255,.08)",actionBorder:"rgba(255,255,255,.15)",actionHoverBg:"rgba(255,255,255,.14)",actionHoverBorder:"rgba(255,255,255,.25)",actionText:"#f0f0f0",backdrop:"blur(16px) saturate(1.4)"},w={toastBg:"rgba(255,255,255,.97)",toastBorder:"rgba(0,0,0,.08)",toastShadow:"0 16px 48px rgba(0,0,0,.08),0 4px 12px rgba(0,0,0,.05),0 1px 3px rgba(0,0,0,.06)",title:"#1a1a1a",desc:"rgba(0,0,0,.5)",footerBg:"rgba(0,0,0,.025)",footerBorder:"rgba(0,0,0,.06)",footerText:"rgba(0,0,0,.35)",footerLink:"rgba(0,0,0,.6)",progressTrack:"rgba(0,0,0,.05)",closeBtnColor:"rgba(0,0,0,.25)",closeBtnHover:"rgba(0,0,0,.6)",closeBtnHoverBg:"rgba(0,0,0,.05)",actionBg:"rgba(0,0,0,.05)",actionBorder:"rgba(0,0,0,.12)",actionHoverBg:"rgba(0,0,0,.1)",actionHoverBorder:"rgba(0,0,0,.2)",actionText:"#1a1a1a",backdrop:"blur(16px) saturate(1.2)"},T={dark:k,light:w},B=function(t){return t?"string"==typeof t?T[t]||k:u(u({},k),t):k},C=function(){return o("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",children:[i("circle",{cx:"10",cy:"10",r:"9",stroke:"#f87171",strokeWidth:"1.5",opacity:".3"}),i("path",{d:"M10 6v5",stroke:"#f87171",strokeWidth:"1.5",strokeLinecap:"round"}),i("circle",{cx:"10",cy:"13.5",r:".75",fill:"#f87171"})]})},S=function(){return o("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",children:[i("path",{d:"M10 2.5L1.5 17h17L10 2.5z",stroke:"#fbbf24",strokeWidth:"1.3",strokeLinejoin:"round",opacity:".35"}),i("path",{d:"M10 8v4",stroke:"#fbbf24",strokeWidth:"1.5",strokeLinecap:"round"}),i("circle",{cx:"10",cy:"14.5",r:".75",fill:"#fbbf24"})]})},j=function(){return o("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",children:[i("circle",{cx:"10",cy:"10",r:"9",stroke:"#60a5fa",strokeWidth:"1.5",opacity:".3"}),i("path",{d:"M10 9v5",stroke:"#60a5fa",strokeWidth:"1.5",strokeLinecap:"round"}),i("circle",{cx:"10",cy:"6.5",r:".75",fill:"#60a5fa"})]})},O=function(){return o("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",style:{animation:"toastywave-spin .7s linear infinite"},children:[i("circle",{cx:"10",cy:"10",r:"8",stroke:"currentColor",strokeWidth:"1.8",opacity:".15"}),i("path",{d:"M10 2a8 8 0 018 8",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",opacity:".5"})]})},M=function(){return i("svg",{width:"14",height:"14",viewBox:"0 0 14 14",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",children:i("path",{d:"M3.5 3.5l7 7M10.5 3.5l-7 7"})})},W={success:i(function(){return o("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",children:[i("circle",{cx:"10",cy:"10",r:"9",stroke:"#4ade80",strokeWidth:"1.5",opacity:".3"}),i("path",{d:"M6.5 10.5l2 2 5-5",stroke:"#4ade80",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})]})},{}),error:i(C,{}),warning:i(S,{}),info:i(j,{}),loading:i(O,{})},A={success:"#4ade80",error:"#f87171",warning:"#fbbf24",info:"#60a5fa",loading:"#a78bfa",default:"#888"};function L(r){var c=r.data,s=r.onDismiss,l=r.position,u=r.theme,f=d(t("enter"),2),p=f[0],g=f[1],b=d(t(!1),2),h=b[0],y=b[1],v=d(t(c.duration),2),x=v[0],m=v[1],k=n(null),w=n(Date.now()),T=l.startsWith("top"),B=c.duration!==1/0,C=B&&!1!==c.showCountdown,S=u;e(function(){if(B&&!h){w.current=Date.now();var t=w.current+x;return k.current=setInterval(function(){var e=t-Date.now();e<=0?(clearInterval(k.current),g("exit"),setTimeout(function(){return s(c.id,c.dedupeKey)},320)):m(e)},50),function(){return clearInterval(k.current)}}k.current&&clearInterval(k.current)},[h,B]),e(function(){c.duration!==1/0&&m(c.duration)},[c.type,c.duration,c.createdAt]),e(function(){var t=requestAnimationFrame(function(){return g("visible")});return function(){return cancelAnimationFrame(t)}},[]);var j,O,L=function(){g("exit"),setTimeout(function(){return s(c.id,c.dedupeKey)},320)},D=B?Math.max(0,x/c.duration):1,H=Math.ceil(x/1e3),I=T?-24:24,P={enter:"translateY(".concat(I,"px) scale(.95)"),visible:"translateY(0) scale(1)",exit:"translateY(".concat(I,"px) scale(.95)")};return o("div",{onMouseEnter:function(){return!h&&y(!0)},onMouseLeave:function(){return y(!1)},style:{width:420,maxWidth:"calc(100vw - 32px)",background:S.toastBg,backdropFilter:S.backdrop,WebkitBackdropFilter:S.backdrop,border:"1px solid ".concat(S.toastBorder),borderRadius:12,overflow:"hidden",transform:P[p],opacity:"visible"===p?1:0,transition:"all .32s cubic-bezier(.16,1,.3,1)",boxShadow:S.toastShadow},children:[o("div",{style:{padding:"14px 16px",display:"flex",alignItems:"flex-start",gap:12},children:[(c.icon||"default"!==c.type)&&i("div",{style:{flexShrink:0,marginTop:1,color:S.title},children:c.icon||W[c.type]}),o("div",{style:{flex:1,minWidth:0},children:[i("div",{style:{fontSize:14,fontWeight:600,color:S.title,lineHeight:1.4},children:c.message}),c.description&&i("div",{style:{fontSize:13,color:S.desc,marginTop:4,lineHeight:1.45},children:c.description}),c.action&&i("button",{onClick:function(t){t.stopPropagation(),c.action.onClick&&c.action.onClick(),L()},onMouseEnter:function(t){t.currentTarget.style.background=S.actionHoverBg,t.currentTarget.style.borderColor=S.actionHoverBorder},onMouseLeave:function(t){t.currentTarget.style.background=S.actionBg,t.currentTarget.style.borderColor=S.actionBorder},style:{marginTop:10,padding:"6px 14px",fontSize:13,fontWeight:600,fontFamily:"inherit",borderRadius:6,border:"1px solid ".concat(S.actionBorder),background:S.actionBg,color:S.actionText,cursor:"pointer",transition:"all .15s ease"},children:c.action.label})]}),i("button",{onClick:function(t){t.stopPropagation(),L()},onMouseEnter:function(t){t.currentTarget.style.color=S.closeBtnHover,t.currentTarget.style.background=S.closeBtnHoverBg},onMouseLeave:function(t){t.currentTarget.style.color=S.closeBtnColor,t.currentTarget.style.background="transparent"},style:{flexShrink:0,width:28,height:28,border:"none",background:"transparent",color:S.closeBtnColor,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",borderRadius:6,transition:"all .15s ease",padding:0},children:i(M,{})})]}),C&&i("div",{style:{borderTop:"1px solid ".concat(S.footerBorder),padding:"8px 16px",background:S.footerBg,display:"flex",alignItems:"center"},children:i("div",{style:{fontSize:12,color:S.footerText},children:h?c.pausedText:o(a,{children:[(j=c.countdownText,O=H,j.replace(/\{seconds\}/g,String(O)).replace(/\{s\}/g,1!==O?"s":""))," ",i("span",{onClick:function(t){t.stopPropagation(),y(!0)},style:{color:S.footerLink,fontWeight:600,cursor:"pointer",textDecoration:"underline",textUnderlineOffset:2},children:c.stopText})]})})}),B&&!h&&i("div",{style:{height:2,background:S.progressTrack,position:"relative"},children:i("div",{style:{position:"absolute",left:0,top:0,height:"100%",width:"".concat(100*D,"%"),background:A[c.type]||A.default,transition:"width .1s linear",borderRadius:"0 1px 1px 0"}})})]})}function D(n){var a=n.position,c=void 0===a?"bottom-right":a,s=n.theme,l=void 0===s?"dark":s,p=n.container,g=d(t([]),2),h=g[0],v=g[1],x=B(l);e(function(){return b=function(t){t._dismiss?v(function(e){var r=e.find(function(e){return e.id===t.id});return r&&y(r.dedupeKey),e.filter(function(e){return e.id!==t.id})}):v(function(e){if(t.replace){var r=e.find(function(e){return e.id===t.id});return r&&y(r.dedupeKey),e.map(function(e){return e.id===t.id?u({},t):e})}return[].concat(f(e),[t])})},function(){b=null}},[]);var m=r(function(t,e){y(e),v(function(e){return e.filter(function(e){return e.id!==t})})},[]),k=d(c.split("-"),2),w=k[0],T=k[1],C="center"===T;return o("div",{style:u(u({position:p?"absolute":"fixed",zIndex:99999,display:"flex",flexDirection:"top"===w?"column":"column-reverse",alignItems:C?"center":"left"===T?"flex-start":"flex-end",gap:10,padding:p?12:20,pointerEvents:"none"},"top"===w?{top:0}:{bottom:0}),C?{left:0,right:0}:"left"===T?{left:0}:{right:0}),children:[i("style",{children:"@keyframes toastywave-spin{to{transform:rotate(360deg)}}"}),h.map(function(t){return i("div",{style:{pointerEvents:"auto"},children:i(L,{data:t,onDismiss:m,position:c,theme:x})},t.id)})]})}export{D as Toaster,k as darkTheme,m as default,w as lightTheme,x as registerActionPreset,B as resolveTheme,m as toast};
|
|
2
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/index.jsx"],"sourcesContent":["import { useState, useEffect, useCallback, useRef, createContext, useContext } from \"react\";\n\n/* ═══════════════════════════════════════════════════════════════\n TOASTYWAVE - Lightweight React Toast Notification System\n ═══════════════════════════════════════════════════════════════ */\n\n// ── Internal State ──────────────────────────────────────────────\n\nlet _id = 0;\nlet _addToast = null;\nlet _active = new Map();\n\nconst _unreg = (k) => _active.delete(k);\n\n// ── Public API ──────────────────────────────────────────────────\n\n// ── Action Presets ───────────────────────────────────────────────\n\nconst actionPresets = {\n undo: (onUndo) => ({\n label: \"Undo\",\n onClick: onUndo,\n }),\n};\n\n/**\n * Register a custom action preset.\n * @param {string} name - Preset name\n * @param {Function} factory - Factory function (onAction) => { label, onClick }\n */\nconst registerActionPreset = (name, factory) => {\n actionPresets[name] = factory;\n};\n\n/**\n * Resolve action from preset string or custom object.\n * @param {string|Object} action - \"undo\", { preset: \"undo\", onAction }, or { label, onClick }\n * @returns {Object|null} Resolved action object\n */\nconst resolveAction = (action) => {\n if (!action) return null;\n if (typeof action === \"string\") {\n // Preset name only (e.g., \"undo\") - return preset with no-op\n const factory = actionPresets[action];\n return factory ? factory(() => {}) : null;\n }\n if (action.preset) {\n // Preset with callback (e.g., { preset: \"undo\", onAction: () => {...} })\n const factory = actionPresets[action.preset];\n return factory ? factory(action.onAction || (() => {})) : null;\n }\n // Custom action object { label, onClick }\n return action;\n};\n\n/**\n * Show a toast notification.\n *\n * @param {string} message - The toast title/message\n * @param {Object} [opts] - Options\n * @param {string} [opts.type=\"default\"] - Toast type: \"default\"|\"success\"|\"error\"|\"warning\"|\"info\"|\"loading\"\n * @param {string} [opts.description] - Secondary text below the message\n * @param {number} [opts.duration=5000] - Auto-dismiss duration in ms. Use Infinity to persist.\n * @param {string|Object} [opts.action] - Action button: preset name (\"undo\"), preset config ({ preset: \"undo\", onAction }), or custom ({ label, onClick })\n * @param {React.ReactNode} [opts.icon] - Custom icon element. Overrides the default type icon.\n * @param {string} [opts.dedupeKey] - Custom dedup key. Defaults to `${type}::${message}`\n * @param {string} [opts.countdownText] - Custom countdown text. Use `{seconds}` as placeholder.\n * @param {string} [opts.pausedText] - Custom text shown when timer is paused.\n * @param {string} [opts.stopText] - Custom \"Click to stop\" text.\n * @param {boolean} [opts.showCountdown=true] - Whether to show the countdown footer.\n * @returns {number} Toast ID\n */\nconst toast = (message, opts = {}) => {\n const dk = opts.dedupeKey || `${opts.type || \"default\"}::${message}`;\n if (_active.has(dk)) return _active.get(dk);\n const id = ++_id;\n const resolvedAction = resolveAction(opts.action);\n const t = {\n id,\n message,\n type: \"default\",\n duration: 5000,\n showCountdown: true,\n countdownText: \"This message will close in {seconds} second{s}.\",\n pausedText: \"Timer paused\",\n stopText: \"Click to stop.\",\n ...opts,\n action: resolvedAction,\n dedupeKey: dk,\n createdAt: Date.now(),\n };\n _active.set(dk, id);\n if (_addToast) _addToast(t);\n return id;\n};\n\ntoast.success = (m, o) => toast(m, { ...o, type: \"success\" });\ntoast.error = (m, o) => toast(m, { ...o, type: \"error\" });\ntoast.warning = (m, o) => toast(m, { ...o, type: \"warning\" });\ntoast.info = (m, o) => toast(m, { ...o, type: \"info\" });\ntoast.loading = (m, o) => toast(m, { ...o, type: \"loading\", duration: Infinity });\n\n/**\n * Show a promise-based toast that transitions from loading → success/error.\n *\n * @param {Promise} promise\n * @param {Object} msgs - { loading, success, error }\n * @param {Object} [opts] - Same options as toast()\n * @returns {number} Toast ID\n */\ntoast.promise = (promise, msgs, o) => {\n const id = toast(msgs.loading, { ...o, type: \"loading\", duration: Infinity });\n promise\n .then(() => {\n if (_addToast)\n _addToast({\n id, message: msgs.success, type: \"success\", duration: 5000,\n showCountdown: true,\n countdownText: o?.countdownText || \"This message will close in {seconds} second{s}.\",\n pausedText: o?.pausedText || \"Timer paused\",\n stopText: o?.stopText || \"Click to stop.\",\n createdAt: Date.now(), replace: true, dedupeKey: `p-ok-${id}`,\n });\n })\n .catch(() => {\n if (_addToast)\n _addToast({\n id, message: msgs.error, type: \"error\", duration: 5000,\n showCountdown: true,\n countdownText: o?.countdownText || \"This message will close in {seconds} second{s}.\",\n pausedText: o?.pausedText || \"Timer paused\",\n stopText: o?.stopText || \"Click to stop.\",\n createdAt: Date.now(), replace: true, dedupeKey: `p-err-${id}`,\n });\n });\n return id;\n};\n\n/**\n * Programmatically dismiss a toast by ID.\n * @param {number} id\n */\ntoast.dismiss = (id) => {\n if (_addToast) _addToast({ id, _dismiss: true });\n};\n\n// ── Default Themes ──────────────────────────────────────────────\n\nconst darkTheme = {\n toastBg: \"rgba(30,30,32,.95)\",\n toastBorder: \"rgba(255,255,255,.08)\",\n toastShadow: \"0 16px 48px rgba(0,0,0,.5),0 2px 8px rgba(0,0,0,.3),inset 0 1px 0 rgba(255,255,255,.04)\",\n title: \"#f0f0f0\",\n desc: \"rgba(255,255,255,.5)\",\n footerBg: \"rgba(0,0,0,.15)\",\n footerBorder: \"rgba(255,255,255,.06)\",\n footerText: \"rgba(255,255,255,.35)\",\n footerLink: \"rgba(255,255,255,.6)\",\n progressTrack: \"rgba(255,255,255,.04)\",\n closeBtnColor: \"rgba(255,255,255,.3)\",\n closeBtnHover: \"rgba(255,255,255,.7)\",\n closeBtnHoverBg: \"rgba(255,255,255,.06)\",\n actionBg: \"rgba(255,255,255,.08)\",\n actionBorder: \"rgba(255,255,255,.15)\",\n actionHoverBg: \"rgba(255,255,255,.14)\",\n actionHoverBorder: \"rgba(255,255,255,.25)\",\n actionText: \"#f0f0f0\",\n backdrop: \"blur(16px) saturate(1.4)\",\n};\n\nconst lightTheme = {\n toastBg: \"rgba(255,255,255,.97)\",\n toastBorder: \"rgba(0,0,0,.08)\",\n toastShadow: \"0 16px 48px rgba(0,0,0,.08),0 4px 12px rgba(0,0,0,.05),0 1px 3px rgba(0,0,0,.06)\",\n title: \"#1a1a1a\",\n desc: \"rgba(0,0,0,.5)\",\n footerBg: \"rgba(0,0,0,.025)\",\n footerBorder: \"rgba(0,0,0,.06)\",\n footerText: \"rgba(0,0,0,.35)\",\n footerLink: \"rgba(0,0,0,.6)\",\n progressTrack: \"rgba(0,0,0,.05)\",\n closeBtnColor: \"rgba(0,0,0,.25)\",\n closeBtnHover: \"rgba(0,0,0,.6)\",\n closeBtnHoverBg: \"rgba(0,0,0,.05)\",\n actionBg: \"rgba(0,0,0,.05)\",\n actionBorder: \"rgba(0,0,0,.12)\",\n actionHoverBg: \"rgba(0,0,0,.1)\",\n actionHoverBorder: \"rgba(0,0,0,.2)\",\n actionText: \"#1a1a1a\",\n backdrop: \"blur(16px) saturate(1.2)\",\n};\n\nconst builtInThemes = { dark: darkTheme, light: lightTheme };\n\n/**\n * Resolve a theme by name or merge a custom theme object on top of the dark base.\n * @param {\"dark\"|\"light\"|Object} themeOrName\n * @returns {Object} Resolved theme tokens\n */\nconst resolveTheme = (themeOrName) => {\n if (!themeOrName) return darkTheme;\n if (typeof themeOrName === \"string\") return builtInThemes[themeOrName] || darkTheme;\n return { ...darkTheme, ...themeOrName };\n};\n\n// ── SVG Icons ───────────────────────────────────────────────────\n\nconst CheckIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <circle cx=\"10\" cy=\"10\" r=\"9\" stroke=\"#4ade80\" strokeWidth=\"1.5\" opacity=\".3\" />\n <path d=\"M6.5 10.5l2 2 5-5\" stroke=\"#4ade80\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n);\nconst ErrorIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <circle cx=\"10\" cy=\"10\" r=\"9\" stroke=\"#f87171\" strokeWidth=\"1.5\" opacity=\".3\" />\n <path d=\"M10 6v5\" stroke=\"#f87171\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n <circle cx=\"10\" cy=\"13.5\" r=\".75\" fill=\"#f87171\" />\n </svg>\n);\nconst WarningIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M10 2.5L1.5 17h17L10 2.5z\" stroke=\"#fbbf24\" strokeWidth=\"1.3\" strokeLinejoin=\"round\" opacity=\".35\" />\n <path d=\"M10 8v4\" stroke=\"#fbbf24\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n <circle cx=\"10\" cy=\"14.5\" r=\".75\" fill=\"#fbbf24\" />\n </svg>\n);\nconst InfoIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <circle cx=\"10\" cy=\"10\" r=\"9\" stroke=\"#60a5fa\" strokeWidth=\"1.5\" opacity=\".3\" />\n <path d=\"M10 9v5\" stroke=\"#60a5fa\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n <circle cx=\"10\" cy=\"6.5\" r=\".75\" fill=\"#60a5fa\" />\n </svg>\n);\nconst LoadingIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" style={{ animation: \"toastywave-spin .7s linear infinite\" }}>\n <circle cx=\"10\" cy=\"10\" r=\"8\" stroke=\"currentColor\" strokeWidth=\"1.8\" opacity=\".15\" />\n <path d=\"M10 2a8 8 0 018 8\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" opacity=\".5\" />\n </svg>\n);\nconst CloseIcon = () => (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\">\n <path d=\"M3.5 3.5l7 7M10.5 3.5l-7 7\" />\n </svg>\n);\n\nconst iconMap = {\n success: <CheckIcon />,\n error: <ErrorIcon />,\n warning: <WarningIcon />,\n info: <InfoIcon />,\n loading: <LoadingIcon />,\n};\n\nconst accentMap = {\n success: \"#4ade80\",\n error: \"#f87171\",\n warning: \"#fbbf24\",\n info: \"#60a5fa\",\n loading: \"#a78bfa\",\n default: \"#888\",\n};\n\n// ── Countdown Text Formatter ────────────────────────────────────\n\nconst formatCountdown = (template, seconds) => {\n return template\n .replace(/\\{seconds\\}/g, String(seconds))\n .replace(/\\{s\\}/g, seconds !== 1 ? \"s\" : \"\");\n};\n\n// ── Toast Item ──────────────────────────────────────────────────\n\nfunction ToastItem({ data, onDismiss, position, theme }) {\n const [phase, setPhase] = useState(\"enter\");\n const [paused, setPaused] = useState(false);\n const [remain, setRemain] = useState(data.duration);\n const ivRef = useRef(null);\n const startRef = useRef(Date.now());\n const isTop = position.startsWith(\"top\");\n const hasDur = data.duration !== Infinity;\n const showFooter = hasDur && data.showCountdown !== false;\n const th = theme;\n\n useEffect(() => {\n if (!hasDur || paused) {\n if (ivRef.current) clearInterval(ivRef.current);\n return;\n }\n startRef.current = Date.now();\n const end = startRef.current + remain;\n ivRef.current = setInterval(() => {\n const left = end - Date.now();\n if (left <= 0) {\n clearInterval(ivRef.current);\n setPhase(\"exit\");\n setTimeout(() => onDismiss(data.id, data.dedupeKey), 320);\n } else {\n setRemain(left);\n }\n }, 50);\n return () => clearInterval(ivRef.current);\n }, [paused, hasDur]);\n\n useEffect(() => {\n if (data.duration !== Infinity) setRemain(data.duration);\n }, [data.type, data.duration, data.createdAt]);\n\n useEffect(() => {\n const r = requestAnimationFrame(() => setPhase(\"visible\"));\n return () => cancelAnimationFrame(r);\n }, []);\n\n const dismiss = () => {\n setPhase(\"exit\");\n setTimeout(() => onDismiss(data.id, data.dedupeKey), 320);\n };\n\n const stopTimer = (e) => {\n e.stopPropagation();\n setPaused(true);\n };\n\n const progress = hasDur ? Math.max(0, remain / data.duration) : 1;\n const secs = Math.ceil(remain / 1000);\n const enterY = isTop ? -24 : 24;\n const tf = {\n enter: `translateY(${enterY}px) scale(.95)`,\n visible: \"translateY(0) scale(1)\",\n exit: `translateY(${enterY}px) scale(.95)`,\n };\n\n return (\n <div\n onMouseEnter={() => !paused && setPaused(true)}\n onMouseLeave={() => setPaused(false)}\n style={{\n width: 420,\n maxWidth: \"calc(100vw - 32px)\",\n background: th.toastBg,\n backdropFilter: th.backdrop,\n WebkitBackdropFilter: th.backdrop,\n border: `1px solid ${th.toastBorder}`,\n borderRadius: 12,\n overflow: \"hidden\",\n transform: tf[phase],\n opacity: phase === \"visible\" ? 1 : 0,\n transition: \"all .32s cubic-bezier(.16,1,.3,1)\",\n boxShadow: th.toastShadow,\n }}\n >\n {/* Content */}\n <div style={{ padding: \"14px 16px\", display: \"flex\", alignItems: \"flex-start\", gap: 12 }}>\n {(data.icon || data.type !== \"default\") && (\n <div style={{ flexShrink: 0, marginTop: 1, color: th.title }}>\n {data.icon || iconMap[data.type]}\n </div>\n )}\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ fontSize: 14, fontWeight: 600, color: th.title, lineHeight: 1.4 }}>\n {data.message}\n </div>\n {data.description && (\n <div style={{ fontSize: 13, color: th.desc, marginTop: 4, lineHeight: 1.45 }}>\n {data.description}\n </div>\n )}\n {data.action && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n if (data.action.onClick) data.action.onClick();\n dismiss();\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = th.actionHoverBg;\n e.currentTarget.style.borderColor = th.actionHoverBorder;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = th.actionBg;\n e.currentTarget.style.borderColor = th.actionBorder;\n }}\n style={{\n marginTop: 10,\n padding: \"6px 14px\",\n fontSize: 13,\n fontWeight: 600,\n fontFamily: \"inherit\",\n borderRadius: 6,\n border: `1px solid ${th.actionBorder}`,\n background: th.actionBg,\n color: th.actionText,\n cursor: \"pointer\",\n transition: \"all .15s ease\",\n }}\n >\n {data.action.label}\n </button>\n )}\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n dismiss();\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.color = th.closeBtnHover;\n e.currentTarget.style.background = th.closeBtnHoverBg;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.color = th.closeBtnColor;\n e.currentTarget.style.background = \"transparent\";\n }}\n style={{\n flexShrink: 0,\n width: 28,\n height: 28,\n border: \"none\",\n background: \"transparent\",\n color: th.closeBtnColor,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n borderRadius: 6,\n transition: \"all .15s ease\",\n padding: 0,\n }}\n >\n <CloseIcon />\n </button>\n </div>\n\n {/* Countdown footer */}\n {showFooter && (\n <div\n style={{\n borderTop: `1px solid ${th.footerBorder}`,\n padding: \"8px 16px\",\n background: th.footerBg,\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <div style={{ fontSize: 12, color: th.footerText }}>\n {paused ? (\n data.pausedText\n ) : (\n <>\n {formatCountdown(data.countdownText, secs)}{\" \"}\n <span\n onClick={stopTimer}\n style={{\n color: th.footerLink,\n fontWeight: 600,\n cursor: \"pointer\",\n textDecoration: \"underline\",\n textUnderlineOffset: 2,\n }}\n >\n {data.stopText}\n </span>\n </>\n )}\n </div>\n </div>\n )}\n\n {/* Progress bar */}\n {hasDur && !paused && (\n <div style={{ height: 2, background: th.progressTrack, position: \"relative\" }}>\n <div\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n height: \"100%\",\n width: `${progress * 100}%`,\n background: accentMap[data.type] || accentMap.default,\n transition: \"width .1s linear\",\n borderRadius: \"0 1px 1px 0\",\n }}\n />\n </div>\n )}\n </div>\n );\n}\n\n// ── Toaster Component ───────────────────────────────────────────\n\n/**\n * Toaster container component. Place once in your app.\n *\n * @param {Object} props\n * @param {\"top-left\"|\"top-center\"|\"top-right\"|\"bottom-left\"|\"bottom-center\"|\"bottom-right\"} [props.position=\"bottom-right\"]\n * @param {\"dark\"|\"light\"|Object} [props.theme=\"dark\"] - Built-in theme name or custom theme object\n * @param {React.RefObject} [props.container] - Optional ref to scope toasts inside a container (uses absolute positioning)\n */\nfunction Toaster({ position = \"bottom-right\", theme = \"dark\", container }) {\n const [toasts, setToasts] = useState([]);\n const resolvedThemeObj = resolveTheme(theme);\n\n useEffect(() => {\n _addToast = (t) => {\n if (t._dismiss) {\n setToasts((p) => {\n const f = p.find((x) => x.id === t.id);\n if (f) _unreg(f.dedupeKey);\n return p.filter((x) => x.id !== t.id);\n });\n return;\n }\n setToasts((p) => {\n if (t.replace) {\n const o = p.find((x) => x.id === t.id);\n if (o) _unreg(o.dedupeKey);\n return p.map((x) => (x.id === t.id ? { ...t } : x));\n }\n return [...p, t];\n });\n };\n return () => {\n _addToast = null;\n };\n }, []);\n\n const dismiss = useCallback((id, dk) => {\n _unreg(dk);\n setToasts((p) => p.filter((x) => x.id !== id));\n }, []);\n\n const [vPos, hPos] = position.split(\"-\");\n const isCenter = hPos === \"center\";\n\n return (\n <div\n style={{\n position: container ? \"absolute\" : \"fixed\",\n zIndex: 99999,\n display: \"flex\",\n flexDirection: vPos === \"top\" ? \"column\" : \"column-reverse\",\n alignItems: isCenter ? \"center\" : hPos === \"left\" ? \"flex-start\" : \"flex-end\",\n gap: 10,\n padding: container ? 12 : 20,\n pointerEvents: \"none\",\n ...(vPos === \"top\" ? { top: 0 } : { bottom: 0 }),\n ...(isCenter ? { left: 0, right: 0 } : hPos === \"left\" ? { left: 0 } : { right: 0 }),\n }}\n >\n <style>{`@keyframes toastywave-spin{to{transform:rotate(360deg)}}`}</style>\n {toasts.map((t) => (\n <div key={t.id} style={{ pointerEvents: \"auto\" }}>\n <ToastItem data={t} onDismiss={dismiss} position={position} theme={resolvedThemeObj} />\n </div>\n ))}\n </div>\n );\n}\n\n// ── Exports ─────────────────────────────────────────────────────\n\nexport { toast, Toaster, darkTheme, lightTheme, resolveTheme, registerActionPreset };\nexport default toast;\n"],"names":["_id","_addToast","_active","Map","_unreg","k","actionPresets","undo","onUndo","label","onClick","registerActionPreset","name","factory","toast","message","opts","arguments","length","undefined","dk","dedupeKey","concat","type","has","get","id","resolvedAction","action","preset","onAction","resolveAction","t","_objectSpread","duration","showCountdown","countdownText","pausedText","stopText","createdAt","Date","now","set","success","m","o","error","warning","info","loading","Infinity","promise","msgs","then","replace","dismiss","_dismiss","darkTheme","toastBg","toastBorder","toastShadow","title","desc","footerBg","footerBorder","footerText","footerLink","progressTrack","closeBtnColor","closeBtnHover","closeBtnHoverBg","actionBg","actionBorder","actionHoverBg","actionHoverBorder","actionText","backdrop","lightTheme","builtInThemes","dark","light","resolveTheme","themeOrName","ErrorIcon","_jsxs","width","height","viewBox","fill","children","_jsx","cx","cy","r","stroke","strokeWidth","opacity","d","strokeLinecap","WarningIcon","strokeLinejoin","InfoIcon","LoadingIcon","style","animation","CloseIcon","iconMap","accentMap","default","ToastItem","_ref","data","onDismiss","position","theme","_useState2","_slicedToArray","useState","phase","setPhase","_useState4","paused","setPaused","_useState6","remain","setRemain","ivRef","useRef","startRef","isTop","startsWith","hasDur","showFooter","th","useEffect","current","end","setInterval","left","clearInterval","setTimeout","requestAnimationFrame","cancelAnimationFrame","template","seconds","progress","Math","max","secs","ceil","enterY","tf","enter","visible","exit","onMouseEnter","onMouseLeave","maxWidth","background","backdropFilter","WebkitBackdropFilter","border","borderRadius","overflow","transform","transition","boxShadow","padding","display","alignItems","gap","icon","flexShrink","marginTop","color","flex","minWidth","fontSize","fontWeight","lineHeight","description","e","stopPropagation","currentTarget","borderColor","fontFamily","cursor","justifyContent","borderTop","_Fragment","String","textDecoration","textUnderlineOffset","top","Toaster","_ref2","_ref2$position","_ref2$theme","container","_useState8","toasts","setToasts","resolvedThemeObj","p","f","find","x","filter","map","_toConsumableArray","useCallback","_position$split2","split","vPos","hPos","isCenter","zIndex","flexDirection","pointerEvents","bottom","right"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "toastywave",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Lightweight React toast notifications with deduplication, countdown timers, theming, and container scoping.",
|
|
5
|
+
"main": "dist/index.cjs.js",
|
|
6
|
+
"module": "dist/index.esm.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.esm.js",
|
|
11
|
+
"require": "./dist/index.cjs.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "rollup -c && cp src/index.d.ts dist/",
|
|
22
|
+
"dev": "bun run build && bun run playground",
|
|
23
|
+
"watch": "rollup -c -w",
|
|
24
|
+
"playground": "cd playground && bun run dev",
|
|
25
|
+
"playground:install": "cd playground && bun install",
|
|
26
|
+
"prepublishOnly": "bun run build"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"react": ">=17.0.0",
|
|
30
|
+
"react-dom": ">=17.0.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@rollup/plugin-babel": "^6.0.4",
|
|
34
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
35
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
36
|
+
"rollup": "^4.9.0",
|
|
37
|
+
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
38
|
+
"@babel/core": "^7.24.0",
|
|
39
|
+
"@babel/preset-env": "^7.24.0",
|
|
40
|
+
"@babel/preset-react": "^7.23.3"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"react",
|
|
44
|
+
"toast",
|
|
45
|
+
"notification",
|
|
46
|
+
"toastywave",
|
|
47
|
+
"snackbar",
|
|
48
|
+
"alert",
|
|
49
|
+
"lightweight",
|
|
50
|
+
"dedup",
|
|
51
|
+
"theming"
|
|
52
|
+
],
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "https://github.com/papiguy/toastywave"
|
|
56
|
+
},
|
|
57
|
+
"license": "MIT",
|
|
58
|
+
"author": "",
|
|
59
|
+
"sideEffects": false
|
|
60
|
+
}
|