toast-23 1.0.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/README.md +266 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +119 -0
- package/dist/index.mjs +524 -0
- package/dist/index.mjs.map +1 -0
- package/dist/style.css +1 -0
- package/package.json +78 -0
package/README.md
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# ๐ toast-23
|
|
4
|
+
|
|
5
|
+
**A lightweight, accessible, fully-typed React toast notification library.**
|
|
6
|
+
|
|
7
|
+
Zero runtime dependencies ยท CSS animations ยท Dark mode ยท Promise tracking ยท Queue system
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/toast-23)
|
|
10
|
+
[](https://bundlephobia.com/package/toast-23)
|
|
11
|
+
[](./LICENSE)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- ๐จ **5 variants** โ success, error, warning, info, default
|
|
20
|
+
- ๐ **6 positions** โ top-right, top-left, top-center, bottom-right, bottom-left, bottom-center
|
|
21
|
+
- โณ **Promise API** โ track async operations with loading โ success / error
|
|
22
|
+
- โณ **Loading toast** โ `toast.loading()` with manual update
|
|
23
|
+
- ๐งฉ **Custom JSX** โ `toast.custom()` for fully custom content
|
|
24
|
+
- ๐ **Update & Deduplicate** โ update existing toasts via `id`, prevent duplicates
|
|
25
|
+
- ๐ฆ **Queue system** โ configurable max visible toasts with +N badge
|
|
26
|
+
- ๐งน **Dismiss & Remove** โ dismiss all, remove instantly, configurable `removeDelay`
|
|
27
|
+
- ๐ **Dark mode** โ automatic (`prefers-color-scheme`) + manual (`.dark` class)
|
|
28
|
+
- โฟ **Accessible** โ ARIA live regions, keyboard-navigable dismiss
|
|
29
|
+
- ๐ญ **CSS animations** โ smooth enter/exit transitions, hover-pause with progress reversal
|
|
30
|
+
- ๐ชถ **Lightweight** โ zero runtime dependencies beyond React
|
|
31
|
+
- ๐ **Fully typed** โ complete TypeScript API
|
|
32
|
+
- ๐ฒ **Tree-shakeable** โ ESM + CJS dual output
|
|
33
|
+
- ๐ **Standalone API** โ `createToast23()` for Angular, Vue, Svelte, vanilla JS
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install toast-23
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
yarn add toast-23
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pnpm add toast-23
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
### 1. Import the stylesheet
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
// In your app entry (e.g., main.tsx or layout.tsx)
|
|
59
|
+
import "toast-23/styles.css";
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 2. Wrap your app with the provider
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
import { Toast23Provider } from "toast-23";
|
|
66
|
+
|
|
67
|
+
function App() {
|
|
68
|
+
return (
|
|
69
|
+
<Toast23Provider position="top-right" maxVisible={5} duration={4000}>
|
|
70
|
+
<YourApp />
|
|
71
|
+
</Toast23Provider>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 3. Use the hook
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
import { useToast } from "toast-23";
|
|
80
|
+
|
|
81
|
+
function MyComponent() {
|
|
82
|
+
const toast = useToast();
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<div>
|
|
86
|
+
<button onClick={() => toast("Hello world!")}>Default</button>
|
|
87
|
+
<button onClick={() => toast.success("Saved successfully!")}>
|
|
88
|
+
Success
|
|
89
|
+
</button>
|
|
90
|
+
<button onClick={() => toast.error("Something went wrong")}>Error</button>
|
|
91
|
+
<button onClick={() => toast.warning("Please check your input")}>
|
|
92
|
+
Warning
|
|
93
|
+
</button>
|
|
94
|
+
<button onClick={() => toast.info("New update available")}>Info</button>
|
|
95
|
+
</div>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## API Reference
|
|
103
|
+
|
|
104
|
+
### `<Toast23Provider>`
|
|
105
|
+
|
|
106
|
+
| Prop | Type | Default | Description |
|
|
107
|
+
| ------------ | --------------- | ------------- | ------------------------------------- |
|
|
108
|
+
| `maxVisible` | `number` | `5` | Maximum simultaneously visible toasts |
|
|
109
|
+
| `position` | `ToastPosition` | `"top-right"` | Default screen position |
|
|
110
|
+
| `duration` | `number` | `4000` | Default auto-dismiss duration (ms) |
|
|
111
|
+
|
|
112
|
+
### `useToast()`
|
|
113
|
+
|
|
114
|
+
Returns a **callable** `ToastApi` object:
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
const toast = useToast();
|
|
118
|
+
|
|
119
|
+
// Direct call โ default variant
|
|
120
|
+
const id = toast("Message", options?);
|
|
121
|
+
|
|
122
|
+
// Variant shortcuts
|
|
123
|
+
toast.success("Saved!", options?);
|
|
124
|
+
toast.error("Failed!", options?);
|
|
125
|
+
toast.warning("Watch out!", options?);
|
|
126
|
+
toast.info("FYI", options?);
|
|
127
|
+
|
|
128
|
+
// Manual dismiss
|
|
129
|
+
toast.dismiss(id);
|
|
130
|
+
|
|
131
|
+
// Promise tracking
|
|
132
|
+
toast.promise(fetchData(), {
|
|
133
|
+
loading: "Loading...",
|
|
134
|
+
success: "Done!",
|
|
135
|
+
error: "Something failed",
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### `ToastOptions`
|
|
140
|
+
|
|
141
|
+
| Property | Type | Default | Description |
|
|
142
|
+
| ------------- | --------------- | ---------------- | ---------------------------------- |
|
|
143
|
+
| `title` | `string` | โ | Optional heading |
|
|
144
|
+
| `variant` | `ToastVariant` | `"default"` | Visual variant |
|
|
145
|
+
| `duration` | `number` | Provider default | Auto-dismiss ms (`0` = persistent) |
|
|
146
|
+
| `position` | `ToastPosition` | Provider default | Screen position override |
|
|
147
|
+
| `dismissible` | `boolean` | `true` | Show dismiss button |
|
|
148
|
+
|
|
149
|
+
### Types
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
type ToastVariant = "success" | "error" | "warning" | "info" | "default";
|
|
153
|
+
type ToastPosition = "top-right" | "top-left" | "bottom-right" | "bottom-left";
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Promise API
|
|
159
|
+
|
|
160
|
+
Track async operations with automatic loading โ result transitions:
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
const toast = useToast();
|
|
164
|
+
|
|
165
|
+
// Basic
|
|
166
|
+
toast.promise(saveData(), {
|
|
167
|
+
loading: "Saving...",
|
|
168
|
+
success: "Saved!",
|
|
169
|
+
error: "Failed to save",
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// Dynamic messages
|
|
173
|
+
toast.promise(fetchUser(id), {
|
|
174
|
+
loading: "Fetching user...",
|
|
175
|
+
success: (user) => `Welcome, ${user.name}!`,
|
|
176
|
+
error: (err) => `Error: ${err.message}`,
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Dark Mode
|
|
183
|
+
|
|
184
|
+
toast-23 supports dark mode in two ways:
|
|
185
|
+
|
|
186
|
+
1. **Automatic** โ respects `prefers-color-scheme: dark`
|
|
187
|
+
2. **Manual** โ add the `dark` class to any ancestor (e.g., `<html class="dark">`)
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Customization
|
|
192
|
+
|
|
193
|
+
Override CSS variables or classes to customize the look:
|
|
194
|
+
|
|
195
|
+
```css
|
|
196
|
+
/* Override colors */
|
|
197
|
+
.toast23-item--success {
|
|
198
|
+
background: #d1fae5;
|
|
199
|
+
border-color: #6ee7b7;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* Override progress bar */
|
|
203
|
+
.toast23-progress--success {
|
|
204
|
+
background: #10b981;
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## SSR Support
|
|
211
|
+
|
|
212
|
+
toast-23 is SSR-safe. All browser APIs are guarded behind `useEffect`:
|
|
213
|
+
|
|
214
|
+
- โ
Next.js (App Router & Pages Router)
|
|
215
|
+
- โ
Remix
|
|
216
|
+
- โ
Gatsby
|
|
217
|
+
- โ
Astro (React islands)
|
|
218
|
+
- โ
Angular (via `createToast23()`)
|
|
219
|
+
- โ
Vue.js (via `createToast23()`)
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Testing
|
|
224
|
+
|
|
225
|
+
toast-23 uses [Vitest](https://vitest.dev/) with [Testing Library](https://testing-library.com/):
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
# Run tests
|
|
229
|
+
npm test
|
|
230
|
+
|
|
231
|
+
# Watch mode
|
|
232
|
+
npm run test:watch
|
|
233
|
+
|
|
234
|
+
# Coverage
|
|
235
|
+
npm run test:coverage
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## CI/CD
|
|
241
|
+
|
|
242
|
+
GitHub Actions workflow at `.github/workflows/ci.yml`:
|
|
243
|
+
|
|
244
|
+
- **Lint** โ TypeScript type checking
|
|
245
|
+
- **Test** โ Vitest test suite (Node 18, 20, 22)
|
|
246
|
+
- **Build** โ Vite library build with DTS generation
|
|
247
|
+
- **Publish** โ Auto-publish to npm on version bump (requires `NPM_TOKEN` secret)
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Suggested Improvements for v2
|
|
252
|
+
|
|
253
|
+
- [ ] Swipe-to-dismiss on mobile
|
|
254
|
+
- [ ] Stacked/collapsed mode for overflow
|
|
255
|
+
- [ ] Undo action support
|
|
256
|
+
- [ ] Theming via CSS custom properties (design tokens)
|
|
257
|
+
- [ ] Headless mode (bring your own UI)
|
|
258
|
+
- [ ] Rich content: icons, avatars, action buttons
|
|
259
|
+
- [ ] Sound notifications
|
|
260
|
+
- [ ] Persistent toasts (survive page navigation)
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## License
|
|
265
|
+
|
|
266
|
+
MIT ยฉ toast-23 contributors
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),l=require("react"),D=require("react-dom/client");function A(e){const n=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const r in e)if(r!=="default"){const t=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(n,r,t.get?t:{enumerable:!0,get:()=>e[r]})}}return n.default=e,Object.freeze(n)}const y=A(l),k=l.createContext(null);function P(e,n){switch(n.type){case"ADD":return[...e,n.toast];case"UPSERT":return e.some(t=>t.id===n.toast.id)?e.map(t=>t.id===n.toast.id?{...t,...n.toast,version:t.version+1,isExiting:!1}:t):[...e,n.toast];case"UPDATE":return e.map(r=>r.id===n.id?{...r,...n.updates,version:r.version+1,isExiting:!1}:r);case"DISMISS":return n.id?e.map(r=>r.id===n.id?{...r,isExiting:!0}:r):e.map(r=>({...r,isExiting:!0}));case"REMOVE":return n.id?e.filter(r=>r.id!==n.id):[];default:return e}}const _=e=>o.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:"1.25em",height:"1.25em",fill:"none",...e,children:[o.jsx("circle",{cx:12,cy:12,r:10,fill:"currentColor"}),o.jsx("path",{d:"M8 12.5l2.5 2.5 5-5",stroke:"#fff",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",fill:"none"})]}),p=e=>o.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:"1.25em",height:"1.25em",fill:"none",...e,children:[o.jsx("circle",{cx:12,cy:12,r:10,fill:"currentColor"}),o.jsx("line",{x1:12,y1:8,x2:12,y2:13,stroke:"#fff",strokeWidth:2,strokeLinecap:"round"}),o.jsx("circle",{cx:12,cy:16,r:1,fill:"#fff"})]}),q=e=>o.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:"1.25em",height:"1.25em",fill:"none",...e,children:[o.jsx("path",{d:"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z",fill:"currentColor"}),o.jsx("line",{x1:12,y1:9.5,x2:12,y2:14,stroke:"#fff",strokeWidth:2,strokeLinecap:"round"}),o.jsx("circle",{cx:12,cy:17,r:1,fill:"#fff"})]}),b=e=>o.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:"1.25em",height:"1.25em",fill:"none",...e,children:[o.jsx("circle",{cx:12,cy:12,r:10,fill:"currentColor"}),o.jsx("line",{x1:12,y1:11,x2:12,y2:16,stroke:"#fff",strokeWidth:2,strokeLinecap:"round"}),o.jsx("circle",{cx:12,cy:8,r:1,fill:"#fff"})]}),$=e=>o.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",width:"0.875em",height:"0.875em",...e,children:[o.jsx("line",{x1:18,y1:6,x2:6,y2:18}),o.jsx("line",{x1:6,y1:6,x2:18,y2:18})]}),B=e=>o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",width:"1.25em",height:"1.25em",className:"toast23-spinner",...e,children:o.jsx("path",{d:"M21 12a9 9 0 1 1-6.219-8.56"})});let W=0;function U(){return`t23-${++W}-${Math.random().toString(36).slice(2,9)}`}function w(...e){return e.filter(Boolean).join(" ")}const F={success:_,error:p,warning:q,info:b,default:b,loading:B},X=300,z=200,M=y.memo(({toast:e,onDismiss:n,onRemove:r})=>{const[t,u]=l.useState(!1);l.useEffect(()=>{const v=requestAnimationFrame(()=>u(!0));return()=>cancelAnimationFrame(v)},[]),l.useEffect(()=>{if(!e.isExiting)return;const v=e.removeDelay??X,E=setTimeout(()=>r(e.id),v);return()=>clearTimeout(E)},[e.isExiting,e.id,e.removeDelay,r]);const[m,g]=l.useState(!1),d=l.useRef(e.duration),c=l.useRef(0),[x,f]=l.useState(100),[a,i]=l.useState("none"),s=l.useRef(0);l.useEffect(()=>{d.current=e.duration,f(100),i("none")},[e.version,e.duration]),l.useEffect(()=>{if(e.duration<=0||e.variant==="loading"||!t||e.isExiting)return;if(m){const I=Date.now()-c.current;d.current=Math.max(0,d.current-I);const L=Math.max(z,I);i(`width ${L}ms ease-out`),f(100);return}c.current=Date.now();const v=d.current;s.current=requestAnimationFrame(()=>{i(`width ${v}ms linear`),f(0)});const E=setTimeout(()=>{n(e.id)},v);return()=>{clearTimeout(E),cancelAnimationFrame(s.current)}},[m,t,e.isExiting,e.duration,e.variant,e.id,e.version,n]);const h=l.useCallback(()=>g(!0),[]),T=l.useCallback(()=>g(!1),[]),S=F[e.variant]??b;return e.isCustom?o.jsx("div",{className:w("toast23-item toast23-item--custom",!t&&"toast23-item--entering",e.isExiting&&"toast23-item--exiting"),role:"alert","aria-live":"polite","aria-atomic":"true",onMouseEnter:h,onMouseLeave:T,children:e.message}):o.jsxs("div",{className:w("toast23-item",`toast23-item--${e.variant}`,!t&&"toast23-item--entering",e.isExiting&&"toast23-item--exiting"),role:"alert","aria-live":e.variant==="error"?"assertive":"polite","aria-atomic":"true",onMouseEnter:h,onMouseLeave:T,children:[o.jsx("span",{className:w("toast23-icon",`toast23-icon--${e.variant}`),children:o.jsx(S,{})}),o.jsxs("div",{className:"toast23-content",children:[e.title&&o.jsx("div",{className:"toast23-title",children:e.title}),o.jsx("div",{className:w("toast23-message",e.title&&"toast23-message--with-title"),children:e.message})]}),e.dismissible&&o.jsx("button",{type:"button",className:"toast23-dismiss",onClick:()=>n(e.id),"aria-label":"Dismiss notification",children:o.jsx($,{})}),e.duration>0&&e.variant!=="loading"&&o.jsx("div",{className:w("toast23-progress",`toast23-progress--${e.variant}`),style:{width:`${x}%`,transition:a}})]})});M.displayName="ToastItem";const N=y.memo(({position:e,toasts:n,maxVisible:r})=>{const t=l.useContext(k);if(!t)return null;const u=n.filter(c=>!c.isExiting),m=n.filter(c=>c.isExiting),g=[...u.slice(0,r),...m];if(g.length===0)return null;const d=Math.max(0,u.length-r);return o.jsxs("div",{className:w("toast23-container",`toast23-container--${e}`),"aria-label":"Notifications",role:"region",children:[g.map(c=>o.jsx(M,{toast:c,onDismiss:t.dismissToast,onRemove:t.removeToast},c.id)),d>0&&o.jsxs("div",{className:"toast23-queue-badge","aria-live":"polite",children:["+",d," more"]})]})});N.displayName="ToastContainer";const H=["top-right","top-left","top-center","bottom-right","bottom-left","bottom-center"],C=({children:e,maxVisible:n=5,position:r="top-right",duration:t=5e3})=>{const[u,m]=l.useReducer(P,[]),g=l.useCallback((i,s)=>{const h=(s==null?void 0:s.id)??U(),T={id:h,message:i,title:s==null?void 0:s.title,variant:(s==null?void 0:s.variant)??"default",duration:(s==null?void 0:s.duration)??t,position:(s==null?void 0:s.position)??r,dismissible:(s==null?void 0:s.dismissible)??!0,removeDelay:(s==null?void 0:s.removeDelay)??1e3,isExiting:!1,createdAt:Date.now(),version:0,isCustom:s==null?void 0:s.isCustom};return s!=null&&s.id?m({type:"UPSERT",toast:T}):m({type:"ADD",toast:T}),h},[t,r]),d=l.useCallback((i,s)=>{m({type:"UPDATE",id:i,updates:s})},[]),c=l.useCallback(i=>{m({type:"DISMISS",id:i})},[]),x=l.useCallback(i=>{m({type:"REMOVE",id:i})},[]),f=l.useMemo(()=>({addToast:g,updateToast:d,dismissToast:c,removeToast:x,config:{maxVisible:n,position:r,duration:t}}),[g,d,c,x,n,r,t]),a=l.useMemo(()=>{const i={"top-right":[],"top-left":[],"top-center":[],"bottom-right":[],"bottom-left":[],"bottom-center":[]};for(const s of u)i[s.position].push(s);return i},[u]);return o.jsxs(k.Provider,{value:f,children:[e,H.map(i=>a[i].length>0?o.jsx(N,{position:i,toasts:a[i],maxVisible:n},i):null)]})};C.displayName="Toast23Provider";function R(){const e=l.useContext(k);if(!e)throw new Error("[toast-23] useToast() must be used inside a <Toast23Provider>. Wrap your application root with <Toast23Provider> to fix this.");return l.useMemo(()=>{const n=(r,t)=>e.addToast(r,t);return n.success=(r,t)=>e.addToast(r,{...t,variant:"success"}),n.error=(r,t)=>e.addToast(r,{...t,variant:"error"}),n.warning=(r,t)=>e.addToast(r,{...t,variant:"warning"}),n.info=(r,t)=>e.addToast(r,{...t,variant:"info"}),n.loading=(r,t)=>e.addToast(r,{...t,variant:"loading",duration:(t==null?void 0:t.duration)??0,dismissible:(t==null?void 0:t.dismissible)??!1}),n.custom=(r,t)=>e.addToast(r,{...t,variant:"default",isCustom:!0}),n.dismiss=r=>e.dismissToast(r),n.remove=r=>e.removeToast(r),n.promise=async(r,t,u)=>{const m=e.addToast(t.loading,{...u,variant:"loading",duration:0,dismissible:!1}),g=typeof r=="function"?r():r;try{const d=await g,c=typeof t.success=="function"?t.success(d):t.success;return e.updateToast(m,{message:c,variant:"success",duration:(u==null?void 0:u.duration)??e.config.duration,dismissible:!0}),d}catch(d){const c=typeof t.error=="function"?t.error(d):t.error;throw e.updateToast(m,{message:c,variant:"error",duration:(u==null?void 0:u.duration)??e.config.duration,dismissible:!0}),d}},n},[e.addToast,e.updateToast,e.dismissToast,e.removeToast,e.config.duration])}let j=null;function V(){const e=R();return y.useEffect(()=>{j&&(j(e),j=null)},[e]),null}function G(e={}){const{position:n="top-right",maxVisible:r=5,duration:t=5e3}=e,u=document.createElement("div");u.setAttribute("data-toast23-standalone",""),u.style.display="contents",document.body.appendChild(u);let m=D.createRoot(u);const g=new Promise(a=>{j=a}),d=[];let c=null;g.then(a=>{c=a;for(const i of d)i.method==="__call__"?a(...i.args):a[i.method](...i.args);d.length=0}),m.render(y.createElement(C,{position:n,maxVisible:r,duration:t},y.createElement(V)));const x=(a,...i)=>c?c[a](...i):(d.push({method:a,args:i}),"queued"),f=(a,i)=>c?c(a,i):(d.push({method:"__call__",args:[a,i]}),"queued");return f.success=(a,i)=>x("success",a,i),f.error=(a,i)=>x("error",a,i),f.warning=(a,i)=>x("warning",a,i),f.info=(a,i)=>x("info",a,i),f.loading=(a,i)=>x("loading",a,i),f.custom=(a,i)=>x("custom",a,i),f.dismiss=a=>x("dismiss",a),f.remove=a=>x("remove",a),f.promise=(a,i,s)=>c?c.promise(a,i,s):g.then(h=>h.promise(a,i,s)),f.destroy=()=>{m&&(m.unmount(),m=null),u.remove(),c=null},f}exports.Toast23Provider=C;exports.createToast23=G;exports.useToast=R;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/context.tsx","../src/icons.tsx","../src/utils.ts","../src/toast-item.tsx","../src/toast-container.tsx","../src/provider.tsx","../src/use-toast.ts","../src/standalone.ts"],"sourcesContent":["/**\r\n * toast-23 โ React Context & Reducer\r\n */\r\n\r\nimport { createContext } from \"react\";\r\nimport type {\r\n InternalToast,\r\n ToasterAction,\r\n ToasterContextValue,\r\n} from \"./types\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Context โ consumed by useToast() and internal components\r\n// ---------------------------------------------------------------------------\r\n\r\nexport const ToasterContext = createContext<ToasterContextValue | null>(null);\r\n\r\n// ---------------------------------------------------------------------------\r\n// Reducer โ pure state transitions for the toast queue\r\n// ---------------------------------------------------------------------------\r\n\r\nexport function toasterReducer(\r\n state: InternalToast[],\r\n action: ToasterAction,\r\n): InternalToast[] {\r\n switch (action.type) {\r\n case \"ADD\":\r\n return [...state, action.toast];\r\n\r\n case \"UPSERT\": {\r\n const exists = state.some((t) => t.id === action.toast.id);\r\n if (exists) {\r\n return state.map((t) =>\r\n t.id === action.toast.id\r\n ? {\r\n ...t,\r\n ...action.toast,\r\n version: t.version + 1,\r\n isExiting: false,\r\n }\r\n : t,\r\n );\r\n }\r\n return [...state, action.toast];\r\n }\r\n\r\n case \"UPDATE\":\r\n return state.map((t) =>\r\n t.id === action.id\r\n ? {\r\n ...t,\r\n ...action.updates,\r\n // Bump version so progress bar restarts\r\n version: t.version + 1,\r\n // If the toast was exiting, cancel exit on update\r\n isExiting: false,\r\n }\r\n : t,\r\n );\r\n\r\n case \"DISMISS\":\r\n // Omit id โ dismiss all\r\n if (!action.id) {\r\n return state.map((t) => ({ ...t, isExiting: true }));\r\n }\r\n return state.map((t) =>\r\n t.id === action.id ? { ...t, isExiting: true } : t,\r\n );\r\n\r\n case \"REMOVE\":\r\n // Omit id โ remove all instantly\r\n if (!action.id) return [];\r\n return state.filter((t) => t.id !== action.id);\r\n\r\n default:\r\n return state;\r\n }\r\n}\r\n","/**\r\n * toast-23 โ Inline SVG Icons (Filled style)\r\n *\r\n * Solid colored circles/triangles with white inner symbols,\r\n * matching the visual design reference.\r\n */\r\n\r\nimport type { SVGProps, FC } from \"react\";\r\n\r\ntype IconProps = SVGProps<SVGSVGElement>;\r\n\r\n/** Green filled circle with white checkmark */\r\nexport const CheckCircleIcon: FC<IconProps> = (props: IconProps) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n width=\"1.25em\"\r\n height=\"1.25em\"\r\n fill=\"none\"\r\n {...props}\r\n >\r\n <circle cx={12} cy={12} r={10} fill=\"currentColor\" />\r\n <path\r\n d=\"M8 12.5l2.5 2.5 5-5\"\r\n stroke=\"#fff\"\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n fill=\"none\"\r\n />\r\n </svg>\r\n);\r\n\r\n/** Red filled circle with white exclamation */\r\nexport const XCircleIcon: FC<IconProps> = (props: IconProps) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n width=\"1.25em\"\r\n height=\"1.25em\"\r\n fill=\"none\"\r\n {...props}\r\n >\r\n <circle cx={12} cy={12} r={10} fill=\"currentColor\" />\r\n <line\r\n x1={12}\r\n y1={8}\r\n x2={12}\r\n y2={13}\r\n stroke=\"#fff\"\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n />\r\n <circle cx={12} cy={16} r={1} fill=\"#fff\" />\r\n </svg>\r\n);\r\n\r\n/** Yellow filled triangle with white exclamation */\r\nexport const AlertTriangleIcon: FC<IconProps> = (props: IconProps) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n width=\"1.25em\"\r\n height=\"1.25em\"\r\n fill=\"none\"\r\n {...props}\r\n >\r\n <path\r\n d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"\r\n fill=\"currentColor\"\r\n />\r\n <line\r\n x1={12}\r\n y1={9.5}\r\n x2={12}\r\n y2={14}\r\n stroke=\"#fff\"\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n />\r\n <circle cx={12} cy={17} r={1} fill=\"#fff\" />\r\n </svg>\r\n);\r\n\r\n/** Blue filled circle with white \"i\" */\r\nexport const InfoIcon: FC<IconProps> = (props: IconProps) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n width=\"1.25em\"\r\n height=\"1.25em\"\r\n fill=\"none\"\r\n {...props}\r\n >\r\n <circle cx={12} cy={12} r={10} fill=\"currentColor\" />\r\n <line\r\n x1={12}\r\n y1={11}\r\n x2={12}\r\n y2={16}\r\n stroke=\"#fff\"\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n />\r\n <circle cx={12} cy={8} r={1} fill=\"#fff\" />\r\n </svg>\r\n);\r\n\r\n/** Thin X icon for dismiss button */\r\nexport const XIcon: FC<IconProps> = (props: IconProps) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n width=\"0.875em\"\r\n height=\"0.875em\"\r\n {...props}\r\n >\r\n <line x1={18} y1={6} x2={6} y2={18} />\r\n <line x1={6} y1={6} x2={18} y2={18} />\r\n </svg>\r\n);\r\n\r\n/** CSS-only loading spinner */\r\nexport const SpinnerIcon: FC<IconProps> = (props: IconProps) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n width=\"1.25em\"\r\n height=\"1.25em\"\r\n className=\"toast23-spinner\"\r\n {...props}\r\n >\r\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\r\n </svg>\r\n);\r\n","/**\r\n * toast-23 โ Utility helpers\r\n */\r\n\r\nlet counter = 0;\r\n\r\n/**\r\n * Generate a unique toast id.\r\n * Works in SSR (no dependency on `crypto`).\r\n */\r\nexport function generateId(): string {\r\n return `t23-${++counter}-${Math.random().toString(36).slice(2, 9)}`;\r\n}\r\n\r\n/**\r\n * Deterministic class-name builder (replaces clsx dependency).\r\n */\r\nexport function cx(...args: (string | false | null | undefined | 0)[]): string {\r\n return args.filter(Boolean).join(\" \");\r\n}\r\n","/**\r\n * toast-23 โ Individual Toast Component\r\n *\r\n * Manages its own enter / exit CSS transitions and auto-dismiss timer.\r\n * Progress bar is JS-driven so it can reverse (refill) on hover.\r\n */\r\n\r\n\"use client\";\r\n\r\nimport * as React from \"react\";\r\nimport { useCallback, useEffect, useRef, useState } from \"react\";\r\nimport type { InternalToast } from \"./types\";\r\nimport {\r\n CheckCircleIcon,\r\n XCircleIcon,\r\n AlertTriangleIcon,\r\n InfoIcon,\r\n SpinnerIcon,\r\n XIcon,\r\n} from \"./icons\";\r\nimport { cx } from \"./utils\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Icon map\r\n// ---------------------------------------------------------------------------\r\n\r\nconst variantIcon: Record<string, React.FC<React.SVGProps<SVGSVGElement>>> = {\r\n success: CheckCircleIcon,\r\n error: XCircleIcon,\r\n warning: AlertTriangleIcon,\r\n info: InfoIcon,\r\n default: InfoIcon,\r\n loading: SpinnerIcon,\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Component\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface ToastItemProps {\r\n toast: InternalToast;\r\n onDismiss: (id: string) => void;\r\n onRemove: (id: string) => void;\r\n}\r\n\r\nconst EXIT_DURATION = 300; // ms โ must match CSS transition duration\r\nconst MIN_REFILL_DURATION = 200; // ms โ minimum refill time so very short hovers aren't instant\r\n\r\nexport const ToastItem: React.FC<ToastItemProps> = React.memo(\r\n ({ toast, onDismiss, onRemove }) => {\r\n // ----- animation state -----\r\n const [hasEntered, setHasEntered] = useState(false);\r\n\r\n // Trigger enter transition on next frame\r\n useEffect(() => {\r\n const raf = requestAnimationFrame(() => setHasEntered(true));\r\n return () => cancelAnimationFrame(raf);\r\n }, []);\r\n\r\n // When the provider marks the toast as exiting, wait for the CSS\r\n // transition to finish then actually remove it from state.\r\n useEffect(() => {\r\n if (!toast.isExiting) return;\r\n const delay = toast.removeDelay ?? EXIT_DURATION;\r\n const timer = setTimeout(() => onRemove(toast.id), delay);\r\n return () => clearTimeout(timer);\r\n }, [toast.isExiting, toast.id, toast.removeDelay, onRemove]);\r\n\r\n // ----- auto-dismiss timer with hover-pause -----\r\n const [isPaused, setIsPaused] = useState(false);\r\n const remainingRef = useRef(toast.duration);\r\n const startRef = useRef(0);\r\n\r\n // ----- JS-driven progress bar -----\r\n // progress: 100 = full, 0 = empty\r\n const [progress, setProgress] = useState(100);\r\n // transition duration for the progress bar\r\n const [progressTransition, setProgressTransition] = useState(\"none\");\r\n const rafRef = useRef<number>(0);\r\n\r\n // Reset remaining time when version changes (e.g. promise resolved)\r\n useEffect(() => {\r\n remainingRef.current = toast.duration;\r\n setProgress(100);\r\n setProgressTransition(\"none\");\r\n }, [toast.version, toast.duration]);\r\n\r\n useEffect(() => {\r\n // Don't auto-dismiss: persistent, loading, still entering, or already exiting\r\n if (\r\n toast.duration <= 0 ||\r\n toast.variant === \"loading\" ||\r\n !hasEntered ||\r\n toast.isExiting\r\n )\r\n return;\r\n\r\n if (isPaused) {\r\n // How long the bar was shrinking before hover\r\n const elapsed = Date.now() - startRef.current;\r\n // Snapshot remaining time\r\n remainingRef.current = Math.max(0, remainingRef.current - elapsed);\r\n\r\n // Reverse at the same speed it was shrinking (proportional duration)\r\n const refillDuration = Math.max(MIN_REFILL_DURATION, elapsed);\r\n setProgressTransition(`width ${refillDuration}ms ease-out`);\r\n setProgress(100);\r\n return;\r\n }\r\n\r\n // Start shrinking\r\n startRef.current = Date.now();\r\n const remaining = remainingRef.current;\r\n\r\n // Set transition to match remaining time and shrink to 0\r\n // Use rAF to ensure the refill transition has settled before starting shrink\r\n rafRef.current = requestAnimationFrame(() => {\r\n setProgressTransition(`width ${remaining}ms linear`);\r\n setProgress(0);\r\n });\r\n\r\n const timer = setTimeout(() => {\r\n onDismiss(toast.id);\r\n }, remaining);\r\n\r\n return () => {\r\n clearTimeout(timer);\r\n cancelAnimationFrame(rafRef.current);\r\n };\r\n }, [\r\n isPaused,\r\n hasEntered,\r\n toast.isExiting,\r\n toast.duration,\r\n toast.variant,\r\n toast.id,\r\n toast.version,\r\n onDismiss,\r\n ]);\r\n\r\n // ----- handlers -----\r\n const handleMouseEnter = useCallback(() => setIsPaused(true), []);\r\n const handleMouseLeave = useCallback(() => setIsPaused(false), []);\r\n\r\n // ----- render -----\r\n const Icon = variantIcon[toast.variant] ?? InfoIcon;\r\n\r\n // Custom toast โ render raw content with no default chrome\r\n if (toast.isCustom) {\r\n return (\r\n <div\r\n className={cx(\r\n \"toast23-item toast23-item--custom\",\r\n !hasEntered && \"toast23-item--entering\",\r\n toast.isExiting && \"toast23-item--exiting\",\r\n )}\r\n role=\"alert\"\r\n aria-live=\"polite\"\r\n aria-atomic=\"true\"\r\n onMouseEnter={handleMouseEnter}\r\n onMouseLeave={handleMouseLeave}\r\n >\r\n {toast.message}\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div\r\n className={cx(\r\n \"toast23-item\",\r\n `toast23-item--${toast.variant}`,\r\n !hasEntered && \"toast23-item--entering\",\r\n toast.isExiting && \"toast23-item--exiting\",\r\n )}\r\n role=\"alert\"\r\n aria-live={toast.variant === \"error\" ? \"assertive\" : \"polite\"}\r\n aria-atomic=\"true\"\r\n onMouseEnter={handleMouseEnter}\r\n onMouseLeave={handleMouseLeave}\r\n >\r\n {/* Icon */}\r\n <span className={cx(\"toast23-icon\", `toast23-icon--${toast.variant}`)}>\r\n <Icon />\r\n </span>\r\n\r\n {/* Content */}\r\n <div className=\"toast23-content\">\r\n {toast.title && <div className=\"toast23-title\">{toast.title}</div>}\r\n <div\r\n className={cx(\r\n \"toast23-message\",\r\n toast.title && \"toast23-message--with-title\",\r\n )}\r\n >\r\n {toast.message}\r\n </div>\r\n </div>\r\n\r\n {/* Dismiss button */}\r\n {toast.dismissible && (\r\n <button\r\n type=\"button\"\r\n className=\"toast23-dismiss\"\r\n onClick={() => onDismiss(toast.id)}\r\n aria-label=\"Dismiss notification\"\r\n >\r\n <XIcon />\r\n </button>\r\n )}\r\n\r\n {/* Progress bar โ JS-driven width for hover reversal */}\r\n {toast.duration > 0 && toast.variant !== \"loading\" && (\r\n <div\r\n className={cx(\r\n \"toast23-progress\",\r\n `toast23-progress--${toast.variant}`,\r\n )}\r\n style={{\r\n width: `${progress}%`,\r\n transition: progressTransition,\r\n }}\r\n />\r\n )}\r\n </div>\r\n );\r\n },\r\n);\r\n\r\nToastItem.displayName = \"ToastItem\";\r\n","/**\r\n * toast-23 โ Positioned Toast Container\r\n *\r\n * Renders a group of toasts for a given screen position.\r\n * Handles queue logic: only `maxVisible` non-exiting toasts are shown,\r\n * plus any currently animating-out toasts.\r\n */\r\n\r\n\"use client\";\r\n\r\nimport * as React from \"react\";\r\nimport { useContext } from \"react\";\r\nimport type { InternalToast, ToastPosition } from \"./types\";\r\nimport { ToasterContext } from \"./context\";\r\nimport { ToastItem } from \"./toast-item\";\r\nimport { cx } from \"./utils\";\r\n\r\ninterface ToastContainerProps {\r\n position: ToastPosition;\r\n toasts: InternalToast[];\r\n maxVisible: number;\r\n}\r\n\r\nexport const ToastContainer: React.FC<ToastContainerProps> = React.memo(\r\n ({ position, toasts, maxVisible }: ToastContainerProps) => {\r\n const ctx = useContext(ToasterContext);\r\n if (!ctx) return null;\r\n\r\n // Separate active vs. exiting toasts\r\n const active = toasts.filter((t) => !t.isExiting);\r\n const exiting = toasts.filter((t) => t.isExiting);\r\n\r\n // Only show up to maxVisible active toasts, plus all currently exiting\r\n const visible = [...active.slice(0, maxVisible), ...exiting];\r\n\r\n if (visible.length === 0) return null;\r\n\r\n // Queue count for optional badge\r\n const queuedCount = Math.max(0, active.length - maxVisible);\r\n\r\n return (\r\n <div\r\n className={cx(\"toast23-container\", `toast23-container--${position}`)}\r\n aria-label=\"Notifications\"\r\n role=\"region\"\r\n >\r\n {visible.map((toast) => (\r\n <ToastItem\r\n key={toast.id}\r\n toast={toast}\r\n onDismiss={ctx.dismissToast}\r\n onRemove={ctx.removeToast}\r\n />\r\n ))}\r\n {queuedCount > 0 && (\r\n <div className=\"toast23-queue-badge\" aria-live=\"polite\">\r\n +{queuedCount} more\r\n </div>\r\n )}\r\n </div>\r\n );\r\n },\r\n);\r\n\r\nToastContainer.displayName = \"ToastContainer\";\r\n","/**\r\n * toast-23 โ Toast23Provider\r\n *\r\n * Wrap your application with this provider to enable toast notifications.\r\n *\r\n * ```tsx\r\n * <Toast23Provider position=\"top-right\" maxVisible={5}>\r\n * <App />\r\n * </Toast23Provider>\r\n * ```\r\n */\r\n\r\n\"use client\";\r\n\r\nimport { useCallback, useMemo, useReducer } from \"react\";\r\nimport type {\r\n InternalToast,\r\n Toast23ProviderProps,\r\n ToasterContextValue,\r\n ToastOptions,\r\n ToastPosition,\r\n} from \"./types\";\r\nimport type { ReactNode } from \"react\";\r\nimport { ToasterContext, toasterReducer } from \"./context\";\r\nimport { ToastContainer } from \"./toast-container\";\r\nimport { generateId } from \"./utils\";\r\n\r\nconst ALL_POSITIONS: ToastPosition[] = [\r\n \"top-right\",\r\n \"top-left\",\r\n \"top-center\",\r\n \"bottom-right\",\r\n \"bottom-left\",\r\n \"bottom-center\",\r\n];\r\n\r\nexport const Toast23Provider: React.FC<Toast23ProviderProps> = ({\r\n children,\r\n maxVisible = 5,\r\n position: defaultPosition = \"top-right\" as ToastPosition,\r\n duration: defaultDuration = 5000,\r\n}) => {\r\n const [toasts, dispatch] = useReducer(toasterReducer, []);\r\n\r\n // ------ stable callbacks (dispatch is always stable from useReducer) ------\r\n\r\n const addToast = useCallback(\r\n (message: string | ReactNode, options?: ToastOptions & { variant?: any; isCustom?: boolean }): string => {\r\n const id = options?.id ?? generateId();\r\n const toast: InternalToast = {\r\n id,\r\n message,\r\n title: options?.title,\r\n variant: options?.variant ?? \"default\",\r\n duration: options?.duration ?? defaultDuration,\r\n position: options?.position ?? defaultPosition,\r\n dismissible: options?.dismissible ?? true,\r\n removeDelay: options?.removeDelay ?? 1000,\r\n isExiting: false,\r\n createdAt: Date.now(),\r\n version: 0,\r\n isCustom: options?.isCustom,\r\n };\r\n // If an id was provided, upsert (update-or-insert)\r\n if (options?.id) {\r\n dispatch({ type: \"UPSERT\", toast });\r\n } else {\r\n dispatch({ type: \"ADD\", toast });\r\n }\r\n return id;\r\n },\r\n [defaultDuration, defaultPosition],\r\n );\r\n\r\n const updateToast = useCallback(\r\n (\r\n id: string,\r\n updates: Partial<\r\n Pick<\r\n InternalToast,\r\n \"message\" | \"title\" | \"variant\" | \"duration\" | \"dismissible\"\r\n >\r\n >,\r\n ) => {\r\n dispatch({ type: \"UPDATE\", id, updates });\r\n },\r\n [],\r\n );\r\n\r\n const dismissToast = useCallback((id?: string) => {\r\n dispatch({ type: \"DISMISS\", id });\r\n }, []);\r\n\r\n const removeToast = useCallback((id?: string) => {\r\n dispatch({ type: \"REMOVE\", id });\r\n }, []);\r\n\r\n // ------ context value (stable as long as callbacks are stable) ------\r\n\r\n const contextValue: ToasterContextValue = useMemo(\r\n () => ({\r\n addToast,\r\n updateToast,\r\n dismissToast,\r\n removeToast,\r\n config: {\r\n maxVisible,\r\n position: defaultPosition,\r\n duration: defaultDuration,\r\n },\r\n }),\r\n [\r\n addToast,\r\n updateToast,\r\n dismissToast,\r\n removeToast,\r\n maxVisible,\r\n defaultPosition,\r\n defaultDuration,\r\n ],\r\n );\r\n\r\n // ------ group toasts by position ------\r\n\r\n const groupedToasts = useMemo(() => {\r\n const groups: Record<ToastPosition, InternalToast[]> = {\r\n \"top-right\": [],\r\n \"top-left\": [],\r\n \"top-center\": [],\r\n \"bottom-right\": [],\r\n \"bottom-left\": [],\r\n \"bottom-center\": [],\r\n };\r\n for (const t of toasts) {\r\n groups[t.position].push(t);\r\n }\r\n return groups;\r\n }, [toasts]);\r\n\r\n return (\r\n <ToasterContext.Provider value={contextValue}>\r\n {children}\r\n\r\n {/* Render one container per position that has toasts */}\r\n {ALL_POSITIONS.map((pos) =>\r\n groupedToasts[pos].length > 0 ? (\r\n <ToastContainer\r\n key={pos}\r\n position={pos}\r\n toasts={groupedToasts[pos]}\r\n maxVisible={maxVisible}\r\n />\r\n ) : null,\r\n )}\r\n </ToasterContext.Provider>\r\n );\r\n};\r\n\r\nToast23Provider.displayName = \"Toast23Provider\";\r\n","/**\r\n * toast-23 โ useToast Hook\r\n *\r\n * Returns a callable `ToastApi` object:\r\n *\r\n * ```ts\r\n * const toast = useToast();\r\n *\r\n * toast(\"Hello!\"); // default variant\r\n * toast.success(\"Done!\"); // success variant\r\n * toast.error(\"Oops\"); // error variant\r\n * toast.promise(fetchData(), { ... }); // promise tracking\r\n * toast.dismiss(id); // manual dismiss\r\n * ```\r\n */\r\n\r\n\"use client\";\r\n\r\nimport { useContext, useMemo } from \"react\";\r\nimport { ToasterContext } from \"./context\";\r\nimport type { ToastApi, ToastOptions, PromiseOptions } from \"./types\";\r\nimport type { ReactNode } from \"react\";\r\n\r\nexport function useToast(): ToastApi {\r\n const ctx = useContext(ToasterContext);\r\n\r\n if (!ctx) {\r\n throw new Error(\r\n \"[toast-23] useToast() must be used inside a <Toast23Provider>. \" +\r\n \"Wrap your application root with <Toast23Provider> to fix this.\",\r\n );\r\n }\r\n\r\n return useMemo(() => {\r\n // Base callable โ toast(\"message\", opts?)\r\n const toast = ((message: string | ReactNode, options?: ToastOptions) =>\r\n ctx.addToast(message, options)) as ToastApi;\r\n\r\n // Variant shortcuts\r\n toast.success = (msg, opts) =>\r\n ctx.addToast(msg, { ...opts, variant: \"success\" });\r\n\r\n toast.error = (msg, opts) =>\r\n ctx.addToast(msg, { ...opts, variant: \"error\" });\r\n\r\n toast.warning = (msg, opts) =>\r\n ctx.addToast(msg, { ...opts, variant: \"warning\" });\r\n\r\n toast.info = (msg, opts) => ctx.addToast(msg, { ...opts, variant: \"info\" });\r\n\r\n // Loading shortcut\r\n toast.loading = (msg, opts) =>\r\n ctx.addToast(msg, {\r\n ...opts,\r\n variant: \"loading\" as any,\r\n duration: opts?.duration ?? 0,\r\n dismissible: opts?.dismissible ?? false,\r\n });\r\n\r\n // Custom toast โ no default styles\r\n toast.custom = (content, opts) =>\r\n ctx.addToast(content, { ...opts, variant: \"default\", isCustom: true });\r\n\r\n // Dismiss (with optional id โ omit to dismiss all)\r\n toast.dismiss = (id?: string) => ctx.dismissToast(id);\r\n\r\n // Remove instantly (with optional id โ omit to remove all)\r\n toast.remove = (id?: string) => ctx.removeToast(id);\r\n\r\n // Promise tracking (accepts Promise or () => Promise, optional 3rd arg for toast options)\r\n toast.promise = async <T>(\r\n promiseOrFn: Promise<T> | (() => Promise<T>),\r\n opts: PromiseOptions<T>,\r\n toastOpts?: ToastOptions,\r\n ): Promise<T> => {\r\n const id = ctx.addToast(opts.loading, {\r\n ...toastOpts,\r\n variant: \"loading\" as any,\r\n duration: 0,\r\n dismissible: false,\r\n } as ToastOptions);\r\n\r\n const promise =\r\n typeof promiseOrFn === \"function\" ? promiseOrFn() : promiseOrFn;\r\n\r\n try {\r\n const result = await promise;\r\n const msg =\r\n typeof opts.success === \"function\"\r\n ? opts.success(result)\r\n : opts.success;\r\n ctx.updateToast(id, {\r\n message: msg,\r\n variant: \"success\",\r\n duration: toastOpts?.duration ?? ctx.config.duration,\r\n dismissible: true,\r\n });\r\n return result;\r\n } catch (error) {\r\n const msg =\r\n typeof opts.error === \"function\" ? opts.error(error) : opts.error;\r\n ctx.updateToast(id, {\r\n message: msg,\r\n variant: \"error\",\r\n duration: toastOpts?.duration ?? ctx.config.duration,\r\n dismissible: true,\r\n });\r\n throw error;\r\n }\r\n };\r\n\r\n return toast;\r\n }, [\r\n ctx.addToast,\r\n ctx.updateToast,\r\n ctx.dismissToast,\r\n ctx.removeToast,\r\n ctx.config.duration,\r\n ]);\r\n}\r\n","/**\r\n * toast-23 โ Standalone / Imperative API\r\n *\r\n * Use this when you need toast notifications outside of React (Angular, Vue,\r\n * Svelte, vanilla JS, etc.). It internally bootstraps a minimal React root.\r\n *\r\n * ```ts\r\n * import { createToast23 } from \"toast-23\";\r\n *\r\n * const toast = createToast23({ position: \"top-right\" });\r\n *\r\n * toast.success(\"Saved!\");\r\n * toast.error(\"Something went wrong\");\r\n * toast.dismiss(id);\r\n *\r\n * // Cleanup when done (e.g. on app destroy)\r\n * toast.destroy();\r\n * ```\r\n */\r\n\r\nimport * as React from \"react\";\r\nimport { createRoot, type Root } from \"react-dom/client\";\r\nimport { Toast23Provider } from \"./provider\";\r\nimport { useToast } from \"./use-toast\";\r\nimport type {\r\n ToastPosition,\r\n ToastOptions,\r\n PromiseOptions,\r\n ToastApi,\r\n} from \"./types\";\r\nimport type { ReactNode } from \"react\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface StandaloneOptions {\r\n /** Where on screen toasts appear. @default \"top-right\" */\r\n position?: ToastPosition;\r\n /** Max simultaneous toasts. @default 5 */\r\n maxVisible?: number;\r\n /** Default auto-dismiss duration in ms. @default 5000 */\r\n duration?: number;\r\n}\r\n\r\nexport interface StandaloneToastApi {\r\n /** Show a default toast. Returns the toast id. */\r\n (message: string | ReactNode, options?: ToastOptions): string;\r\n /** Show a success toast. */\r\n success: (message: string, options?: Omit<ToastOptions, \"variant\">) => string;\r\n /** Show an error toast. */\r\n error: (message: string, options?: Omit<ToastOptions, \"variant\">) => string;\r\n /** Show a warning toast. */\r\n warning: (message: string, options?: Omit<ToastOptions, \"variant\">) => string;\r\n /** Show an info toast. */\r\n info: (message: string, options?: Omit<ToastOptions, \"variant\">) => string;\r\n /** Show a loading toast. Returns the toast id for later update. */\r\n loading: (message: string, options?: Omit<ToastOptions, \"variant\">) => string;\r\n /** Show a custom toast with JSX content and no default styles. */\r\n custom: (\r\n content: ReactNode,\r\n options?: Omit<ToastOptions, \"variant\">,\r\n ) => string;\r\n /** Track an async operation with loading โ success / error transitions. */\r\n promise: <T>(\r\n promise: Promise<T> | (() => Promise<T>),\r\n options: PromiseOptions<T>,\r\n toastOptions?: ToastOptions,\r\n ) => Promise<T>;\r\n /** Manually dismiss a toast by id. Omit id to dismiss all. */\r\n dismiss: (id?: string) => void;\r\n /** Instantly remove a toast from DOM (no exit animation). Omit id to remove all. */\r\n remove: (id?: string) => void;\r\n /** Unmount the React root and remove the container from the DOM. */\r\n destroy: () => void;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Bridge component โ captures the useToast API and passes it out\r\n// ---------------------------------------------------------------------------\r\n\r\nlet _resolveApi: ((api: ToastApi) => void) | null = null;\r\n\r\nfunction Bridge() {\r\n const api = useToast();\r\n\r\n // Resolve the promise on first render; update the ref on every render\r\n // so the external caller always has the latest stable API reference.\r\n React.useEffect(() => {\r\n if (_resolveApi) {\r\n _resolveApi(api);\r\n _resolveApi = null;\r\n }\r\n }, [api]);\r\n\r\n // Also store on ref for synchronous access after first mount\r\n\r\n return null;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Factory\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Create a standalone toast API that works outside of React.\r\n *\r\n * Internally mounts a tiny React tree (provider + bridge) into a hidden\r\n * container. Returns a callable toast object with `.success()`, `.error()`, etc.\r\n *\r\n * Call `.destroy()` when your application unmounts to clean up.\r\n */\r\nexport function createToast23(\r\n options: StandaloneOptions = {},\r\n): StandaloneToastApi {\r\n const { position = \"top-right\", maxVisible = 5, duration = 5000 } = options;\r\n\r\n // Create a hidden container\r\n const container = document.createElement(\"div\");\r\n container.setAttribute(\"data-toast23-standalone\", \"\");\r\n container.style.display = \"contents\"; // invisible wrapper\r\n document.body.appendChild(container);\r\n\r\n // We need to wait for React to render before the API is available.\r\n // Use a promise + queue approach so calls before mount are buffered.\r\n let root: Root | null = createRoot(container);\r\n\r\n const apiReady = new Promise<ToastApi>((resolve) => {\r\n _resolveApi = resolve;\r\n });\r\n\r\n // Queue for calls made before React has mounted\r\n type QueuedCall = { method: string; args: unknown[] };\r\n const queue: QueuedCall[] = [];\r\n let resolvedApi: ToastApi | null = null;\r\n\r\n // Flush queued calls once the API is ready\r\n apiReady.then((api) => {\r\n resolvedApi = api;\r\n for (const call of queue) {\r\n if (call.method === \"__call__\") {\r\n (api as any)(...call.args);\r\n } else {\r\n (api as any)[call.method](...call.args);\r\n }\r\n }\r\n queue.length = 0;\r\n });\r\n\r\n // Mount React tree\r\n root.render(\r\n React.createElement(\r\n Toast23Provider,\r\n { position, maxVisible, duration } as any,\r\n React.createElement(Bridge),\r\n ),\r\n );\r\n\r\n // Build the proxy API\r\n const proxyCall = (method: string, ...args: unknown[]): any => {\r\n if (resolvedApi) {\r\n return (resolvedApi as any)[method](...args);\r\n }\r\n queue.push({ method, args });\r\n return \"queued\";\r\n };\r\n\r\n const toast = ((message: string | ReactNode, opts?: ToastOptions) => {\r\n if (resolvedApi) return resolvedApi(message, opts);\r\n queue.push({ method: \"__call__\", args: [message, opts] });\r\n return \"queued\";\r\n }) as StandaloneToastApi;\r\n\r\n toast.success = (msg, opts) => proxyCall(\"success\", msg, opts);\r\n toast.error = (msg, opts) => proxyCall(\"error\", msg, opts);\r\n toast.warning = (msg, opts) => proxyCall(\"warning\", msg, opts);\r\n toast.info = (msg, opts) => proxyCall(\"info\", msg, opts);\r\n toast.loading = (msg, opts) => proxyCall(\"loading\", msg, opts);\r\n toast.custom = (content, opts) => proxyCall(\"custom\", content, opts);\r\n toast.dismiss = (id?) => proxyCall(\"dismiss\", id);\r\n toast.remove = (id?) => proxyCall(\"remove\", id);\r\n\r\n toast.promise = (promise, opts, toastOpts?) => {\r\n if (resolvedApi) return resolvedApi.promise(promise, opts, toastOpts);\r\n // For promises, we need to wait for the API\r\n return apiReady.then((api) => api.promise(promise, opts, toastOpts));\r\n };\r\n\r\n toast.destroy = () => {\r\n if (root) {\r\n root.unmount();\r\n root = null;\r\n }\r\n container.remove();\r\n resolvedApi = null;\r\n };\r\n\r\n return toast;\r\n}\r\n"],"names":["ToasterContext","createContext","toasterReducer","state","action","t","CheckCircleIcon","props","jsxs","jsx","XCircleIcon","AlertTriangleIcon","InfoIcon","XIcon","SpinnerIcon","counter","generateId","cx","args","variantIcon","EXIT_DURATION","MIN_REFILL_DURATION","ToastItem","React","toast","onDismiss","onRemove","hasEntered","setHasEntered","useState","useEffect","raf","delay","timer","isPaused","setIsPaused","remainingRef","useRef","startRef","progress","setProgress","progressTransition","setProgressTransition","rafRef","elapsed","refillDuration","remaining","handleMouseEnter","useCallback","handleMouseLeave","Icon","ToastContainer","position","toasts","maxVisible","ctx","useContext","active","exiting","visible","queuedCount","ALL_POSITIONS","Toast23Provider","children","defaultPosition","defaultDuration","dispatch","useReducer","addToast","message","options","id","updateToast","updates","dismissToast","removeToast","contextValue","useMemo","groupedToasts","groups","pos","useToast","msg","opts","content","promiseOrFn","toastOpts","promise","result","error","_resolveApi","Bridge","api","createToast23","duration","container","root","createRoot","apiReady","resolve","queue","resolvedApi","call","proxyCall","method"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Create a standalone toast API that works outside of React.
|
|
5
|
+
*
|
|
6
|
+
* Internally mounts a tiny React tree (provider + bridge) into a hidden
|
|
7
|
+
* container. Returns a callable toast object with `.success()`, `.error()`, etc.
|
|
8
|
+
*
|
|
9
|
+
* Call `.destroy()` when your application unmounts to clean up.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createToast23(options?: StandaloneOptions): StandaloneToastApi;
|
|
12
|
+
|
|
13
|
+
/** Options for `toast.promise()`. */
|
|
14
|
+
export declare interface PromiseOptions<T> {
|
|
15
|
+
/** Message shown while the promise is pending. */
|
|
16
|
+
loading: string;
|
|
17
|
+
/** Message on fulfillment. Can be a function receiving the resolved value. */
|
|
18
|
+
success: string | ((data: T) => string);
|
|
19
|
+
/** Message on rejection. Can be a function receiving the error. */
|
|
20
|
+
error: string | ((err: unknown) => string);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export declare interface StandaloneOptions {
|
|
24
|
+
/** Where on screen toasts appear. @default "top-right" */
|
|
25
|
+
position?: ToastPosition;
|
|
26
|
+
/** Max simultaneous toasts. @default 5 */
|
|
27
|
+
maxVisible?: number;
|
|
28
|
+
/** Default auto-dismiss duration in ms. @default 5000 */
|
|
29
|
+
duration?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export declare interface StandaloneToastApi {
|
|
33
|
+
/** Show a default toast. Returns the toast id. */
|
|
34
|
+
(message: string | ReactNode, options?: ToastOptions): string;
|
|
35
|
+
/** Show a success toast. */
|
|
36
|
+
success: (message: string, options?: Omit<ToastOptions, "variant">) => string;
|
|
37
|
+
/** Show an error toast. */
|
|
38
|
+
error: (message: string, options?: Omit<ToastOptions, "variant">) => string;
|
|
39
|
+
/** Show a warning toast. */
|
|
40
|
+
warning: (message: string, options?: Omit<ToastOptions, "variant">) => string;
|
|
41
|
+
/** Show an info toast. */
|
|
42
|
+
info: (message: string, options?: Omit<ToastOptions, "variant">) => string;
|
|
43
|
+
/** Show a loading toast. Returns the toast id for later update. */
|
|
44
|
+
loading: (message: string, options?: Omit<ToastOptions, "variant">) => string;
|
|
45
|
+
/** Show a custom toast with JSX content and no default styles. */
|
|
46
|
+
custom: (content: ReactNode, options?: Omit<ToastOptions, "variant">) => string;
|
|
47
|
+
/** Track an async operation with loading โ success / error transitions. */
|
|
48
|
+
promise: <T>(promise: Promise<T> | (() => Promise<T>), options: PromiseOptions<T>, toastOptions?: ToastOptions) => Promise<T>;
|
|
49
|
+
/** Manually dismiss a toast by id. Omit id to dismiss all. */
|
|
50
|
+
dismiss: (id?: string) => void;
|
|
51
|
+
/** Instantly remove a toast from DOM (no exit animation). Omit id to remove all. */
|
|
52
|
+
remove: (id?: string) => void;
|
|
53
|
+
/** Unmount the React root and remove the container from the DOM. */
|
|
54
|
+
destroy: () => void;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export declare const Toast23Provider: React.FC<Toast23ProviderProps>;
|
|
58
|
+
|
|
59
|
+
/** Props for `<Toast23Provider>`. */
|
|
60
|
+
export declare interface Toast23ProviderProps {
|
|
61
|
+
children: ReactNode;
|
|
62
|
+
/** Maximum number of simultaneously visible toasts. @default 5 */
|
|
63
|
+
maxVisible?: number;
|
|
64
|
+
/** Default position on screen. @default "top-right" */
|
|
65
|
+
position?: ToastPosition;
|
|
66
|
+
/** Default auto-dismiss duration in ms. @default 5000 */
|
|
67
|
+
duration?: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The callable toast API returned by `useToast()`.
|
|
72
|
+
*
|
|
73
|
+
* Can be invoked directly โ `toast("hi")` โ or via variant helpers.
|
|
74
|
+
*/
|
|
75
|
+
export declare interface ToastApi {
|
|
76
|
+
(message: string | ReactNode, options?: ToastOptions): string;
|
|
77
|
+
success: (message: string, options?: Omit<ToastOptions, "variant">) => string;
|
|
78
|
+
error: (message: string, options?: Omit<ToastOptions, "variant">) => string;
|
|
79
|
+
warning: (message: string, options?: Omit<ToastOptions, "variant">) => string;
|
|
80
|
+
info: (message: string, options?: Omit<ToastOptions, "variant">) => string;
|
|
81
|
+
/** Show a loading toast. Returns the toast id for later update. */
|
|
82
|
+
loading: (message: string, options?: Omit<ToastOptions, "variant">) => string;
|
|
83
|
+
/** Show a custom toast with JSX content and no default styles. */
|
|
84
|
+
custom: (content: ReactNode, options?: Omit<ToastOptions, "variant">) => string;
|
|
85
|
+
/** Track an async operation with loading โ success / error transitions. */
|
|
86
|
+
promise: <T>(promise: Promise<T> | (() => Promise<T>), options: PromiseOptions<T>, toastOptions?: ToastOptions) => Promise<T>;
|
|
87
|
+
/** Manually dismiss a toast by id. Omit id to dismiss all. */
|
|
88
|
+
dismiss: (id?: string) => void;
|
|
89
|
+
/** Instantly remove a toast from DOM (no exit animation). Omit id to remove all. */
|
|
90
|
+
remove: (id?: string) => void;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Options accepted when creating a toast. */
|
|
94
|
+
export declare interface ToastOptions {
|
|
95
|
+
/** Provide a fixed id to update an existing toast or prevent duplicates. */
|
|
96
|
+
id?: string;
|
|
97
|
+
/** Optional heading displayed above the message. */
|
|
98
|
+
title?: string;
|
|
99
|
+
/** Visual variant. Defaults to `"default"`. */
|
|
100
|
+
variant?: ToastVariant;
|
|
101
|
+
/** Auto-dismiss duration in ms. `0` = persistent. Defaults to provider value. */
|
|
102
|
+
duration?: number;
|
|
103
|
+
/** Screen position override. Defaults to provider value. */
|
|
104
|
+
position?: ToastPosition;
|
|
105
|
+
/** Whether the user can manually dismiss the toast. Defaults to `true`. */
|
|
106
|
+
dismissible?: boolean;
|
|
107
|
+
/** Delay in ms before removing from DOM after dismiss (for exit animation). @default 1000 */
|
|
108
|
+
removeDelay?: number;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Screen position where toasts are rendered. */
|
|
112
|
+
export declare type ToastPosition = "top-right" | "top-left" | "top-center" | "bottom-right" | "bottom-left" | "bottom-center";
|
|
113
|
+
|
|
114
|
+
/** Visual variant of a toast notification. */
|
|
115
|
+
export declare type ToastVariant = "success" | "error" | "warning" | "info" | "default";
|
|
116
|
+
|
|
117
|
+
export declare function useToast(): ToastApi;
|
|
118
|
+
|
|
119
|
+
export { }
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
import { jsx as c, jsxs as h } from "react/jsx-runtime";
|
|
2
|
+
import * as E from "react";
|
|
3
|
+
import { createContext as B, useState as k, useEffect as I, useRef as M, useCallback as T, useContext as D, useReducer as q, useMemo as N } from "react";
|
|
4
|
+
import { createRoot as W } from "react-dom/client";
|
|
5
|
+
const A = B(null);
|
|
6
|
+
function j(e, s) {
|
|
7
|
+
switch (s.type) {
|
|
8
|
+
case "ADD":
|
|
9
|
+
return [...e, s.toast];
|
|
10
|
+
case "UPSERT":
|
|
11
|
+
return e.some((r) => r.id === s.toast.id) ? e.map(
|
|
12
|
+
(r) => r.id === s.toast.id ? {
|
|
13
|
+
...r,
|
|
14
|
+
...s.toast,
|
|
15
|
+
version: r.version + 1,
|
|
16
|
+
isExiting: !1
|
|
17
|
+
} : r
|
|
18
|
+
) : [...e, s.toast];
|
|
19
|
+
case "UPDATE":
|
|
20
|
+
return e.map(
|
|
21
|
+
(t) => t.id === s.id ? {
|
|
22
|
+
...t,
|
|
23
|
+
...s.updates,
|
|
24
|
+
// Bump version so progress bar restarts
|
|
25
|
+
version: t.version + 1,
|
|
26
|
+
// If the toast was exiting, cancel exit on update
|
|
27
|
+
isExiting: !1
|
|
28
|
+
} : t
|
|
29
|
+
);
|
|
30
|
+
case "DISMISS":
|
|
31
|
+
return s.id ? e.map(
|
|
32
|
+
(t) => t.id === s.id ? { ...t, isExiting: !0 } : t
|
|
33
|
+
) : e.map((t) => ({ ...t, isExiting: !0 }));
|
|
34
|
+
case "REMOVE":
|
|
35
|
+
return s.id ? e.filter((t) => t.id !== s.id) : [];
|
|
36
|
+
default:
|
|
37
|
+
return e;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const U = (e) => /* @__PURE__ */ h(
|
|
41
|
+
"svg",
|
|
42
|
+
{
|
|
43
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
44
|
+
viewBox: "0 0 24 24",
|
|
45
|
+
width: "1.25em",
|
|
46
|
+
height: "1.25em",
|
|
47
|
+
fill: "none",
|
|
48
|
+
...e,
|
|
49
|
+
children: [
|
|
50
|
+
/* @__PURE__ */ c("circle", { cx: 12, cy: 12, r: 10, fill: "currentColor" }),
|
|
51
|
+
/* @__PURE__ */ c(
|
|
52
|
+
"path",
|
|
53
|
+
{
|
|
54
|
+
d: "M8 12.5l2.5 2.5 5-5",
|
|
55
|
+
stroke: "#fff",
|
|
56
|
+
strokeWidth: 2,
|
|
57
|
+
strokeLinecap: "round",
|
|
58
|
+
strokeLinejoin: "round",
|
|
59
|
+
fill: "none"
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
), F = (e) => /* @__PURE__ */ h(
|
|
65
|
+
"svg",
|
|
66
|
+
{
|
|
67
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
68
|
+
viewBox: "0 0 24 24",
|
|
69
|
+
width: "1.25em",
|
|
70
|
+
height: "1.25em",
|
|
71
|
+
fill: "none",
|
|
72
|
+
...e,
|
|
73
|
+
children: [
|
|
74
|
+
/* @__PURE__ */ c("circle", { cx: 12, cy: 12, r: 10, fill: "currentColor" }),
|
|
75
|
+
/* @__PURE__ */ c(
|
|
76
|
+
"line",
|
|
77
|
+
{
|
|
78
|
+
x1: 12,
|
|
79
|
+
y1: 8,
|
|
80
|
+
x2: 12,
|
|
81
|
+
y2: 13,
|
|
82
|
+
stroke: "#fff",
|
|
83
|
+
strokeWidth: 2,
|
|
84
|
+
strokeLinecap: "round"
|
|
85
|
+
}
|
|
86
|
+
),
|
|
87
|
+
/* @__PURE__ */ c("circle", { cx: 12, cy: 16, r: 1, fill: "#fff" })
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
), X = (e) => /* @__PURE__ */ h(
|
|
91
|
+
"svg",
|
|
92
|
+
{
|
|
93
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
94
|
+
viewBox: "0 0 24 24",
|
|
95
|
+
width: "1.25em",
|
|
96
|
+
height: "1.25em",
|
|
97
|
+
fill: "none",
|
|
98
|
+
...e,
|
|
99
|
+
children: [
|
|
100
|
+
/* @__PURE__ */ c(
|
|
101
|
+
"path",
|
|
102
|
+
{
|
|
103
|
+
d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z",
|
|
104
|
+
fill: "currentColor"
|
|
105
|
+
}
|
|
106
|
+
),
|
|
107
|
+
/* @__PURE__ */ c(
|
|
108
|
+
"line",
|
|
109
|
+
{
|
|
110
|
+
x1: 12,
|
|
111
|
+
y1: 9.5,
|
|
112
|
+
x2: 12,
|
|
113
|
+
y2: 14,
|
|
114
|
+
stroke: "#fff",
|
|
115
|
+
strokeWidth: 2,
|
|
116
|
+
strokeLinecap: "round"
|
|
117
|
+
}
|
|
118
|
+
),
|
|
119
|
+
/* @__PURE__ */ c("circle", { cx: 12, cy: 17, r: 1, fill: "#fff" })
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
), L = (e) => /* @__PURE__ */ h(
|
|
123
|
+
"svg",
|
|
124
|
+
{
|
|
125
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
126
|
+
viewBox: "0 0 24 24",
|
|
127
|
+
width: "1.25em",
|
|
128
|
+
height: "1.25em",
|
|
129
|
+
fill: "none",
|
|
130
|
+
...e,
|
|
131
|
+
children: [
|
|
132
|
+
/* @__PURE__ */ c("circle", { cx: 12, cy: 12, r: 10, fill: "currentColor" }),
|
|
133
|
+
/* @__PURE__ */ c(
|
|
134
|
+
"line",
|
|
135
|
+
{
|
|
136
|
+
x1: 12,
|
|
137
|
+
y1: 11,
|
|
138
|
+
x2: 12,
|
|
139
|
+
y2: 16,
|
|
140
|
+
stroke: "#fff",
|
|
141
|
+
strokeWidth: 2,
|
|
142
|
+
strokeLinecap: "round"
|
|
143
|
+
}
|
|
144
|
+
),
|
|
145
|
+
/* @__PURE__ */ c("circle", { cx: 12, cy: 8, r: 1, fill: "#fff" })
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
), z = (e) => /* @__PURE__ */ h(
|
|
149
|
+
"svg",
|
|
150
|
+
{
|
|
151
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
152
|
+
viewBox: "0 0 24 24",
|
|
153
|
+
fill: "none",
|
|
154
|
+
stroke: "currentColor",
|
|
155
|
+
strokeWidth: 2,
|
|
156
|
+
strokeLinecap: "round",
|
|
157
|
+
strokeLinejoin: "round",
|
|
158
|
+
width: "0.875em",
|
|
159
|
+
height: "0.875em",
|
|
160
|
+
...e,
|
|
161
|
+
children: [
|
|
162
|
+
/* @__PURE__ */ c("line", { x1: 18, y1: 6, x2: 6, y2: 18 }),
|
|
163
|
+
/* @__PURE__ */ c("line", { x1: 6, y1: 6, x2: 18, y2: 18 })
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
), H = (e) => /* @__PURE__ */ c(
|
|
167
|
+
"svg",
|
|
168
|
+
{
|
|
169
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
170
|
+
viewBox: "0 0 24 24",
|
|
171
|
+
fill: "none",
|
|
172
|
+
stroke: "currentColor",
|
|
173
|
+
strokeWidth: 2,
|
|
174
|
+
strokeLinecap: "round",
|
|
175
|
+
strokeLinejoin: "round",
|
|
176
|
+
width: "1.25em",
|
|
177
|
+
height: "1.25em",
|
|
178
|
+
className: "toast23-spinner",
|
|
179
|
+
...e,
|
|
180
|
+
children: /* @__PURE__ */ c("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
let V = 0;
|
|
184
|
+
function G() {
|
|
185
|
+
return `t23-${++V}-${Math.random().toString(36).slice(2, 9)}`;
|
|
186
|
+
}
|
|
187
|
+
function w(...e) {
|
|
188
|
+
return e.filter(Boolean).join(" ");
|
|
189
|
+
}
|
|
190
|
+
const J = {
|
|
191
|
+
success: U,
|
|
192
|
+
error: F,
|
|
193
|
+
warning: X,
|
|
194
|
+
info: L,
|
|
195
|
+
default: L,
|
|
196
|
+
loading: H
|
|
197
|
+
}, K = 300, Q = 200, S = E.memo(
|
|
198
|
+
({ toast: e, onDismiss: s, onRemove: t }) => {
|
|
199
|
+
const [r, l] = k(!1);
|
|
200
|
+
I(() => {
|
|
201
|
+
const x = requestAnimationFrame(() => l(!0));
|
|
202
|
+
return () => cancelAnimationFrame(x);
|
|
203
|
+
}, []), I(() => {
|
|
204
|
+
if (!e.isExiting) return;
|
|
205
|
+
const x = e.removeDelay ?? K, b = setTimeout(() => t(e.id), x);
|
|
206
|
+
return () => clearTimeout(b);
|
|
207
|
+
}, [e.isExiting, e.id, e.removeDelay, t]);
|
|
208
|
+
const [u, f] = k(!1), d = M(e.duration), a = M(0), [g, m] = k(100), [o, i] = k("none"), n = M(0);
|
|
209
|
+
I(() => {
|
|
210
|
+
d.current = e.duration, m(100), i("none");
|
|
211
|
+
}, [e.version, e.duration]), I(() => {
|
|
212
|
+
if (e.duration <= 0 || e.variant === "loading" || !r || e.isExiting)
|
|
213
|
+
return;
|
|
214
|
+
if (u) {
|
|
215
|
+
const R = Date.now() - a.current;
|
|
216
|
+
d.current = Math.max(0, d.current - R);
|
|
217
|
+
const $ = Math.max(Q, R);
|
|
218
|
+
i(`width ${$}ms ease-out`), m(100);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
a.current = Date.now();
|
|
222
|
+
const x = d.current;
|
|
223
|
+
n.current = requestAnimationFrame(() => {
|
|
224
|
+
i(`width ${x}ms linear`), m(0);
|
|
225
|
+
});
|
|
226
|
+
const b = setTimeout(() => {
|
|
227
|
+
s(e.id);
|
|
228
|
+
}, x);
|
|
229
|
+
return () => {
|
|
230
|
+
clearTimeout(b), cancelAnimationFrame(n.current);
|
|
231
|
+
};
|
|
232
|
+
}, [
|
|
233
|
+
u,
|
|
234
|
+
r,
|
|
235
|
+
e.isExiting,
|
|
236
|
+
e.duration,
|
|
237
|
+
e.variant,
|
|
238
|
+
e.id,
|
|
239
|
+
e.version,
|
|
240
|
+
s
|
|
241
|
+
]);
|
|
242
|
+
const v = T(() => f(!0), []), y = T(() => f(!1), []), p = J[e.variant] ?? L;
|
|
243
|
+
return e.isCustom ? /* @__PURE__ */ c(
|
|
244
|
+
"div",
|
|
245
|
+
{
|
|
246
|
+
className: w(
|
|
247
|
+
"toast23-item toast23-item--custom",
|
|
248
|
+
!r && "toast23-item--entering",
|
|
249
|
+
e.isExiting && "toast23-item--exiting"
|
|
250
|
+
),
|
|
251
|
+
role: "alert",
|
|
252
|
+
"aria-live": "polite",
|
|
253
|
+
"aria-atomic": "true",
|
|
254
|
+
onMouseEnter: v,
|
|
255
|
+
onMouseLeave: y,
|
|
256
|
+
children: e.message
|
|
257
|
+
}
|
|
258
|
+
) : /* @__PURE__ */ h(
|
|
259
|
+
"div",
|
|
260
|
+
{
|
|
261
|
+
className: w(
|
|
262
|
+
"toast23-item",
|
|
263
|
+
`toast23-item--${e.variant}`,
|
|
264
|
+
!r && "toast23-item--entering",
|
|
265
|
+
e.isExiting && "toast23-item--exiting"
|
|
266
|
+
),
|
|
267
|
+
role: "alert",
|
|
268
|
+
"aria-live": e.variant === "error" ? "assertive" : "polite",
|
|
269
|
+
"aria-atomic": "true",
|
|
270
|
+
onMouseEnter: v,
|
|
271
|
+
onMouseLeave: y,
|
|
272
|
+
children: [
|
|
273
|
+
/* @__PURE__ */ c("span", { className: w("toast23-icon", `toast23-icon--${e.variant}`), children: /* @__PURE__ */ c(p, {}) }),
|
|
274
|
+
/* @__PURE__ */ h("div", { className: "toast23-content", children: [
|
|
275
|
+
e.title && /* @__PURE__ */ c("div", { className: "toast23-title", children: e.title }),
|
|
276
|
+
/* @__PURE__ */ c(
|
|
277
|
+
"div",
|
|
278
|
+
{
|
|
279
|
+
className: w(
|
|
280
|
+
"toast23-message",
|
|
281
|
+
e.title && "toast23-message--with-title"
|
|
282
|
+
),
|
|
283
|
+
children: e.message
|
|
284
|
+
}
|
|
285
|
+
)
|
|
286
|
+
] }),
|
|
287
|
+
e.dismissible && /* @__PURE__ */ c(
|
|
288
|
+
"button",
|
|
289
|
+
{
|
|
290
|
+
type: "button",
|
|
291
|
+
className: "toast23-dismiss",
|
|
292
|
+
onClick: () => s(e.id),
|
|
293
|
+
"aria-label": "Dismiss notification",
|
|
294
|
+
children: /* @__PURE__ */ c(z, {})
|
|
295
|
+
}
|
|
296
|
+
),
|
|
297
|
+
e.duration > 0 && e.variant !== "loading" && /* @__PURE__ */ c(
|
|
298
|
+
"div",
|
|
299
|
+
{
|
|
300
|
+
className: w(
|
|
301
|
+
"toast23-progress",
|
|
302
|
+
`toast23-progress--${e.variant}`
|
|
303
|
+
),
|
|
304
|
+
style: {
|
|
305
|
+
width: `${g}%`,
|
|
306
|
+
transition: o
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
)
|
|
310
|
+
]
|
|
311
|
+
}
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
);
|
|
315
|
+
S.displayName = "ToastItem";
|
|
316
|
+
const _ = E.memo(
|
|
317
|
+
({ position: e, toasts: s, maxVisible: t }) => {
|
|
318
|
+
const r = D(A);
|
|
319
|
+
if (!r) return null;
|
|
320
|
+
const l = s.filter((a) => !a.isExiting), u = s.filter((a) => a.isExiting), f = [...l.slice(0, t), ...u];
|
|
321
|
+
if (f.length === 0) return null;
|
|
322
|
+
const d = Math.max(0, l.length - t);
|
|
323
|
+
return /* @__PURE__ */ h(
|
|
324
|
+
"div",
|
|
325
|
+
{
|
|
326
|
+
className: w("toast23-container", `toast23-container--${e}`),
|
|
327
|
+
"aria-label": "Notifications",
|
|
328
|
+
role: "region",
|
|
329
|
+
children: [
|
|
330
|
+
f.map((a) => /* @__PURE__ */ c(
|
|
331
|
+
S,
|
|
332
|
+
{
|
|
333
|
+
toast: a,
|
|
334
|
+
onDismiss: r.dismissToast,
|
|
335
|
+
onRemove: r.removeToast
|
|
336
|
+
},
|
|
337
|
+
a.id
|
|
338
|
+
)),
|
|
339
|
+
d > 0 && /* @__PURE__ */ h("div", { className: "toast23-queue-badge", "aria-live": "polite", children: [
|
|
340
|
+
"+",
|
|
341
|
+
d,
|
|
342
|
+
" more"
|
|
343
|
+
] })
|
|
344
|
+
]
|
|
345
|
+
}
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
);
|
|
349
|
+
_.displayName = "ToastContainer";
|
|
350
|
+
const Y = [
|
|
351
|
+
"top-right",
|
|
352
|
+
"top-left",
|
|
353
|
+
"top-center",
|
|
354
|
+
"bottom-right",
|
|
355
|
+
"bottom-left",
|
|
356
|
+
"bottom-center"
|
|
357
|
+
], P = ({
|
|
358
|
+
children: e,
|
|
359
|
+
maxVisible: s = 5,
|
|
360
|
+
position: t = "top-right",
|
|
361
|
+
duration: r = 5e3
|
|
362
|
+
}) => {
|
|
363
|
+
const [l, u] = q(j, []), f = T(
|
|
364
|
+
(i, n) => {
|
|
365
|
+
const v = (n == null ? void 0 : n.id) ?? G(), y = {
|
|
366
|
+
id: v,
|
|
367
|
+
message: i,
|
|
368
|
+
title: n == null ? void 0 : n.title,
|
|
369
|
+
variant: (n == null ? void 0 : n.variant) ?? "default",
|
|
370
|
+
duration: (n == null ? void 0 : n.duration) ?? r,
|
|
371
|
+
position: (n == null ? void 0 : n.position) ?? t,
|
|
372
|
+
dismissible: (n == null ? void 0 : n.dismissible) ?? !0,
|
|
373
|
+
removeDelay: (n == null ? void 0 : n.removeDelay) ?? 1e3,
|
|
374
|
+
isExiting: !1,
|
|
375
|
+
createdAt: Date.now(),
|
|
376
|
+
version: 0,
|
|
377
|
+
isCustom: n == null ? void 0 : n.isCustom
|
|
378
|
+
};
|
|
379
|
+
return n != null && n.id ? u({ type: "UPSERT", toast: y }) : u({ type: "ADD", toast: y }), v;
|
|
380
|
+
},
|
|
381
|
+
[r, t]
|
|
382
|
+
), d = T(
|
|
383
|
+
(i, n) => {
|
|
384
|
+
u({ type: "UPDATE", id: i, updates: n });
|
|
385
|
+
},
|
|
386
|
+
[]
|
|
387
|
+
), a = T((i) => {
|
|
388
|
+
u({ type: "DISMISS", id: i });
|
|
389
|
+
}, []), g = T((i) => {
|
|
390
|
+
u({ type: "REMOVE", id: i });
|
|
391
|
+
}, []), m = N(
|
|
392
|
+
() => ({
|
|
393
|
+
addToast: f,
|
|
394
|
+
updateToast: d,
|
|
395
|
+
dismissToast: a,
|
|
396
|
+
removeToast: g,
|
|
397
|
+
config: {
|
|
398
|
+
maxVisible: s,
|
|
399
|
+
position: t,
|
|
400
|
+
duration: r
|
|
401
|
+
}
|
|
402
|
+
}),
|
|
403
|
+
[
|
|
404
|
+
f,
|
|
405
|
+
d,
|
|
406
|
+
a,
|
|
407
|
+
g,
|
|
408
|
+
s,
|
|
409
|
+
t,
|
|
410
|
+
r
|
|
411
|
+
]
|
|
412
|
+
), o = N(() => {
|
|
413
|
+
const i = {
|
|
414
|
+
"top-right": [],
|
|
415
|
+
"top-left": [],
|
|
416
|
+
"top-center": [],
|
|
417
|
+
"bottom-right": [],
|
|
418
|
+
"bottom-left": [],
|
|
419
|
+
"bottom-center": []
|
|
420
|
+
};
|
|
421
|
+
for (const n of l)
|
|
422
|
+
i[n.position].push(n);
|
|
423
|
+
return i;
|
|
424
|
+
}, [l]);
|
|
425
|
+
return /* @__PURE__ */ h(A.Provider, { value: m, children: [
|
|
426
|
+
e,
|
|
427
|
+
Y.map(
|
|
428
|
+
(i) => o[i].length > 0 ? /* @__PURE__ */ c(
|
|
429
|
+
_,
|
|
430
|
+
{
|
|
431
|
+
position: i,
|
|
432
|
+
toasts: o[i],
|
|
433
|
+
maxVisible: s
|
|
434
|
+
},
|
|
435
|
+
i
|
|
436
|
+
) : null
|
|
437
|
+
)
|
|
438
|
+
] });
|
|
439
|
+
};
|
|
440
|
+
P.displayName = "Toast23Provider";
|
|
441
|
+
function Z() {
|
|
442
|
+
const e = D(A);
|
|
443
|
+
if (!e)
|
|
444
|
+
throw new Error(
|
|
445
|
+
"[toast-23] useToast() must be used inside a <Toast23Provider>. Wrap your application root with <Toast23Provider> to fix this."
|
|
446
|
+
);
|
|
447
|
+
return N(() => {
|
|
448
|
+
const s = (t, r) => e.addToast(t, r);
|
|
449
|
+
return s.success = (t, r) => e.addToast(t, { ...r, variant: "success" }), s.error = (t, r) => e.addToast(t, { ...r, variant: "error" }), s.warning = (t, r) => e.addToast(t, { ...r, variant: "warning" }), s.info = (t, r) => e.addToast(t, { ...r, variant: "info" }), s.loading = (t, r) => e.addToast(t, {
|
|
450
|
+
...r,
|
|
451
|
+
variant: "loading",
|
|
452
|
+
duration: (r == null ? void 0 : r.duration) ?? 0,
|
|
453
|
+
dismissible: (r == null ? void 0 : r.dismissible) ?? !1
|
|
454
|
+
}), s.custom = (t, r) => e.addToast(t, { ...r, variant: "default", isCustom: !0 }), s.dismiss = (t) => e.dismissToast(t), s.remove = (t) => e.removeToast(t), s.promise = async (t, r, l) => {
|
|
455
|
+
const u = e.addToast(r.loading, {
|
|
456
|
+
...l,
|
|
457
|
+
variant: "loading",
|
|
458
|
+
duration: 0,
|
|
459
|
+
dismissible: !1
|
|
460
|
+
}), f = typeof t == "function" ? t() : t;
|
|
461
|
+
try {
|
|
462
|
+
const d = await f, a = typeof r.success == "function" ? r.success(d) : r.success;
|
|
463
|
+
return e.updateToast(u, {
|
|
464
|
+
message: a,
|
|
465
|
+
variant: "success",
|
|
466
|
+
duration: (l == null ? void 0 : l.duration) ?? e.config.duration,
|
|
467
|
+
dismissible: !0
|
|
468
|
+
}), d;
|
|
469
|
+
} catch (d) {
|
|
470
|
+
const a = typeof r.error == "function" ? r.error(d) : r.error;
|
|
471
|
+
throw e.updateToast(u, {
|
|
472
|
+
message: a,
|
|
473
|
+
variant: "error",
|
|
474
|
+
duration: (l == null ? void 0 : l.duration) ?? e.config.duration,
|
|
475
|
+
dismissible: !0
|
|
476
|
+
}), d;
|
|
477
|
+
}
|
|
478
|
+
}, s;
|
|
479
|
+
}, [
|
|
480
|
+
e.addToast,
|
|
481
|
+
e.updateToast,
|
|
482
|
+
e.dismissToast,
|
|
483
|
+
e.removeToast,
|
|
484
|
+
e.config.duration
|
|
485
|
+
]);
|
|
486
|
+
}
|
|
487
|
+
let C = null;
|
|
488
|
+
function O() {
|
|
489
|
+
const e = Z();
|
|
490
|
+
return E.useEffect(() => {
|
|
491
|
+
C && (C(e), C = null);
|
|
492
|
+
}, [e]), null;
|
|
493
|
+
}
|
|
494
|
+
function ie(e = {}) {
|
|
495
|
+
const { position: s = "top-right", maxVisible: t = 5, duration: r = 5e3 } = e, l = document.createElement("div");
|
|
496
|
+
l.setAttribute("data-toast23-standalone", ""), l.style.display = "contents", document.body.appendChild(l);
|
|
497
|
+
let u = W(l);
|
|
498
|
+
const f = new Promise((o) => {
|
|
499
|
+
C = o;
|
|
500
|
+
}), d = [];
|
|
501
|
+
let a = null;
|
|
502
|
+
f.then((o) => {
|
|
503
|
+
a = o;
|
|
504
|
+
for (const i of d)
|
|
505
|
+
i.method === "__call__" ? o(...i.args) : o[i.method](...i.args);
|
|
506
|
+
d.length = 0;
|
|
507
|
+
}), u.render(
|
|
508
|
+
E.createElement(
|
|
509
|
+
P,
|
|
510
|
+
{ position: s, maxVisible: t, duration: r },
|
|
511
|
+
E.createElement(O)
|
|
512
|
+
)
|
|
513
|
+
);
|
|
514
|
+
const g = (o, ...i) => a ? a[o](...i) : (d.push({ method: o, args: i }), "queued"), m = (o, i) => a ? a(o, i) : (d.push({ method: "__call__", args: [o, i] }), "queued");
|
|
515
|
+
return m.success = (o, i) => g("success", o, i), m.error = (o, i) => g("error", o, i), m.warning = (o, i) => g("warning", o, i), m.info = (o, i) => g("info", o, i), m.loading = (o, i) => g("loading", o, i), m.custom = (o, i) => g("custom", o, i), m.dismiss = (o) => g("dismiss", o), m.remove = (o) => g("remove", o), m.promise = (o, i, n) => a ? a.promise(o, i, n) : f.then((v) => v.promise(o, i, n)), m.destroy = () => {
|
|
516
|
+
u && (u.unmount(), u = null), l.remove(), a = null;
|
|
517
|
+
}, m;
|
|
518
|
+
}
|
|
519
|
+
export {
|
|
520
|
+
P as Toast23Provider,
|
|
521
|
+
ie as createToast23,
|
|
522
|
+
Z as useToast
|
|
523
|
+
};
|
|
524
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/context.tsx","../src/icons.tsx","../src/utils.ts","../src/toast-item.tsx","../src/toast-container.tsx","../src/provider.tsx","../src/use-toast.ts","../src/standalone.ts"],"sourcesContent":["/**\r\n * toast-23 โ React Context & Reducer\r\n */\r\n\r\nimport { createContext } from \"react\";\r\nimport type {\r\n InternalToast,\r\n ToasterAction,\r\n ToasterContextValue,\r\n} from \"./types\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Context โ consumed by useToast() and internal components\r\n// ---------------------------------------------------------------------------\r\n\r\nexport const ToasterContext = createContext<ToasterContextValue | null>(null);\r\n\r\n// ---------------------------------------------------------------------------\r\n// Reducer โ pure state transitions for the toast queue\r\n// ---------------------------------------------------------------------------\r\n\r\nexport function toasterReducer(\r\n state: InternalToast[],\r\n action: ToasterAction,\r\n): InternalToast[] {\r\n switch (action.type) {\r\n case \"ADD\":\r\n return [...state, action.toast];\r\n\r\n case \"UPSERT\": {\r\n const exists = state.some((t) => t.id === action.toast.id);\r\n if (exists) {\r\n return state.map((t) =>\r\n t.id === action.toast.id\r\n ? {\r\n ...t,\r\n ...action.toast,\r\n version: t.version + 1,\r\n isExiting: false,\r\n }\r\n : t,\r\n );\r\n }\r\n return [...state, action.toast];\r\n }\r\n\r\n case \"UPDATE\":\r\n return state.map((t) =>\r\n t.id === action.id\r\n ? {\r\n ...t,\r\n ...action.updates,\r\n // Bump version so progress bar restarts\r\n version: t.version + 1,\r\n // If the toast was exiting, cancel exit on update\r\n isExiting: false,\r\n }\r\n : t,\r\n );\r\n\r\n case \"DISMISS\":\r\n // Omit id โ dismiss all\r\n if (!action.id) {\r\n return state.map((t) => ({ ...t, isExiting: true }));\r\n }\r\n return state.map((t) =>\r\n t.id === action.id ? { ...t, isExiting: true } : t,\r\n );\r\n\r\n case \"REMOVE\":\r\n // Omit id โ remove all instantly\r\n if (!action.id) return [];\r\n return state.filter((t) => t.id !== action.id);\r\n\r\n default:\r\n return state;\r\n }\r\n}\r\n","/**\r\n * toast-23 โ Inline SVG Icons (Filled style)\r\n *\r\n * Solid colored circles/triangles with white inner symbols,\r\n * matching the visual design reference.\r\n */\r\n\r\nimport type { SVGProps, FC } from \"react\";\r\n\r\ntype IconProps = SVGProps<SVGSVGElement>;\r\n\r\n/** Green filled circle with white checkmark */\r\nexport const CheckCircleIcon: FC<IconProps> = (props: IconProps) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n width=\"1.25em\"\r\n height=\"1.25em\"\r\n fill=\"none\"\r\n {...props}\r\n >\r\n <circle cx={12} cy={12} r={10} fill=\"currentColor\" />\r\n <path\r\n d=\"M8 12.5l2.5 2.5 5-5\"\r\n stroke=\"#fff\"\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n fill=\"none\"\r\n />\r\n </svg>\r\n);\r\n\r\n/** Red filled circle with white exclamation */\r\nexport const XCircleIcon: FC<IconProps> = (props: IconProps) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n width=\"1.25em\"\r\n height=\"1.25em\"\r\n fill=\"none\"\r\n {...props}\r\n >\r\n <circle cx={12} cy={12} r={10} fill=\"currentColor\" />\r\n <line\r\n x1={12}\r\n y1={8}\r\n x2={12}\r\n y2={13}\r\n stroke=\"#fff\"\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n />\r\n <circle cx={12} cy={16} r={1} fill=\"#fff\" />\r\n </svg>\r\n);\r\n\r\n/** Yellow filled triangle with white exclamation */\r\nexport const AlertTriangleIcon: FC<IconProps> = (props: IconProps) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n width=\"1.25em\"\r\n height=\"1.25em\"\r\n fill=\"none\"\r\n {...props}\r\n >\r\n <path\r\n d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"\r\n fill=\"currentColor\"\r\n />\r\n <line\r\n x1={12}\r\n y1={9.5}\r\n x2={12}\r\n y2={14}\r\n stroke=\"#fff\"\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n />\r\n <circle cx={12} cy={17} r={1} fill=\"#fff\" />\r\n </svg>\r\n);\r\n\r\n/** Blue filled circle with white \"i\" */\r\nexport const InfoIcon: FC<IconProps> = (props: IconProps) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n width=\"1.25em\"\r\n height=\"1.25em\"\r\n fill=\"none\"\r\n {...props}\r\n >\r\n <circle cx={12} cy={12} r={10} fill=\"currentColor\" />\r\n <line\r\n x1={12}\r\n y1={11}\r\n x2={12}\r\n y2={16}\r\n stroke=\"#fff\"\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n />\r\n <circle cx={12} cy={8} r={1} fill=\"#fff\" />\r\n </svg>\r\n);\r\n\r\n/** Thin X icon for dismiss button */\r\nexport const XIcon: FC<IconProps> = (props: IconProps) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n width=\"0.875em\"\r\n height=\"0.875em\"\r\n {...props}\r\n >\r\n <line x1={18} y1={6} x2={6} y2={18} />\r\n <line x1={6} y1={6} x2={18} y2={18} />\r\n </svg>\r\n);\r\n\r\n/** CSS-only loading spinner */\r\nexport const SpinnerIcon: FC<IconProps> = (props: IconProps) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n width=\"1.25em\"\r\n height=\"1.25em\"\r\n className=\"toast23-spinner\"\r\n {...props}\r\n >\r\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\r\n </svg>\r\n);\r\n","/**\r\n * toast-23 โ Utility helpers\r\n */\r\n\r\nlet counter = 0;\r\n\r\n/**\r\n * Generate a unique toast id.\r\n * Works in SSR (no dependency on `crypto`).\r\n */\r\nexport function generateId(): string {\r\n return `t23-${++counter}-${Math.random().toString(36).slice(2, 9)}`;\r\n}\r\n\r\n/**\r\n * Deterministic class-name builder (replaces clsx dependency).\r\n */\r\nexport function cx(...args: (string | false | null | undefined | 0)[]): string {\r\n return args.filter(Boolean).join(\" \");\r\n}\r\n","/**\r\n * toast-23 โ Individual Toast Component\r\n *\r\n * Manages its own enter / exit CSS transitions and auto-dismiss timer.\r\n * Progress bar is JS-driven so it can reverse (refill) on hover.\r\n */\r\n\r\n\"use client\";\r\n\r\nimport * as React from \"react\";\r\nimport { useCallback, useEffect, useRef, useState } from \"react\";\r\nimport type { InternalToast } from \"./types\";\r\nimport {\r\n CheckCircleIcon,\r\n XCircleIcon,\r\n AlertTriangleIcon,\r\n InfoIcon,\r\n SpinnerIcon,\r\n XIcon,\r\n} from \"./icons\";\r\nimport { cx } from \"./utils\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Icon map\r\n// ---------------------------------------------------------------------------\r\n\r\nconst variantIcon: Record<string, React.FC<React.SVGProps<SVGSVGElement>>> = {\r\n success: CheckCircleIcon,\r\n error: XCircleIcon,\r\n warning: AlertTriangleIcon,\r\n info: InfoIcon,\r\n default: InfoIcon,\r\n loading: SpinnerIcon,\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Component\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface ToastItemProps {\r\n toast: InternalToast;\r\n onDismiss: (id: string) => void;\r\n onRemove: (id: string) => void;\r\n}\r\n\r\nconst EXIT_DURATION = 300; // ms โ must match CSS transition duration\r\nconst MIN_REFILL_DURATION = 200; // ms โ minimum refill time so very short hovers aren't instant\r\n\r\nexport const ToastItem: React.FC<ToastItemProps> = React.memo(\r\n ({ toast, onDismiss, onRemove }) => {\r\n // ----- animation state -----\r\n const [hasEntered, setHasEntered] = useState(false);\r\n\r\n // Trigger enter transition on next frame\r\n useEffect(() => {\r\n const raf = requestAnimationFrame(() => setHasEntered(true));\r\n return () => cancelAnimationFrame(raf);\r\n }, []);\r\n\r\n // When the provider marks the toast as exiting, wait for the CSS\r\n // transition to finish then actually remove it from state.\r\n useEffect(() => {\r\n if (!toast.isExiting) return;\r\n const delay = toast.removeDelay ?? EXIT_DURATION;\r\n const timer = setTimeout(() => onRemove(toast.id), delay);\r\n return () => clearTimeout(timer);\r\n }, [toast.isExiting, toast.id, toast.removeDelay, onRemove]);\r\n\r\n // ----- auto-dismiss timer with hover-pause -----\r\n const [isPaused, setIsPaused] = useState(false);\r\n const remainingRef = useRef(toast.duration);\r\n const startRef = useRef(0);\r\n\r\n // ----- JS-driven progress bar -----\r\n // progress: 100 = full, 0 = empty\r\n const [progress, setProgress] = useState(100);\r\n // transition duration for the progress bar\r\n const [progressTransition, setProgressTransition] = useState(\"none\");\r\n const rafRef = useRef<number>(0);\r\n\r\n // Reset remaining time when version changes (e.g. promise resolved)\r\n useEffect(() => {\r\n remainingRef.current = toast.duration;\r\n setProgress(100);\r\n setProgressTransition(\"none\");\r\n }, [toast.version, toast.duration]);\r\n\r\n useEffect(() => {\r\n // Don't auto-dismiss: persistent, loading, still entering, or already exiting\r\n if (\r\n toast.duration <= 0 ||\r\n toast.variant === \"loading\" ||\r\n !hasEntered ||\r\n toast.isExiting\r\n )\r\n return;\r\n\r\n if (isPaused) {\r\n // How long the bar was shrinking before hover\r\n const elapsed = Date.now() - startRef.current;\r\n // Snapshot remaining time\r\n remainingRef.current = Math.max(0, remainingRef.current - elapsed);\r\n\r\n // Reverse at the same speed it was shrinking (proportional duration)\r\n const refillDuration = Math.max(MIN_REFILL_DURATION, elapsed);\r\n setProgressTransition(`width ${refillDuration}ms ease-out`);\r\n setProgress(100);\r\n return;\r\n }\r\n\r\n // Start shrinking\r\n startRef.current = Date.now();\r\n const remaining = remainingRef.current;\r\n\r\n // Set transition to match remaining time and shrink to 0\r\n // Use rAF to ensure the refill transition has settled before starting shrink\r\n rafRef.current = requestAnimationFrame(() => {\r\n setProgressTransition(`width ${remaining}ms linear`);\r\n setProgress(0);\r\n });\r\n\r\n const timer = setTimeout(() => {\r\n onDismiss(toast.id);\r\n }, remaining);\r\n\r\n return () => {\r\n clearTimeout(timer);\r\n cancelAnimationFrame(rafRef.current);\r\n };\r\n }, [\r\n isPaused,\r\n hasEntered,\r\n toast.isExiting,\r\n toast.duration,\r\n toast.variant,\r\n toast.id,\r\n toast.version,\r\n onDismiss,\r\n ]);\r\n\r\n // ----- handlers -----\r\n const handleMouseEnter = useCallback(() => setIsPaused(true), []);\r\n const handleMouseLeave = useCallback(() => setIsPaused(false), []);\r\n\r\n // ----- render -----\r\n const Icon = variantIcon[toast.variant] ?? InfoIcon;\r\n\r\n // Custom toast โ render raw content with no default chrome\r\n if (toast.isCustom) {\r\n return (\r\n <div\r\n className={cx(\r\n \"toast23-item toast23-item--custom\",\r\n !hasEntered && \"toast23-item--entering\",\r\n toast.isExiting && \"toast23-item--exiting\",\r\n )}\r\n role=\"alert\"\r\n aria-live=\"polite\"\r\n aria-atomic=\"true\"\r\n onMouseEnter={handleMouseEnter}\r\n onMouseLeave={handleMouseLeave}\r\n >\r\n {toast.message}\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div\r\n className={cx(\r\n \"toast23-item\",\r\n `toast23-item--${toast.variant}`,\r\n !hasEntered && \"toast23-item--entering\",\r\n toast.isExiting && \"toast23-item--exiting\",\r\n )}\r\n role=\"alert\"\r\n aria-live={toast.variant === \"error\" ? \"assertive\" : \"polite\"}\r\n aria-atomic=\"true\"\r\n onMouseEnter={handleMouseEnter}\r\n onMouseLeave={handleMouseLeave}\r\n >\r\n {/* Icon */}\r\n <span className={cx(\"toast23-icon\", `toast23-icon--${toast.variant}`)}>\r\n <Icon />\r\n </span>\r\n\r\n {/* Content */}\r\n <div className=\"toast23-content\">\r\n {toast.title && <div className=\"toast23-title\">{toast.title}</div>}\r\n <div\r\n className={cx(\r\n \"toast23-message\",\r\n toast.title && \"toast23-message--with-title\",\r\n )}\r\n >\r\n {toast.message}\r\n </div>\r\n </div>\r\n\r\n {/* Dismiss button */}\r\n {toast.dismissible && (\r\n <button\r\n type=\"button\"\r\n className=\"toast23-dismiss\"\r\n onClick={() => onDismiss(toast.id)}\r\n aria-label=\"Dismiss notification\"\r\n >\r\n <XIcon />\r\n </button>\r\n )}\r\n\r\n {/* Progress bar โ JS-driven width for hover reversal */}\r\n {toast.duration > 0 && toast.variant !== \"loading\" && (\r\n <div\r\n className={cx(\r\n \"toast23-progress\",\r\n `toast23-progress--${toast.variant}`,\r\n )}\r\n style={{\r\n width: `${progress}%`,\r\n transition: progressTransition,\r\n }}\r\n />\r\n )}\r\n </div>\r\n );\r\n },\r\n);\r\n\r\nToastItem.displayName = \"ToastItem\";\r\n","/**\r\n * toast-23 โ Positioned Toast Container\r\n *\r\n * Renders a group of toasts for a given screen position.\r\n * Handles queue logic: only `maxVisible` non-exiting toasts are shown,\r\n * plus any currently animating-out toasts.\r\n */\r\n\r\n\"use client\";\r\n\r\nimport * as React from \"react\";\r\nimport { useContext } from \"react\";\r\nimport type { InternalToast, ToastPosition } from \"./types\";\r\nimport { ToasterContext } from \"./context\";\r\nimport { ToastItem } from \"./toast-item\";\r\nimport { cx } from \"./utils\";\r\n\r\ninterface ToastContainerProps {\r\n position: ToastPosition;\r\n toasts: InternalToast[];\r\n maxVisible: number;\r\n}\r\n\r\nexport const ToastContainer: React.FC<ToastContainerProps> = React.memo(\r\n ({ position, toasts, maxVisible }: ToastContainerProps) => {\r\n const ctx = useContext(ToasterContext);\r\n if (!ctx) return null;\r\n\r\n // Separate active vs. exiting toasts\r\n const active = toasts.filter((t) => !t.isExiting);\r\n const exiting = toasts.filter((t) => t.isExiting);\r\n\r\n // Only show up to maxVisible active toasts, plus all currently exiting\r\n const visible = [...active.slice(0, maxVisible), ...exiting];\r\n\r\n if (visible.length === 0) return null;\r\n\r\n // Queue count for optional badge\r\n const queuedCount = Math.max(0, active.length - maxVisible);\r\n\r\n return (\r\n <div\r\n className={cx(\"toast23-container\", `toast23-container--${position}`)}\r\n aria-label=\"Notifications\"\r\n role=\"region\"\r\n >\r\n {visible.map((toast) => (\r\n <ToastItem\r\n key={toast.id}\r\n toast={toast}\r\n onDismiss={ctx.dismissToast}\r\n onRemove={ctx.removeToast}\r\n />\r\n ))}\r\n {queuedCount > 0 && (\r\n <div className=\"toast23-queue-badge\" aria-live=\"polite\">\r\n +{queuedCount} more\r\n </div>\r\n )}\r\n </div>\r\n );\r\n },\r\n);\r\n\r\nToastContainer.displayName = \"ToastContainer\";\r\n","/**\r\n * toast-23 โ Toast23Provider\r\n *\r\n * Wrap your application with this provider to enable toast notifications.\r\n *\r\n * ```tsx\r\n * <Toast23Provider position=\"top-right\" maxVisible={5}>\r\n * <App />\r\n * </Toast23Provider>\r\n * ```\r\n */\r\n\r\n\"use client\";\r\n\r\nimport { useCallback, useMemo, useReducer } from \"react\";\r\nimport type {\r\n InternalToast,\r\n Toast23ProviderProps,\r\n ToasterContextValue,\r\n ToastOptions,\r\n ToastPosition,\r\n} from \"./types\";\r\nimport type { ReactNode } from \"react\";\r\nimport { ToasterContext, toasterReducer } from \"./context\";\r\nimport { ToastContainer } from \"./toast-container\";\r\nimport { generateId } from \"./utils\";\r\n\r\nconst ALL_POSITIONS: ToastPosition[] = [\r\n \"top-right\",\r\n \"top-left\",\r\n \"top-center\",\r\n \"bottom-right\",\r\n \"bottom-left\",\r\n \"bottom-center\",\r\n];\r\n\r\nexport const Toast23Provider: React.FC<Toast23ProviderProps> = ({\r\n children,\r\n maxVisible = 5,\r\n position: defaultPosition = \"top-right\" as ToastPosition,\r\n duration: defaultDuration = 5000,\r\n}) => {\r\n const [toasts, dispatch] = useReducer(toasterReducer, []);\r\n\r\n // ------ stable callbacks (dispatch is always stable from useReducer) ------\r\n\r\n const addToast = useCallback(\r\n (message: string | ReactNode, options?: ToastOptions & { variant?: any; isCustom?: boolean }): string => {\r\n const id = options?.id ?? generateId();\r\n const toast: InternalToast = {\r\n id,\r\n message,\r\n title: options?.title,\r\n variant: options?.variant ?? \"default\",\r\n duration: options?.duration ?? defaultDuration,\r\n position: options?.position ?? defaultPosition,\r\n dismissible: options?.dismissible ?? true,\r\n removeDelay: options?.removeDelay ?? 1000,\r\n isExiting: false,\r\n createdAt: Date.now(),\r\n version: 0,\r\n isCustom: options?.isCustom,\r\n };\r\n // If an id was provided, upsert (update-or-insert)\r\n if (options?.id) {\r\n dispatch({ type: \"UPSERT\", toast });\r\n } else {\r\n dispatch({ type: \"ADD\", toast });\r\n }\r\n return id;\r\n },\r\n [defaultDuration, defaultPosition],\r\n );\r\n\r\n const updateToast = useCallback(\r\n (\r\n id: string,\r\n updates: Partial<\r\n Pick<\r\n InternalToast,\r\n \"message\" | \"title\" | \"variant\" | \"duration\" | \"dismissible\"\r\n >\r\n >,\r\n ) => {\r\n dispatch({ type: \"UPDATE\", id, updates });\r\n },\r\n [],\r\n );\r\n\r\n const dismissToast = useCallback((id?: string) => {\r\n dispatch({ type: \"DISMISS\", id });\r\n }, []);\r\n\r\n const removeToast = useCallback((id?: string) => {\r\n dispatch({ type: \"REMOVE\", id });\r\n }, []);\r\n\r\n // ------ context value (stable as long as callbacks are stable) ------\r\n\r\n const contextValue: ToasterContextValue = useMemo(\r\n () => ({\r\n addToast,\r\n updateToast,\r\n dismissToast,\r\n removeToast,\r\n config: {\r\n maxVisible,\r\n position: defaultPosition,\r\n duration: defaultDuration,\r\n },\r\n }),\r\n [\r\n addToast,\r\n updateToast,\r\n dismissToast,\r\n removeToast,\r\n maxVisible,\r\n defaultPosition,\r\n defaultDuration,\r\n ],\r\n );\r\n\r\n // ------ group toasts by position ------\r\n\r\n const groupedToasts = useMemo(() => {\r\n const groups: Record<ToastPosition, InternalToast[]> = {\r\n \"top-right\": [],\r\n \"top-left\": [],\r\n \"top-center\": [],\r\n \"bottom-right\": [],\r\n \"bottom-left\": [],\r\n \"bottom-center\": [],\r\n };\r\n for (const t of toasts) {\r\n groups[t.position].push(t);\r\n }\r\n return groups;\r\n }, [toasts]);\r\n\r\n return (\r\n <ToasterContext.Provider value={contextValue}>\r\n {children}\r\n\r\n {/* Render one container per position that has toasts */}\r\n {ALL_POSITIONS.map((pos) =>\r\n groupedToasts[pos].length > 0 ? (\r\n <ToastContainer\r\n key={pos}\r\n position={pos}\r\n toasts={groupedToasts[pos]}\r\n maxVisible={maxVisible}\r\n />\r\n ) : null,\r\n )}\r\n </ToasterContext.Provider>\r\n );\r\n};\r\n\r\nToast23Provider.displayName = \"Toast23Provider\";\r\n","/**\r\n * toast-23 โ useToast Hook\r\n *\r\n * Returns a callable `ToastApi` object:\r\n *\r\n * ```ts\r\n * const toast = useToast();\r\n *\r\n * toast(\"Hello!\"); // default variant\r\n * toast.success(\"Done!\"); // success variant\r\n * toast.error(\"Oops\"); // error variant\r\n * toast.promise(fetchData(), { ... }); // promise tracking\r\n * toast.dismiss(id); // manual dismiss\r\n * ```\r\n */\r\n\r\n\"use client\";\r\n\r\nimport { useContext, useMemo } from \"react\";\r\nimport { ToasterContext } from \"./context\";\r\nimport type { ToastApi, ToastOptions, PromiseOptions } from \"./types\";\r\nimport type { ReactNode } from \"react\";\r\n\r\nexport function useToast(): ToastApi {\r\n const ctx = useContext(ToasterContext);\r\n\r\n if (!ctx) {\r\n throw new Error(\r\n \"[toast-23] useToast() must be used inside a <Toast23Provider>. \" +\r\n \"Wrap your application root with <Toast23Provider> to fix this.\",\r\n );\r\n }\r\n\r\n return useMemo(() => {\r\n // Base callable โ toast(\"message\", opts?)\r\n const toast = ((message: string | ReactNode, options?: ToastOptions) =>\r\n ctx.addToast(message, options)) as ToastApi;\r\n\r\n // Variant shortcuts\r\n toast.success = (msg, opts) =>\r\n ctx.addToast(msg, { ...opts, variant: \"success\" });\r\n\r\n toast.error = (msg, opts) =>\r\n ctx.addToast(msg, { ...opts, variant: \"error\" });\r\n\r\n toast.warning = (msg, opts) =>\r\n ctx.addToast(msg, { ...opts, variant: \"warning\" });\r\n\r\n toast.info = (msg, opts) => ctx.addToast(msg, { ...opts, variant: \"info\" });\r\n\r\n // Loading shortcut\r\n toast.loading = (msg, opts) =>\r\n ctx.addToast(msg, {\r\n ...opts,\r\n variant: \"loading\" as any,\r\n duration: opts?.duration ?? 0,\r\n dismissible: opts?.dismissible ?? false,\r\n });\r\n\r\n // Custom toast โ no default styles\r\n toast.custom = (content, opts) =>\r\n ctx.addToast(content, { ...opts, variant: \"default\", isCustom: true });\r\n\r\n // Dismiss (with optional id โ omit to dismiss all)\r\n toast.dismiss = (id?: string) => ctx.dismissToast(id);\r\n\r\n // Remove instantly (with optional id โ omit to remove all)\r\n toast.remove = (id?: string) => ctx.removeToast(id);\r\n\r\n // Promise tracking (accepts Promise or () => Promise, optional 3rd arg for toast options)\r\n toast.promise = async <T>(\r\n promiseOrFn: Promise<T> | (() => Promise<T>),\r\n opts: PromiseOptions<T>,\r\n toastOpts?: ToastOptions,\r\n ): Promise<T> => {\r\n const id = ctx.addToast(opts.loading, {\r\n ...toastOpts,\r\n variant: \"loading\" as any,\r\n duration: 0,\r\n dismissible: false,\r\n } as ToastOptions);\r\n\r\n const promise =\r\n typeof promiseOrFn === \"function\" ? promiseOrFn() : promiseOrFn;\r\n\r\n try {\r\n const result = await promise;\r\n const msg =\r\n typeof opts.success === \"function\"\r\n ? opts.success(result)\r\n : opts.success;\r\n ctx.updateToast(id, {\r\n message: msg,\r\n variant: \"success\",\r\n duration: toastOpts?.duration ?? ctx.config.duration,\r\n dismissible: true,\r\n });\r\n return result;\r\n } catch (error) {\r\n const msg =\r\n typeof opts.error === \"function\" ? opts.error(error) : opts.error;\r\n ctx.updateToast(id, {\r\n message: msg,\r\n variant: \"error\",\r\n duration: toastOpts?.duration ?? ctx.config.duration,\r\n dismissible: true,\r\n });\r\n throw error;\r\n }\r\n };\r\n\r\n return toast;\r\n }, [\r\n ctx.addToast,\r\n ctx.updateToast,\r\n ctx.dismissToast,\r\n ctx.removeToast,\r\n ctx.config.duration,\r\n ]);\r\n}\r\n","/**\r\n * toast-23 โ Standalone / Imperative API\r\n *\r\n * Use this when you need toast notifications outside of React (Angular, Vue,\r\n * Svelte, vanilla JS, etc.). It internally bootstraps a minimal React root.\r\n *\r\n * ```ts\r\n * import { createToast23 } from \"toast-23\";\r\n *\r\n * const toast = createToast23({ position: \"top-right\" });\r\n *\r\n * toast.success(\"Saved!\");\r\n * toast.error(\"Something went wrong\");\r\n * toast.dismiss(id);\r\n *\r\n * // Cleanup when done (e.g. on app destroy)\r\n * toast.destroy();\r\n * ```\r\n */\r\n\r\nimport * as React from \"react\";\r\nimport { createRoot, type Root } from \"react-dom/client\";\r\nimport { Toast23Provider } from \"./provider\";\r\nimport { useToast } from \"./use-toast\";\r\nimport type {\r\n ToastPosition,\r\n ToastOptions,\r\n PromiseOptions,\r\n ToastApi,\r\n} from \"./types\";\r\nimport type { ReactNode } from \"react\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface StandaloneOptions {\r\n /** Where on screen toasts appear. @default \"top-right\" */\r\n position?: ToastPosition;\r\n /** Max simultaneous toasts. @default 5 */\r\n maxVisible?: number;\r\n /** Default auto-dismiss duration in ms. @default 5000 */\r\n duration?: number;\r\n}\r\n\r\nexport interface StandaloneToastApi {\r\n /** Show a default toast. Returns the toast id. */\r\n (message: string | ReactNode, options?: ToastOptions): string;\r\n /** Show a success toast. */\r\n success: (message: string, options?: Omit<ToastOptions, \"variant\">) => string;\r\n /** Show an error toast. */\r\n error: (message: string, options?: Omit<ToastOptions, \"variant\">) => string;\r\n /** Show a warning toast. */\r\n warning: (message: string, options?: Omit<ToastOptions, \"variant\">) => string;\r\n /** Show an info toast. */\r\n info: (message: string, options?: Omit<ToastOptions, \"variant\">) => string;\r\n /** Show a loading toast. Returns the toast id for later update. */\r\n loading: (message: string, options?: Omit<ToastOptions, \"variant\">) => string;\r\n /** Show a custom toast with JSX content and no default styles. */\r\n custom: (\r\n content: ReactNode,\r\n options?: Omit<ToastOptions, \"variant\">,\r\n ) => string;\r\n /** Track an async operation with loading โ success / error transitions. */\r\n promise: <T>(\r\n promise: Promise<T> | (() => Promise<T>),\r\n options: PromiseOptions<T>,\r\n toastOptions?: ToastOptions,\r\n ) => Promise<T>;\r\n /** Manually dismiss a toast by id. Omit id to dismiss all. */\r\n dismiss: (id?: string) => void;\r\n /** Instantly remove a toast from DOM (no exit animation). Omit id to remove all. */\r\n remove: (id?: string) => void;\r\n /** Unmount the React root and remove the container from the DOM. */\r\n destroy: () => void;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Bridge component โ captures the useToast API and passes it out\r\n// ---------------------------------------------------------------------------\r\n\r\nlet _resolveApi: ((api: ToastApi) => void) | null = null;\r\n\r\nfunction Bridge() {\r\n const api = useToast();\r\n\r\n // Resolve the promise on first render; update the ref on every render\r\n // so the external caller always has the latest stable API reference.\r\n React.useEffect(() => {\r\n if (_resolveApi) {\r\n _resolveApi(api);\r\n _resolveApi = null;\r\n }\r\n }, [api]);\r\n\r\n // Also store on ref for synchronous access after first mount\r\n\r\n return null;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Factory\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Create a standalone toast API that works outside of React.\r\n *\r\n * Internally mounts a tiny React tree (provider + bridge) into a hidden\r\n * container. Returns a callable toast object with `.success()`, `.error()`, etc.\r\n *\r\n * Call `.destroy()` when your application unmounts to clean up.\r\n */\r\nexport function createToast23(\r\n options: StandaloneOptions = {},\r\n): StandaloneToastApi {\r\n const { position = \"top-right\", maxVisible = 5, duration = 5000 } = options;\r\n\r\n // Create a hidden container\r\n const container = document.createElement(\"div\");\r\n container.setAttribute(\"data-toast23-standalone\", \"\");\r\n container.style.display = \"contents\"; // invisible wrapper\r\n document.body.appendChild(container);\r\n\r\n // We need to wait for React to render before the API is available.\r\n // Use a promise + queue approach so calls before mount are buffered.\r\n let root: Root | null = createRoot(container);\r\n\r\n const apiReady = new Promise<ToastApi>((resolve) => {\r\n _resolveApi = resolve;\r\n });\r\n\r\n // Queue for calls made before React has mounted\r\n type QueuedCall = { method: string; args: unknown[] };\r\n const queue: QueuedCall[] = [];\r\n let resolvedApi: ToastApi | null = null;\r\n\r\n // Flush queued calls once the API is ready\r\n apiReady.then((api) => {\r\n resolvedApi = api;\r\n for (const call of queue) {\r\n if (call.method === \"__call__\") {\r\n (api as any)(...call.args);\r\n } else {\r\n (api as any)[call.method](...call.args);\r\n }\r\n }\r\n queue.length = 0;\r\n });\r\n\r\n // Mount React tree\r\n root.render(\r\n React.createElement(\r\n Toast23Provider,\r\n { position, maxVisible, duration } as any,\r\n React.createElement(Bridge),\r\n ),\r\n );\r\n\r\n // Build the proxy API\r\n const proxyCall = (method: string, ...args: unknown[]): any => {\r\n if (resolvedApi) {\r\n return (resolvedApi as any)[method](...args);\r\n }\r\n queue.push({ method, args });\r\n return \"queued\";\r\n };\r\n\r\n const toast = ((message: string | ReactNode, opts?: ToastOptions) => {\r\n if (resolvedApi) return resolvedApi(message, opts);\r\n queue.push({ method: \"__call__\", args: [message, opts] });\r\n return \"queued\";\r\n }) as StandaloneToastApi;\r\n\r\n toast.success = (msg, opts) => proxyCall(\"success\", msg, opts);\r\n toast.error = (msg, opts) => proxyCall(\"error\", msg, opts);\r\n toast.warning = (msg, opts) => proxyCall(\"warning\", msg, opts);\r\n toast.info = (msg, opts) => proxyCall(\"info\", msg, opts);\r\n toast.loading = (msg, opts) => proxyCall(\"loading\", msg, opts);\r\n toast.custom = (content, opts) => proxyCall(\"custom\", content, opts);\r\n toast.dismiss = (id?) => proxyCall(\"dismiss\", id);\r\n toast.remove = (id?) => proxyCall(\"remove\", id);\r\n\r\n toast.promise = (promise, opts, toastOpts?) => {\r\n if (resolvedApi) return resolvedApi.promise(promise, opts, toastOpts);\r\n // For promises, we need to wait for the API\r\n return apiReady.then((api) => api.promise(promise, opts, toastOpts));\r\n };\r\n\r\n toast.destroy = () => {\r\n if (root) {\r\n root.unmount();\r\n root = null;\r\n }\r\n container.remove();\r\n resolvedApi = null;\r\n };\r\n\r\n return toast;\r\n}\r\n"],"names":["ToasterContext","createContext","toasterReducer","state","action","t","CheckCircleIcon","props","jsxs","jsx","XCircleIcon","AlertTriangleIcon","InfoIcon","XIcon","SpinnerIcon","counter","generateId","cx","args","variantIcon","EXIT_DURATION","MIN_REFILL_DURATION","ToastItem","React","toast","onDismiss","onRemove","hasEntered","setHasEntered","useState","useEffect","raf","delay","timer","isPaused","setIsPaused","remainingRef","useRef","startRef","progress","setProgress","progressTransition","setProgressTransition","rafRef","elapsed","refillDuration","remaining","handleMouseEnter","useCallback","handleMouseLeave","Icon","ToastContainer","position","toasts","maxVisible","ctx","useContext","active","exiting","visible","queuedCount","ALL_POSITIONS","Toast23Provider","children","defaultPosition","defaultDuration","dispatch","useReducer","addToast","message","options","id","updateToast","updates","dismissToast","removeToast","contextValue","useMemo","groupedToasts","groups","pos","useToast","msg","opts","content","promiseOrFn","toastOpts","promise","result","error","_resolveApi","Bridge","api","createToast23","duration","container","root","createRoot","apiReady","resolve","queue","resolvedApi","call","proxyCall","method"],"mappings":"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"}
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.toast23-container,.toast23-container *,.toast23-container *:before,.toast23-container *:after{box-sizing:border-box;margin:0;padding:0}.toast23-container{position:fixed;z-index:9999;display:flex;flex-direction:column;gap:.75rem;padding:1rem;pointer-events:none;max-height:100vh;overflow:hidden}.toast23-container--top-right{top:0;right:0}.toast23-container--top-left{top:0;left:0}.toast23-container--top-center{top:0;left:50%;transform:translate(-50%);align-items:center}.toast23-container--bottom-right{bottom:0;right:0;flex-direction:column-reverse}.toast23-container--bottom-left{bottom:0;left:0;flex-direction:column-reverse}.toast23-container--bottom-center{bottom:0;left:50%;transform:translate(-50%);flex-direction:column-reverse;align-items:center}.toast23-item{pointer-events:auto;position:relative;display:flex;align-items:flex-start;gap:.75rem;min-width:320px;max-width:26rem;padding:.875rem 1rem;border-radius:.75rem;border:1px solid;overflow:hidden;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;line-height:1.5;box-shadow:0 4px 6px -1px #00000014,0 2px 4px -2px #0000000d;transform:translate(0);opacity:1;transition:transform .3s cubic-bezier(.4,0,.2,1),opacity .3s cubic-bezier(.4,0,.2,1);cursor:default}.toast23-item:hover{box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000000f}.toast23-container--top-right .toast23-item--entering,.toast23-container--top-right .toast23-item--exiting,.toast23-container--bottom-right .toast23-item--entering,.toast23-container--bottom-right .toast23-item--exiting{transform:translate(calc(100% + 1rem));opacity:0}.toast23-container--top-left .toast23-item--entering,.toast23-container--top-left .toast23-item--exiting,.toast23-container--bottom-left .toast23-item--entering,.toast23-container--bottom-left .toast23-item--exiting{transform:translate(calc(-100% - 1rem));opacity:0}.toast23-container--top-center .toast23-item--entering,.toast23-container--top-center .toast23-item--exiting{transform:translateY(-100%);opacity:0}.toast23-container--bottom-center .toast23-item--entering,.toast23-container--bottom-center .toast23-item--exiting{transform:translateY(100%);opacity:0}.toast23-item--success{background:#f0fdf4f2;border-color:#bbf7d0}.toast23-item--error{background:#fef2f2f2;border-color:#fecaca}.toast23-item--warning{background:#fefce8f2;border-color:#fef08a}.toast23-item--info{background:#eff6fff2;border-color:#bfdbfe}.toast23-item--default,.toast23-item--loading{background:#f9fafbf2;border-color:#e5e7eb}@media (prefers-color-scheme: dark){.toast23-item--success{background:#16653440;border-color:#166534}.toast23-item--error{background:#991b1b40;border-color:#991b1b}.toast23-item--warning{background:#854d0e40;border-color:#854d0e}.toast23-item--info{background:#1e40af40;border-color:#1e40af}.toast23-item--default,.toast23-item--loading{background:#37415180;border-color:#4b5563}.toast23-title{color:#f9fafb!important}.toast23-message{color:#e5e7eb!important}.toast23-message--with-title{color:#d1d5db!important}.toast23-dismiss{color:#9ca3af!important}.toast23-dismiss:hover{color:#e5e7eb!important}.toast23-queue-badge{color:#d1d5db!important;background:#374151b3!important;border-color:#4b5563!important}}.dark .toast23-item--success{background:#16653440;border-color:#166534}.dark .toast23-item--error{background:#991b1b40;border-color:#991b1b}.dark .toast23-item--warning{background:#854d0e40;border-color:#854d0e}.dark .toast23-item--info{background:#1e40af40;border-color:#1e40af}.dark .toast23-item--default,.dark .toast23-item--loading{background:#37415180;border-color:#4b5563}.dark .toast23-title{color:#f9fafb}.dark .toast23-message{color:#e5e7eb}.dark .toast23-message--with-title{color:#d1d5db}.dark .toast23-dismiss{color:#9ca3af}.dark .toast23-dismiss:hover{color:#e5e7eb}.dark .toast23-queue-badge{color:#d1d5db;background:#374151b3;border-color:#4b5563}.toast23-icon{display:flex;align-items:center;flex-shrink:0;margin-top:1px}.toast23-icon--success{color:#22c55e}.toast23-icon--error{color:#ef4444}.toast23-icon--warning{color:#eab308}.toast23-icon--info{color:#3b82f6}.toast23-icon--default{color:#6b7280}.toast23-icon--loading{color:#3b82f6}.toast23-content{flex:1;min-width:0}.toast23-title{font-size:.875rem;font-weight:600;color:#111827;margin-bottom:.125rem;line-height:1.3}.toast23-message{font-size:.875rem;font-weight:500;color:#1f2937;word-break:break-word}.toast23-message--with-title{color:#6b7280;font-weight:400}.toast23-dismiss{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:1.5rem;height:1.5rem;border:none;background:transparent;color:#9ca3af;cursor:pointer;border-radius:.25rem;transition:color .15s ease,background-color .15s ease;margin:-.125rem -.25rem 0 0;padding:0}.toast23-dismiss:hover{color:#374151;background:#0000000d}.toast23-dismiss:focus-visible{outline:2px solid #3b82f6;outline-offset:1px}.toast23-progress{position:absolute;bottom:0;left:0;height:3.5px;border-radius:0 0 0 .75rem}.toast23-progress--success{background:#22c55e}.toast23-progress--error{background:#ef4444}.toast23-progress--warning{background:#eab308}.toast23-progress--info{background:#3b82f6}.toast23-progress--default{background:#6b7280}.toast23-queue-badge{font-family:inherit;font-size:.75rem;font-weight:500;color:#6b7280;background:#fffc;border:1px solid #e5e7eb;border-radius:9999px;padding:.25rem .75rem;text-align:center;pointer-events:none;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.toast23-spinner{animation:toast23-spin .7s linear infinite}@keyframes toast23-spin{to{transform:rotate(360deg)}}@media (max-width: 480px){.toast23-container{padding:.75rem;left:0!important;right:0!important}.toast23-item{min-width:0;max-width:100%}}
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "toast-23",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A lightweight, accessible, fully-typed React toast notification library with zero dependencies.",
|
|
5
|
+
"author": "",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.cjs",
|
|
9
|
+
"module": "./dist/index.mjs",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.mjs"
|
|
16
|
+
},
|
|
17
|
+
"require": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.cjs"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"./styles.css": "./dist/style.css"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"sideEffects": [
|
|
28
|
+
"*.css"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"dev": "vite",
|
|
32
|
+
"build": "tsc --noEmit && vite build",
|
|
33
|
+
"lint": "tsc --noEmit",
|
|
34
|
+
"test": "vitest run",
|
|
35
|
+
"test:watch": "vitest",
|
|
36
|
+
"test:coverage": "vitest run --coverage",
|
|
37
|
+
"prepublishOnly": "npm run build"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"react": ">=18.0.0",
|
|
41
|
+
"react-dom": ">=18.0.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
45
|
+
"@testing-library/react": "^16.3.2",
|
|
46
|
+
"@testing-library/user-event": "^14.6.1",
|
|
47
|
+
"@types/react": "^18.2.0",
|
|
48
|
+
"@types/react-dom": "^18.2.0",
|
|
49
|
+
"@vitejs/plugin-react": "^4.2.0",
|
|
50
|
+
"jsdom": "^28.1.0",
|
|
51
|
+
"react": "^18.2.0",
|
|
52
|
+
"react-dom": "^18.2.0",
|
|
53
|
+
"typescript": "^5.3.0",
|
|
54
|
+
"vite": "^5.4.0",
|
|
55
|
+
"vite-plugin-dts": "^3.9.0",
|
|
56
|
+
"vitest": "^4.0.18"
|
|
57
|
+
},
|
|
58
|
+
"keywords": [
|
|
59
|
+
"react",
|
|
60
|
+
"toast",
|
|
61
|
+
"notifications",
|
|
62
|
+
"toaster",
|
|
63
|
+
"alert",
|
|
64
|
+
"snackbar",
|
|
65
|
+
"react-toast",
|
|
66
|
+
"typescript",
|
|
67
|
+
"accessible",
|
|
68
|
+
"toast-23"
|
|
69
|
+
],
|
|
70
|
+
"repository": {
|
|
71
|
+
"type": "git",
|
|
72
|
+
"url": ""
|
|
73
|
+
},
|
|
74
|
+
"homepage": "",
|
|
75
|
+
"bugs": {
|
|
76
|
+
"url": ""
|
|
77
|
+
}
|
|
78
|
+
}
|