react-native-bread 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -4
- package/lib/commonjs/constants.js +1 -0
- package/lib/commonjs/pool.js +1 -0
- package/lib/commonjs/toast-api.js +1 -1
- package/lib/commonjs/toast-icons.js +1 -0
- package/lib/commonjs/toast.js +1 -1
- package/lib/commonjs/use-toast-state.js +1 -0
- package/lib/module/constants.js +1 -0
- package/lib/module/pool.js +1 -0
- package/lib/module/toast-api.js +1 -1
- package/lib/module/toast-icons.js +1 -0
- package/lib/module/toast.js +1 -1
- package/lib/module/use-toast-state.js +1 -0
- package/lib/typescript/constants.d.ts +18 -0
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/pool.d.ts +16 -0
- package/lib/typescript/toast-api.d.ts +29 -2
- package/lib/typescript/toast-icons.d.ts +10 -0
- package/lib/typescript/types.d.ts +41 -0
- package/lib/typescript/use-toast-state.d.ts +16 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ An extremely lightweight, opinionated toast component for React Native.
|
|
|
11
11
|
- Zero setup - add one component, start toasting. No hooks, no providers
|
|
12
12
|
- Built for mobile with smooth 60fps animations powered by Reanimated
|
|
13
13
|
- Natural swipe gestures that feel native to the platform
|
|
14
|
-
- Multiple toast types: `success`, `error`, `info`, and `
|
|
14
|
+
- Multiple toast types: `success`, `error`, `info`, `promise`, and `custom`
|
|
15
15
|
- Promise handling with automatic loading → success/error states
|
|
16
16
|
- Complex animations and gestures but with high performance
|
|
17
17
|
- Toast stacking with configurable limits
|
|
@@ -35,11 +35,11 @@ This package requires the following peer dependencies:
|
|
|
35
35
|
|
|
36
36
|
| Package | Version |
|
|
37
37
|
|---------|---------|
|
|
38
|
-
| [react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started) | >= 4.
|
|
38
|
+
| [react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started) | >= 4.1.0 |
|
|
39
39
|
| [react-native-gesture-handler](https://docs.swmansion.com/react-native-gesture-handler/docs/) | >= 2.25.0 |
|
|
40
40
|
| [react-native-safe-area-context](https://docs.expo.dev/versions/latest/sdk/safe-area-context/) | >= 5.0.0 |
|
|
41
41
|
| [react-native-svg](https://github.com/software-mansion/react-native-svg) | >= 15.8.0 |
|
|
42
|
-
| [react-native-worklets](https://github.com/margelo/react-native-worklets-core) | >= 0.
|
|
42
|
+
| [react-native-worklets](https://github.com/margelo/react-native-worklets-core) | >= 0.5.0 |
|
|
43
43
|
|
|
44
44
|
If you don't have these installed, you can install all peer dependencies at once:
|
|
45
45
|
|
|
@@ -53,7 +53,7 @@ Or with npm:
|
|
|
53
53
|
npm install react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-svg react-native-worklets
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
> **Note**: `react-native-reanimated`
|
|
56
|
+
> **Note**: Make sure your `react-native-reanimated` and `react-native-worklets` versions are compatible. Reanimated 4.1.x works with worklets 0.5.x-0.7.x, while Reanimated 4.2.x requires worklets 0.7.x only.
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
## Usage
|
|
@@ -115,6 +115,15 @@ toast.promise(fetchData(), {
|
|
|
115
115
|
success: { title: 'Done!', description: 'Data loaded' },
|
|
116
116
|
error: (err) => ({ title: 'Failed', description: err.message }),
|
|
117
117
|
});
|
|
118
|
+
|
|
119
|
+
// Custom toast - fully custom content with animations
|
|
120
|
+
toast.custom(({ dismiss }) => (
|
|
121
|
+
<View style={{ padding: 16, flexDirection: 'row', alignItems: 'center' }}>
|
|
122
|
+
<Image source={{ uri: 'avatar.png' }} style={{ width: 40, height: 40 }} />
|
|
123
|
+
<Text>New message from John</Text>
|
|
124
|
+
<Button title="Reply" onPress={dismiss} />
|
|
125
|
+
</View>
|
|
126
|
+
));
|
|
118
127
|
```
|
|
119
128
|
|
|
120
129
|
## Customization
|
|
@@ -134,6 +143,36 @@ toast.success('Saved!', {
|
|
|
134
143
|
});
|
|
135
144
|
```
|
|
136
145
|
|
|
146
|
+
### Custom Toasts
|
|
147
|
+
|
|
148
|
+
Create fully custom toasts where you control all the content. Your component fills the entire toast container and receives all entry/exit/stack animations automatically:
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
// Using a render function (recommended - gives access to dismiss)
|
|
152
|
+
toast.custom(({ dismiss, id, type, isExiting }) => (
|
|
153
|
+
<View style={{ padding: 16, flexDirection: 'row', alignItems: 'center', gap: 12 }}>
|
|
154
|
+
<Image source={{ uri: 'avatar.png' }} style={{ width: 44, height: 44, borderRadius: 22 }} />
|
|
155
|
+
<View style={{ flex: 1 }}>
|
|
156
|
+
<Text style={{ fontWeight: '600' }}>New message</Text>
|
|
157
|
+
<Text style={{ color: '#666' }}>Hey, check this out!</Text>
|
|
158
|
+
</View>
|
|
159
|
+
<Pressable onPress={dismiss}>
|
|
160
|
+
<Text style={{ color: '#3b82f6' }}>Reply</Text>
|
|
161
|
+
</Pressable>
|
|
162
|
+
</View>
|
|
163
|
+
));
|
|
164
|
+
|
|
165
|
+
// Or pass a React component directly
|
|
166
|
+
toast.custom(<MyNotificationCard />);
|
|
167
|
+
|
|
168
|
+
// With options
|
|
169
|
+
toast.custom(<MyToast />, {
|
|
170
|
+
duration: 5000,
|
|
171
|
+
dismissible: false,
|
|
172
|
+
style: { backgroundColor: '#fef2f2' }
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
137
176
|
### Global Configuration
|
|
138
177
|
|
|
139
178
|
Customize all toasts globally via the `config` prop on `<BreadLoaf />`:
|
|
@@ -174,6 +213,7 @@ Available options include:
|
|
|
174
213
|
| `toast.error(title, description?)` | Show error toast |
|
|
175
214
|
| `toast.info(title, description?)` | Show info toast |
|
|
176
215
|
| `toast.promise(promise, messages)` | Show loading → success/error toast |
|
|
216
|
+
| `toast.custom(content, options?)` | Show fully custom toast with your own content |
|
|
177
217
|
| `toast.dismiss(id)` | Dismiss a specific toast |
|
|
178
218
|
| `toast.dismissAll()` | Dismiss all toasts |
|
|
179
219
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.SWIPE_EXIT_OFFSET=exports.STACK_TRANSITION_DURATION=exports.STACK_SCALE_PER_ITEM=exports.STACK_OFFSET_PER_ITEM=exports.SPRING_BACK_DURATION=exports.POOL_SIZE=exports.MAX_DRAG_RESISTANCE=exports.MAX_DRAG_CLAMP=exports.ICON_SIZE=exports.ICON_ANIMATION_DURATION=exports.EXIT_OFFSET=exports.EXIT_DURATION=exports.ENTRY_OFFSET=exports.ENTRY_DURATION=exports.EASING=exports.DISMISS_VELOCITY_THRESHOLD=exports.DISMISS_THRESHOLD=void 0;var _=require("react-native-reanimated");exports.ICON_SIZE=28,exports.POOL_SIZE=5,exports.ENTRY_DURATION=400,exports.EXIT_DURATION=350,exports.STACK_TRANSITION_DURATION=300,exports.SPRING_BACK_DURATION=650,exports.ICON_ANIMATION_DURATION=350,exports.ENTRY_OFFSET=80,exports.EXIT_OFFSET=100,exports.SWIPE_EXIT_OFFSET=200,exports.MAX_DRAG_CLAMP=180,exports.MAX_DRAG_RESISTANCE=60,exports.DISMISS_THRESHOLD=40,exports.DISMISS_VELOCITY_THRESHOLD=300,exports.STACK_OFFSET_PER_ITEM=10,exports.STACK_SCALE_PER_ITEM=.05,exports.EASING=_.Easing.bezier(.25,.1,.25,1);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.slotTrackers=exports.releaseSlot=exports.getSlotIndex=exports.animationPool=void 0;var e=require("react-native-reanimated"),t=require("./constants.js");exports.animationPool=Array.from({length:t.POOL_SIZE},()=>({progress:(0,e.makeMutable)(0),translationY:(0,e.makeMutable)(0),stackIndex:(0,e.makeMutable)(0)}));const r=exports.slotTrackers=Array.from({length:t.POOL_SIZE},()=>({wasExiting:!1,prevIndex:0,initialized:!1})),a=new Map,i=new Set;exports.getSlotIndex=e=>{if(a.has(e))return a.get(e)??0;for(let o=0;o<t.POOL_SIZE;o++)if(!i.has(o))return a.set(e,o),i.add(o),r[o].initialized=!1,r[o].wasExiting=!1,r[o].prevIndex=0,o;return 0};exports.releaseSlot=e=>{const t=a.get(e);void 0!==t&&(i.delete(t),a.delete(e),r[t].initialized=!1,r[t].wasExiting=!1,r[t].prevIndex=0)};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.toast=void 0;var t=require("./toast-store.js");const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.toast=void 0;var t=require("react-native-worklets"),o=require("./toast-store.js");const s=t=>t?"string"==typeof t?{description:t}:{description:t.description,duration:t.duration,options:t}:{},e=t=>"string"==typeof t?{title:t}:t,r=(t,s,e,r)=>{o.toastStore.show(t,s,e,r)};r.custom=(t,s)=>{const e=s?.type??"info";return o.toastStore.show("",void 0,e,s?.duration,{...s,customContent:t})},r.success=(t,e,r)=>{const{description:i,duration:n,options:c}=s(e);o.toastStore.show(t,i,"success",r??n,c)},r.error=(t,e,r)=>{const{description:i,duration:n,options:c}=s(e);o.toastStore.show(t,i,"error",r??n,c)},r.info=(t,e,r)=>{const{description:i,duration:n,options:c}=s(e);o.toastStore.show(t,i,"info",r??n,c)},r.promise=async(s,r)=>{const i=e(r.loading);let n="";await new Promise(s=>{(0,t.scheduleOnRN)(()=>{n=o.toastStore.show(i.title,i.description,"loading",i.duration??36e5),s()})});try{const i=await s,c=e(r.success);return(0,t.scheduleOnRN)(()=>{o.toastStore.updateToast(n,{title:c.title,description:c.description,type:"success",duration:c.duration??4e3})}),{data:i,success:!0}}catch(s){const i=s instanceof Error?s:new Error(String(s)),c=((t,o)=>e("function"==typeof t?t(o):t))(r.error,i);return(0,t.scheduleOnRN)(()=>{o.toastStore.updateToast(n,{title:c.title,description:c.description,type:"error",duration:c.duration??4e3})}),{error:i,success:!1}}},r.dismiss=t=>{o.toastStore.hide(t)},r.dismissAll=()=>{o.toastStore.hideAll()};exports.toast=r;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.resolveIcon=exports.AnimatedIcon=void 0;var e=require("react"),t=require("react-native"),r=function(e,t){if("function"==typeof WeakMap)var r=new WeakMap,n=new WeakMap;return function(e,t){if(!t&&e&&e.__esModule)return e;var i,o,s={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return s;if(i=t?n:r){if(i.has(e))return i.get(e);i.set(e,s)}for(const t in e)"default"!==t&&{}.hasOwnProperty.call(e,t)&&((o=(i=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,t))&&(o.get||o.set)?i(s,t,o):s[t]=e[t]);return s}(e,t)}(require("react-native-reanimated")),n=require("./constants.js"),i=require("./icons/index.js"),o=require("react/jsx-runtime");const s=(e,r,s,a)=>{if(s)return"function"==typeof s?s({color:r,size:n.ICON_SIZE}):s;if(a)return a({color:r,size:n.ICON_SIZE});switch(e){case"success":default:return(0,o.jsx)(i.GreenCheck,{width:36,height:36,fill:r});case"error":return(0,o.jsx)(i.RedX,{width:n.ICON_SIZE,height:n.ICON_SIZE,fill:r});case"loading":return(0,o.jsx)(t.ActivityIndicator,{size:n.ICON_SIZE,color:r});case"info":return(0,o.jsx)(i.InfoIcon,{width:n.ICON_SIZE,height:n.ICON_SIZE,fill:r})}};exports.resolveIcon=s;exports.AnimatedIcon=(0,e.memo)(({type:t,color:i,custom:a,config:c})=>{const u=(0,r.useSharedValue)(0);(0,e.useEffect)(()=>{u.value=(0,r.withTiming)(1,{duration:n.ICON_ANIMATION_DURATION,easing:r.Easing.out(r.Easing.back(1.5))})},[u]);const l=(0,r.useAnimatedStyle)(()=>({opacity:u.value,transform:[{scale:.7+.3*u.value}]}));return(0,o.jsx)(r.default.View,{style:l,children:s(t,i,a,c)})});
|
package/lib/commonjs/toast.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ToastContainer=void 0;var t=require("react"),e=require("react-native"),i=require("react-native-gesture-handler"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ToastContainer=void 0;var t=require("react"),e=require("react-native"),i=require("react-native-gesture-handler"),o=function(t,e){if("function"==typeof WeakMap)var i=new WeakMap,o=new WeakMap;return function(t,e){if(!e&&t&&t.__esModule)return t;var n,s,a={__proto__:null,default:t};if(null===t||"object"!=typeof t&&"function"!=typeof t)return a;if(n=e?o:i){if(n.has(t))return n.get(t);n.set(t,a)}for(const e in t)"default"!==e&&{}.hasOwnProperty.call(t,e)&&((s=(n=Object.defineProperty)&&Object.getOwnPropertyDescriptor(t,e))&&(s.get||s.set)?n(a,e,s):a[e]=t[e]);return a}(t,e)}(require("react-native-reanimated")),n=require("react-native-safe-area-context"),s=require("react-native-worklets"),a=require("./constants.js"),r=require("./icons/index.js"),l=require("./pool.js"),u=require("./toast-icons.js"),c=require("./toast-store.js"),d=require("./use-toast-state.js"),p=require("react/jsx-runtime");exports.ToastContainer=()=>{const{top:r,bottom:l}=(0,n.useSafeAreaInsets)(),{visibleToasts:u,theme:c,toastsWithIndex:T,isBottom:I,topToastRef:h,isBottomRef:f,isDismissibleRef:E}=(0,d.useToastState)(),m=(0,o.useSharedValue)(!1),x=(0,t.useMemo)(()=>i.Gesture.Pan().onStart(()=>{"worklet";m.set(!1)}).onUpdate(t=>{"worklet";if(!E.current.value)return;const e=h.current.value;if(!e)return;const{slot:i}=e,o=f.current.value,n=t.translationY,s=o?n:-n,r=o?-n:n;if(s>0){const e=o?Math.min(n,a.MAX_DRAG_CLAMP):Math.max(n,-a.MAX_DRAG_CLAMP);i.translationY.value=e;const r=s>a.DISMISS_THRESHOLD||(o?t.velocityY>a.DISMISS_VELOCITY_THRESHOLD:t.velocityY<-a.DISMISS_VELOCITY_THRESHOLD);m.set(r)}else{const t=a.MAX_DRAG_RESISTANCE*(1-Math.exp(-r/250));i.translationY.value=o?-Math.min(t,a.MAX_DRAG_RESISTANCE):Math.min(t,a.MAX_DRAG_RESISTANCE),m.value=!1}}).onEnd(()=>{"worklet";if(!E.current.value)return;const t=h.current.value;if(!t)return;const{slot:e}=t,i=f.current.value;if(m.value){e.progress.value=(0,o.withTiming)(0,{duration:a.EXIT_DURATION,easing:a.EASING});const n=i?a.SWIPE_EXIT_OFFSET:-a.SWIPE_EXIT_OFFSET;e.translationY.value=(0,o.withTiming)(e.translationY.value+n,{duration:a.EXIT_DURATION,easing:a.EASING}),(0,s.scheduleOnRN)(t.dismiss)}else e.translationY.value=(0,o.withTiming)(0,{duration:a.SPRING_BACK_DURATION,easing:a.EASING})}),[m,E,h,f]),v=(0,t.useCallback)(t=>{h.current.value=t},[h]);if(0===u.length)return null;const _=I?l:r,y=I?{bottom:_+c.offset+2}:{top:_+c.offset+2};return(0,p.jsx)(i.GestureDetector,{gesture:x,children:(0,p.jsx)(e.View,{style:[S.container,y],pointerEvents:"box-none",children:T.map(({toast:t,index:e})=>(0,p.jsx)(g,{toast:t,index:e,theme:c,position:c.position,isTopToast:0===e,registerTopToast:v},t.id))})})};const T=({toast:i,index:n,theme:s,position:d,isTopToast:T,registerTopToast:g})=>{const[I]=(0,t.useState)(()=>(0,l.getSlotIndex)(i.id)),h=l.animationPool[I],f=l.slotTrackers[I],E="bottom"===d,m=E?a.ENTRY_OFFSET:-a.ENTRY_OFFSET,x=E?a.EXIT_OFFSET:-a.EXIT_OFFSET,[v,_]=(0,t.useState)("loading"===i.type),[y,A]=(0,t.useState)(!1);(0,t.useEffect)(()=>{h.progress.value=0,h.translationY.value=0,h.stackIndex.value=n,h.progress.value=(0,o.withTiming)(1,{duration:a.ENTRY_DURATION,easing:a.EASING});const t=setTimeout(()=>A(!0),50);return()=>{clearTimeout(t),(0,l.releaseSlot)(i.id)}},[]);const w=(0,t.useCallback)(()=>{c.toastStore.hide(i.id)},[i.id]);(0,t.useEffect)(()=>{let t=null;return i.isExiting&&!f.wasExiting&&(f.wasExiting=!0,h.progress.value=(0,o.withTiming)(0,{duration:a.EXIT_DURATION,easing:a.EASING}),h.translationY.value=(0,o.withTiming)(x,{duration:a.EXIT_DURATION,easing:a.EASING})),f.initialized&&n!==f.prevIndex&&(h.stackIndex.value=(0,o.withTiming)(n,{duration:a.STACK_TRANSITION_DURATION,easing:a.EASING})),f.prevIndex=n,f.initialized=!0,"loading"===i.type?_(!0):v&&(t=setTimeout(()=>_(!1),a.ICON_ANIMATION_DURATION+50)),T&&g({slot:h,dismiss:w}),()=>{t&&clearTimeout(t),T&&g(null)}},[i.isExiting,n,h,f,x,i.type,v,T,g,w]);const C=v&&"loading"!==i.type,R=(0,o.useAnimatedStyle)(()=>{const t=(0,o.interpolate)(h.progress.value,[0,1],[m,0]),e=E?h.stackIndex.value*a.STACK_OFFSET_PER_ITEM:h.stackIndex.value*-a.STACK_OFFSET_PER_ITEM,i=1-h.stackIndex.value*a.STACK_SCALE_PER_ITEM,n=t+h.translationY.value+e,s=(0,o.interpolate)(h.progress.value,[0,1],[0,1]),r=E?h.translationY.value:-h.translationY.value,l=s*(r>0?(0,o.interpolate)(r,[0,130],[1,0],"clamp"):1);return{transform:[{translateY:n},{scale:i*(0,o.interpolate)(Math.abs(h.translationY.value),[0,50],[1,.98],"clamp")}],opacity:l,zIndex:1e3-Math.round(h.stackIndex.value)}}),{options:O}=i,M=s.colors[i.type];if(void 0!==O?.customContent){const t=O.customContent;return(0,p.jsx)(o.default.View,{style:[S.toast,S.customContentToast,E?S.toastBottom:S.toastTop,{backgroundColor:M.background},s.toastStyle,O.style,R],children:"function"==typeof t?t({id:i.id,dismiss:w,type:i.type,isExiting:!!i.isExiting}):t})}const N="loading"!==i.type&&(O?.showCloseButton??s.showCloseButton);return(0,p.jsxs)(o.default.View,{style:[S.toast,E?S.toastBottom:S.toastTop,{backgroundColor:M.background},s.rtl&&S.rtl,s.toastStyle,O?.style,R],children:[(0,p.jsx)(e.View,{style:S.iconContainer,children:y&&(C?(0,p.jsx)(u.AnimatedIcon,{type:i.type,color:M.accent,custom:O?.icon,config:s.icons[i.type]},i.type):(0,u.resolveIcon)(i.type,M.accent,O?.icon,s.icons[i.type]))}),(0,p.jsxs)(e.View,{style:S.textContainer,children:[(0,p.jsx)(e.Text,{maxFontSizeMultiplier:1.35,allowFontScaling:!1,style:[S.title,{color:M.accent},s.rtl&&{textAlign:"right"},s.titleStyle,O?.titleStyle],children:i.title}),i.description&&(0,p.jsx)(e.Text,{allowFontScaling:!1,maxFontSizeMultiplier:1.35,style:[S.description,s.rtl&&{textAlign:"right"},s.descriptionStyle,O?.descriptionStyle],children:i.description})]}),N&&(0,p.jsx)(e.Pressable,{style:S.closeButton,onPress:w,hitSlop:12,children:(0,p.jsx)(r.CloseIcon,{width:20,height:20})})]})},g=(0,t.memo)(T,(t,e)=>t.toast.id===e.toast.id&&t.toast.type===e.toast.type&&t.toast.title===e.toast.title&&t.toast.description===e.toast.description&&t.toast.isExiting===e.toast.isExiting&&t.index===e.index&&t.position===e.position&&t.theme===e.theme&&t.isTopToast===e.isTopToast),S=e.StyleSheet.create({container:{position:"absolute",left:16,right:16,zIndex:1e3},toast:{flexDirection:"row",alignItems:"center",gap:12,minHeight:36,borderRadius:20,borderCurve:"continuous",position:"absolute",left:0,right:0,paddingHorizontal:12,paddingVertical:10,shadowColor:"#000",shadowOffset:{width:0,height:8},shadowOpacity:.05,shadowRadius:24,elevation:8},customContentToast:{padding:0,paddingHorizontal:0,paddingVertical:0,overflow:"hidden"},rtl:{flexDirection:"row-reverse"},toastTop:{top:0},toastBottom:{bottom:0},iconContainer:{width:48,height:48,alignItems:"center",justifyContent:"center",marginLeft:8},textContainer:{flex:1,gap:1,justifyContent:"center"},title:{fontSize:14,fontWeight:"700",lineHeight:20},description:{color:"#6B7280",fontSize:12,fontWeight:"500",lineHeight:16},closeButton:{padding:4,alignItems:"center",justifyContent:"center"}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.useToastState=void 0;var t=require("react"),e=require("react-native-reanimated"),s=require("./toast-store.js");exports.useToastState=()=>{const[i,o]=(0,t.useState)([]),[n,a]=(0,t.useState)(()=>s.toastStore.getTheme()),r=(0,t.useRef)((0,e.makeMutable)(null)),u=(0,t.useRef)((0,e.makeMutable)("bottom"===n.position)),l=(0,t.useRef)((0,e.makeMutable)(!0)),m="bottom"===n.position,b=i.find(t=>!t.isExiting),c=b?.options?.dismissible??n.dismissible;(0,t.useEffect)(()=>{const t=s.toastStore.getState().visibleToasts,e=s.toastStore.getTheme();o(t);const i=t.find(t=>!t.isExiting);u.current.value="bottom"===e.position,l.current.value=i?.options?.dismissible??e.dismissible;let n=null,r=null;const m=s.toastStore.subscribe(t=>{n=t.visibleToasts,null===r&&(r=requestAnimationFrame(()=>{const t=n??s.toastStore.getState().visibleToasts,e=s.toastStore.getTheme();n&&(o(n),n=null),r=null,a(t=>t===e?t:e);const i=t.find(t=>!t.isExiting);u.current.value="bottom"===e.position,l.current.value=i?.options?.dismissible??e.dismissible}))});return m},[]);const d=(0,t.useMemo)(()=>{const t=new Map;let e=0;for(const s of i)t.set(s.id,s.isExiting?-1:e),s.isExiting||e++;return[...i].reverse().map(e=>({toast:e,index:t.get(e.id)??0}))},[i]);return{visibleToasts:i,theme:n,toastsWithIndex:d,isBottom:m,isTopDismissible:c,topToastRef:r,isBottomRef:u,isDismissibleRef:l}};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";import{Easing as t}from"react-native-reanimated";export const ICON_SIZE=28;export const POOL_SIZE=5;export const ENTRY_DURATION=400;export const EXIT_DURATION=350;export const STACK_TRANSITION_DURATION=300;export const SPRING_BACK_DURATION=650;export const ICON_ANIMATION_DURATION=350;export const ENTRY_OFFSET=80;export const EXIT_OFFSET=100;export const SWIPE_EXIT_OFFSET=200;export const MAX_DRAG_CLAMP=180;export const MAX_DRAG_RESISTANCE=60;export const DISMISS_THRESHOLD=40;export const DISMISS_VELOCITY_THRESHOLD=300;export const STACK_OFFSET_PER_ITEM=10;export const STACK_SCALE_PER_ITEM=.05;export const EASING=t.bezier(.25,.1,.25,1);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";import{makeMutable as t}from"react-native-reanimated";import{POOL_SIZE as e}from"./constants.js";export const animationPool=Array.from({length:e},()=>({progress:t(0),translationY:t(0),stackIndex:t(0)}));export const slotTrackers=Array.from({length:e},()=>({wasExiting:!1,prevIndex:0,initialized:!1}));const r=new Map,s=new Set;export const getSlotIndex=t=>{if(r.has(t))return r.get(t)??0;for(let o=0;o<e;o++)if(!s.has(o))return r.set(t,o),s.add(o),slotTrackers[o].initialized=!1,slotTrackers[o].wasExiting=!1,slotTrackers[o].prevIndex=0,o;return 0};export const releaseSlot=t=>{const e=r.get(t);void 0!==e&&(s.delete(e),r.delete(t),slotTrackers[e].initialized=!1,slotTrackers[e].wasExiting=!1,slotTrackers[e].prevIndex=0)};
|
package/lib/module/toast-api.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{
|
|
1
|
+
"use strict";import{scheduleOnRN as t}from"react-native-worklets";import{toastStore as o}from"./toast-store.js";const s=t=>t?"string"==typeof t?{description:t}:{description:t.description,duration:t.duration,options:t}:{},i=t=>"string"==typeof t?{title:t}:t,r=(t,s,i,r)=>{o.show(t,s,i,r)};r.custom=(t,s)=>{const i=s?.type??"info";return o.show("",void 0,i,s?.duration,{...s,customContent:t})},r.success=(t,i,r)=>{const{description:e,duration:n,options:c}=s(i);o.show(t,e,"success",r??n,c)},r.error=(t,i,r)=>{const{description:e,duration:n,options:c}=s(i);o.show(t,e,"error",r??n,c)},r.info=(t,i,r)=>{const{description:e,duration:n,options:c}=s(i);o.show(t,e,"info",r??n,c)},r.promise=async(s,r)=>{const e=i(r.loading);let n="";await new Promise(s=>{t(()=>{n=o.show(e.title,e.description,"loading",e.duration??36e5),s()})});try{const e=await s,c=i(r.success);return t(()=>{o.updateToast(n,{title:c.title,description:c.description,type:"success",duration:c.duration??4e3})}),{data:e,success:!0}}catch(s){const e=s instanceof Error?s:new Error(String(s)),c=((t,o)=>i("function"==typeof t?t(o):t))(r.error,e);return t(()=>{o.updateToast(n,{title:c.title,description:c.description,type:"error",duration:c.duration??4e3})}),{error:e,success:!1}}},r.dismiss=t=>{o.hide(t)},r.dismissAll=()=>{o.hideAll()};export const toast=r;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";import{memo as t,useEffect as e}from"react";import{ActivityIndicator as r}from"react-native";import o,{Easing as i,useAnimatedStyle as c,useSharedValue as n,withTiming as s}from"react-native-reanimated";import{ICON_ANIMATION_DURATION as a,ICON_SIZE as l}from"./constants.js";import{GreenCheck as u,InfoIcon as f,RedX as m}from"./icons/index.js";import{jsx as h}from"react/jsx-runtime";export const resolveIcon=(t,e,o,i)=>{if(o)return"function"==typeof o?o({color:e,size:l}):o;if(i)return i({color:e,size:l});switch(t){case"success":default:return h(u,{width:36,height:36,fill:e});case"error":return h(m,{width:l,height:l,fill:e});case"loading":return h(r,{size:l,color:e});case"info":return h(f,{width:l,height:l,fill:e})}};export const AnimatedIcon=t(({type:t,color:r,custom:l,config:u})=>{const f=n(0);e(()=>{f.value=s(1,{duration:a,easing:i.out(i.back(1.5))})},[f]);const m=c(()=>({opacity:f.value,transform:[{scale:.7+.3*f.value}]}));return h(o.View,{style:m,children:resolveIcon(t,r,l,u)})});
|
package/lib/module/toast.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{memo as t,useCallback as e,useEffect as
|
|
1
|
+
"use strict";import{memo as t,useCallback as e,useEffect as o,useMemo as i,useState as n}from"react";import{Pressable as s,StyleSheet as a,Text as r,View as l}from"react-native";import{Gesture as c,GestureDetector as u}from"react-native-gesture-handler";import d,{interpolate as p,useAnimatedStyle as m,useSharedValue as g,withTiming as h}from"react-native-reanimated";import{useSafeAreaInsets as f}from"react-native-safe-area-context";import{scheduleOnRN as v}from"react-native-worklets";import{DISMISS_THRESHOLD as x,DISMISS_VELOCITY_THRESHOLD as y,EASING as T,ENTRY_DURATION as w,ENTRY_OFFSET as C,EXIT_DURATION as b,EXIT_OFFSET as Y,ICON_ANIMATION_DURATION as k,MAX_DRAG_CLAMP as I,MAX_DRAG_RESISTANCE as S,SPRING_BACK_DURATION as j,STACK_OFFSET_PER_ITEM as z,STACK_SCALE_PER_ITEM as B,STACK_TRANSITION_DURATION as E,SWIPE_EXIT_OFFSET as M}from"./constants.js";import{CloseIcon as H}from"./icons/index.js";import{animationPool as R,getSlotIndex as F,releaseSlot as V,slotTrackers as D}from"./pool.js";import{AnimatedIcon as W,resolveIcon as A}from"./toast-icons.js";import{toastStore as O}from"./toast-store.js";import{useToastState as P}from"./use-toast-state.js";import{jsx as L,jsxs as U}from"react/jsx-runtime";export const ToastContainer=()=>{const{top:t,bottom:o}=f(),{visibleToasts:n,theme:s,toastsWithIndex:a,isBottom:r,topToastRef:d,isBottomRef:p,isDismissibleRef:m}=P(),w=g(!1),C=i(()=>c.Pan().onStart(()=>{"worklet";w.set(!1)}).onUpdate(t=>{"worklet";if(!m.current.value)return;const e=d.current.value;if(!e)return;const{slot:o}=e,i=p.current.value,n=t.translationY,s=i?n:-n,a=i?-n:n;if(s>0){const e=i?Math.min(n,I):Math.max(n,-I);o.translationY.value=e;const a=s>x||(i?t.velocityY>y:t.velocityY<-y);w.set(a)}else{const t=S*(1-Math.exp(-a/250));o.translationY.value=i?-Math.min(t,S):Math.min(t,S),w.value=!1}}).onEnd(()=>{"worklet";if(!m.current.value)return;const t=d.current.value;if(!t)return;const{slot:e}=t,o=p.current.value;if(w.value){e.progress.value=h(0,{duration:b,easing:T});const i=o?M:-M;e.translationY.value=h(e.translationY.value+i,{duration:b,easing:T}),v(t.dismiss)}else e.translationY.value=h(0,{duration:j,easing:T})}),[w,m,d,p]),Y=e(t=>{d.current.value=t},[d]);if(0===n.length)return null;const k=r?o:t,z=r?{bottom:k+s.offset+2}:{top:k+s.offset+2};return L(u,{gesture:C,children:L(l,{style:[G.container,z],pointerEvents:"box-none",children:a.map(({toast:t,index:e})=>L(q,{toast:t,index:e,theme:s,position:s.position,isTopToast:0===e,registerTopToast:Y},t.id))})})};const q=t(({toast:t,index:i,theme:a,position:c,isTopToast:u,registerTopToast:g})=>{const[f]=n(()=>F(t.id)),v=R[f],x=D[f],y="bottom"===c,I=y?C:-C,S=y?Y:-Y,[j,M]=n("loading"===t.type),[P,q]=n(!1);o(()=>{v.progress.value=0,v.translationY.value=0,v.stackIndex.value=i,v.progress.value=h(1,{duration:w,easing:T});const e=setTimeout(()=>q(!0),50);return()=>{clearTimeout(e),V(t.id)}},[]);const J=e(()=>{O.hide(t.id)},[t.id]);o(()=>{let e=null;return t.isExiting&&!x.wasExiting&&(x.wasExiting=!0,v.progress.value=h(0,{duration:b,easing:T}),v.translationY.value=h(S,{duration:b,easing:T})),x.initialized&&i!==x.prevIndex&&(v.stackIndex.value=h(i,{duration:E,easing:T})),x.prevIndex=i,x.initialized=!0,"loading"===t.type?M(!0):j&&(e=setTimeout(()=>M(!1),k+50)),u&&g({slot:v,dismiss:J}),()=>{e&&clearTimeout(e),u&&g(null)}},[t.isExiting,i,v,x,S,t.type,j,u,g,J]);const K=j&&"loading"!==t.type,N=m(()=>{const t=p(v.progress.value,[0,1],[I,0]),e=y?v.stackIndex.value*z:v.stackIndex.value*-z,o=1-v.stackIndex.value*B,i=t+v.translationY.value+e,n=p(v.progress.value,[0,1],[0,1]),s=y?v.translationY.value:-v.translationY.value,a=n*(s>0?p(s,[0,130],[1,0],"clamp"):1);return{transform:[{translateY:i},{scale:o*p(Math.abs(v.translationY.value),[0,50],[1,.98],"clamp")}],opacity:a,zIndex:1e3-Math.round(v.stackIndex.value)}}),{options:Q}=t,X=a.colors[t.type];if(void 0!==Q?.customContent){const e=Q.customContent;return L(d.View,{style:[G.toast,G.customContentToast,y?G.toastBottom:G.toastTop,{backgroundColor:X.background},a.toastStyle,Q.style,N],children:"function"==typeof e?e({id:t.id,dismiss:J,type:t.type,isExiting:!!t.isExiting}):e})}const Z="loading"!==t.type&&(Q?.showCloseButton??a.showCloseButton);return U(d.View,{style:[G.toast,y?G.toastBottom:G.toastTop,{backgroundColor:X.background},a.rtl&&G.rtl,a.toastStyle,Q?.style,N],children:[L(l,{style:G.iconContainer,children:P&&(K?L(W,{type:t.type,color:X.accent,custom:Q?.icon,config:a.icons[t.type]},t.type):A(t.type,X.accent,Q?.icon,a.icons[t.type]))}),U(l,{style:G.textContainer,children:[L(r,{maxFontSizeMultiplier:1.35,allowFontScaling:!1,style:[G.title,{color:X.accent},a.rtl&&{textAlign:"right"},a.titleStyle,Q?.titleStyle],children:t.title}),t.description&&L(r,{allowFontScaling:!1,maxFontSizeMultiplier:1.35,style:[G.description,a.rtl&&{textAlign:"right"},a.descriptionStyle,Q?.descriptionStyle],children:t.description})]}),Z&&L(s,{style:G.closeButton,onPress:J,hitSlop:12,children:L(H,{width:20,height:20})})]})},(t,e)=>t.toast.id===e.toast.id&&t.toast.type===e.toast.type&&t.toast.title===e.toast.title&&t.toast.description===e.toast.description&&t.toast.isExiting===e.toast.isExiting&&t.index===e.index&&t.position===e.position&&t.theme===e.theme&&t.isTopToast===e.isTopToast),G=a.create({container:{position:"absolute",left:16,right:16,zIndex:1e3},toast:{flexDirection:"row",alignItems:"center",gap:12,minHeight:36,borderRadius:20,borderCurve:"continuous",position:"absolute",left:0,right:0,paddingHorizontal:12,paddingVertical:10,shadowColor:"#000",shadowOffset:{width:0,height:8},shadowOpacity:.05,shadowRadius:24,elevation:8},customContentToast:{padding:0,paddingHorizontal:0,paddingVertical:0,overflow:"hidden"},rtl:{flexDirection:"row-reverse"},toastTop:{top:0},toastBottom:{bottom:0},iconContainer:{width:48,height:48,alignItems:"center",justifyContent:"center",marginLeft:8},textContainer:{flex:1,gap:1,justifyContent:"center"},title:{fontSize:14,fontWeight:"700",lineHeight:20},description:{color:"#6B7280",fontSize:12,fontWeight:"500",lineHeight:16},closeButton:{padding:4,alignItems:"center",justifyContent:"center"}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";import{useEffect as t,useMemo as i,useRef as s,useState as e}from"react";import{makeMutable as o}from"react-native-reanimated";import{toastStore as n}from"./toast-store.js";export const useToastState=()=>{const[r,l]=e([]),[m,a]=e(()=>n.getTheme()),u=s(o(null)),b=s(o("bottom"===m.position)),c=s(o(!0)),p="bottom"===m.position,d=r.find(t=>!t.isExiting),f=d?.options?.dismissible??m.dismissible;t(()=>{const t=n.getState().visibleToasts,i=n.getTheme();l(t);const s=t.find(t=>!t.isExiting);b.current.value="bottom"===i.position,c.current.value=s?.options?.dismissible??i.dismissible;let e=null,o=null;const r=n.subscribe(t=>{e=t.visibleToasts,null===o&&(o=requestAnimationFrame(()=>{const t=e??n.getState().visibleToasts,i=n.getTheme();e&&(l(e),e=null),o=null,a(t=>t===i?t:i);const s=t.find(t=>!t.isExiting);b.current.value="bottom"===i.position,c.current.value=s?.options?.dismissible??i.dismissible}))});return r},[]);const g=i(()=>{const t=new Map;let i=0;for(const s of r)t.set(s.id,s.isExiting?-1:i),s.isExiting||i++;return[...r].reverse().map(i=>({toast:i,index:t.get(i.id)??0}))},[r]);return{visibleToasts:r,theme:m,toastsWithIndex:g,isBottom:p,isTopDismissible:f,topToastRef:u,isBottomRef:b,isDismissibleRef:c}};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const ICON_SIZE = 28;
|
|
2
|
+
export declare const POOL_SIZE = 5;
|
|
3
|
+
export declare const ENTRY_DURATION = 400;
|
|
4
|
+
export declare const EXIT_DURATION = 350;
|
|
5
|
+
export declare const STACK_TRANSITION_DURATION = 300;
|
|
6
|
+
export declare const SPRING_BACK_DURATION = 650;
|
|
7
|
+
export declare const ICON_ANIMATION_DURATION = 350;
|
|
8
|
+
export declare const ENTRY_OFFSET = 80;
|
|
9
|
+
export declare const EXIT_OFFSET = 100;
|
|
10
|
+
export declare const SWIPE_EXIT_OFFSET = 200;
|
|
11
|
+
export declare const MAX_DRAG_CLAMP = 180;
|
|
12
|
+
export declare const MAX_DRAG_RESISTANCE = 60;
|
|
13
|
+
export declare const DISMISS_THRESHOLD = 40;
|
|
14
|
+
export declare const DISMISS_VELOCITY_THRESHOLD = 300;
|
|
15
|
+
export declare const STACK_OFFSET_PER_ITEM = 10;
|
|
16
|
+
export declare const STACK_SCALE_PER_ITEM = 0.05;
|
|
17
|
+
export declare const EASING: import("react-native-reanimated").EasingFunctionFactory;
|
|
18
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -3,5 +3,5 @@ export { ToastContainer } from "./toast";
|
|
|
3
3
|
export { toast } from "./toast-api";
|
|
4
4
|
export { BreadLoaf } from "./toast-provider";
|
|
5
5
|
export { toastStore } from "./toast-store";
|
|
6
|
-
export type { ErrorMessageInput, IconProps, IconRenderFn, MessageInput, PromiseMessages, PromiseResult, Toast, ToastConfig, ToastOptions, ToastPosition, ToastState, ToastType, ToastTypeColors, } from "./types";
|
|
6
|
+
export type { CustomContentProps, CustomContentRenderFn, ErrorMessageInput, IconProps, IconRenderFn, MessageInput, PromiseMessages, PromiseResult, Toast, ToastConfig, ToastOptions, ToastPosition, ToastState, ToastType, ToastTypeColors, } from "./types";
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type SharedValue } from "react-native-reanimated";
|
|
2
|
+
export interface AnimSlot {
|
|
3
|
+
progress: SharedValue<number>;
|
|
4
|
+
translationY: SharedValue<number>;
|
|
5
|
+
stackIndex: SharedValue<number>;
|
|
6
|
+
}
|
|
7
|
+
export interface SlotTracker {
|
|
8
|
+
wasExiting: boolean;
|
|
9
|
+
prevIndex: number;
|
|
10
|
+
initialized: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare const animationPool: AnimSlot[];
|
|
13
|
+
export declare const slotTrackers: SlotTracker[];
|
|
14
|
+
export declare const getSlotIndex: (toastId: string) => number;
|
|
15
|
+
export declare const releaseSlot: (toastId: string) => void;
|
|
16
|
+
//# sourceMappingURL=pool.d.ts.map
|
|
@@ -1,7 +1,34 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { CustomContentRenderFn, PromiseMessages, PromiseResult, ToastOptions, ToastType } from "./types";
|
|
3
3
|
type DescriptionOrOptions = string | ToastOptions;
|
|
4
|
+
interface CustomToastOptions extends Omit<ToastOptions, "customContent" | "icon" | "titleStyle" | "descriptionStyle"> {
|
|
5
|
+
type?: ToastType;
|
|
6
|
+
}
|
|
4
7
|
type BaseToastFn = ((title: string, description?: string, type?: ToastType, duration?: number) => void) & {
|
|
8
|
+
/**
|
|
9
|
+
* Show a fully custom toast where you control all the content.
|
|
10
|
+
* The content you provide fills the entire toast container and receives entry/exit animations.
|
|
11
|
+
* @param content - ReactNode or render function that receives { id, dismiss, type, isExiting }
|
|
12
|
+
* @param options - Optional configuration for duration, dismissible, style, etc.
|
|
13
|
+
* @returns The toast ID
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* // Simple custom content
|
|
17
|
+
* toast.custom(<MyCustomToast />);
|
|
18
|
+
*
|
|
19
|
+
* // With render function for dismiss access
|
|
20
|
+
* toast.custom(({ dismiss }) => (
|
|
21
|
+
* <View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
|
22
|
+
* <Text>Custom toast!</Text>
|
|
23
|
+
* <Button title="Close" onPress={dismiss} />
|
|
24
|
+
* </View>
|
|
25
|
+
* ));
|
|
26
|
+
*
|
|
27
|
+
* // With options
|
|
28
|
+
* toast.custom(<MyToast />, { duration: 5000, dismissible: false });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
custom: (content: ReactNode | CustomContentRenderFn, options?: CustomToastOptions) => string;
|
|
5
32
|
/**
|
|
6
33
|
* Show a success toast with a green checkmark icon.
|
|
7
34
|
* @param title - The toast title
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { IconRenderFn, ToastType } from "./types";
|
|
3
|
+
export declare const resolveIcon: (type: ToastType, color: string, custom?: ReactNode | IconRenderFn, config?: IconRenderFn) => string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | null | undefined;
|
|
4
|
+
export declare const AnimatedIcon: import("react").MemoExoticComponent<({ type, color, custom, config, }: {
|
|
5
|
+
type: ToastType;
|
|
6
|
+
color: string;
|
|
7
|
+
custom?: ReactNode | IconRenderFn;
|
|
8
|
+
config?: IconRenderFn;
|
|
9
|
+
}) => import("react/jsx-runtime").JSX.Element>;
|
|
10
|
+
//# sourceMappingURL=toast-icons.d.ts.map
|
|
@@ -15,6 +15,19 @@ export interface IconProps {
|
|
|
15
15
|
/** Default icon size */
|
|
16
16
|
size: number;
|
|
17
17
|
}
|
|
18
|
+
/** Props passed to custom content render functions */
|
|
19
|
+
export interface CustomContentProps {
|
|
20
|
+
/** Toast ID */
|
|
21
|
+
id: string;
|
|
22
|
+
/** Dismiss this toast */
|
|
23
|
+
dismiss: () => void;
|
|
24
|
+
/** Toast type */
|
|
25
|
+
type: ToastType;
|
|
26
|
+
/** Whether the toast is currently exiting */
|
|
27
|
+
isExiting: boolean;
|
|
28
|
+
}
|
|
29
|
+
/** Custom content render function for fully custom toasts */
|
|
30
|
+
export type CustomContentRenderFn = (props: CustomContentProps) => ReactNode;
|
|
18
31
|
/** Custom icon render function */
|
|
19
32
|
export type IconRenderFn = (props: IconProps) => ReactNode;
|
|
20
33
|
export interface ToastTheme {
|
|
@@ -63,6 +76,12 @@ export interface ToastOptions {
|
|
|
63
76
|
dismissible?: boolean;
|
|
64
77
|
/** Whether to show the close button on this toast (overrides config) */
|
|
65
78
|
showCloseButton?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Custom content that fully replaces the default toast layout.
|
|
81
|
+
* When provided, icon, title, description, and close button are not rendered.
|
|
82
|
+
* Receives props: { id, dismiss, type, isExiting }
|
|
83
|
+
*/
|
|
84
|
+
customContent?: ReactNode | CustomContentRenderFn;
|
|
66
85
|
}
|
|
67
86
|
/** Configuration options for customizing toast behavior and appearance. All properties are optional. */
|
|
68
87
|
export type ToastConfig = {
|
|
@@ -100,4 +119,26 @@ export interface PromiseResult<T> {
|
|
|
100
119
|
error?: Error;
|
|
101
120
|
success: boolean;
|
|
102
121
|
}
|
|
122
|
+
export interface TopToastRef {
|
|
123
|
+
slot: {
|
|
124
|
+
progress: {
|
|
125
|
+
value: number;
|
|
126
|
+
};
|
|
127
|
+
translationY: {
|
|
128
|
+
value: number;
|
|
129
|
+
};
|
|
130
|
+
stackIndex: {
|
|
131
|
+
value: number;
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
dismiss: () => void;
|
|
135
|
+
}
|
|
136
|
+
export interface ToastItemProps {
|
|
137
|
+
toast: Toast;
|
|
138
|
+
index: number;
|
|
139
|
+
theme: ToastTheme;
|
|
140
|
+
position: ToastPosition;
|
|
141
|
+
isTopToast: boolean;
|
|
142
|
+
registerTopToast: (values: TopToastRef | null) => void;
|
|
143
|
+
}
|
|
103
144
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Toast } from "./toast-store";
|
|
2
|
+
import type { ToastTheme, TopToastRef } from "./types";
|
|
3
|
+
export declare const useToastState: () => {
|
|
4
|
+
visibleToasts: Toast[];
|
|
5
|
+
theme: ToastTheme;
|
|
6
|
+
toastsWithIndex: {
|
|
7
|
+
toast: Toast;
|
|
8
|
+
index: number;
|
|
9
|
+
}[];
|
|
10
|
+
isBottom: boolean;
|
|
11
|
+
isTopDismissible: boolean;
|
|
12
|
+
topToastRef: import("react").RefObject<import("react-native-reanimated/lib/typescript/commonTypes").Mutable<TopToastRef | null>>;
|
|
13
|
+
isBottomRef: import("react").RefObject<import("react-native-reanimated/lib/typescript/commonTypes").Mutable<boolean>>;
|
|
14
|
+
isDismissibleRef: import("react").RefObject<import("react-native-reanimated/lib/typescript/commonTypes").Mutable<boolean>>;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=use-toast-state.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-bread",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "A lightweight toast library for React Native with premium feeling animations and complex gesture support",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -53,10 +53,10 @@
|
|
|
53
53
|
"react": ">=18.0.0",
|
|
54
54
|
"react-native": ">=0.76.0",
|
|
55
55
|
"react-native-gesture-handler": ">=2.25.0",
|
|
56
|
-
"react-native-reanimated": ">=4.
|
|
56
|
+
"react-native-reanimated": ">=4.1.0",
|
|
57
57
|
"react-native-safe-area-context": ">=5.0.0",
|
|
58
58
|
"react-native-svg": ">=15.8.0",
|
|
59
|
-
"react-native-worklets": ">=0.
|
|
59
|
+
"react-native-worklets": ">=0.5.0"
|
|
60
60
|
},
|
|
61
61
|
"peerDependenciesMeta": {
|
|
62
62
|
"react-native-gesture-handler": {
|