@shaquillehinds/react-native-bottom-sheet 0.0.1 → 0.0.2

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
@@ -10,8 +10,9 @@ A performant, highly customizable bottom sheet component for React Native that j
10
10
  - 🎯 **Multiple Snap Points** - Define custom snap positions as percentages of screen height
11
11
  - 📱 **Keyboard Aware** - Intelligent keyboard avoidance with per-input customization
12
12
  - 🎨 **Fully Customizable** - Style every aspect from bumper to backdrop
13
- - 🔄 **Portal Support** - Optional portal rendering for complex navigation hierarchies
14
- - 📜 **Scrollable Content** - Built-in FlatList and ScrollView components with proper gesture handling
13
+ - 🔄 **Portal System** - Renders at app root level above navigation with `BottomSheetPortalProvider`
14
+ - 🎪 **Advanced Portal APIs** - Manual portal control with `useBottomSheetPortal` and `useBottomSheetPortalComponent`
15
+ - 📜 **Scrollable Content** - Built-in FlatList and ScrollView components with proper gesture handlin
15
16
  - ⚡ **High Performance** - Optimized animations using `useImperativeHandle` for render isolation
16
17
  - 🎭 **Modal & Inline Modes** - Use as a full modal or inline component
17
18
  - 🔒 **Type Safe** - Full TypeScript support with comprehensive type definitions
@@ -40,8 +41,41 @@ This package requires the following peer dependencies:
40
41
  npm install react-native-reanimated react-native-gesture-handler @shaquillehinds/react-native-essentials
41
42
  ```
42
43
 
44
+ ### Setup
45
+
46
+ Wrap your app with `BottomSheetPortalProvider` at the root level:
47
+
48
+ ```tsx
49
+ import { BottomSheetPortalProvider } from '@shaquillehinds/react-native-bottom-sheet';
50
+
51
+ export default function App() {
52
+ return (
53
+ <BottomSheetPortalProvider>
54
+ {/* Your app content */}
55
+ </BottomSheetPortalProvider>
56
+ );
57
+ }
58
+ ```
59
+
60
+ This provider enables bottom sheets to render at the top level of your app, above all other content including navigation.
61
+
43
62
  ## Quick Start
44
63
 
64
+ First, wrap your app with the portal provider:
65
+
66
+ ```tsx
67
+ // App.tsx
68
+ import { BottomSheetPortalProvider } from '@shaquillehinds/react-native-bottom-sheet';
69
+
70
+ export default function App() {
71
+ return (
72
+ <BottomSheetPortalProvider>
73
+ <YourApp />
74
+ </BottomSheetPortalProvider>
75
+ );
76
+ }
77
+ ```
78
+
45
79
  ### Basic Modal Bottom Sheet
46
80
 
47
81
  ```tsx
@@ -53,7 +87,7 @@ import {
53
87
  } from '@shaquillehinds/react-native-bottom-sheet';
54
88
  import type { BottomModalRefObject } from '@shaquillehinds/react-native-bottom-sheet';
55
89
 
56
- export default function App() {
90
+ export default function MyScreen() {
57
91
  const [showModal, setShowModal] = useState(false);
58
92
  const bottomSheetRef = useRef<BottomModalRefObject>(null);
59
93
 
@@ -110,6 +144,110 @@ Optimized FlatList with proper gesture handling inside bottom sheets.
110
144
 
111
145
  Optimized ScrollView with proper gesture handling inside bottom sheets.
112
146
 
147
+ ## Portal System
148
+
149
+ The portal system allows bottom sheets to render at the root level of your app, ensuring they appear above all content including navigation stacks.
150
+
151
+ ### `BottomSheetPortalProvider`
152
+
153
+ **Required**: Wrap your app root with this provider to enable portal functionality.
154
+
155
+ ```tsx
156
+ import { BottomSheetPortalProvider } from '@shaquillehinds/react-native-bottom-sheet';
157
+
158
+ export default function App() {
159
+ return (
160
+ <BottomSheetPortalProvider>
161
+ <Navigation />
162
+ </BottomSheetPortalProvider>
163
+ );
164
+ }
165
+ ```
166
+
167
+ **Props:**
168
+
169
+ | Prop | Type | Default | Description |
170
+ | --------------------- | -------- | ------- | ------------------------------------------------------------------ |
171
+ | `unMountBufferTimeMS` | `number` | `100` | Delay before removing portal items (prevents premature unmounting) |
172
+ | `updateBufferTimeMS` | `number` | - | Throttle time for portal updates (prevents infinite update loops) |
173
+
174
+ ### `useBottomSheetPortal`
175
+
176
+ Access portal context to manually mount/update/unmount portal items.
177
+
178
+ ```tsx
179
+ import { useBottomSheetPortal } from '@shaquillehinds/react-native-bottom-sheet';
180
+
181
+ function MyComponent() {
182
+ const portal = useBottomSheetPortal();
183
+
184
+ useEffect(() => {
185
+ if (portal) {
186
+ const key = portal.mount('my-portal-key', <MyPortalContent />);
187
+ return () => portal.unmount(key);
188
+ }
189
+ }, []);
190
+
191
+ return <View />;
192
+ }
193
+ ```
194
+
195
+ **Methods:**
196
+
197
+ ```typescript
198
+ {
199
+ mount: (key: string | number, element: ReactNode, onMount?: (key) => void) => PortalKey;
200
+ update: (key: string | number, element: ReactNode) => void;
201
+ unmount: (key: string | number, onUnMount?: (key) => void) => void;
202
+ }
203
+ ```
204
+
205
+ ### `useBottomSheetPortalComponent`
206
+
207
+ Simplified hook for mounting a component to the portal with automatic lifecycle management.
208
+
209
+ ```tsx
210
+ import { useBottomSheetPortalComponent } from '@shaquillehinds/react-native-bottom-sheet';
211
+
212
+ function MyComponent() {
213
+ const [showOverlay, setShowOverlay] = useState(true);
214
+
215
+ useBottomSheetPortalComponent({
216
+ name: 'my-overlay',
217
+ Component: showOverlay ? <OverlayContent /> : null,
218
+ disable: !showOverlay,
219
+ });
220
+
221
+ return <View />;
222
+ }
223
+ ```
224
+
225
+ **Props:**
226
+
227
+ | Prop | Type | Description |
228
+ | --------------------- | --------------- | ------------------------------------------------ |
229
+ | `name` | `string` | Unique identifier for the portal component |
230
+ | `Component` | `ReactNode` | The component to render in the portal |
231
+ | `disable` | `boolean` | Disables portal rendering when true |
232
+ | `CustomPortalContext` | `React.Context` | Use a custom portal context (for scoped portals) |
233
+
234
+ ### Types
235
+
236
+ ```typescript
237
+ import type {
238
+ PortalItem,
239
+ PortalKey,
240
+ PortalContextValue,
241
+ } from '@shaquillehinds/react-native-bottom-sheet';
242
+
243
+ type PortalItem = {
244
+ key: PortalKey;
245
+ element: ReactNode;
246
+ };
247
+
248
+ type PortalKey = number | string;
249
+ ```
250
+
113
251
  ## API Reference
114
252
 
115
253
  ### Props
@@ -468,9 +606,37 @@ Or use opacity animation:
468
606
 
469
607
  ### Portal Management
470
608
 
471
- By default, the bottom sheet uses a portal to render at the root level. You can customize this:
609
+ By default, bottom sheets use the portal system to render at the root level, ensuring they appear above all content.
610
+
611
+ #### Using Default Portal (Recommended)
612
+
613
+ The bottom sheet automatically uses the portal when `BottomSheetPortalProvider` is set up:
614
+
615
+ ```tsx
616
+ // App.tsx
617
+ import { BottomSheetPortalProvider } from '@shaquillehinds/react-native-bottom-sheet';
618
+
619
+ export default function App() {
620
+ return (
621
+ <BottomSheetPortalProvider>
622
+ <NavigationContainer>
623
+ <Stack.Navigator>
624
+ <Stack.Screen name="Home" component={HomeScreen} />
625
+ </Stack.Navigator>
626
+ </NavigationContainer>
627
+ </BottomSheetPortalProvider>
628
+ );
629
+ }
472
630
 
473
- #### Disable Portal
631
+ // HomeScreen.tsx - bottom sheet will render above navigation
632
+ <BottomSheetModal showModal={showModal} setShowModal={setShowModal}>
633
+ <YourContent />
634
+ </BottomSheetModal>;
635
+ ```
636
+
637
+ #### Disable Portal Rendering
638
+
639
+ If you want the bottom sheet to render in its natural position in the component tree:
474
640
 
475
641
  ```tsx
476
642
  <BottomSheetModal
@@ -482,26 +648,124 @@ By default, the bottom sheet uses a portal to render at the root level. You can
482
648
  </BottomSheetModal>
483
649
  ```
484
650
 
485
- #### Custom Portal Context
651
+ #### Custom Portal Context (Advanced)
652
+
653
+ Create scoped portals for specific parts of your app:
486
654
 
487
655
  ```tsx
488
- import { createPortalContext } from '@shaquillehinds/react-native-essentials';
656
+ import {
657
+ BottomSheetPortalProvider,
658
+ useBottomSheetPortal,
659
+ } from '@shaquillehinds/react-native-bottom-sheet';
660
+ import { createContext } from 'react';
661
+ import type { PortalContextValue } from '@shaquillehinds/react-native-bottom-sheet';
489
662
 
490
- const MyPortalContext = createPortalContext();
663
+ // Create a custom portal context
664
+ const MyCustomPortalContext = createContext<PortalContextValue | undefined>(
665
+ undefined
666
+ );
491
667
 
492
- // In your app root
493
- <MyPortalContext.Provider>
494
- <YourApp />
495
- </MyPortalContext.Provider>
668
+ // Wrap specific section with custom portal provider
669
+ function MySection() {
670
+ return (
671
+ <BottomSheetPortalProvider CustomPortalContext={MyCustomPortalContext}>
672
+ <MySectionContent />
673
+ </BottomSheetPortalProvider>
674
+ );
675
+ }
496
676
 
497
- // In your component
677
+ // Use the custom context in your bottom sheet
498
678
  <BottomSheetModal
499
- CustomPortalContext={MyPortalContext}
679
+ CustomPortalContext={MyCustomPortalContext}
500
680
  showModal={showModal}
501
681
  setShowModal={setShowModal}
502
682
  >
503
683
  <YourContent />
504
- </BottomSheetModal>
684
+ </BottomSheetModal>;
685
+ ```
686
+
687
+ #### Manual Portal Control
688
+
689
+ For advanced use cases where you need direct portal control:
690
+
691
+ ```tsx
692
+ import { useBottomSheetPortal } from '@shaquillehinds/react-native-bottom-sheet';
693
+
694
+ function CustomPortalComponent() {
695
+ const portal = useBottomSheetPortal();
696
+ const [portalKey, setPortalKey] = useState<string | number | null>(null);
697
+
698
+ const mountContent = () => {
699
+ if (portal) {
700
+ const key = portal.mount(
701
+ 'custom-content',
702
+ <View style={{ padding: 20, backgroundColor: 'white' }}>
703
+ <Text>Portal Content</Text>
704
+ </View>,
705
+ (key) => console.log('Mounted:', key)
706
+ );
707
+ setPortalKey(key);
708
+ }
709
+ };
710
+
711
+ const updateContent = () => {
712
+ if (portal && portalKey) {
713
+ portal.update(
714
+ portalKey,
715
+ <View style={{ padding: 20, backgroundColor: 'blue' }}>
716
+ <Text>Updated Content</Text>
717
+ </View>
718
+ );
719
+ }
720
+ };
721
+
722
+ const unmountContent = () => {
723
+ if (portal && portalKey) {
724
+ portal.unmount(portalKey, (key) => console.log('Unmounted:', key));
725
+ setPortalKey(null);
726
+ }
727
+ };
728
+
729
+ return (
730
+ <View>
731
+ <Button title="Mount" onPress={mountContent} />
732
+ <Button title="Update" onPress={updateContent} />
733
+ <Button title="Unmount" onPress={unmountContent} />
734
+ </View>
735
+ );
736
+ }
737
+ ```
738
+
739
+ #### Using Portal Component Hook
740
+
741
+ Simplified component-based portal management with automatic cleanup:
742
+
743
+ ```tsx
744
+ import { useBottomSheetPortalComponent } from '@shaquillehinds/react-native-bottom-sheet';
745
+
746
+ function ToastNotification() {
747
+ const [message, setMessage] = useState('');
748
+ const [show, setShow] = useState(false);
749
+
750
+ // Automatically mounts/unmounts based on show state
751
+ useBottomSheetPortalComponent({
752
+ name: 'toast-notification',
753
+ Component: show ? (
754
+ <View style={{ position: 'absolute', top: 50, alignSelf: 'center' }}>
755
+ <Text>{message}</Text>
756
+ </View>
757
+ ) : null,
758
+ disable: !show,
759
+ });
760
+
761
+ const showToast = (msg: string) => {
762
+ setMessage(msg);
763
+ setShow(true);
764
+ setTimeout(() => setShow(false), 3000);
765
+ };
766
+
767
+ return <Button title="Show Toast" onPress={() => showToast('Hello!')} />;
768
+ }
505
769
  ```
506
770
 
507
771
  ### Navigation Integration
@@ -533,18 +797,36 @@ bottomSheetRef.current?.closeModal({
533
797
  Full TypeScript support with comprehensive type definitions:
534
798
 
535
799
  ```typescript
800
+ // Component Props
536
801
  import type {
537
802
  BottomSheetProps,
538
803
  BottomSheetModalProps,
804
+ BottomSheetFlatlistProps,
805
+ BottomSheetScrollViewProps,
806
+ } from '@shaquillehinds/react-native-bottom-sheet';
807
+
808
+ // Ref Types
809
+ import type {
539
810
  BottomModalRefObject,
540
811
  BottomSheetRefObject,
541
812
  BottomModalRef,
542
813
  BottomSheetRef,
814
+ } from '@shaquillehinds/react-native-bottom-sheet';
815
+
816
+ // State and Config Types
817
+ import type {
543
818
  ModalState,
544
819
  AnimateCloseModalProps,
545
820
  CloseModalProps,
546
821
  OpenModalProps,
547
822
  } from '@shaquillehinds/react-native-bottom-sheet';
823
+
824
+ // Portal Types
825
+ import type {
826
+ PortalItem,
827
+ PortalKey,
828
+ PortalContextValue,
829
+ } from '@shaquillehinds/react-native-bottom-sheet';
548
830
  ```
549
831
 
550
832
  ## Examples
@@ -705,6 +987,166 @@ export default function FormExample() {
705
987
  }
706
988
  ```
707
989
 
990
+ ### Custom Portal Overlay Example
991
+
992
+ ```tsx
993
+ import React, { useState } from 'react';
994
+ import { View, Text, Button, TouchableOpacity, StyleSheet } from 'react-native';
995
+ import {
996
+ BottomSheetPortalProvider,
997
+ useBottomSheetPortalComponent,
998
+ } from '@shaquillehinds/react-native-bottom-sheet';
999
+
1000
+ // App root with provider
1001
+ export default function App() {
1002
+ return (
1003
+ <BottomSheetPortalProvider>
1004
+ <MyScreen />
1005
+ </BottomSheetPortalProvider>
1006
+ );
1007
+ }
1008
+
1009
+ // Screen with custom portal overlay
1010
+ function MyScreen() {
1011
+ const [showOverlay, setShowOverlay] = useState(false);
1012
+ const [message, setMessage] = useState('');
1013
+
1014
+ // Mount custom overlay to portal
1015
+ useBottomSheetPortalComponent({
1016
+ name: 'custom-overlay',
1017
+ Component: showOverlay ? (
1018
+ <TouchableOpacity
1019
+ style={styles.overlay}
1020
+ activeOpacity={1}
1021
+ onPress={() => setShowOverlay(false)}
1022
+ >
1023
+ <View style={styles.overlayContent}>
1024
+ <Text style={styles.overlayText}>{message}</Text>
1025
+ <Button title="Close" onPress={() => setShowOverlay(false)} />
1026
+ </View>
1027
+ </TouchableOpacity>
1028
+ ) : null,
1029
+ disable: !showOverlay,
1030
+ });
1031
+
1032
+ const showCustomOverlay = (msg: string) => {
1033
+ setMessage(msg);
1034
+ setShowOverlay(true);
1035
+ };
1036
+
1037
+ return (
1038
+ <View style={styles.container}>
1039
+ <Button
1040
+ title="Show Portal Overlay"
1041
+ onPress={() => showCustomOverlay('This is rendered in the portal!')}
1042
+ />
1043
+ </View>
1044
+ );
1045
+ }
1046
+
1047
+ const styles = StyleSheet.create({
1048
+ container: {
1049
+ flex: 1,
1050
+ justifyContent: 'center',
1051
+ alignItems: 'center',
1052
+ },
1053
+ overlay: {
1054
+ ...StyleSheet.absoluteFillObject,
1055
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
1056
+ justifyContent: 'center',
1057
+ alignItems: 'center',
1058
+ },
1059
+ overlayContent: {
1060
+ backgroundColor: 'white',
1061
+ padding: 30,
1062
+ borderRadius: 10,
1063
+ alignItems: 'center',
1064
+ },
1065
+ overlayText: {
1066
+ fontSize: 18,
1067
+ marginBottom: 20,
1068
+ },
1069
+ });
1070
+ ```
1071
+
1072
+ ### Multi-Level Portal Example
1073
+
1074
+ ```tsx
1075
+ import React, { createContext, useState } from 'react';
1076
+ import { View, Button } from 'react-native';
1077
+ import {
1078
+ BottomSheetPortalProvider,
1079
+ BottomSheetModal,
1080
+ } from '@shaquillehinds/react-native-bottom-sheet';
1081
+ import type { PortalContextValue } from '@shaquillehinds/react-native-bottom-sheet';
1082
+
1083
+ // Create custom portal contexts for different levels
1084
+ const ScreenPortalContext = createContext<PortalContextValue | undefined>(
1085
+ undefined
1086
+ );
1087
+ const DialogPortalContext = createContext<PortalContextValue | undefined>(
1088
+ undefined
1089
+ );
1090
+
1091
+ export default function App() {
1092
+ return (
1093
+ // Global portal for app-wide modals
1094
+ <BottomSheetPortalProvider>
1095
+ <Navigation />
1096
+ </BottomSheetPortalProvider>
1097
+ );
1098
+ }
1099
+
1100
+ function MyScreen() {
1101
+ const [showScreenModal, setShowScreenModal] = useState(false);
1102
+ const [showDialogModal, setShowDialogModal] = useState(false);
1103
+
1104
+ return (
1105
+ // Screen-specific portal
1106
+ <BottomSheetPortalProvider CustomPortalContext={ScreenPortalContext}>
1107
+ <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
1108
+ <Button
1109
+ title="Open Screen Modal"
1110
+ onPress={() => setShowScreenModal(true)}
1111
+ />
1112
+
1113
+ {/* Modal using screen portal */}
1114
+ <BottomSheetModal
1115
+ CustomPortalContext={ScreenPortalContext}
1116
+ showModal={showScreenModal}
1117
+ setShowModal={setShowScreenModal}
1118
+ snapPoints={[50]}
1119
+ >
1120
+ <View style={{ padding: 20 }}>
1121
+ <Text>Screen-level modal</Text>
1122
+ <Button
1123
+ title="Open Dialog"
1124
+ onPress={() => setShowDialogModal(true)}
1125
+ />
1126
+
1127
+ {/* Nested modal using dialog portal */}
1128
+ <BottomSheetPortalProvider
1129
+ CustomPortalContext={DialogPortalContext}
1130
+ >
1131
+ <BottomSheetModal
1132
+ CustomPortalContext={DialogPortalContext}
1133
+ showModal={showDialogModal}
1134
+ setShowModal={setShowDialogModal}
1135
+ snapPoints={[30]}
1136
+ >
1137
+ <View style={{ padding: 20 }}>
1138
+ <Text>Dialog-level modal</Text>
1139
+ </View>
1140
+ </BottomSheetModal>
1141
+ </BottomSheetPortalProvider>
1142
+ </View>
1143
+ </BottomSheetModal>
1144
+ </View>
1145
+ </BottomSheetPortalProvider>
1146
+ );
1147
+ }
1148
+ ```
1149
+
708
1150
  ## Performance Best Practices
709
1151
 
710
1152
  1. **Use `useImperativeHandle` pattern**: This package follows the render isolation pattern to prevent parent re-renders when animating
@@ -805,6 +1247,95 @@ function FilterPanel() {
805
1247
  }
806
1248
  ```
807
1249
 
1250
+ ### Toast Notification (Using Portal)
1251
+
1252
+ ```tsx
1253
+ import { useBottomSheetPortalComponent } from '@shaquillehinds/react-native-bottom-sheet';
1254
+
1255
+ function useToast() {
1256
+ const [message, setMessage] = useState('');
1257
+ const [visible, setVisible] = useState(false);
1258
+
1259
+ useBottomSheetPortalComponent({
1260
+ name: 'toast',
1261
+ Component: visible ? (
1262
+ <Animated.View
1263
+ entering={SlideInDown}
1264
+ exiting={SlideOutUp}
1265
+ style={{
1266
+ position: 'absolute',
1267
+ top: 50,
1268
+ alignSelf: 'center',
1269
+ backgroundColor: '#333',
1270
+ padding: 15,
1271
+ borderRadius: 8,
1272
+ }}
1273
+ >
1274
+ <Text style={{ color: 'white' }}>{message}</Text>
1275
+ </Animated.View>
1276
+ ) : null,
1277
+ disable: !visible,
1278
+ });
1279
+
1280
+ const show = (msg: string) => {
1281
+ setMessage(msg);
1282
+ setVisible(true);
1283
+ setTimeout(() => setVisible(false), 3000);
1284
+ };
1285
+
1286
+ return { show };
1287
+ }
1288
+
1289
+ // Usage
1290
+ function MyComponent() {
1291
+ const toast = useToast();
1292
+
1293
+ return <Button title="Show Toast" onPress={() => toast.show('Hello!')} />;
1294
+ }
1295
+ ```
1296
+
1297
+ ### Loading Overlay (Using Portal)
1298
+
1299
+ ```tsx
1300
+ import { useBottomSheetPortalComponent } from '@shaquillehinds/react-native-bottom-sheet';
1301
+
1302
+ function useLoadingOverlay() {
1303
+ const [isLoading, setIsLoading] = useState(false);
1304
+
1305
+ useBottomSheetPortalComponent({
1306
+ name: 'loading-overlay',
1307
+ Component: isLoading ? (
1308
+ <View
1309
+ style={{
1310
+ ...StyleSheet.absoluteFillObject,
1311
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
1312
+ justifyContent: 'center',
1313
+ alignItems: 'center',
1314
+ }}
1315
+ >
1316
+ <ActivityIndicator size="large" color="#fff" />
1317
+ </View>
1318
+ ) : null,
1319
+ disable: !isLoading,
1320
+ });
1321
+
1322
+ return { setIsLoading };
1323
+ }
1324
+
1325
+ // Usage
1326
+ function MyComponent() {
1327
+ const { setIsLoading } = useLoadingOverlay();
1328
+
1329
+ const handleSubmit = async () => {
1330
+ setIsLoading(true);
1331
+ await api.submit();
1332
+ setIsLoading(false);
1333
+ };
1334
+
1335
+ return <Button title="Submit" onPress={handleSubmit} />;
1336
+ }
1337
+ ```
1338
+
808
1339
  ## Troubleshooting
809
1340
 
810
1341
  ### Modal doesn't appear
@@ -819,6 +1350,55 @@ module.exports = {
819
1350
  };
820
1351
  ```
821
1352
 
1353
+ **Also verify `BottomSheetPortalProvider` is set up at your app root:**
1354
+
1355
+ ```tsx
1356
+ // App.tsx
1357
+ import { BottomSheetPortalProvider } from '@shaquillehinds/react-native-bottom-sheet';
1358
+
1359
+ export default function App() {
1360
+ return (
1361
+ <BottomSheetPortalProvider>
1362
+ <YourNavigator />
1363
+ </BottomSheetPortalProvider>
1364
+ );
1365
+ }
1366
+ ```
1367
+
1368
+ ### Modal appears behind navigation or other elements
1369
+
1370
+ This typically means the portal provider is not at a high enough level in your component tree. The provider should wrap your navigation container:
1371
+
1372
+ ```tsx
1373
+ // ✅ Correct - Provider wraps navigation
1374
+ <BottomSheetPortalProvider>
1375
+ <NavigationContainer>
1376
+ <Stack.Navigator>
1377
+ {/* screens */}
1378
+ </Stack.Navigator>
1379
+ </NavigationContainer>
1380
+ </BottomSheetPortalProvider>
1381
+
1382
+ // ❌ Incorrect - Provider inside navigation
1383
+ <NavigationContainer>
1384
+ <BottomSheetPortalProvider>
1385
+ <Stack.Navigator>
1386
+ {/* screens */}
1387
+ </Stack.Navigator>
1388
+ </BottomSheetPortalProvider>
1389
+ </NavigationContainer>
1390
+ ```
1391
+
1392
+ ### Portal content flickers or unmounts unexpectedly
1393
+
1394
+ Adjust the `unMountBufferTimeMS` prop on the provider:
1395
+
1396
+ ```tsx
1397
+ <BottomSheetPortalProvider unMountBufferTimeMS={200}>
1398
+ <YourApp />
1399
+ </BottomSheetPortalProvider>
1400
+ ```
1401
+
822
1402
  ### Scrolling issues
823
1403
 
824
1404
  Always use `BottomSheetFlatlist` or `BottomSheetScrollView` for scrollable content inside the bottom sheet.
@@ -3,9 +3,34 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ var _exportNames = {
7
+ BottomSheetPortalProvider: true,
8
+ useBottomSheetPortalComponent: true,
9
+ useBottomSheetPortal: true
10
+ };
11
+ Object.defineProperty(exports, "BottomSheetPortalProvider", {
12
+ enumerable: true,
13
+ get: function () {
14
+ return _reactNativeEssentials.PortalProvider;
15
+ }
16
+ });
17
+ Object.defineProperty(exports, "useBottomSheetPortal", {
18
+ enumerable: true,
19
+ get: function () {
20
+ return _reactNativeEssentials.usePortal;
21
+ }
22
+ });
23
+ Object.defineProperty(exports, "useBottomSheetPortalComponent", {
24
+ enumerable: true,
25
+ get: function () {
26
+ return _reactNativeEssentials.usePortalComponent;
27
+ }
28
+ });
29
+ var _reactNativeEssentials = require("@shaquillehinds/react-native-essentials");
6
30
  var _index = require("./BottomSheet/index.js");
7
31
  Object.keys(_index).forEach(function (key) {
8
32
  if (key === "default" || key === "__esModule") return;
33
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
9
34
  if (key in exports && exports[key] === _index[key]) return;
10
35
  Object.defineProperty(exports, key, {
11
36
  enumerable: true,
@@ -1 +1 @@
1
- {"version":3,"names":["_index","require","Object","keys","forEach","key","exports","defineProperty","enumerable","get"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,MAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAL,MAAA,CAAAK,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAT,MAAA,CAAAK,GAAA;IAAA;EAAA;AAAA","ignoreList":[]}
1
+ {"version":3,"names":["_reactNativeEssentials","require","_index","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,sBAAA,GAAAC,OAAA;AAOA,IAAAC,MAAA,GAAAD,OAAA;AAAAE,MAAA,CAAAC,IAAA,CAAAF,MAAA,EAAAG,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAJ,MAAA,CAAAI,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAZ,MAAA,CAAAI,GAAA;IAAA;EAAA;AAAA","ignoreList":[]}
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
2
 
3
+ export { PortalProvider as BottomSheetPortalProvider, usePortalComponent as useBottomSheetPortalComponent, usePortal as useBottomSheetPortal } from '@shaquillehinds/react-native-essentials';
3
4
  export * from "./BottomSheet/index.js";
4
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":[],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,cAAc,wBAAe","ignoreList":[]}
1
+ {"version":3,"names":["PortalProvider","BottomSheetPortalProvider","usePortalComponent","useBottomSheetPortalComponent","usePortal","useBottomSheetPortal"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SACEA,cAAc,IAAIC,yBAAyB,EAE3CC,kBAAkB,IAAIC,6BAA6B,EACnDC,SAAS,IAAIC,oBAAoB,QAC5B,yCAAyC;AAEhD,cAAc,wBAAe","ignoreList":[]}
@@ -1,2 +1,3 @@
1
+ export { PortalProvider as BottomSheetPortalProvider, type PortalItem, usePortalComponent as useBottomSheetPortalComponent, usePortal as useBottomSheetPortal, } from '@shaquillehinds/react-native-essentials';
1
2
  export * from './BottomSheet';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,IAAI,yBAAyB,EAC3C,KAAK,UAAU,EACf,kBAAkB,IAAI,6BAA6B,EACnD,SAAS,IAAI,oBAAoB,GAClC,MAAM,yCAAyC,CAAC;AAEjD,cAAc,eAAe,CAAC"}
@@ -1,2 +1,3 @@
1
+ export { PortalProvider as BottomSheetPortalProvider, type PortalItem, usePortalComponent as useBottomSheetPortalComponent, usePortal as useBottomSheetPortal, } from '@shaquillehinds/react-native-essentials';
1
2
  export * from './BottomSheet';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,IAAI,yBAAyB,EAC3C,KAAK,UAAU,EACf,kBAAkB,IAAI,6BAA6B,EACnD,SAAS,IAAI,oBAAoB,GAClC,MAAM,yCAAyC,CAAC;AAEjD,cAAc,eAAe,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shaquillehinds/react-native-bottom-sheet",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "A simple bottom sheet for react native that just works.",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/commonjs/index.js",
package/src/index.tsx CHANGED
@@ -1 +1,8 @@
1
+ export {
2
+ PortalProvider as BottomSheetPortalProvider,
3
+ type PortalItem,
4
+ usePortalComponent as useBottomSheetPortalComponent,
5
+ usePortal as useBottomSheetPortal,
6
+ } from '@shaquillehinds/react-native-essentials';
7
+
1
8
  export * from './BottomSheet';