react-native-bread 0.5.3 → 0.6.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 CHANGED
@@ -6,20 +6,19 @@ An extremely lightweight, opinionated toast component for React Native.
6
6
 
7
7
  ## Features
8
8
 
9
- - **Extremely lightweight** package, only 14KB packed size
9
+ - **Lightweight** - only 20KB packed size
10
+ - **New Architecture** - built exclusively for React Native 0.76+ with Fabric
10
11
  - Clean, imperative API inspired by [Sonner](https://sonner.emilkowal.ski/)
11
12
  - Zero setup - add one component, start toasting. No hooks, no providers
12
- - Built for mobile with smooth 60fps animations powered by Reanimated
13
+ - Smooth 60fps animations powered by Reanimated
13
14
  - Natural swipe gestures that feel native to the platform
14
15
  - Multiple toast types: `success`, `error`, `info`, `promise`, and `custom`
15
16
  - Promise handling with automatic loading → success/error states
16
- - Complex animations and gestures but with high performance
17
17
  - Toast stacking with configurable limits
18
- - Position toasts at top or bottom of screen
19
- - **RTL built-in support** - perfect for Arabic and other RTL languages
18
+ - **Works above modals** - automatic on iOS, simple setup on Android
19
+ - **RTL support** - perfect for Arabic and other RTL languages
20
20
  - Completely customizable - colors, icons, styles, animations
21
21
  - Full Expo compatibility
22
- - Imperative API works anywhere - components, utilities, event handlers
23
22
 
24
23
 
25
24
 
@@ -38,19 +37,20 @@ This package requires the following peer dependencies:
38
37
  | [react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started) | >= 4.1.0 |
39
38
  | [react-native-gesture-handler](https://docs.swmansion.com/react-native-gesture-handler/docs/) | >= 2.25.0 |
40
39
  | [react-native-safe-area-context](https://docs.expo.dev/versions/latest/sdk/safe-area-context/) | >= 5.0.0 |
40
+ | [react-native-screens](https://docs.swmansion.com/react-native-screens/) | >= 4.0.0 |
41
41
  | [react-native-svg](https://github.com/software-mansion/react-native-svg) | >= 15.8.0 |
42
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
 
46
46
  ```sh
47
- bun add react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-svg react-native-worklets
47
+ bun add react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-screens react-native-svg react-native-worklets
48
48
  ```
49
49
 
50
50
  Or with npm:
51
51
 
52
52
  ```sh
53
- npm install react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-svg react-native-worklets
53
+ npm install react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-screens react-native-svg react-native-worklets
54
54
  ```
55
55
 
56
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.
@@ -217,9 +217,43 @@ Available options include:
217
217
  | `toast.dismiss(id)` | Dismiss a specific toast |
218
218
  | `toast.dismissAll()` | Dismiss all toasts |
219
219
 
220
- ## Known Issues
220
+ ## Toasts in Modals
221
221
 
222
- **Modal Pages**: Toasts may render behind React Native's `screenOptions={{ presentation: "modal" }}` since they are mounted at the native layer above the whole app.
222
+ Toasts automatically appear above native modals on **iOS**.
223
223
 
224
- **Solution**: Use `screenOptions={{ presentation: "containedModal" }}`, or add another `<BreadLoaf>` inside the modal page.
224
+ On **Android**, you have two options:
225
+
226
+ ### Option 1: Use a Contained Modal
227
+
228
+ The simplest fix is to use `containedModal` presentation instead of `modal`. On Android, `modal` and `containedModal` look nearly identical, so this is an easy swap:
229
+
230
+ ```tsx
231
+ <Stack.Screen
232
+ name="(modal)"
233
+ options={{ presentation: Platform.OS === "android" ? "containedModal" : "modal" }}
234
+ />
235
+ ```
236
+
237
+ This renders the modal within the React hierarchy on Android, so toasts from your root `<BreadLoaf />` remain visible.
238
+
239
+ ### Option 2: Use ToastPortal
240
+
241
+ If you need native modals, add `<ToastPortal />` inside your modal layouts:
242
+
243
+ ```tsx
244
+ // app/(modal)/_layout.tsx
245
+ import { Stack } from "expo-router";
246
+ import { ToastPortal } from "react-native-bread";
247
+
248
+ export default function ModalLayout() {
249
+ return (
250
+ <>
251
+ <Stack screenOptions={{ headerShown: false }} />
252
+ <ToastPortal />
253
+ </>
254
+ );
255
+ }
256
+ ```
257
+
258
+ The `ToastPortal` component only renders on Android - it returns `null` on iOS, so no platform check is needed.
225
259
 
@@ -39,6 +39,12 @@ Object.defineProperty(exports, "ToastContainer", {
39
39
  return _toast.ToastContainer;
40
40
  }
41
41
  });
42
+ Object.defineProperty(exports, "ToastPortal", {
43
+ enumerable: true,
44
+ get: function () {
45
+ return _toastProvider.ToastPortal;
46
+ }
47
+ });
42
48
  Object.defineProperty(exports, "toast", {
43
49
  enumerable: true,
44
50
  get: function () {
@@ -4,11 +4,20 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.BreadLoaf = BreadLoaf;
7
+ exports.ToastPortal = ToastPortal;
7
8
  var _react = require("react");
8
9
  var _reactNative = require("react-native");
10
+ var _reactNativeScreens = require("react-native-screens");
9
11
  var _toast = require("./toast.js");
10
12
  var _toastStore = require("./toast-store.js");
11
13
  var _jsxRuntime = require("react/jsx-runtime");
14
+ function ToastContent() {
15
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
16
+ style: styles.container,
17
+ pointerEvents: "box-none",
18
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_toast.ToastContainer, {})
19
+ });
20
+ }
12
21
  /**
13
22
  * Toast component that enables toast notifications in your app.
14
23
  * Add `<BreadLoaf />` to your root layout to start showing toasts.
@@ -51,11 +60,50 @@ function BreadLoaf({
51
60
  _toastStore.toastStore.setConfig(undefined);
52
61
  };
53
62
  }, [config]);
54
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
55
- style: styles.container,
56
- pointerEvents: "box-none",
57
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_toast.ToastContainer, {})
58
- });
63
+
64
+ // iOS: use FullWindowOverlay to render above native modals
65
+ if (_reactNative.Platform.OS === "ios") {
66
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeScreens.FullWindowOverlay, {
67
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ToastContent, {})
68
+ });
69
+ }
70
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(ToastContent, {});
71
+ }
72
+
73
+ /**
74
+ * Lightweight toast renderer for use inside modal screens.
75
+ *
76
+ * On Android, native modals render above the root React view, so toasts from
77
+ * the main `<BreadLoaf />` won't be visible. Add `<ToastPortal />` inside your
78
+ * modal layouts to show toasts above modal content.
79
+ *
80
+ * This component only renders on Android - it returns `null` on iOS where
81
+ * `<BreadLoaf />` already handles modal overlay via `FullWindowOverlay`.
82
+ *
83
+ * This component only renders toasts - it does not accept configuration.
84
+ * All styling/behavior is inherited from your root `<BreadLoaf />` config.
85
+ *
86
+ * @example
87
+ * ```tsx
88
+ * // app/(modal)/_layout.tsx
89
+ * import { Stack } from 'expo-router';
90
+ * import { ToastPortal } from 'react-native-bread';
91
+ *
92
+ * export default function ModalLayout() {
93
+ * return (
94
+ * <>
95
+ * <Stack screenOptions={{ headerShown: false }} />
96
+ * <ToastPortal />
97
+ * </>
98
+ * );
99
+ * }
100
+ * ```
101
+ */
102
+ function ToastPortal() {
103
+ if (_reactNative.Platform.OS !== "android") {
104
+ return null;
105
+ }
106
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(ToastContent, {});
59
107
  }
60
108
  const styles = _reactNative.StyleSheet.create({
61
109
  container: {
@@ -6,7 +6,7 @@
6
6
  export { CloseIcon, GreenCheck, InfoIcon, RedX } from "./icons/index.js";
7
7
  export { ToastContainer } from "./toast.js";
8
8
  export { toast } from "./toast-api.js";
9
- export { BreadLoaf } from "./toast-provider.js";
9
+ export { BreadLoaf, ToastPortal } from "./toast-provider.js";
10
10
 
11
11
  // Store (for advanced usage)
12
12
  export { toastStore } from "./toast-store.js";
@@ -1,10 +1,18 @@
1
1
  "use strict";
2
2
 
3
3
  import { useEffect } from "react";
4
- import { StyleSheet, View } from "react-native";
4
+ import { Platform, StyleSheet, View } from "react-native";
5
+ import { FullWindowOverlay } from "react-native-screens";
5
6
  import { ToastContainer } from "./toast.js";
6
7
  import { toastStore } from "./toast-store.js";
7
8
  import { jsx as _jsx } from "react/jsx-runtime";
9
+ function ToastContent() {
10
+ return /*#__PURE__*/_jsx(View, {
11
+ style: styles.container,
12
+ pointerEvents: "box-none",
13
+ children: /*#__PURE__*/_jsx(ToastContainer, {})
14
+ });
15
+ }
8
16
  /**
9
17
  * Toast component that enables toast notifications in your app.
10
18
  * Add `<BreadLoaf />` to your root layout to start showing toasts.
@@ -47,11 +55,50 @@ export function BreadLoaf({
47
55
  toastStore.setConfig(undefined);
48
56
  };
49
57
  }, [config]);
50
- return /*#__PURE__*/_jsx(View, {
51
- style: styles.container,
52
- pointerEvents: "box-none",
53
- children: /*#__PURE__*/_jsx(ToastContainer, {})
54
- });
58
+
59
+ // iOS: use FullWindowOverlay to render above native modals
60
+ if (Platform.OS === "ios") {
61
+ return /*#__PURE__*/_jsx(FullWindowOverlay, {
62
+ children: /*#__PURE__*/_jsx(ToastContent, {})
63
+ });
64
+ }
65
+ return /*#__PURE__*/_jsx(ToastContent, {});
66
+ }
67
+
68
+ /**
69
+ * Lightweight toast renderer for use inside modal screens.
70
+ *
71
+ * On Android, native modals render above the root React view, so toasts from
72
+ * the main `<BreadLoaf />` won't be visible. Add `<ToastPortal />` inside your
73
+ * modal layouts to show toasts above modal content.
74
+ *
75
+ * This component only renders on Android - it returns `null` on iOS where
76
+ * `<BreadLoaf />` already handles modal overlay via `FullWindowOverlay`.
77
+ *
78
+ * This component only renders toasts - it does not accept configuration.
79
+ * All styling/behavior is inherited from your root `<BreadLoaf />` config.
80
+ *
81
+ * @example
82
+ * ```tsx
83
+ * // app/(modal)/_layout.tsx
84
+ * import { Stack } from 'expo-router';
85
+ * import { ToastPortal } from 'react-native-bread';
86
+ *
87
+ * export default function ModalLayout() {
88
+ * return (
89
+ * <>
90
+ * <Stack screenOptions={{ headerShown: false }} />
91
+ * <ToastPortal />
92
+ * </>
93
+ * );
94
+ * }
95
+ * ```
96
+ */
97
+ export function ToastPortal() {
98
+ if (Platform.OS !== "android") {
99
+ return null;
100
+ }
101
+ return /*#__PURE__*/_jsx(ToastContent, {});
55
102
  }
56
103
  const styles = StyleSheet.create({
57
104
  container: {
@@ -1,7 +1,7 @@
1
1
  export { CloseIcon, GreenCheck, InfoIcon, RedX } from "./icons";
2
2
  export { ToastContainer } from "./toast";
3
3
  export { toast } from "./toast-api";
4
- export { BreadLoaf } from "./toast-provider";
4
+ export { BreadLoaf, ToastPortal } from "./toast-provider";
5
5
  export { toastStore } from "./toast-store";
6
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
@@ -49,5 +49,35 @@ interface BreadLoafProps {
49
49
  * ```
50
50
  */
51
51
  export declare function BreadLoaf({ config }: BreadLoafProps): import("react/jsx-runtime").JSX.Element;
52
+ /**
53
+ * Lightweight toast renderer for use inside modal screens.
54
+ *
55
+ * On Android, native modals render above the root React view, so toasts from
56
+ * the main `<BreadLoaf />` won't be visible. Add `<ToastPortal />` inside your
57
+ * modal layouts to show toasts above modal content.
58
+ *
59
+ * This component only renders on Android - it returns `null` on iOS where
60
+ * `<BreadLoaf />` already handles modal overlay via `FullWindowOverlay`.
61
+ *
62
+ * This component only renders toasts - it does not accept configuration.
63
+ * All styling/behavior is inherited from your root `<BreadLoaf />` config.
64
+ *
65
+ * @example
66
+ * ```tsx
67
+ * // app/(modal)/_layout.tsx
68
+ * import { Stack } from 'expo-router';
69
+ * import { ToastPortal } from 'react-native-bread';
70
+ *
71
+ * export default function ModalLayout() {
72
+ * return (
73
+ * <>
74
+ * <Stack screenOptions={{ headerShown: false }} />
75
+ * <ToastPortal />
76
+ * </>
77
+ * );
78
+ * }
79
+ * ```
80
+ */
81
+ export declare function ToastPortal(): import("react/jsx-runtime").JSX.Element | null;
52
82
  export {};
53
83
  //# sourceMappingURL=toast-provider.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-bread",
3
- "version": "0.5.3",
3
+ "version": "0.6.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",
@@ -43,6 +43,7 @@
43
43
  "react-native-gesture-handler": "~2.28.0",
44
44
  "react-native-reanimated": "~4.2.1",
45
45
  "react-native-safe-area-context": "~5.4.0",
46
+ "react-native-screens": "~4.16.0",
46
47
  "react-native-svg": "15.12.1",
47
48
  "react-native-worklets": "0.7.2",
48
49
  "terser": "^5.44.1",
@@ -54,6 +55,7 @@
54
55
  "react-native-gesture-handler": ">=2.25.0",
55
56
  "react-native-reanimated": ">=4.1.0",
56
57
  "react-native-safe-area-context": ">=5.0.0",
58
+ "react-native-screens": ">=4.0.0",
57
59
  "react-native-svg": ">=15.8.0",
58
60
  "react-native-worklets": ">=0.5.0"
59
61
  },
@@ -67,6 +69,9 @@
67
69
  "react-native-safe-area-context": {
68
70
  "optional": false
69
71
  },
72
+ "react-native-screens": {
73
+ "optional": false
74
+ },
70
75
  "react-native-svg": {
71
76
  "optional": false
72
77
  }