@lodev09/react-native-true-sheet 3.8.0-beta.1 → 3.8.0-beta.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.
Files changed (68) hide show
  1. package/android/src/main/java/com/lodev09/truesheet/TrueSheetModule.kt +22 -2
  2. package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +29 -31
  3. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +10 -9
  4. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetStackManager.kt +6 -12
  5. package/ios/TrueSheetContainerView.mm +7 -0
  6. package/ios/TrueSheetContentView.mm +7 -1
  7. package/ios/TrueSheetModule.mm +33 -9
  8. package/ios/TrueSheetView.h +3 -1
  9. package/ios/TrueSheetView.mm +47 -40
  10. package/ios/TrueSheetViewController.h +1 -0
  11. package/ios/TrueSheetViewController.mm +4 -8
  12. package/ios/core/RNScreensEventObserver.mm +23 -15
  13. package/lib/module/TrueSheet.js +45 -26
  14. package/lib/module/TrueSheet.js.map +1 -1
  15. package/lib/module/TrueSheet.web.js +26 -40
  16. package/lib/module/TrueSheet.web.js.map +1 -1
  17. package/lib/module/TrueSheetProvider.js +1 -0
  18. package/lib/module/TrueSheetProvider.js.map +1 -1
  19. package/lib/module/TrueSheetProvider.web.js +7 -32
  20. package/lib/module/TrueSheetProvider.web.js.map +1 -1
  21. package/lib/module/index.js +1 -1
  22. package/lib/module/index.js.map +1 -1
  23. package/lib/module/mocks/index.js +3 -0
  24. package/lib/module/mocks/index.js.map +1 -1
  25. package/lib/module/mocks/reanimated.js +2 -0
  26. package/lib/module/mocks/reanimated.js.map +1 -1
  27. package/lib/module/navigation/TrueSheetRouter.js +42 -8
  28. package/lib/module/navigation/TrueSheetRouter.js.map +1 -1
  29. package/lib/module/navigation/screen/useSheetScreenState.js +8 -17
  30. package/lib/module/navigation/screen/useSheetScreenState.js.map +1 -1
  31. package/lib/module/reanimated/ReanimatedTrueSheet.web.js +2 -2
  32. package/lib/module/reanimated/ReanimatedTrueSheet.web.js.map +1 -1
  33. package/lib/module/specs/NativeTrueSheetModule.js.map +1 -1
  34. package/lib/typescript/src/TrueSheet.d.ts +29 -2
  35. package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
  36. package/lib/typescript/src/TrueSheet.types.d.ts +0 -48
  37. package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
  38. package/lib/typescript/src/TrueSheet.web.d.ts +4 -2
  39. package/lib/typescript/src/TrueSheet.web.d.ts.map +1 -1
  40. package/lib/typescript/src/TrueSheetProvider.d.ts +3 -2
  41. package/lib/typescript/src/TrueSheetProvider.d.ts.map +1 -1
  42. package/lib/typescript/src/TrueSheetProvider.web.d.ts +6 -14
  43. package/lib/typescript/src/TrueSheetProvider.web.d.ts.map +1 -1
  44. package/lib/typescript/src/index.d.ts +1 -1
  45. package/lib/typescript/src/index.d.ts.map +1 -1
  46. package/lib/typescript/src/mocks/index.d.ts +6 -3
  47. package/lib/typescript/src/mocks/index.d.ts.map +1 -1
  48. package/lib/typescript/src/mocks/reanimated.d.ts +4 -2
  49. package/lib/typescript/src/mocks/reanimated.d.ts.map +1 -1
  50. package/lib/typescript/src/navigation/TrueSheetRouter.d.ts.map +1 -1
  51. package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts.map +1 -1
  52. package/lib/typescript/src/reanimated/ReanimatedTrueSheet.web.d.ts +4 -3
  53. package/lib/typescript/src/reanimated/ReanimatedTrueSheet.web.d.ts.map +1 -1
  54. package/lib/typescript/src/specs/NativeTrueSheetModule.d.ts +9 -1
  55. package/lib/typescript/src/specs/NativeTrueSheetModule.d.ts.map +1 -1
  56. package/package.json +1 -1
  57. package/src/TrueSheet.tsx +45 -35
  58. package/src/TrueSheet.types.ts +0 -50
  59. package/src/TrueSheet.web.tsx +32 -50
  60. package/src/TrueSheetProvider.tsx +7 -2
  61. package/src/TrueSheetProvider.web.tsx +19 -38
  62. package/src/index.ts +1 -1
  63. package/src/mocks/index.ts +7 -6
  64. package/src/mocks/reanimated.ts +4 -5
  65. package/src/navigation/TrueSheetRouter.ts +51 -16
  66. package/src/navigation/screen/useSheetScreenState.ts +5 -11
  67. package/src/reanimated/ReanimatedTrueSheet.web.tsx +28 -30
  68. package/src/specs/NativeTrueSheetModule.ts +10 -1
@@ -116,40 +116,74 @@ export const TrueSheetRouter = (
116
116
  }
117
117
 
118
118
  case 'GO_BACK':
119
- case 'POP':
120
119
  case 'DISMISS': {
120
+ return this.getStateForAction(state, StackActions.pop(1), options);
121
+ }
122
+
123
+ case 'POP': {
121
124
  // Only base screen remains - let parent navigator handle it
122
125
  if (state.routes.length <= 1) {
123
126
  return null;
124
127
  }
125
128
 
126
- // Find the route to dismiss
127
- const routeIndex =
128
- action.target === state.key && 'source' in action && action.source
129
- ? state.routes.findIndex((r) => r.key === action.source)
130
- : state.index;
129
+ const count =
130
+ 'payload' in action && typeof action.payload?.count === 'number'
131
+ ? action.payload.count
132
+ : 1;
133
+
134
+ // Calculate how many routes we can actually pop (don't pop base screen)
135
+ const maxPopCount = state.routes.length - 1;
136
+ const actualCount = Math.min(count, maxPopCount);
131
137
 
132
138
  // Base screen - let parent navigator handle it
133
- if (routeIndex === 0) {
139
+ if (actualCount <= 0) {
134
140
  return null;
135
141
  }
136
142
 
137
- // Mark the route as closing instead of removing it
143
+ // Target index is the route we want to stay on (land on after pop)
144
+ // closingIndex is the first route to be dismissed (the one after target)
145
+ const targetIndex = state.routes.length - 1 - actualCount;
146
+ const closingIndex = targetIndex + 1;
147
+
148
+ // Mark only the bottom-most route to pop as closing
149
+ // The sheet's dismiss() will handle dismissing sheets above it first
138
150
  return {
139
151
  ...state,
152
+ index: closingIndex,
140
153
  routes: state.routes.map((route, i) =>
141
- i === routeIndex
142
- ? {
143
- ...route,
144
- closing: true,
145
- }
146
- : route
154
+ i === closingIndex ? { ...route, closing: true } : route
147
155
  ),
148
156
  };
149
157
  }
150
158
 
159
+ case 'POP_TO_TOP': {
160
+ const popCount = state.routes.length - 1;
161
+ return this.getStateForAction(state, StackActions.pop(popCount), options);
162
+ }
163
+
164
+ case 'POP_TO': {
165
+ const targetName =
166
+ 'payload' in action && typeof action.payload?.name === 'string'
167
+ ? action.payload.name
168
+ : null;
169
+
170
+ if (!targetName) {
171
+ return null;
172
+ }
173
+
174
+ const targetIndex = state.routes.findIndex((r) => r.name === targetName);
175
+
176
+ // Target not found or is the current route
177
+ if (targetIndex === -1 || targetIndex >= state.index) {
178
+ return null;
179
+ }
180
+
181
+ const popCount = state.routes.length - 1 - targetIndex;
182
+ return this.getStateForAction(state, StackActions.pop(popCount), options);
183
+ }
184
+
151
185
  case 'REMOVE': {
152
- // Actually remove the closing route
186
+ // Actually remove the closing route and all routes above it
153
187
  const routeKey = action.source;
154
188
  const routeIndex = routeKey
155
189
  ? state.routes.findIndex((r) => r.key === routeKey)
@@ -159,7 +193,8 @@ export const TrueSheetRouter = (
159
193
  return state;
160
194
  }
161
195
 
162
- const routes = state.routes.filter((_, i) => i !== routeIndex);
196
+ // Remove the route and all routes above it (they were dismissed together)
197
+ const routes = state.routes.filter((_, i) => i < routeIndex);
163
198
 
164
199
  return {
165
200
  ...state,
@@ -47,14 +47,9 @@ export const useSheetScreenState = (props: UseSheetScreenStateProps) => {
47
47
  useEffect(() => {
48
48
  if (closing && !isDismissedRef.current) {
49
49
  isDismissedRef.current = true;
50
- (async () => {
51
- await ref.current?.dismiss();
52
- navigation.dispatch({ ...TrueSheetActions.remove(), source: routeKey });
53
- })();
54
- } else if (closing && isDismissedRef.current) {
55
- navigation.dispatch({ ...TrueSheetActions.remove(), source: routeKey });
50
+ ref.current?.dismiss();
56
51
  }
57
- }, [closing, navigation, routeKey]);
52
+ }, [closing]);
58
53
 
59
54
  useEffect(() => {
60
55
  if (isFirstRenderRef.current) {
@@ -77,10 +72,9 @@ export const useSheetScreenState = (props: UseSheetScreenStateProps) => {
77
72
 
78
73
  const onDidDismiss = () => {
79
74
  emitEvent('sheetDidDismiss', undefined);
80
- if (!isDismissedRef.current) {
81
- isDismissedRef.current = true;
82
- navigation.goBack();
83
- }
75
+ isDismissedRef.current = true;
76
+ // Remove route from state (works for both programmatic and user-initiated dismiss)
77
+ navigation.dispatch({ ...TrueSheetActions.remove(), source: routeKey });
84
78
  };
85
79
 
86
80
  return {
@@ -1,8 +1,8 @@
1
1
  import { forwardRef, useEffect } from 'react';
2
2
  import { useWindowDimensions } from 'react-native';
3
3
 
4
- import { TrueSheet } from '../TrueSheet.web';
5
- import type { TrueSheetProps, TrueSheetRef, PositionChangeEvent } from '../TrueSheet.types';
4
+ import { TrueSheet } from '../TrueSheet';
5
+ import type { TrueSheetProps, PositionChangeEvent } from '../TrueSheet.types';
6
6
  import { useReanimatedTrueSheet } from './ReanimatedTrueSheetProvider';
7
7
 
8
8
  interface ReanimatedTrueSheetProps extends TrueSheetProps {
@@ -25,7 +25,7 @@ interface ReanimatedTrueSheetProps extends TrueSheetProps {
25
25
  * import { ReanimatedTrueSheet, ReanimatedTrueSheetProvider } from '@lodev09/react-native-true-sheet/reanimated'
26
26
  *
27
27
  * function MyScreen() {
28
- * const sheetRef = useRef<TrueSheetRef>(null)
28
+ * const sheetRef = useRef<TrueSheet>(null)
29
29
  *
30
30
  * return (
31
31
  * <ReanimatedTrueSheetProvider>
@@ -43,36 +43,34 @@ interface ReanimatedTrueSheetProps extends TrueSheetProps {
43
43
  * }
44
44
  * ```
45
45
  */
46
- export const ReanimatedTrueSheet = forwardRef<TrueSheetRef, ReanimatedTrueSheetProps>(
47
- (props, ref) => {
48
- const { onPositionChange, detents = [0.5, 1], ...rest } = props;
49
- const { height: windowHeight } = useWindowDimensions();
46
+ export const ReanimatedTrueSheet = forwardRef<TrueSheet, ReanimatedTrueSheetProps>((props, ref) => {
47
+ const { onPositionChange, detents = [0.5, 1], ...rest } = props;
48
+ const { height: windowHeight } = useWindowDimensions();
50
49
 
51
- const { animatedPosition, animatedIndex, animatedDetent } = useReanimatedTrueSheet();
50
+ const { animatedPosition, animatedIndex, animatedDetent } = useReanimatedTrueSheet();
52
51
 
53
- // Reset animated values when component unmounts
54
- useEffect(() => {
55
- return () => {
56
- animatedPosition.value = windowHeight;
57
- animatedIndex.value = -1;
58
- animatedDetent.value = 0;
59
- };
60
- }, [windowHeight]);
52
+ // Reset animated values when component unmounts
53
+ useEffect(() => {
54
+ return () => {
55
+ animatedPosition.value = windowHeight;
56
+ animatedIndex.value = -1;
57
+ animatedDetent.value = 0;
58
+ };
59
+ }, [windowHeight]);
61
60
 
62
- const handlePositionChange = (event: PositionChangeEvent) => {
63
- const { position, index, detent } = event.nativeEvent;
61
+ const handlePositionChange = (event: PositionChangeEvent) => {
62
+ const { position, index, detent } = event.nativeEvent;
64
63
 
65
- // Sync with provider's shared values
66
- animatedPosition.value = position;
67
- animatedIndex.value = index;
68
- animatedDetent.value = detent;
64
+ // Sync with provider's shared values
65
+ animatedPosition.value = position;
66
+ animatedIndex.value = index;
67
+ animatedDetent.value = detent;
69
68
 
70
- // Call user's callback
71
- onPositionChange?.(event);
72
- };
69
+ // Call user's callback
70
+ onPositionChange?.(event);
71
+ };
73
72
 
74
- return (
75
- <TrueSheet ref={ref} detents={detents} onPositionChange={handlePositionChange} {...rest} />
76
- );
77
- }
78
- );
73
+ return (
74
+ <TrueSheet ref={ref} detents={detents} onPositionChange={handlePositionChange} {...rest} />
75
+ );
76
+ });
@@ -20,7 +20,7 @@ interface Spec extends TurboModule {
20
20
  presentByRef(viewTag: number, index: number, animated: boolean): Promise<void>;
21
21
 
22
22
  /**
23
- * Dismiss a sheet by reference
23
+ * Dismiss a sheet and all sheets presented on top of it
24
24
  * @param viewTag - Native view tag of the sheet component
25
25
  * @param animated - Whether to animate the dismissal
26
26
  * @returns Promise that resolves when sheet is fully dismissed
@@ -28,6 +28,15 @@ interface Spec extends TurboModule {
28
28
  */
29
29
  dismissByRef(viewTag: number, animated: boolean): Promise<void>;
30
30
 
31
+ /**
32
+ * Dismiss only the sheets presented on top of this sheet, keeping this sheet presented
33
+ * @param viewTag - Native view tag of the sheet component
34
+ * @param animated - Whether to animate the dismissal
35
+ * @returns Promise that resolves when all child sheets are fully dismissed
36
+ * @throws DISMISS_FAILED if dismissal fails
37
+ */
38
+ dismissStackByRef(viewTag: number, animated: boolean): Promise<void>;
39
+
31
40
  /**
32
41
  * Resize a sheet to a different index by reference
33
42
  * @param viewTag - Native view tag of the sheet component