react-native-bread 0.5.2 → 0.5.3

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.
@@ -1 +1,252 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.toastStore=void 0;const t={position:"top",offset:0,rtl:!1,stacking:!0,maxStack:3,dismissible:!0,showCloseButton:!0,colors:{success:{accent:"#28B770",background:"#FFFFFF"},error:{accent:"#F05964",background:"#FFFFFF"},info:{accent:"#EDBE43",background:"#FFFFFF"},loading:{accent:"#232323",background:"#FFFFFF"}},icons:{},toastStyle:{},titleStyle:{},descriptionStyle:{},defaultDuration:4e3};exports.toastStore=new class{state={visibleToasts:[]};theme=t;listeners=new Set;toastIdCounter=0;timeouts=new Map;subscribe=t=>(this.listeners.add(t),()=>{this.listeners.delete(t)});emit(){for(const t of this.listeners)t(this.state)}setState(t){this.state={...this.state,...t},this.emit()}getState=()=>this.state;getTheme=()=>this.theme;setConfig=s=>{this.theme=function(s){if(!s)return t;const e={...t.colors};if(s.colors)for(const i of Object.keys(s.colors)){const o=s.colors[i];o&&(e[i]={...t.colors[i],...o})}return{position:s.position??t.position,offset:s.offset??t.offset,rtl:s.rtl??t.rtl,stacking:s.stacking??t.stacking,maxStack:s.maxStack??t.maxStack,dismissible:s.dismissible??t.dismissible,showCloseButton:s.showCloseButton??t.showCloseButton,colors:e,icons:{...t.icons,...s.icons},toastStyle:{...t.toastStyle,...s.toastStyle},titleStyle:{...t.titleStyle,...s.titleStyle},descriptionStyle:{...t.descriptionStyle,...s.descriptionStyle},defaultDuration:s.defaultDuration??t.defaultDuration}}(s)};show=(t,s,e="success",i,o)=>{const a=i??o?.duration??this.theme.defaultDuration,l=this.theme.stacking?this.theme.maxStack:1,n="toast-"+ ++this.toastIdCounter,c={id:n,title:t,description:s??o?.description,type:e,duration:a,createdAt:Date.now(),isExiting:!1,options:o},{visibleToasts:r}=this.state,h=r.filter(t=>!t.isExiting);if(h.length>=l){const t=h.slice(l-1);for(const s of t){const t=this.timeouts.get(s.id);t&&(clearTimeout(t),this.timeouts.delete(s.id))}const s=new Set(t.map(t=>t.id));if(!this.theme.stacking)return this.setState({visibleToasts:r.map(t=>s.has(t.id)?{...t,isExiting:!0}:t)}),setTimeout(()=>{for(const s of t)this.removeToast(s.id);this.addToast(c,a)},130),n;this.setState({visibleToasts:r.filter(t=>!s.has(t.id))})}return this.addToast(c,a),n};addToast(t,s){this.setState({visibleToasts:[t,...this.state.visibleToasts.filter(t=>!t.isExiting)]}),this.scheduleTimeout(t.id,s,0),this.rescheduleAllTimeouts()}scheduleTimeout(t,s,e){const i=this.timeouts.get(t);i&&clearTimeout(i);const o=setTimeout(()=>{this.hide(t)},s*(e+1));this.timeouts.set(t,o)}rescheduleAllTimeouts(){const{visibleToasts:t}=this.state;t.forEach((t,s)=>{t.isExiting||0===s||this.scheduleTimeout(t.id,t.duration,s)})}hide=t=>{const{visibleToasts:s}=this.state,e=s.find(s=>s.id===t);if(!e||e.isExiting)return;const i=this.timeouts.get(t);i&&(clearTimeout(i),this.timeouts.delete(t)),this.setState({visibleToasts:s.map(s=>s.id===t?{...s,isExiting:!0}:s)}),setTimeout(()=>{this.removeToast(t)},350)};removeToast(t){const s=this.timeouts.get(t);s&&(clearTimeout(s),this.timeouts.delete(t)),this.setState({visibleToasts:this.state.visibleToasts.filter(s=>s.id!==t)}),this.rescheduleAllTimeouts()}updateToast=(t,s)=>{const{visibleToasts:e}=this.state,i=e.findIndex(s=>s.id===t);-1!==i&&(this.setState({visibleToasts:e.map(e=>e.id===t?{...e,...s}:e)}),void 0!==s.duration&&this.scheduleTimeout(t,s.duration,i))};hideAll=()=>{for(const t of this.timeouts.values())clearTimeout(t);this.timeouts.clear(),this.setState({visibleToasts:[]})}};
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.toastStore = void 0;
7
+ const EXIT_DURATION = 350;
8
+ const DEFAULT_THEME = {
9
+ position: "top",
10
+ offset: 0,
11
+ rtl: false,
12
+ stacking: true,
13
+ maxStack: 3,
14
+ dismissible: true,
15
+ showCloseButton: true,
16
+ colors: {
17
+ success: {
18
+ accent: "#28B770",
19
+ background: "#FFFFFF"
20
+ },
21
+ error: {
22
+ accent: "#F05964",
23
+ background: "#FFFFFF"
24
+ },
25
+ info: {
26
+ accent: "#EDBE43",
27
+ background: "#FFFFFF"
28
+ },
29
+ loading: {
30
+ accent: "#232323",
31
+ background: "#FFFFFF"
32
+ }
33
+ },
34
+ icons: {},
35
+ toastStyle: {},
36
+ titleStyle: {},
37
+ descriptionStyle: {},
38
+ defaultDuration: 4000
39
+ };
40
+ function mergeConfig(config) {
41
+ if (!config) return DEFAULT_THEME;
42
+ const mergedColors = {
43
+ ...DEFAULT_THEME.colors
44
+ };
45
+ if (config.colors) {
46
+ for (const type of Object.keys(config.colors)) {
47
+ const userColors = config.colors[type];
48
+ if (userColors) {
49
+ mergedColors[type] = {
50
+ ...DEFAULT_THEME.colors[type],
51
+ ...userColors
52
+ };
53
+ }
54
+ }
55
+ }
56
+ return {
57
+ position: config.position ?? DEFAULT_THEME.position,
58
+ offset: config.offset ?? DEFAULT_THEME.offset,
59
+ rtl: config.rtl ?? DEFAULT_THEME.rtl,
60
+ stacking: config.stacking ?? DEFAULT_THEME.stacking,
61
+ maxStack: config.maxStack ?? DEFAULT_THEME.maxStack,
62
+ dismissible: config.dismissible ?? DEFAULT_THEME.dismissible,
63
+ showCloseButton: config.showCloseButton ?? DEFAULT_THEME.showCloseButton,
64
+ colors: mergedColors,
65
+ icons: {
66
+ ...DEFAULT_THEME.icons,
67
+ ...config.icons
68
+ },
69
+ toastStyle: {
70
+ ...DEFAULT_THEME.toastStyle,
71
+ ...config.toastStyle
72
+ },
73
+ titleStyle: {
74
+ ...DEFAULT_THEME.titleStyle,
75
+ ...config.titleStyle
76
+ },
77
+ descriptionStyle: {
78
+ ...DEFAULT_THEME.descriptionStyle,
79
+ ...config.descriptionStyle
80
+ },
81
+ defaultDuration: config.defaultDuration ?? DEFAULT_THEME.defaultDuration
82
+ };
83
+ }
84
+ class ToastStore {
85
+ state = {
86
+ visibleToasts: []
87
+ };
88
+ theme = DEFAULT_THEME;
89
+ listeners = new Set();
90
+ toastIdCounter = 0;
91
+ timeouts = new Map();
92
+ subscribe = listener => {
93
+ this.listeners.add(listener);
94
+ return () => {
95
+ this.listeners.delete(listener);
96
+ };
97
+ };
98
+ emit() {
99
+ for (const listener of this.listeners) {
100
+ listener(this.state);
101
+ }
102
+ }
103
+ setState(partial) {
104
+ this.state = {
105
+ ...this.state,
106
+ ...partial
107
+ };
108
+ this.emit();
109
+ }
110
+ getState = () => this.state;
111
+ getTheme = () => this.theme;
112
+ setConfig = config => {
113
+ this.theme = mergeConfig(config);
114
+ };
115
+ show = (title, description, type = "success", duration, options) => {
116
+ const actualDuration = duration ?? options?.duration ?? this.theme.defaultDuration;
117
+ const maxToasts = this.theme.stacking ? this.theme.maxStack : 1;
118
+ const id = `toast-${++this.toastIdCounter}`;
119
+ const newToast = {
120
+ id,
121
+ title,
122
+ description: description ?? options?.description,
123
+ type,
124
+ duration: actualDuration,
125
+ createdAt: Date.now(),
126
+ isExiting: false,
127
+ options
128
+ };
129
+ const {
130
+ visibleToasts
131
+ } = this.state;
132
+ const activeToasts = visibleToasts.filter(t => !t.isExiting);
133
+ if (activeToasts.length >= maxToasts) {
134
+ const toastsToRemove = activeToasts.slice(maxToasts - 1);
135
+ for (const toast of toastsToRemove) {
136
+ const timeout = this.timeouts.get(toast.id);
137
+ if (timeout) {
138
+ clearTimeout(timeout);
139
+ this.timeouts.delete(toast.id);
140
+ }
141
+ }
142
+ const removeIds = new Set(toastsToRemove.map(t => t.id));
143
+ if (this.theme.stacking) {
144
+ this.setState({
145
+ visibleToasts: visibleToasts.filter(t => !removeIds.has(t.id))
146
+ });
147
+ } else {
148
+ this.setState({
149
+ visibleToasts: visibleToasts.map(t => removeIds.has(t.id) ? {
150
+ ...t,
151
+ isExiting: true
152
+ } : t)
153
+ });
154
+ setTimeout(() => {
155
+ for (const toast of toastsToRemove) {
156
+ this.removeToast(toast.id);
157
+ }
158
+ this.addToast(newToast, actualDuration);
159
+ }, EXIT_DURATION - 220);
160
+ return id;
161
+ }
162
+ }
163
+ this.addToast(newToast, actualDuration);
164
+ return id;
165
+ };
166
+ addToast(toast, duration) {
167
+ this.setState({
168
+ visibleToasts: [toast, ...this.state.visibleToasts.filter(t => !t.isExiting)]
169
+ });
170
+ this.scheduleTimeout(toast.id, duration, 0);
171
+ this.rescheduleAllTimeouts();
172
+ }
173
+ scheduleTimeout(id, baseDuration, index) {
174
+ const existingTimeout = this.timeouts.get(id);
175
+ if (existingTimeout) {
176
+ clearTimeout(existingTimeout);
177
+ }
178
+ const duration = baseDuration * (index + 1);
179
+ const timeout = setTimeout(() => {
180
+ this.hide(id);
181
+ }, duration);
182
+ this.timeouts.set(id, timeout);
183
+ }
184
+ rescheduleAllTimeouts() {
185
+ const {
186
+ visibleToasts
187
+ } = this.state;
188
+ visibleToasts.forEach((toast, index) => {
189
+ if (toast.isExiting || index === 0) return;
190
+ this.scheduleTimeout(toast.id, toast.duration, index);
191
+ });
192
+ }
193
+ hide = id => {
194
+ const {
195
+ visibleToasts
196
+ } = this.state;
197
+ const toast = visibleToasts.find(t => t.id === id);
198
+ if (!toast || toast.isExiting) return;
199
+ const timeout = this.timeouts.get(id);
200
+ if (timeout) {
201
+ clearTimeout(timeout);
202
+ this.timeouts.delete(id);
203
+ }
204
+ this.setState({
205
+ visibleToasts: visibleToasts.map(t => t.id === id ? {
206
+ ...t,
207
+ isExiting: true
208
+ } : t)
209
+ });
210
+ setTimeout(() => {
211
+ this.removeToast(id);
212
+ }, EXIT_DURATION);
213
+ };
214
+ removeToast(id) {
215
+ const timeout = this.timeouts.get(id);
216
+ if (timeout) {
217
+ clearTimeout(timeout);
218
+ this.timeouts.delete(id);
219
+ }
220
+ this.setState({
221
+ visibleToasts: this.state.visibleToasts.filter(t => t.id !== id)
222
+ });
223
+ this.rescheduleAllTimeouts();
224
+ }
225
+ updateToast = (id, data) => {
226
+ const {
227
+ visibleToasts
228
+ } = this.state;
229
+ const index = visibleToasts.findIndex(t => t.id === id);
230
+ if (index === -1) return;
231
+ this.setState({
232
+ visibleToasts: visibleToasts.map(t => t.id === id ? {
233
+ ...t,
234
+ ...data
235
+ } : t)
236
+ });
237
+ if (data.duration !== undefined) {
238
+ this.scheduleTimeout(id, data.duration, index);
239
+ }
240
+ };
241
+ hideAll = () => {
242
+ for (const timeout of this.timeouts.values()) {
243
+ clearTimeout(timeout);
244
+ }
245
+ this.timeouts.clear();
246
+ this.setState({
247
+ visibleToasts: []
248
+ });
249
+ };
250
+ }
251
+ const toastStore = exports.toastStore = new ToastStore();
252
+ //# sourceMappingURL=toast-store.js.map
@@ -1 +1,351 @@
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"}});
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ToastContainer = void 0;
7
+ var _react = require("react");
8
+ var _reactNative = require("react-native");
9
+ var _reactNativeGestureHandler = require("react-native-gesture-handler");
10
+ var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
11
+ var _reactNativeSafeAreaContext = require("react-native-safe-area-context");
12
+ var _reactNativeWorklets = require("react-native-worklets");
13
+ var _constants = require("./constants.js");
14
+ var _index = require("./icons/index.js");
15
+ var _pool = require("./pool.js");
16
+ var _toastIcons = require("./toast-icons.js");
17
+ var _toastStore = require("./toast-store.js");
18
+ var _useToastState = require("./use-toast-state.js");
19
+ var _jsxRuntime = require("react/jsx-runtime");
20
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
21
+ const ToastContainer = () => {
22
+ const {
23
+ top,
24
+ bottom
25
+ } = (0, _reactNativeSafeAreaContext.useSafeAreaInsets)();
26
+ const {
27
+ visibleToasts,
28
+ theme,
29
+ toastsWithIndex,
30
+ isBottom,
31
+ topToastRef,
32
+ isBottomRef,
33
+ isDismissibleRef
34
+ } = (0, _useToastState.useToastState)();
35
+ const shouldDismiss = (0, _reactNativeReanimated.useSharedValue)(false);
36
+ const panGesture = (0, _react.useMemo)(() => _reactNativeGestureHandler.Gesture.Pan().onStart(() => {
37
+ "worklet";
38
+
39
+ shouldDismiss.set(false);
40
+ }).onUpdate(event => {
41
+ "worklet";
42
+
43
+ if (!isDismissibleRef.current.value) return;
44
+ const ref = topToastRef.current.value;
45
+ if (!ref) return;
46
+ const {
47
+ slot
48
+ } = ref;
49
+ const bottom = isBottomRef.current.value;
50
+ const rawY = event.translationY;
51
+ const dismissDrag = bottom ? rawY : -rawY;
52
+ const resistDrag = bottom ? -rawY : rawY;
53
+ if (dismissDrag > 0) {
54
+ const clampedY = bottom ? Math.min(rawY, _constants.MAX_DRAG_CLAMP) : Math.max(rawY, -_constants.MAX_DRAG_CLAMP);
55
+ slot.translationY.value = clampedY;
56
+ const shouldTriggerDismiss = dismissDrag > _constants.DISMISS_THRESHOLD || (bottom ? event.velocityY > _constants.DISMISS_VELOCITY_THRESHOLD : event.velocityY < -_constants.DISMISS_VELOCITY_THRESHOLD);
57
+ shouldDismiss.set(shouldTriggerDismiss);
58
+ } else {
59
+ const exponentialDrag = _constants.MAX_DRAG_RESISTANCE * (1 - Math.exp(-resistDrag / 250));
60
+ slot.translationY.value = bottom ? -Math.min(exponentialDrag, _constants.MAX_DRAG_RESISTANCE) : Math.min(exponentialDrag, _constants.MAX_DRAG_RESISTANCE);
61
+ shouldDismiss.value = false;
62
+ }
63
+ }).onEnd(() => {
64
+ "worklet";
65
+
66
+ if (!isDismissibleRef.current.value) return;
67
+ const ref = topToastRef.current.value;
68
+ if (!ref) return;
69
+ const {
70
+ slot
71
+ } = ref;
72
+ const bottom = isBottomRef.current.value;
73
+ if (shouldDismiss.value) {
74
+ slot.progress.value = (0, _reactNativeReanimated.withTiming)(0, {
75
+ duration: _constants.EXIT_DURATION,
76
+ easing: _constants.EASING
77
+ });
78
+ const exitOffset = bottom ? _constants.SWIPE_EXIT_OFFSET : -_constants.SWIPE_EXIT_OFFSET;
79
+ slot.translationY.value = (0, _reactNativeReanimated.withTiming)(slot.translationY.value + exitOffset, {
80
+ duration: _constants.EXIT_DURATION,
81
+ easing: _constants.EASING
82
+ });
83
+ (0, _reactNativeWorklets.scheduleOnRN)(ref.dismiss);
84
+ } else {
85
+ slot.translationY.value = (0, _reactNativeReanimated.withTiming)(0, {
86
+ duration: _constants.SPRING_BACK_DURATION,
87
+ easing: _constants.EASING
88
+ });
89
+ }
90
+ }), [shouldDismiss, isDismissibleRef, topToastRef, isBottomRef]);
91
+ const registerTopToast = (0, _react.useCallback)(values => {
92
+ topToastRef.current.value = values;
93
+ }, [topToastRef]);
94
+ if (visibleToasts.length === 0) return null;
95
+ const inset = isBottom ? bottom : top;
96
+ const positionStyle = isBottom ? {
97
+ bottom: inset + theme.offset + 2
98
+ } : {
99
+ top: inset + theme.offset + 2
100
+ };
101
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector, {
102
+ gesture: panGesture,
103
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
104
+ style: [styles.container, positionStyle],
105
+ pointerEvents: "box-none",
106
+ children: toastsWithIndex.map(({
107
+ toast,
108
+ index
109
+ }) => /*#__PURE__*/(0, _jsxRuntime.jsx)(MemoizedToastItem, {
110
+ toast: toast,
111
+ index: index,
112
+ theme: theme,
113
+ position: theme.position,
114
+ isTopToast: index === 0,
115
+ registerTopToast: registerTopToast
116
+ }, toast.id))
117
+ })
118
+ });
119
+ };
120
+ exports.ToastContainer = ToastContainer;
121
+ const ToastItem = ({
122
+ toast,
123
+ index,
124
+ theme,
125
+ position,
126
+ isTopToast,
127
+ registerTopToast
128
+ }) => {
129
+ const [slotIdx] = (0, _react.useState)(() => (0, _pool.getSlotIndex)(toast.id));
130
+ const slot = _pool.animationPool[slotIdx];
131
+ const tracker = _pool.slotTrackers[slotIdx];
132
+ const isBottom = position === "bottom";
133
+ const entryFromY = isBottom ? _constants.ENTRY_OFFSET : -_constants.ENTRY_OFFSET;
134
+ const exitToY = isBottom ? _constants.EXIT_OFFSET : -_constants.EXIT_OFFSET;
135
+ const [wasLoading, setWasLoading] = (0, _react.useState)(toast.type === "loading");
136
+ const [showIcon, setShowIcon] = (0, _react.useState)(false);
137
+
138
+ // biome-ignore lint/correctness/useExhaustiveDependencies: mount-only effect
139
+ (0, _react.useEffect)(() => {
140
+ slot.progress.value = 0;
141
+ slot.translationY.value = 0;
142
+ slot.stackIndex.value = index;
143
+ slot.progress.value = (0, _reactNativeReanimated.withTiming)(1, {
144
+ duration: _constants.ENTRY_DURATION,
145
+ easing: _constants.EASING
146
+ });
147
+ const iconTimeout = setTimeout(() => setShowIcon(true), 50);
148
+ return () => {
149
+ clearTimeout(iconTimeout);
150
+ (0, _pool.releaseSlot)(toast.id);
151
+ };
152
+ }, []);
153
+ const dismissToast = (0, _react.useCallback)(() => {
154
+ _toastStore.toastStore.hide(toast.id);
155
+ }, [toast.id]);
156
+ (0, _react.useEffect)(() => {
157
+ let loadingTimeout = null;
158
+ if (toast.isExiting && !tracker.wasExiting) {
159
+ tracker.wasExiting = true;
160
+ slot.progress.value = (0, _reactNativeReanimated.withTiming)(0, {
161
+ duration: _constants.EXIT_DURATION,
162
+ easing: _constants.EASING
163
+ });
164
+ slot.translationY.value = (0, _reactNativeReanimated.withTiming)(exitToY, {
165
+ duration: _constants.EXIT_DURATION,
166
+ easing: _constants.EASING
167
+ });
168
+ }
169
+ if (tracker.initialized && index !== tracker.prevIndex) {
170
+ slot.stackIndex.value = (0, _reactNativeReanimated.withTiming)(index, {
171
+ duration: _constants.STACK_TRANSITION_DURATION,
172
+ easing: _constants.EASING
173
+ });
174
+ }
175
+ tracker.prevIndex = index;
176
+ tracker.initialized = true;
177
+ if (toast.type === "loading") {
178
+ setWasLoading(true);
179
+ } else if (wasLoading) {
180
+ loadingTimeout = setTimeout(() => setWasLoading(false), _constants.ICON_ANIMATION_DURATION + 50);
181
+ }
182
+ if (isTopToast) {
183
+ registerTopToast({
184
+ slot: slot,
185
+ dismiss: dismissToast
186
+ });
187
+ }
188
+ return () => {
189
+ if (loadingTimeout) clearTimeout(loadingTimeout);
190
+ if (isTopToast) registerTopToast(null);
191
+ };
192
+ }, [toast.isExiting, index, slot, tracker, exitToY, toast.type, wasLoading, isTopToast, registerTopToast, dismissToast]);
193
+ const shouldAnimateIcon = wasLoading && toast.type !== "loading";
194
+ const animatedStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => {
195
+ const baseTranslateY = (0, _reactNativeReanimated.interpolate)(slot.progress.value, [0, 1], [entryFromY, 0]);
196
+ const stackOffsetY = isBottom ? slot.stackIndex.value * _constants.STACK_OFFSET_PER_ITEM : slot.stackIndex.value * -_constants.STACK_OFFSET_PER_ITEM;
197
+ const stackScale = 1 - slot.stackIndex.value * _constants.STACK_SCALE_PER_ITEM;
198
+ const finalTranslateY = baseTranslateY + slot.translationY.value + stackOffsetY;
199
+ const progressOpacity = (0, _reactNativeReanimated.interpolate)(slot.progress.value, [0, 1], [0, 1]);
200
+ const dismissDirection = isBottom ? slot.translationY.value : -slot.translationY.value;
201
+ const dragOpacity = dismissDirection > 0 ? (0, _reactNativeReanimated.interpolate)(dismissDirection, [0, 130], [1, 0], "clamp") : 1;
202
+ const opacity = progressOpacity * dragOpacity;
203
+ const dragScale = (0, _reactNativeReanimated.interpolate)(Math.abs(slot.translationY.value), [0, 50], [1, 0.98], "clamp");
204
+ const scale = stackScale * dragScale;
205
+ return {
206
+ transform: [{
207
+ translateY: finalTranslateY
208
+ }, {
209
+ scale
210
+ }],
211
+ opacity,
212
+ zIndex: 1000 - Math.round(slot.stackIndex.value)
213
+ };
214
+ });
215
+ const {
216
+ options
217
+ } = toast;
218
+ const colors = theme.colors[toast.type];
219
+ if (options?.customContent !== undefined) {
220
+ const content = options.customContent;
221
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
222
+ style: [styles.toast, styles.customContentToast, isBottom ? styles.toastBottom : styles.toastTop, {
223
+ backgroundColor: colors.background
224
+ }, theme.toastStyle, options.style, animatedStyle],
225
+ children: typeof content === "function" ? content({
226
+ id: toast.id,
227
+ dismiss: dismissToast,
228
+ type: toast.type,
229
+ isExiting: !!toast.isExiting
230
+ }) : content
231
+ });
232
+ }
233
+ const shouldShowCloseButton = toast.type !== "loading" && (options?.showCloseButton ?? theme.showCloseButton);
234
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeReanimated.default.View, {
235
+ style: [styles.toast, isBottom ? styles.toastBottom : styles.toastTop, {
236
+ backgroundColor: colors.background
237
+ }, theme.rtl && styles.rtl, theme.toastStyle, options?.style, animatedStyle],
238
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
239
+ style: styles.iconContainer,
240
+ children: showIcon && (shouldAnimateIcon ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_toastIcons.AnimatedIcon, {
241
+ type: toast.type,
242
+ color: colors.accent,
243
+ custom: options?.icon,
244
+ config: theme.icons[toast.type]
245
+ }, toast.type) : (0, _toastIcons.resolveIcon)(toast.type, colors.accent, options?.icon, theme.icons[toast.type]))
246
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
247
+ style: styles.textContainer,
248
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
249
+ maxFontSizeMultiplier: 1.35,
250
+ allowFontScaling: false,
251
+ style: [styles.title, {
252
+ color: colors.accent
253
+ }, theme.rtl && {
254
+ textAlign: "right"
255
+ }, theme.titleStyle, options?.titleStyle],
256
+ children: toast.title
257
+ }), toast.description && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
258
+ allowFontScaling: false,
259
+ maxFontSizeMultiplier: 1.35,
260
+ style: [styles.description, theme.rtl && {
261
+ textAlign: "right"
262
+ }, theme.descriptionStyle, options?.descriptionStyle],
263
+ children: toast.description
264
+ })]
265
+ }), shouldShowCloseButton && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
266
+ style: styles.closeButton,
267
+ onPress: dismissToast,
268
+ hitSlop: 12,
269
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.CloseIcon, {
270
+ width: 20,
271
+ height: 20
272
+ })
273
+ })]
274
+ });
275
+ };
276
+ const MemoizedToastItem = /*#__PURE__*/(0, _react.memo)(ToastItem, (prev, next) => {
277
+ return prev.toast.id === next.toast.id && prev.toast.type === next.toast.type && prev.toast.title === next.toast.title && prev.toast.description === next.toast.description && prev.toast.isExiting === next.toast.isExiting && prev.index === next.index && prev.position === next.position && prev.theme === next.theme && prev.isTopToast === next.isTopToast;
278
+ });
279
+ const styles = _reactNative.StyleSheet.create({
280
+ container: {
281
+ position: "absolute",
282
+ left: 16,
283
+ right: 16,
284
+ zIndex: 1000
285
+ },
286
+ toast: {
287
+ flexDirection: "row",
288
+ alignItems: "center",
289
+ gap: 12,
290
+ minHeight: 36,
291
+ borderRadius: 20,
292
+ borderCurve: "continuous",
293
+ position: "absolute",
294
+ left: 0,
295
+ right: 0,
296
+ paddingHorizontal: 12,
297
+ paddingVertical: 10,
298
+ shadowColor: "#000",
299
+ shadowOffset: {
300
+ width: 0,
301
+ height: 8
302
+ },
303
+ shadowOpacity: 0.05,
304
+ shadowRadius: 24,
305
+ elevation: 8
306
+ },
307
+ customContentToast: {
308
+ padding: 0,
309
+ paddingHorizontal: 0,
310
+ paddingVertical: 0,
311
+ overflow: "hidden"
312
+ },
313
+ rtl: {
314
+ flexDirection: "row-reverse"
315
+ },
316
+ toastTop: {
317
+ top: 0
318
+ },
319
+ toastBottom: {
320
+ bottom: 0
321
+ },
322
+ iconContainer: {
323
+ width: 48,
324
+ height: 48,
325
+ alignItems: "center",
326
+ justifyContent: "center",
327
+ marginLeft: 8
328
+ },
329
+ textContainer: {
330
+ flex: 1,
331
+ gap: 1,
332
+ justifyContent: "center"
333
+ },
334
+ title: {
335
+ fontSize: 14,
336
+ fontWeight: "700",
337
+ lineHeight: 20
338
+ },
339
+ description: {
340
+ color: "#6B7280",
341
+ fontSize: 12,
342
+ fontWeight: "500",
343
+ lineHeight: 16
344
+ },
345
+ closeButton: {
346
+ padding: 4,
347
+ alignItems: "center",
348
+ justifyContent: "center"
349
+ }
350
+ });
351
+ //# sourceMappingURL=toast.js.map
@@ -1 +1,6 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ //# sourceMappingURL=types.js.map