@lodev09/react-native-true-sheet 3.3.0-beta.0 → 3.3.0-beta.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.
Files changed (33) hide show
  1. package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +3 -6
  2. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +41 -35
  3. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +0 -9
  4. package/android/src/main/java/com/lodev09/truesheet/core/RNScreensFragmentObserver.kt +0 -14
  5. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetKeyboardHandler.kt +120 -0
  6. package/android/src/main/java/com/lodev09/truesheet/utils/ScreenUtils.kt +9 -9
  7. package/ios/TrueSheetContainerView.h +10 -0
  8. package/ios/TrueSheetContainerView.mm +10 -0
  9. package/ios/TrueSheetFooterView.h +2 -0
  10. package/ios/TrueSheetFooterView.mm +65 -5
  11. package/ios/TrueSheetView.mm +2 -0
  12. package/ios/TrueSheetViewController.mm +0 -54
  13. package/lib/module/TrueSheet.js +0 -2
  14. package/lib/module/TrueSheet.js.map +1 -1
  15. package/lib/module/TrueSheet.web.js +57 -39
  16. package/lib/module/TrueSheet.web.js.map +1 -1
  17. package/lib/module/__mocks__/index.js +81 -0
  18. package/lib/module/__mocks__/index.js.map +1 -0
  19. package/lib/module/fabric/TrueSheetViewNativeComponent.ts +1 -1
  20. package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
  21. package/lib/typescript/src/TrueSheet.types.d.ts +25 -5
  22. package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
  23. package/lib/typescript/src/TrueSheet.web.d.ts.map +1 -1
  24. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +0 -1
  25. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
  26. package/lib/typescript/src/navigation/types.d.ts +1 -1
  27. package/lib/typescript/src/navigation/types.d.ts.map +1 -1
  28. package/package.json +19 -12
  29. package/src/TrueSheet.tsx +1 -2
  30. package/src/TrueSheet.types.ts +26 -5
  31. package/src/TrueSheet.web.tsx +60 -39
  32. package/src/fabric/TrueSheetViewNativeComponent.ts +1 -1
  33. package/src/navigation/types.ts +2 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lodev09/react-native-true-sheet",
3
- "version": "3.3.0-beta.0",
3
+ "version": "3.3.0-beta.2",
4
4
  "description": "The true native bottom sheet experience for your React Native Apps.",
5
5
  "source": "./src/index.ts",
6
6
  "main": "./lib/module/index.js",
@@ -42,8 +42,8 @@
42
42
  "!**/.*"
43
43
  ],
44
44
  "scripts": {
45
- "example": "yarn workspace react-native-true-sheet-example",
46
- "expo-example": "yarn workspace expo-example",
45
+ "bare": "yarn workspace @example/bare",
46
+ "expo": "yarn workspace @example/expo",
47
47
  "docs": "yarn workspace docs",
48
48
  "test": "jest",
49
49
  "typecheck": "tsc",
@@ -52,8 +52,8 @@
52
52
  "tidy": "yarn typecheck && yarn lint && yarn format && scripts/objclint.sh && scripts/ktlint.sh",
53
53
  "clean": "scripts/clean.sh",
54
54
  "prepare": "bob build",
55
- "release": "release-it --only-version",
56
- "release:beta": "yarn release --preRelease=beta"
55
+ "release": "release-it",
56
+ "release:beta": "yarn release -i prerelease"
57
57
  },
58
58
  "keywords": [
59
59
  "react-native",
@@ -105,15 +105,17 @@
105
105
  "react": "19.1.1",
106
106
  "react-native": "0.82.1",
107
107
  "react-native-builder-bob": "^0.40.15",
108
- "react-native-reanimated": "^4.1.5",
109
- "react-native-worklets": "^0.6.1",
108
+ "react-native-reanimated": "^4.2.0",
109
+ "react-native-worklets": "^0.7.0",
110
110
  "react-test-renderer": "19.1.1",
111
111
  "release-it": "^19.0.4",
112
112
  "turbo": "^2.5.6",
113
113
  "typescript": "^5.9.2"
114
114
  },
115
115
  "resolutions": {
116
- "@types/react": "19.1.1"
116
+ "@types/react": "19.1.1",
117
+ "react-native-reanimated": "^4.2.0",
118
+ "react-native-worklets": "^0.7.0"
117
119
  },
118
120
  "peerDependencies": {
119
121
  "@gorhom/bottom-sheet": ">=5",
@@ -138,8 +140,9 @@
138
140
  }
139
141
  },
140
142
  "workspaces": [
141
- "example",
142
- "expo-example",
143
+ "example/bare",
144
+ "example/expo",
145
+ "example/shared",
143
146
  "docs"
144
147
  ],
145
148
  "packageManager": "yarn@4.11.0",
@@ -152,14 +155,17 @@
152
155
  "node_modules/(?!(react-native|@react-native|react-native-reanimated|react-native-worklets|react-native-worklets-core)/)"
153
156
  ],
154
157
  "modulePathIgnorePatterns": [
155
- "<rootDir>/example/node_modules",
158
+ "<rootDir>/example/bare/node_modules",
159
+ "<rootDir>/example/expo/node_modules",
160
+ "<rootDir>/example/shared/node_modules",
156
161
  "<rootDir>/lib/",
157
162
  "<rootDir>/docs/node_modules",
158
163
  "<rootDir>/docs/build"
159
164
  ],
160
165
  "testPathIgnorePatterns": [
161
166
  "/node_modules/",
162
- "<rootDir>/src/__mocks__/"
167
+ "<rootDir>/src/__mocks__/",
168
+ "<rootDir>/example/"
163
169
  ]
164
170
  },
165
171
  "commitlint": {
@@ -208,6 +214,7 @@
208
214
  "react-native-builder-bob": {
209
215
  "source": "src",
210
216
  "output": "lib",
217
+ "exclude": "**/{__tests__,__fixtures__}/**",
211
218
  "targets": [
212
219
  [
213
220
  "module",
package/src/TrueSheet.tsx CHANGED
@@ -364,7 +364,7 @@ export class TrueSheet
364
364
  dimmed = true,
365
365
  initialDetentIndex = -1,
366
366
  initialDetentAnimated = true,
367
- keyboardMode = 'resize',
367
+
368
368
  dimmedDetentIndex,
369
369
  blurTint,
370
370
  blurOptions,
@@ -421,7 +421,6 @@ export class TrueSheet
421
421
  }}
422
422
  dimmed={dimmed}
423
423
  dimmedDetentIndex={dimmedDetentIndex}
424
- keyboardMode={keyboardMode}
425
424
  initialDetentIndex={initialDetentIndex}
426
425
  initialDetentAnimated={initialDetentAnimated}
427
426
  dismissible={dismissible}
@@ -143,6 +143,25 @@ export interface BlurOptions {
143
143
  interaction?: boolean;
144
144
  }
145
145
 
146
+ /**
147
+ * Defines the stack behavior when a modal is presented on web.
148
+ *
149
+ * @platform web
150
+ */
151
+ export type StackBehavior =
152
+ /**
153
+ * Mount the modal on top of the current one.
154
+ */
155
+ | 'push'
156
+ /**
157
+ * Minimize the current modal then mount the new one.
158
+ */
159
+ | 'switch'
160
+ /**
161
+ * Dismiss the current modal then mount the new one.
162
+ */
163
+ | 'replace';
164
+
146
165
  /**
147
166
  * Inset adjustment behavior for the sheet content.
148
167
  */
@@ -393,13 +412,15 @@ export interface TrueSheetProps extends ViewProps {
393
412
  scrollable?: boolean;
394
413
 
395
414
  /**
396
- * Determines how the software keyboard will impact the layout of the sheet.
397
- * Set to `pan` if you're working with `FlatList` with a `TextInput`.
415
+ * Defines the stack behavior when a modal is presented.
416
+ * - `push`: Mount the modal on top of the current one.
417
+ * - `switch`: Minimize the current modal then mount the new one.
418
+ * - `replace`: Dismiss the current modal then mount the new one.
398
419
  *
399
- * @platform android
400
- * @default resize
420
+ * @platform web
421
+ * @default 'switch'
401
422
  */
402
- keyboardMode?: 'resize' | 'pan';
423
+ stackBehavior?: StackBehavior;
403
424
 
404
425
  /**
405
426
  * Called when the sheet's content is mounted and ready.
@@ -6,6 +6,7 @@ import {
6
6
  useCallback,
7
7
  useContext,
8
8
  useEffect,
9
+ useId,
9
10
  useImperativeHandle,
10
11
  useMemo,
11
12
  useRef,
@@ -22,6 +23,7 @@ import {
22
23
  type BottomSheetHandleProps,
23
24
  BottomSheetModal,
24
25
  BottomSheetView,
26
+ BottomSheetScrollView,
25
27
  type SNAP_POINT_TYPE,
26
28
  } from '@gorhom/bottom-sheet';
27
29
  import { useDerivedValue, useSharedValue } from 'react-native-reanimated';
@@ -47,7 +49,10 @@ import type {
47
49
  } from './TrueSheet.types';
48
50
 
49
51
  const DEFAULT_CORNER_RADIUS = 16;
52
+
50
53
  const DEFAULT_GRABBER_COLOR = 'rgba(0, 0, 0, 0.3)';
54
+ const DEFAULT_GRABBER_WIDTH = 32;
55
+ const DEFAULT_GRABBER_HEIGHT = 4;
51
56
 
52
57
  const renderSlot = (slot: TrueSheetProps['header'] | TrueSheetProps['footer']) => {
53
58
  if (!slot) return null;
@@ -87,10 +92,13 @@ export const TrueSheet = forwardRef<TrueSheetRef, TrueSheetProps>((props, ref) =
87
92
  onDidFocus,
88
93
  onWillBlur,
89
94
  onDidBlur,
95
+ stackBehavior = 'switch',
90
96
  style,
91
97
  } = props;
92
98
 
93
99
  const { height: windowHeight } = useWindowDimensions();
100
+ const defaultName = useId();
101
+ const sheetName = name ?? defaultName;
94
102
  const bottomSheetContext = useContext(BottomSheetContext);
95
103
  const modalRef = useRef<BottomSheetModal>(null);
96
104
  const initialDetentIndexRef = useRef(initialDetentIndex);
@@ -100,6 +108,9 @@ export const TrueSheet = forwardRef<TrueSheetRef, TrueSheetProps>((props, ref) =
100
108
  const isMinimized = useRef(false);
101
109
  const isDragging = useRef(false);
102
110
 
111
+ const presentResolver = useRef<(() => void) | null>(null);
112
+ const dismissResolver = useRef<(() => void) | null>(null);
113
+
103
114
  const animatedPosition = useSharedValue(windowHeight);
104
115
  const animatedIndex = useSharedValue(0);
105
116
 
@@ -158,6 +169,12 @@ export const TrueSheet = forwardRef<TrueSheetRef, TrueSheetProps>((props, ref) =
158
169
  if (isPresenting.current) {
159
170
  isPresenting.current = false;
160
171
 
172
+ // Resolve present promise
173
+ if (presentResolver.current) {
174
+ presentResolver.current();
175
+ presentResolver.current = null;
176
+ }
177
+
161
178
  onDidPresent?.({
162
179
  nativeEvent: {
163
180
  index,
@@ -184,6 +201,12 @@ export const TrueSheet = forwardRef<TrueSheetRef, TrueSheetProps>((props, ref) =
184
201
  );
185
202
 
186
203
  const handleDismiss = useCallback(() => {
204
+ // Resolve dismiss promise
205
+ if (dismissResolver.current) {
206
+ dismissResolver.current();
207
+ dismissResolver.current = null;
208
+ }
209
+
187
210
  onDidDismiss?.({ nativeEvent: null } as DidDismissEvent);
188
211
 
189
212
  // Reset states since sheet is being dismissed
@@ -271,22 +294,20 @@ export const TrueSheet = forwardRef<TrueSheetRef, TrueSheetProps>((props, ref) =
271
294
  if (!grabber) {
272
295
  return null;
273
296
  }
297
+
298
+ const height = grabberOptions?.height ?? DEFAULT_GRABBER_HEIGHT;
299
+ const borderRadius = grabberOptions?.cornerRadius ?? height / 2;
300
+
274
301
  return (
275
302
  <BottomSheetHandle
276
303
  {...handleProps}
277
- style={[
278
- styles.handle,
279
- grabberOptions?.topMargin !== undefined && { paddingTop: grabberOptions.topMargin },
280
- ]}
281
- indicatorStyle={[
282
- styles.handleIndicator,
283
- grabberOptions?.width !== undefined && { width: grabberOptions.width },
284
- grabberOptions?.height !== undefined && { height: grabberOptions.height },
285
- grabberOptions?.cornerRadius !== undefined && {
286
- borderRadius: grabberOptions.cornerRadius,
287
- },
288
- { backgroundColor: grabberOptions?.color ?? DEFAULT_GRABBER_COLOR },
289
- ]}
304
+ style={[styles.handle, { paddingTop: grabberOptions?.topMargin }]}
305
+ indicatorStyle={{
306
+ height,
307
+ borderRadius,
308
+ width: grabberOptions?.width ?? DEFAULT_GRABBER_WIDTH,
309
+ backgroundColor: grabberOptions?.color ?? DEFAULT_GRABBER_COLOR,
310
+ }}
290
311
  />
291
312
  );
292
313
  },
@@ -307,14 +328,20 @@ export const TrueSheet = forwardRef<TrueSheetRef, TrueSheetProps>((props, ref) =
307
328
  const ContainerComponent = scrollable ? Fragment : BottomSheetView;
308
329
 
309
330
  const sheetMethodsRef = useRef<TrueSheetRef>({
310
- present: async (index = 0) => {
311
- setSnapIndex(index);
312
- isPresenting.current = true;
313
- modalRef.current?.present();
331
+ present: (index = 0) => {
332
+ return new Promise<void>((resolve) => {
333
+ presentResolver.current = resolve;
334
+ setSnapIndex(index);
335
+ isPresenting.current = true;
336
+ modalRef.current?.present();
337
+ });
314
338
  },
315
- dismiss: async () => {
316
- isDismissing.current = true;
317
- modalRef.current?.dismiss();
339
+ dismiss: () => {
340
+ return new Promise<void>((resolve) => {
341
+ dismissResolver.current = resolve;
342
+ isDismissing.current = true;
343
+ modalRef.current?.dismiss();
344
+ });
318
345
  },
319
346
  resize: async (index: number) => {
320
347
  modalRef.current?.snapToIndex(index);
@@ -325,15 +352,11 @@ export const TrueSheet = forwardRef<TrueSheetRef, TrueSheetProps>((props, ref) =
325
352
 
326
353
  // Register with context provider
327
354
  useEffect(() => {
328
- if (name) {
329
- bottomSheetContext?.register(name, sheetMethodsRef);
330
- }
355
+ bottomSheetContext?.register(sheetName, sheetMethodsRef);
331
356
  return () => {
332
- if (name) {
333
- bottomSheetContext?.unregister(name);
334
- }
357
+ bottomSheetContext?.unregister(sheetName);
335
358
  };
336
- }, [name]);
359
+ }, [sheetName]);
337
360
 
338
361
  // Auto-present on mount if initialDetentIndex is set
339
362
  useEffect(() => {
@@ -353,7 +376,7 @@ export const TrueSheet = forwardRef<TrueSheetRef, TrueSheetProps>((props, ref) =
353
376
  return (
354
377
  <BottomSheetModal
355
378
  ref={modalRef}
356
- name={name}
379
+ name={sheetName}
357
380
  style={[
358
381
  styles.root,
359
382
  { backgroundColor, borderTopLeftRadius: cornerRadius, borderTopRightRadius: cornerRadius },
@@ -372,15 +395,18 @@ export const TrueSheet = forwardRef<TrueSheetRef, TrueSheetProps>((props, ref) =
372
395
  maxDynamicContentSize={maxHeight}
373
396
  snapPoints={snapPoints.length > 0 ? snapPoints : undefined}
374
397
  onDismiss={handleDismiss}
375
- stackBehavior="switch"
398
+ stackBehavior={stackBehavior}
376
399
  backdropComponent={backdropComponent}
400
+ backgroundComponent={null}
377
401
  footerComponent={footerComponent}
378
402
  >
379
403
  <ContainerComponent>
380
- <View style={[styles.container, style]}>
381
- {renderSlot(header)}
382
- {children}
383
- </View>
404
+ {renderSlot(header)}
405
+ {scrollable ? (
406
+ <BottomSheetScrollView contentContainerStyle={style}>{children}</BottomSheetScrollView>
407
+ ) : (
408
+ <View style={style}>{children}</View>
409
+ )}
384
410
  </ContainerComponent>
385
411
  </BottomSheetModal>
386
412
  );
@@ -390,18 +416,13 @@ const styles = StyleSheet.create({
390
416
  root: {
391
417
  overflow: 'hidden',
392
418
  },
393
- container: {},
394
419
  handle: {
395
420
  position: 'absolute',
396
421
  top: 0,
397
422
  left: 0,
398
423
  right: 0,
399
- zIndex: 1,
424
+ zIndex: 999,
400
425
  paddingVertical: 10,
401
426
  pointerEvents: 'none',
402
427
  },
403
- handleIndicator: {
404
- width: 36,
405
- height: 5,
406
- },
407
428
  });
@@ -48,7 +48,7 @@ export interface NativeProps extends ViewProps {
48
48
 
49
49
  // String properties - use empty string as default to avoid nil insertion
50
50
  blurTint?: WithDefault<string, ''>;
51
- keyboardMode?: WithDefault<'resize' | 'pan', 'resize'>;
51
+
52
52
  insetAdjustment?: WithDefault<'automatic' | 'never', 'automatic'>;
53
53
 
54
54
  // Blur options
@@ -138,10 +138,11 @@ export type TrueSheetNavigationOptions = Pick<
138
138
  | 'maxHeight'
139
139
  | 'edgeToEdgeFullScreen'
140
140
  | 'scrollable'
141
- | 'keyboardMode'
142
141
  | 'pageSizing'
143
142
  | 'header'
144
143
  | 'footer'
144
+ | 'insetAdjustment'
145
+ | 'stackBehavior'
145
146
  > & {
146
147
  /**
147
148
  * The detent index to present at.