@laravel-inertia-toast/react 0.2.0 → 0.3.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 ADDED
@@ -0,0 +1,133 @@
1
+ # @laravel-inertia-toast/react
2
+
3
+ React adapter for [Laravel Inertia Toast](https://github.com/veekthoven/laravel-inertia-toast) — beautiful toast notifications for Laravel + Inertia.js applications.
4
+
5
+ ## Demo
6
+
7
+ **React:**
8
+ ![React](../demo/react.png)
9
+
10
+ **See it in action:**
11
+ ![Vue](../demo/toast-demo.gif)
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @laravel-inertia-toast/react
17
+ ```
18
+
19
+ ## Setup
20
+
21
+ ### 1. Add the Provider
22
+
23
+ Wrap your app with `<ToastProvider>` and add `<Toasts />`:
24
+
25
+ ```jsx
26
+ // in your resources/js/app.tsx
27
+
28
+ import { createRoot } from 'react-dom/client';
29
+ import { ToastProvider, Toasts } from '@laravel-inertia-toast/react'
30
+
31
+ setup({ el, App, props }) {
32
+ const root = createRoot(el);
33
+
34
+ root.render(
35
+ <ToastProvider
36
+ config={{
37
+ position: 'top-right'
38
+ duration: 5000,
39
+ maxVisible: 5,
40
+ }}
41
+ >
42
+ <App {...props} />
43
+ <Toasts />
44
+ </ToastProvider>
45
+ );
46
+ },
47
+ ```
48
+
49
+ ### 2. Tailwind CSS
50
+
51
+ Since the toast components use Tailwind classes internally, add the package to Tailwind's source detection.
52
+
53
+ **Tailwind v4** — add this `@source` directive to your CSS file (e.g. `resources/css/app.css`):
54
+
55
+ ```css
56
+ @source "../../node_modules/@laravel-inertia-toast/react/dist/**/*.js";
57
+ ```
58
+
59
+ **Tailwind v3** — add to `tailwind.config.js`:
60
+
61
+ ```js
62
+ module.exports = {
63
+ content: [
64
+ // ...
65
+ './node_modules/@laravel-inertia-toast/react/dist/**/*.js',
66
+ ],
67
+ }
68
+ ```
69
+
70
+ > The relative paths above assume standard Laravel project structure. Adjust if your setup differs.
71
+
72
+ ## Client-Side Usage
73
+
74
+ Use the `useToast()` hook to trigger toasts from your components:
75
+
76
+ ```jsx
77
+ import { useToast } from '@laravel-inertia-toast/react'
78
+
79
+ function MyComponent() {
80
+ const { success, error, info, warning } = useToast()
81
+
82
+ return (
83
+ <>
84
+ <button onClick={() => success('Copied to clipboard!')}>
85
+ Copy
86
+ </button>
87
+ <button onClick={() => error('Item has been removed.', { title: 'Deleted' })}>
88
+ Delete
89
+ </button>
90
+ </>
91
+ )
92
+ }
93
+ ```
94
+
95
+ ### With Title and Duration
96
+
97
+ Pass an options object as the second argument to include a title and/or custom duration:
98
+
99
+ ```jsx
100
+ success('Profile has been updated.', { title: 'Success' })
101
+ warning('Session expiring soon.', { title: 'Warning', duration: 10000 })
102
+ ```
103
+
104
+ ## Server-Side Usage
105
+
106
+ Pair with the PHP package for server-side toasts:
107
+
108
+ ```bash
109
+ composer require veekthoven/laravel-inertia-toast
110
+ ```
111
+
112
+ ```php
113
+ use InertiaToast\Facades\Toast;
114
+
115
+ Toast::success('Profile updated!');
116
+ Toast::error('Something went wrong.', title: 'Error');
117
+ Toast::info('Check your email for a confirmation link.');
118
+ Toast::warning('Your subscription is about to expire.');
119
+
120
+ return redirect()->route('dashboard');
121
+ ```
122
+
123
+ For full documentation, configuration options, and the PHP helper API, see the [main repository](https://github.com/veekthoven/laravel-inertia-toast).
124
+
125
+ ## Requirements
126
+
127
+ - React 18+
128
+ - Inertia.js v2.3.3+
129
+ - Tailwind CSS v3 or v4
130
+
131
+ ## License
132
+
133
+ MIT
package/dist/context.d.ts CHANGED
@@ -1,12 +1,16 @@
1
1
  import React from 'react';
2
2
  import type { ToastConfig, ToastItem } from './types';
3
+ export interface ToastOptions {
4
+ title?: string;
5
+ duration?: number;
6
+ }
3
7
  export interface ToastContextValue {
4
8
  items: ToastItem[];
5
9
  config: ToastConfig;
6
- success: (message: string, duration?: number) => void;
7
- error: (message: string, duration?: number) => void;
8
- info: (message: string, duration?: number) => void;
9
- warning: (message: string, duration?: number) => void;
10
+ success: (message: string, options?: ToastOptions) => void;
11
+ error: (message: string, options?: ToastOptions) => void;
12
+ info: (message: string, options?: ToastOptions) => void;
13
+ warning: (message: string, options?: ToastOptions) => void;
10
14
  remove: (id: string) => void;
11
15
  clear: () => void;
12
16
  }
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),r=require("react"),w=require("@inertiajs/react");let b=0;function y(){return`toast-${++b}-${Date.now()}`}const C={duration:5e3,position:"top-right",maxVisible:5,propKey:"toasts"};function j(e,i){switch(i.type){case"ADD":{const c=[{...i.payload,id:y()},...e.items].slice(0,e.config.maxVisible);return{...e,items:c}}case"REMOVE":return{...e,items:e.items.filter(l=>l.id!==i.payload)};case"CLEAR":return{...e,items:[]};default:return e}}const p=r.createContext(null);function R({children:e,config:i}){const l={...C,...i},[c,n]=r.useReducer(j,{items:[],config:l}),d=r.useRef(l);d.current=l,r.useEffect(()=>w.router.on("flash",o=>{const u=o.detail.flash[d.current.propKey];u&&Array.isArray(u)&&u.forEach(m=>{n({type:"ADD",payload:m})})}),[]);const a=r.useCallback((s,o,u)=>{n({type:"ADD",payload:{message:s,level:o,duration:u??null}})},[]),f={items:c.items,config:c.config,success:r.useCallback((s,o)=>a(s,"success",o),[a]),error:r.useCallback((s,o)=>a(s,"error",o),[a]),info:r.useCallback((s,o)=>a(s,"info",o),[a]),warning:r.useCallback((s,o)=>a(s,"warning",o),[a]),remove:r.useCallback(s=>n({type:"REMOVE",payload:s}),[]),clear:r.useCallback(()=>n({type:"CLEAR"}),[])};return t.jsx(p.Provider,{value:f,children:e})}function h(){const e=r.useContext(p);if(!e)throw new Error("useToast must be used within a <ToastProvider>");return e}const g={success:"bg-green-100 text-green-500",error:"bg-rose-100 text-rose-500",warning:"bg-yellow-100 text-yellow-500",info:"bg-blue-100 text-blue-500"};function T(){return t.jsx("svg",{className:"size-5","aria-hidden":"true",xmlns:"http://www.w3.org/2000/svg",fill:"currentColor",viewBox:"0 0 20 20",children:t.jsx("path",{d:"M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 8.207-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L9 10.586l3.293-3.293a1 1 0 0 1 1.414 1.414Z"})})}function L(){return t.jsx("svg",{className:"size-5","aria-hidden":"true",xmlns:"http://www.w3.org/2000/svg",fill:"currentColor",viewBox:"0 0 20 20",children:t.jsx("path",{d:"M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 11.793a1 1 0 1 1-1.414 1.414L10 11.414l-2.293 2.293a1 1 0 0 1-1.414-1.414L8.586 10 6.293 7.707a1 1 0 0 1 1.414-1.414L10 8.586l2.293-2.293a1 1 0 0 1 1.414 1.414L11.414 10l2.293 2.293Z"})})}function E(){return t.jsx("svg",{className:"size-5",viewBox:"0 0 20 20",fill:"currentColor",children:t.jsx("path",{fillRule:"evenodd",d:"M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z",clipRule:"evenodd"})})}function z(){return t.jsx("svg",{className:"size-5","aria-hidden":"true",xmlns:"http://www.w3.org/2000/svg",fill:"currentColor",viewBox:"0 0 24 24",children:t.jsx("path",{fillRule:"evenodd",d:"M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm8.706-1.442c1.146-.573 2.437.463 2.126 1.706l-.709 2.836.042-.02a.75.75 0 01.67 1.34l-.04.022c-1.147.573-2.438-.463-2.127-1.706l.71-2.836-.042.02a.75.75 0 11-.671-1.34l.041-.022zM12 9a.75.75 0 100-1.5.75.75 0 000 1.5z",clipRule:"evenodd"})})}function A({level:e}){switch(e){case"success":return t.jsx(T,{});case"error":return t.jsx(L,{});case"warning":return t.jsx(E,{});default:return t.jsx(z,{})}}function M(e){return e.includes("right")?"translate-x-full":e.includes("left")?"-translate-x-full":e.startsWith("top")?"-translate-y-full":"translate-y-full"}function v({toast:e,config:i,position:l,onRemove:c}){const n=r.useRef(null),[d,a]=r.useState(!1),f=e.duration??i.duration,s=r.useCallback(()=>{n.current&&(clearTimeout(n.current),n.current=null),a(!1)},[]);r.useEffect(()=>{const m=requestAnimationFrame(()=>a(!0));return()=>cancelAnimationFrame(m)},[]),r.useEffect(()=>(f>0&&(n.current=setTimeout(s,f)),()=>{n.current&&clearTimeout(n.current)}),[f,s]);const o=M(l),u=d?"opacity-100 translate-x-0 translate-y-0 duration-300 ease-out":`opacity-0 ${o} duration-200 ease-in`;return t.jsxs("div",{className:`flex items-center rounded-lg bg-white p-4 text-gray-500 shadow min-w-96 transition ${u}`,role:"alert",onTransitionEnd:()=>{d||c(e.id)},children:[t.jsx("div",{className:`inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg ${g[e.level]??g.info}`,children:t.jsx(A,{level:e.level})}),t.jsx("div",{className:"ml-3 text-sm font-normal",children:e.message}),t.jsxs("button",{type:"button",className:"ml-auto inline-flex items-center justify-center h-8 w-8 rounded-lg bg-white p-1.5 text-gray-400 hover:bg-gray-100 hover:text-gray-900 focus:ring-2 focus:ring-gray-300",onClick:s,"aria-label":"Close",children:[t.jsx("span",{className:"sr-only",children:"Close"}),t.jsx("svg",{"aria-hidden":"true",className:"h-5 w-5",fill:"currentColor",viewBox:"0 0 20 20",xmlns:"http://www.w3.org/2000/svg",children:t.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})]})]})}const x={"top-right":"top-4 right-4 items-end","top-left":"top-4 left-4 items-start","top-center":"top-4 left-1/2 -translate-x-1/2 items-center","bottom-right":"bottom-4 right-4 items-end","bottom-left":"bottom-4 left-4 items-start","bottom-center":"bottom-4 left-1/2 -translate-x-1/2 items-center"};function N(){const{items:e,config:i,remove:l}=h(),c=x[i.position]??x["top-right"];return t.jsx("div",{className:`fixed z-50 flex w-full max-w-sm flex-col gap-3 ${c}`,"aria-live":"polite",children:e.map(n=>t.jsx(v,{toast:n,config:i,position:i.position,onRemove:l},n.id))})}exports.ToastItem=v;exports.ToastProvider=R;exports.Toasts=N;exports.useToast=h;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),r=require("react"),w=require("@inertiajs/react");let b=0;function y(){return`toast-${++b}-${Date.now()}`}const j={duration:5e3,position:"top-right",maxVisible:5,propKey:"toasts"};function C(e,a){switch(a.type){case"ADD":{const u=[{...a.payload,id:y()},...e.items].slice(0,e.config.maxVisible);return{...e,items:u}}case"REMOVE":return{...e,items:e.items.filter(c=>c.id!==a.payload)};case"CLEAR":return{...e,items:[]};default:return e}}const h=r.createContext(null);function R({children:e,config:a}){const c={...j,...a},[u,n]=r.useReducer(C,{items:[],config:c}),d=r.useRef(c);d.current=c,r.useEffect(()=>w.router.on("flash",l=>{const i=l.detail.flash[d.current.propKey];i&&Array.isArray(i)&&i.forEach(m=>{n({type:"ADD",payload:m})})}),[]);const o=r.useCallback((s,l,i)=>{n({type:"ADD",payload:{message:s,level:l,title:(i==null?void 0:i.title)??null,duration:(i==null?void 0:i.duration)??null}})},[]),f={items:u.items,config:u.config,success:r.useCallback((s,l)=>o(s,"success",l),[o]),error:r.useCallback((s,l)=>o(s,"error",l),[o]),info:r.useCallback((s,l)=>o(s,"info",l),[o]),warning:r.useCallback((s,l)=>o(s,"warning",l),[o]),remove:r.useCallback(s=>n({type:"REMOVE",payload:s}),[]),clear:r.useCallback(()=>n({type:"CLEAR"}),[])};return t.jsx(h.Provider,{value:f,children:e})}function v(){const e=r.useContext(h);if(!e)throw new Error("useToast must be used within a <ToastProvider>");return e}const g={success:"bg-green-100 text-green-500",error:"bg-rose-100 text-rose-500",warning:"bg-yellow-100 text-yellow-500",info:"bg-blue-100 text-blue-500"};function T(){return t.jsx("svg",{className:"size-5","aria-hidden":"true",xmlns:"http://www.w3.org/2000/svg",fill:"currentColor",viewBox:"0 0 20 20",children:t.jsx("path",{d:"M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 8.207-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L9 10.586l3.293-3.293a1 1 0 0 1 1.414 1.414Z"})})}function L(){return t.jsx("svg",{className:"size-5","aria-hidden":"true",xmlns:"http://www.w3.org/2000/svg",fill:"currentColor",viewBox:"0 0 20 20",children:t.jsx("path",{d:"M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 11.793a1 1 0 1 1-1.414 1.414L10 11.414l-2.293 2.293a1 1 0 0 1-1.414-1.414L8.586 10 6.293 7.707a1 1 0 0 1 1.414-1.414L10 8.586l2.293-2.293a1 1 0 0 1 1.414 1.414L11.414 10l2.293 2.293Z"})})}function E(){return t.jsx("svg",{className:"size-5",viewBox:"0 0 20 20",fill:"currentColor",children:t.jsx("path",{fillRule:"evenodd",d:"M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z",clipRule:"evenodd"})})}function z(){return t.jsx("svg",{className:"size-5","aria-hidden":"true",xmlns:"http://www.w3.org/2000/svg",fill:"currentColor",viewBox:"0 0 24 24",children:t.jsx("path",{fillRule:"evenodd",d:"M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm8.706-1.442c1.146-.573 2.437.463 2.126 1.706l-.709 2.836.042-.02a.75.75 0 01.67 1.34l-.04.022c-1.147.573-2.438-.463-2.127-1.706l.71-2.836-.042.02a.75.75 0 11-.671-1.34l.041-.022zM12 9a.75.75 0 100-1.5.75.75 0 000 1.5z",clipRule:"evenodd"})})}function A({level:e}){switch(e){case"success":return t.jsx(T,{});case"error":return t.jsx(L,{});case"warning":return t.jsx(E,{});default:return t.jsx(z,{})}}function N(e){return e.includes("right")?"translate-x-full":e.includes("left")?"-translate-x-full":e.startsWith("top")?"-translate-y-full":"translate-y-full"}function p({toast:e,config:a,position:c,onRemove:u}){const n=r.useRef(null),[d,o]=r.useState(!1),f=e.duration??a.duration,s=r.useCallback(()=>{n.current&&(clearTimeout(n.current),n.current=null),o(!1)},[]);r.useEffect(()=>{const m=requestAnimationFrame(()=>o(!0));return()=>cancelAnimationFrame(m)},[]),r.useEffect(()=>(f>0&&(n.current=setTimeout(s,f)),()=>{n.current&&clearTimeout(n.current)}),[f,s]);const l=N(c),i=d?"opacity-100 translate-x-0 translate-y-0 duration-300 ease-out":`opacity-0 ${l} duration-200 ease-in`;return t.jsxs("div",{className:`flex items-center rounded-lg bg-white p-4 text-gray-500 shadow min-w-96 transition ${i}`,role:"alert",onTransitionEnd:()=>{d||u(e.id)},children:[t.jsx("div",{className:`inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg ${g[e.level]??g.info}`,children:t.jsx(A,{level:e.level})}),t.jsxs("div",{className:"ml-3 text-sm font-normal",children:[e.title&&t.jsx("div",{className:"font-semibold text-gray-900 mb-1",children:e.title}),e.message]}),t.jsxs("button",{type:"button",className:"ml-auto inline-flex items-center justify-center h-8 w-8 rounded-lg bg-white p-1.5 text-gray-400 hover:bg-gray-100 hover:text-gray-900 focus:ring-2 focus:ring-gray-300 shrink-0",onClick:s,"aria-label":"Close",children:[t.jsx("span",{className:"sr-only",children:"Close"}),t.jsx("svg",{"aria-hidden":"true",className:"h-5 w-5",fill:"currentColor",viewBox:"0 0 20 20",xmlns:"http://www.w3.org/2000/svg",children:t.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})]})]})}const x={"top-right":"top-4 right-4 items-end","top-left":"top-4 left-4 items-start","top-center":"top-4 left-1/2 -translate-x-1/2 items-center","bottom-right":"bottom-4 right-4 items-end","bottom-left":"bottom-4 left-4 items-start","bottom-center":"bottom-4 left-1/2 -translate-x-1/2 items-center"};function k(){const{items:e,config:a,remove:c}=v(),u=x[a.position]??x["top-right"];return t.jsx("div",{className:`fixed z-50 flex w-full max-w-sm flex-col gap-3 ${u}`,"aria-live":"polite",children:e.map(n=>t.jsx(p,{toast:n,config:a,position:a.position,onRemove:c},n.id))})}exports.ToastItem=p;exports.ToastProvider=R;exports.Toasts=k;exports.useToast=v;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { ToastProvider } from './context';
2
- export type { ToastProviderProps, ToastContextValue } from './context';
2
+ export type { ToastProviderProps, ToastContextValue, ToastOptions } from './context';
3
3
  export { useToast } from './hooks/useToast';
4
4
  export { Toasts } from './components/Toasts';
5
5
  export { ToastItem } from './components/ToastItem';
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { jsx as t, jsxs as p } from "react/jsx-runtime";
2
- import { createContext as y, useReducer as b, useRef as w, useEffect as g, useCallback as c, useContext as C, useState as R } from "react";
1
+ import { jsx as t, jsxs as g } from "react/jsx-runtime";
2
+ import { createContext as y, useReducer as b, useRef as w, useEffect as h, useCallback as u, useContext as C, useState as R } from "react";
3
3
  import { router as L } from "@inertiajs/react";
4
4
  let T = 0;
5
5
  function z() {
@@ -11,19 +11,19 @@ const A = {
11
11
  maxVisible: 5,
12
12
  propKey: "toasts"
13
13
  };
14
- function E(e, i) {
15
- switch (i.type) {
14
+ function E(e, l) {
15
+ switch (l.type) {
16
16
  case "ADD": {
17
- const a = [{
18
- ...i.payload,
17
+ const c = [{
18
+ ...l.payload,
19
19
  id: z()
20
20
  }, ...e.items].slice(0, e.config.maxVisible);
21
- return { ...e, items: a };
21
+ return { ...e, items: c };
22
22
  }
23
23
  case "REMOVE":
24
24
  return {
25
25
  ...e,
26
- items: e.items.filter((l) => l.id !== i.payload)
26
+ items: e.items.filter((a) => a.id !== l.payload)
27
27
  };
28
28
  case "CLEAR":
29
29
  return { ...e, items: [] };
@@ -32,31 +32,31 @@ function E(e, i) {
32
32
  }
33
33
  }
34
34
  const x = y(null);
35
- function S({ children: e, config: i }) {
36
- const l = { ...A, ...i }, [a, n] = b(E, {
35
+ function S({ children: e, config: l }) {
36
+ const a = { ...A, ...l }, [c, n] = b(E, {
37
37
  items: [],
38
- config: l
39
- }), d = w(l);
40
- d.current = l, g(() => L.on("flash", (o) => {
41
- const u = o.detail.flash[d.current.propKey];
42
- u && Array.isArray(u) && u.forEach((m) => {
38
+ config: a
39
+ }), d = w(a);
40
+ d.current = a, h(() => L.on("flash", (i) => {
41
+ const s = i.detail.flash[d.current.propKey];
42
+ s && Array.isArray(s) && s.forEach((m) => {
43
43
  n({ type: "ADD", payload: m });
44
44
  });
45
45
  }), []);
46
- const s = c((r, o, u) => {
46
+ const o = u((r, i, s) => {
47
47
  n({
48
48
  type: "ADD",
49
- payload: { message: r, level: o, duration: u ?? null }
49
+ payload: { message: r, level: i, title: (s == null ? void 0 : s.title) ?? null, duration: (s == null ? void 0 : s.duration) ?? null }
50
50
  });
51
51
  }, []), f = {
52
- items: a.items,
53
- config: a.config,
54
- success: c((r, o) => s(r, "success", o), [s]),
55
- error: c((r, o) => s(r, "error", o), [s]),
56
- info: c((r, o) => s(r, "info", o), [s]),
57
- warning: c((r, o) => s(r, "warning", o), [s]),
58
- remove: c((r) => n({ type: "REMOVE", payload: r }), []),
59
- clear: c(() => n({ type: "CLEAR" }), [])
52
+ items: c.items,
53
+ config: c.config,
54
+ success: u((r, i) => o(r, "success", i), [o]),
55
+ error: u((r, i) => o(r, "error", i), [o]),
56
+ info: u((r, i) => o(r, "info", i), [o]),
57
+ warning: u((r, i) => o(r, "warning", i), [o]),
58
+ remove: u((r) => n({ type: "REMOVE", payload: r }), []),
59
+ clear: u(() => n({ type: "CLEAR" }), [])
60
60
  };
61
61
  return /* @__PURE__ */ t(x.Provider, { value: f, children: e });
62
62
  }
@@ -66,7 +66,7 @@ function N() {
66
66
  throw new Error("useToast must be used within a <ToastProvider>");
67
67
  return e;
68
68
  }
69
- const h = {
69
+ const p = {
70
70
  success: "bg-green-100 text-green-500",
71
71
  error: "bg-rose-100 text-rose-500",
72
72
  warning: "bg-yellow-100 text-yellow-500",
@@ -136,39 +136,42 @@ function B({ level: e }) {
136
136
  function V(e) {
137
137
  return e.includes("right") ? "translate-x-full" : e.includes("left") ? "-translate-x-full" : e.startsWith("top") ? "-translate-y-full" : "translate-y-full";
138
138
  }
139
- function j({ toast: e, config: i, position: l, onRemove: a }) {
140
- const n = w(null), [d, s] = R(!1), f = e.duration ?? i.duration, r = c(() => {
141
- n.current && (clearTimeout(n.current), n.current = null), s(!1);
139
+ function j({ toast: e, config: l, position: a, onRemove: c }) {
140
+ const n = w(null), [d, o] = R(!1), f = e.duration ?? l.duration, r = u(() => {
141
+ n.current && (clearTimeout(n.current), n.current = null), o(!1);
142
142
  }, []);
143
- g(() => {
144
- const m = requestAnimationFrame(() => s(!0));
143
+ h(() => {
144
+ const m = requestAnimationFrame(() => o(!0));
145
145
  return () => cancelAnimationFrame(m);
146
- }, []), g(() => (f > 0 && (n.current = setTimeout(r, f)), () => {
146
+ }, []), h(() => (f > 0 && (n.current = setTimeout(r, f)), () => {
147
147
  n.current && clearTimeout(n.current);
148
148
  }), [f, r]);
149
- const o = V(l), u = d ? "opacity-100 translate-x-0 translate-y-0 duration-300 ease-out" : `opacity-0 ${o} duration-200 ease-in`;
150
- return /* @__PURE__ */ p(
149
+ const i = V(a), s = d ? "opacity-100 translate-x-0 translate-y-0 duration-300 ease-out" : `opacity-0 ${i} duration-200 ease-in`;
150
+ return /* @__PURE__ */ g(
151
151
  "div",
152
152
  {
153
- className: `flex items-center rounded-lg bg-white p-4 text-gray-500 shadow min-w-96 transition ${u}`,
153
+ className: `flex items-center rounded-lg bg-white p-4 text-gray-500 shadow min-w-96 transition ${s}`,
154
154
  role: "alert",
155
155
  onTransitionEnd: () => {
156
- d || a(e.id);
156
+ d || c(e.id);
157
157
  },
158
158
  children: [
159
159
  /* @__PURE__ */ t(
160
160
  "div",
161
161
  {
162
- className: `inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg ${h[e.level] ?? h.info}`,
162
+ className: `inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg ${p[e.level] ?? p.info}`,
163
163
  children: /* @__PURE__ */ t(B, { level: e.level })
164
164
  }
165
165
  ),
166
- /* @__PURE__ */ t("div", { className: "ml-3 text-sm font-normal", children: e.message }),
167
- /* @__PURE__ */ p(
166
+ /* @__PURE__ */ g("div", { className: "ml-3 text-sm font-normal", children: [
167
+ e.title && /* @__PURE__ */ t("div", { className: "font-semibold text-gray-900 mb-1", children: e.title }),
168
+ e.message
169
+ ] }),
170
+ /* @__PURE__ */ g(
168
171
  "button",
169
172
  {
170
173
  type: "button",
171
- className: "ml-auto inline-flex items-center justify-center h-8 w-8 rounded-lg bg-white p-1.5 text-gray-400 hover:bg-gray-100 hover:text-gray-900 focus:ring-2 focus:ring-gray-300",
174
+ className: "ml-auto inline-flex items-center justify-center h-8 w-8 rounded-lg bg-white p-1.5 text-gray-400 hover:bg-gray-100 hover:text-gray-900 focus:ring-2 focus:ring-gray-300 shrink-0",
172
175
  onClick: r,
173
176
  "aria-label": "Close",
174
177
  children: [
@@ -207,13 +210,13 @@ const v = {
207
210
  "bottom-center": "bottom-4 left-1/2 -translate-x-1/2 items-center"
208
211
  };
209
212
  function F() {
210
- const { items: e, config: i, remove: l } = N(), a = v[i.position] ?? v["top-right"];
213
+ const { items: e, config: l, remove: a } = N(), c = v[l.position] ?? v["top-right"];
211
214
  return /* @__PURE__ */ t(
212
215
  "div",
213
216
  {
214
- className: `fixed z-50 flex w-full max-w-sm flex-col gap-3 ${a}`,
217
+ className: `fixed z-50 flex w-full max-w-sm flex-col gap-3 ${c}`,
215
218
  "aria-live": "polite",
216
- children: e.map((n) => /* @__PURE__ */ t(j, { toast: n, config: i, position: i.position, onRemove: l }, n.id))
219
+ children: e.map((n) => /* @__PURE__ */ t(j, { toast: n, config: l, position: l.position, onRemove: a }, n.id))
217
220
  }
218
221
  );
219
222
  }
package/dist/types.d.ts CHANGED
@@ -2,6 +2,7 @@ export type ToastLevel = 'success' | 'error' | 'info' | 'warning';
2
2
  export interface ToastMessage {
3
3
  message: string;
4
4
  level: ToastLevel;
5
+ title: string | null;
5
6
  duration: number | null;
6
7
  }
7
8
  export interface ToastItem extends ToastMessage {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@laravel-inertia-toast/react",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "React toast components for Laravel Inertia Toast",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -15,7 +15,8 @@
15
15
  }
16
16
  },
17
17
  "files": [
18
- "dist"
18
+ "dist",
19
+ "README.md"
19
20
  ],
20
21
  "scripts": {
21
22
  "build": "vite build && tsc --emitDeclarationOnly",