@lodev09/react-native-true-sheet 3.0.0-beta.8 → 3.0.0
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 +13 -6
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +29 -33
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetModule.kt +3 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +48 -43
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +387 -88
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +22 -4
- package/android/src/main/java/com/lodev09/truesheet/core/RNScreensFragmentObserver.kt +0 -5
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDialogObserver.kt +67 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetGrabberView.kt +44 -0
- package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetDragEvents.kt +71 -0
- package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetFocusEvents.kt +65 -0
- package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetLifecycleEvents.kt +94 -0
- package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetStateEvents.kt +56 -0
- package/android/src/main/java/com/lodev09/truesheet/utils/ScreenUtils.kt +37 -33
- package/android/src/main/res/anim/true_sheet_slide_in.xml +13 -0
- package/android/src/main/res/anim/true_sheet_slide_out.xml +13 -0
- package/android/src/main/res/values/styles.xml +13 -1
- package/ios/TrueSheetContainerView.mm +4 -0
- package/ios/TrueSheetContentView.h +2 -1
- package/ios/TrueSheetContentView.mm +91 -11
- package/ios/TrueSheetView.mm +65 -41
- package/ios/TrueSheetViewController.h +21 -10
- package/ios/TrueSheetViewController.mm +330 -165
- package/ios/core/TrueSheetBlurView.h +24 -0
- package/ios/{utils/ConversionUtil.mm → core/TrueSheetBlurView.mm} +65 -3
- package/ios/events/TrueSheetDragEvents.h +39 -0
- package/ios/events/TrueSheetDragEvents.mm +62 -0
- package/ios/events/{OnPositionChangeEvent.h → TrueSheetFocusEvents.h} +8 -5
- package/ios/events/TrueSheetFocusEvents.mm +49 -0
- package/ios/events/TrueSheetLifecycleEvents.h +40 -0
- package/ios/events/TrueSheetLifecycleEvents.mm +71 -0
- package/ios/events/TrueSheetStateEvents.h +35 -0
- package/ios/events/TrueSheetStateEvents.mm +49 -0
- package/ios/utils/GestureUtil.h +7 -0
- package/ios/utils/GestureUtil.mm +12 -0
- package/lib/module/TrueSheet.js +65 -12
- package/lib/module/TrueSheet.js.map +1 -1
- package/lib/module/fabric/TrueSheetViewNativeComponent.ts +15 -5
- package/lib/module/index.js +0 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/reanimated/ReanimatedTrueSheet.js +13 -7
- package/lib/module/reanimated/ReanimatedTrueSheet.js.map +1 -1
- package/lib/module/reanimated/ReanimatedTrueSheetProvider.js +4 -2
- package/lib/module/reanimated/ReanimatedTrueSheetProvider.js.map +1 -1
- package/lib/typescript/src/TrueSheet.d.ts +4 -0
- package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.types.d.ts +58 -6
- package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +14 -5
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +0 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/reanimated/ReanimatedTrueSheet.d.ts.map +1 -1
- package/lib/typescript/src/reanimated/ReanimatedTrueSheetProvider.d.ts +8 -2
- package/lib/typescript/src/reanimated/ReanimatedTrueSheetProvider.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/TrueSheet.tsx +80 -10
- package/src/TrueSheet.types.ts +65 -6
- package/src/__mocks__/index.js +0 -5
- package/src/fabric/TrueSheetViewNativeComponent.ts +15 -5
- package/src/index.ts +0 -1
- package/src/reanimated/ReanimatedTrueSheet.tsx +12 -7
- package/src/reanimated/ReanimatedTrueSheetProvider.tsx +11 -3
- package/android/src/main/java/com/lodev09/truesheet/events/DetentChangeEvent.kt +0 -26
- package/android/src/main/java/com/lodev09/truesheet/events/DidDismissEvent.kt +0 -20
- package/android/src/main/java/com/lodev09/truesheet/events/DidPresentEvent.kt +0 -26
- package/android/src/main/java/com/lodev09/truesheet/events/DragBeginEvent.kt +0 -26
- package/android/src/main/java/com/lodev09/truesheet/events/DragChangeEvent.kt +0 -26
- package/android/src/main/java/com/lodev09/truesheet/events/DragEndEvent.kt +0 -26
- package/android/src/main/java/com/lodev09/truesheet/events/MountEvent.kt +0 -20
- package/android/src/main/java/com/lodev09/truesheet/events/PositionChangeEvent.kt +0 -32
- package/android/src/main/java/com/lodev09/truesheet/events/WillDismissEvent.kt +0 -20
- package/android/src/main/java/com/lodev09/truesheet/events/WillPresentEvent.kt +0 -26
- package/ios/events/OnDetentChangeEvent.h +0 -28
- package/ios/events/OnDetentChangeEvent.mm +0 -30
- package/ios/events/OnDidDismissEvent.h +0 -26
- package/ios/events/OnDidDismissEvent.mm +0 -25
- package/ios/events/OnDidPresentEvent.h +0 -28
- package/ios/events/OnDidPresentEvent.mm +0 -30
- package/ios/events/OnDragBeginEvent.h +0 -28
- package/ios/events/OnDragBeginEvent.mm +0 -30
- package/ios/events/OnDragChangeEvent.h +0 -28
- package/ios/events/OnDragChangeEvent.mm +0 -30
- package/ios/events/OnDragEndEvent.h +0 -28
- package/ios/events/OnDragEndEvent.mm +0 -30
- package/ios/events/OnMountEvent.h +0 -26
- package/ios/events/OnMountEvent.mm +0 -25
- package/ios/events/OnPositionChangeEvent.mm +0 -32
- package/ios/events/OnWillDismissEvent.h +0 -26
- package/ios/events/OnWillDismissEvent.mm +0 -25
- package/ios/events/OnWillPresentEvent.h +0 -28
- package/ios/events/OnWillPresentEvent.mm +0 -30
- package/ios/utils/ConversionUtil.h +0 -24
- package/lib/module/TrueSheetGrabber.js +0 -51
- package/lib/module/TrueSheetGrabber.js.map +0 -1
- package/lib/typescript/src/TrueSheetGrabber.d.ts +0 -39
- package/lib/typescript/src/TrueSheetGrabber.d.ts.map +0 -1
- package/src/TrueSheetGrabber.tsx +0 -82
package/src/TrueSheet.tsx
CHANGED
|
@@ -20,6 +20,10 @@ import type {
|
|
|
20
20
|
DidDismissEvent,
|
|
21
21
|
WillDismissEvent,
|
|
22
22
|
MountEvent,
|
|
23
|
+
WillFocusEvent,
|
|
24
|
+
DidFocusEvent,
|
|
25
|
+
WillBlurEvent,
|
|
26
|
+
DidBlurEvent,
|
|
23
27
|
} from './TrueSheet.types';
|
|
24
28
|
import TrueSheetViewNativeComponent from './fabric/TrueSheetViewNativeComponent';
|
|
25
29
|
import TrueSheetContainerViewNativeComponent from './fabric/TrueSheetContainerViewNativeComponent';
|
|
@@ -29,7 +33,7 @@ import TrueSheetFooterViewNativeComponent from './fabric/TrueSheetFooterViewNati
|
|
|
29
33
|
|
|
30
34
|
import TrueSheetModule from './specs/NativeTrueSheetModule';
|
|
31
35
|
|
|
32
|
-
import { Platform, processColor, StyleSheet, findNodeHandle } from 'react-native';
|
|
36
|
+
import { Platform, processColor, StyleSheet, findNodeHandle, View } from 'react-native';
|
|
33
37
|
|
|
34
38
|
const LINKING_ERROR =
|
|
35
39
|
`The package '@lodev09/react-native-true-sheet' doesn't seem to be linked. Make sure: \n\n` +
|
|
@@ -38,6 +42,9 @@ const LINKING_ERROR =
|
|
|
38
42
|
'- You are not using Expo Go\n' +
|
|
39
43
|
'- You are using the new architecture (Fabric)\n';
|
|
40
44
|
|
|
45
|
+
// Material Design 3 minimum touch target
|
|
46
|
+
const ANDROID_HITBOX_HEIGHT = 48;
|
|
47
|
+
|
|
41
48
|
if (!TrueSheetModule) {
|
|
42
49
|
throw new Error(LINKING_ERROR);
|
|
43
50
|
}
|
|
@@ -88,6 +95,10 @@ export class TrueSheet extends PureComponent<TrueSheetProps, TrueSheetState> {
|
|
|
88
95
|
this.onDragChange = this.onDragChange.bind(this);
|
|
89
96
|
this.onDragEnd = this.onDragEnd.bind(this);
|
|
90
97
|
this.onPositionChange = this.onPositionChange.bind(this);
|
|
98
|
+
this.onWillFocus = this.onWillFocus.bind(this);
|
|
99
|
+
this.onDidFocus = this.onDidFocus.bind(this);
|
|
100
|
+
this.onWillBlur = this.onWillBlur.bind(this);
|
|
101
|
+
this.onDidBlur = this.onDidBlur.bind(this);
|
|
91
102
|
}
|
|
92
103
|
|
|
93
104
|
private validateDetents(): void {
|
|
@@ -250,6 +261,22 @@ export class TrueSheet extends PureComponent<TrueSheetProps, TrueSheetState> {
|
|
|
250
261
|
this.props.onPositionChange?.(event);
|
|
251
262
|
}
|
|
252
263
|
|
|
264
|
+
private onWillFocus(event: WillFocusEvent): void {
|
|
265
|
+
this.props.onWillFocus?.(event);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
private onDidFocus(event: DidFocusEvent): void {
|
|
269
|
+
this.props.onDidFocus?.(event);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
private onWillBlur(event: WillBlurEvent): void {
|
|
273
|
+
this.props.onWillBlur?.(event);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
private onDidBlur(event: DidBlurEvent): void {
|
|
277
|
+
this.props.onDidBlur?.(event);
|
|
278
|
+
}
|
|
279
|
+
|
|
253
280
|
/**
|
|
254
281
|
* Present the Sheet by `index` (Promise-based)
|
|
255
282
|
* @param index - Detent index (default: 0)
|
|
@@ -313,6 +340,7 @@ export class TrueSheet extends PureComponent<TrueSheetProps, TrueSheetState> {
|
|
|
313
340
|
detents = [0.5, 1],
|
|
314
341
|
backgroundColor,
|
|
315
342
|
dismissible = true,
|
|
343
|
+
draggable = true,
|
|
316
344
|
grabber = true,
|
|
317
345
|
dimmed = true,
|
|
318
346
|
initialDetentIndex = -1,
|
|
@@ -323,13 +351,12 @@ export class TrueSheet extends PureComponent<TrueSheetProps, TrueSheetState> {
|
|
|
323
351
|
cornerRadius,
|
|
324
352
|
maxHeight,
|
|
325
353
|
edgeToEdgeFullScreen,
|
|
326
|
-
|
|
354
|
+
scrollable = false,
|
|
327
355
|
pageSizing = true,
|
|
328
356
|
children,
|
|
329
357
|
style,
|
|
330
358
|
header,
|
|
331
359
|
footer,
|
|
332
|
-
testID,
|
|
333
360
|
...rest
|
|
334
361
|
} = this.props;
|
|
335
362
|
|
|
@@ -344,6 +371,18 @@ export class TrueSheet extends PureComponent<TrueSheetProps, TrueSheetState> {
|
|
|
344
371
|
return Math.min(1, detent);
|
|
345
372
|
});
|
|
346
373
|
|
|
374
|
+
const containerStyle =
|
|
375
|
+
this.props.scrollable &&
|
|
376
|
+
Platform.select({
|
|
377
|
+
android: styles.scrollableAndroidContainer,
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
const contentStyle =
|
|
381
|
+
this.props.scrollable &&
|
|
382
|
+
Platform.select({
|
|
383
|
+
android: styles.scrollableAndroidContent,
|
|
384
|
+
});
|
|
385
|
+
|
|
347
386
|
return (
|
|
348
387
|
<TrueSheetViewNativeComponent
|
|
349
388
|
{...rest}
|
|
@@ -360,9 +399,10 @@ export class TrueSheet extends PureComponent<TrueSheetProps, TrueSheetState> {
|
|
|
360
399
|
initialDetentIndex={initialDetentIndex}
|
|
361
400
|
initialDetentAnimated={initialDetentAnimated}
|
|
362
401
|
dismissible={dismissible}
|
|
402
|
+
draggable={draggable}
|
|
363
403
|
maxHeight={maxHeight}
|
|
364
404
|
edgeToEdgeFullScreen={edgeToEdgeFullScreen}
|
|
365
|
-
|
|
405
|
+
scrollable={scrollable}
|
|
366
406
|
pageSizing={pageSizing}
|
|
367
407
|
onMount={this.onMount}
|
|
368
408
|
onWillPresent={this.onWillPresent}
|
|
@@ -374,22 +414,29 @@ export class TrueSheet extends PureComponent<TrueSheetProps, TrueSheetState> {
|
|
|
374
414
|
onDragChange={this.onDragChange}
|
|
375
415
|
onDragEnd={this.onDragEnd}
|
|
376
416
|
onPositionChange={this.onPositionChange}
|
|
417
|
+
onWillFocus={this.onWillFocus}
|
|
418
|
+
onDidFocus={this.onDidFocus}
|
|
419
|
+
onWillBlur={this.onWillBlur}
|
|
420
|
+
onDidBlur={this.onDidBlur}
|
|
377
421
|
>
|
|
378
422
|
{this.state.shouldRenderNativeView && (
|
|
379
|
-
<TrueSheetContainerViewNativeComponent
|
|
423
|
+
<TrueSheetContainerViewNativeComponent style={containerStyle}>
|
|
380
424
|
{header && (
|
|
381
|
-
<TrueSheetHeaderViewNativeComponent
|
|
425
|
+
<TrueSheetHeaderViewNativeComponent>
|
|
382
426
|
{isValidElement(header) ? header : createElement(header)}
|
|
383
427
|
</TrueSheetHeaderViewNativeComponent>
|
|
384
428
|
)}
|
|
385
|
-
<TrueSheetContentViewNativeComponent style={style
|
|
429
|
+
<TrueSheetContentViewNativeComponent style={[style, contentStyle]}>
|
|
386
430
|
{children}
|
|
387
431
|
</TrueSheetContentViewNativeComponent>
|
|
388
432
|
{footer && (
|
|
389
|
-
<TrueSheetFooterViewNativeComponent style={styles.footer}
|
|
433
|
+
<TrueSheetFooterViewNativeComponent style={styles.footer}>
|
|
390
434
|
{isValidElement(footer) ? footer : createElement(footer)}
|
|
391
435
|
</TrueSheetFooterViewNativeComponent>
|
|
392
436
|
)}
|
|
437
|
+
{Platform.OS === 'android' && grabber && draggable && (
|
|
438
|
+
<View collapsable={false} style={styles.grabberHitbox} />
|
|
439
|
+
)}
|
|
393
440
|
</TrueSheetContainerViewNativeComponent>
|
|
394
441
|
)}
|
|
395
442
|
</TrueSheetViewNativeComponent>
|
|
@@ -399,13 +446,36 @@ export class TrueSheet extends PureComponent<TrueSheetProps, TrueSheetState> {
|
|
|
399
446
|
|
|
400
447
|
const styles = StyleSheet.create({
|
|
401
448
|
sheetView: {
|
|
402
|
-
position: 'absolute',
|
|
403
|
-
width: '100%',
|
|
404
449
|
zIndex: -9999,
|
|
450
|
+
position: 'absolute',
|
|
451
|
+
top: 0,
|
|
452
|
+
left: 0,
|
|
453
|
+
right: 0,
|
|
454
|
+
|
|
455
|
+
// Android needs a fixed bottom to avoid jumping content
|
|
456
|
+
bottom: Platform.select({ android: 0 }),
|
|
457
|
+
},
|
|
458
|
+
scrollableAndroidContainer: {
|
|
459
|
+
position: 'absolute',
|
|
460
|
+
top: 0,
|
|
461
|
+
left: 0,
|
|
462
|
+
right: 0,
|
|
463
|
+
bottom: 0,
|
|
464
|
+
},
|
|
465
|
+
scrollableAndroidContent: {
|
|
466
|
+
flexGrow: 1,
|
|
467
|
+
flexBasis: 0,
|
|
405
468
|
},
|
|
406
469
|
footer: {
|
|
407
470
|
position: 'absolute',
|
|
408
471
|
left: 0,
|
|
409
472
|
right: 0,
|
|
410
473
|
},
|
|
474
|
+
grabberHitbox: {
|
|
475
|
+
position: 'absolute',
|
|
476
|
+
top: 0,
|
|
477
|
+
left: 0,
|
|
478
|
+
right: 0,
|
|
479
|
+
height: ANDROID_HITBOX_HEIGHT,
|
|
480
|
+
},
|
|
411
481
|
});
|
package/src/TrueSheet.types.ts
CHANGED
|
@@ -10,14 +10,18 @@ export interface DetentInfoEventPayload {
|
|
|
10
10
|
* The Y position of the sheet relative to the screen.
|
|
11
11
|
*/
|
|
12
12
|
position: number;
|
|
13
|
+
/**
|
|
14
|
+
* The detent value (0-1) for the current index.
|
|
15
|
+
*/
|
|
16
|
+
detent: number;
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
export interface PositionChangeEventPayload extends DetentInfoEventPayload {
|
|
16
20
|
/**
|
|
17
|
-
*
|
|
18
|
-
* When
|
|
21
|
+
* Indicates whether the position value is real-time (e.g., during drag or animation tracking).
|
|
22
|
+
* When false, the position should be animated in JS.
|
|
19
23
|
*/
|
|
20
|
-
|
|
24
|
+
realtime: boolean;
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
export type MountEvent = NativeSyntheticEvent<null>;
|
|
@@ -30,6 +34,10 @@ export type DragBeginEvent = NativeSyntheticEvent<DetentInfoEventPayload>;
|
|
|
30
34
|
export type DragChangeEvent = NativeSyntheticEvent<DetentInfoEventPayload>;
|
|
31
35
|
export type DragEndEvent = NativeSyntheticEvent<DetentInfoEventPayload>;
|
|
32
36
|
export type PositionChangeEvent = NativeSyntheticEvent<PositionChangeEventPayload>;
|
|
37
|
+
export type DidFocusEvent = NativeSyntheticEvent<null>;
|
|
38
|
+
export type DidBlurEvent = NativeSyntheticEvent<null>;
|
|
39
|
+
export type WillFocusEvent = NativeSyntheticEvent<null>;
|
|
40
|
+
export type WillBlurEvent = NativeSyntheticEvent<null>;
|
|
33
41
|
|
|
34
42
|
/**
|
|
35
43
|
* Blur style mapped to native values in IOS.
|
|
@@ -106,6 +114,9 @@ export interface TrueSheetProps extends ViewProps {
|
|
|
106
114
|
* detents={['auto', 0.6, 1]}
|
|
107
115
|
* ```
|
|
108
116
|
*
|
|
117
|
+
* @note It's recommended to sort detents from smallest to largest.
|
|
118
|
+
* When using `auto`, place it at the first index if you plan to adjust content dynamically.
|
|
119
|
+
*
|
|
109
120
|
* @default [0.5, 1]
|
|
110
121
|
*/
|
|
111
122
|
detents?: SheetDetent[];
|
|
@@ -149,6 +160,14 @@ export interface TrueSheetProps extends ViewProps {
|
|
|
149
160
|
*/
|
|
150
161
|
dismissible?: boolean;
|
|
151
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Enables or disables dragging the sheet to resize it.
|
|
165
|
+
* When disabled, the sheet becomes static and can only be resized programmatically.
|
|
166
|
+
*
|
|
167
|
+
* @default true
|
|
168
|
+
*/
|
|
169
|
+
draggable?: boolean;
|
|
170
|
+
|
|
152
171
|
/**
|
|
153
172
|
* Main sheet background color.
|
|
154
173
|
* Uses system default when not provided.
|
|
@@ -192,6 +211,25 @@ export interface TrueSheetProps extends ViewProps {
|
|
|
192
211
|
*/
|
|
193
212
|
blurTint?: BlurTint;
|
|
194
213
|
|
|
214
|
+
/**
|
|
215
|
+
* The intensity of the blur effect (0-100).
|
|
216
|
+
* Only applies when `blurTint` is set.
|
|
217
|
+
* Uses system default if not provided.
|
|
218
|
+
*
|
|
219
|
+
* @platform ios
|
|
220
|
+
*/
|
|
221
|
+
blurIntensity?: number;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Enables or disables user interaction on the blur view.
|
|
225
|
+
* Disabling this can help with visual artifacts (flash) on iOS 18+
|
|
226
|
+
* when touching the sheet content with blur enabled.
|
|
227
|
+
* Uses system default (true) if not provided.
|
|
228
|
+
*
|
|
229
|
+
* @platform ios
|
|
230
|
+
*/
|
|
231
|
+
blurInteraction?: boolean;
|
|
232
|
+
|
|
195
233
|
/**
|
|
196
234
|
* Overrides `large` or `100%` height.
|
|
197
235
|
* Also sets the maximum height for 'auto' detents.
|
|
@@ -219,14 +257,15 @@ export interface TrueSheetProps extends ViewProps {
|
|
|
219
257
|
footer?: ComponentType<unknown> | ReactElement;
|
|
220
258
|
|
|
221
259
|
/**
|
|
222
|
-
*
|
|
260
|
+
* On iOS, automatically pins ScrollView or FlatList to fit within the sheet's available space.
|
|
223
261
|
* When enabled, the ScrollView's top edge will be pinned below any top sibling views,
|
|
224
262
|
* and its left, right, and bottom edges will be pinned to the container.
|
|
225
263
|
*
|
|
226
|
-
*
|
|
264
|
+
* On Android, it adds additional style to the content for scrollable to work.
|
|
265
|
+
*
|
|
227
266
|
* @default false
|
|
228
267
|
*/
|
|
229
|
-
|
|
268
|
+
scrollable?: boolean;
|
|
230
269
|
|
|
231
270
|
/**
|
|
232
271
|
* Determines how the software keyboard will impact the layout of the sheet.
|
|
@@ -294,4 +333,24 @@ export interface TrueSheetProps extends ViewProps {
|
|
|
294
333
|
* Comes with the detent info.
|
|
295
334
|
*/
|
|
296
335
|
onPositionChange?: (event: PositionChangeEvent) => void;
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Called when the sheet is about to regain focus because a sheet presented on top of it is being dismissed.
|
|
339
|
+
*/
|
|
340
|
+
onWillFocus?: (event: WillFocusEvent) => void;
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Called when the sheet regains focus after a sheet presented on top of it is dismissed.
|
|
344
|
+
*/
|
|
345
|
+
onDidFocus?: (event: DidFocusEvent) => void;
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Called when the sheet is about to lose focus because another sheet is being presented on top of it.
|
|
349
|
+
*/
|
|
350
|
+
onWillBlur?: (event: WillBlurEvent) => void;
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Called when the sheet loses focus because another sheet is presented on top of it.
|
|
354
|
+
*/
|
|
355
|
+
onDidBlur?: (event: DidBlurEvent) => void;
|
|
297
356
|
}
|
package/src/__mocks__/index.js
CHANGED
|
@@ -47,11 +47,6 @@ export class ReanimatedTrueSheet extends TrueSheet {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
// Mock TrueSheetGrabber
|
|
51
|
-
export const TrueSheetGrabber = ({ style, ...props }) => (
|
|
52
|
-
<View style={style} {...props} testID="true-sheet-grabber" />
|
|
53
|
-
);
|
|
54
|
-
|
|
55
50
|
// Mock ReanimatedTrueSheetProvider
|
|
56
51
|
export const ReanimatedTrueSheetProvider = ({ children }) => <>{children}</>;
|
|
57
52
|
|
|
@@ -4,24 +4,25 @@ import type {
|
|
|
4
4
|
Double,
|
|
5
5
|
Int32,
|
|
6
6
|
WithDefault,
|
|
7
|
-
Float,
|
|
8
7
|
} from 'react-native/Libraries/Types/CodegenTypes';
|
|
9
8
|
import { codegenNativeComponent } from 'react-native';
|
|
10
9
|
|
|
11
10
|
export interface DetentInfoEventPayload {
|
|
12
11
|
index: Int32;
|
|
13
12
|
position: Double;
|
|
13
|
+
detent: Double;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export interface PositionChangeEventPayload {
|
|
17
|
-
index:
|
|
17
|
+
index: Double;
|
|
18
18
|
position: Double;
|
|
19
|
-
|
|
19
|
+
detent: Double;
|
|
20
|
+
realtime: boolean;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export interface NativeProps extends ViewProps {
|
|
23
24
|
// Array properties
|
|
24
|
-
detents?: ReadonlyArray<
|
|
25
|
+
detents?: ReadonlyArray<Double>;
|
|
25
26
|
|
|
26
27
|
// Number properties - use 0 as default to avoid nil insertion
|
|
27
28
|
maxHeight?: WithDefault<Double, 0>;
|
|
@@ -34,13 +35,18 @@ export interface NativeProps extends ViewProps {
|
|
|
34
35
|
blurTint?: WithDefault<string, ''>;
|
|
35
36
|
keyboardMode?: WithDefault<'resize' | 'pan', 'resize'>;
|
|
36
37
|
|
|
38
|
+
// Blur properties - use -1 as default to indicate "not set" (use system default)
|
|
39
|
+
blurIntensity?: WithDefault<Double, -1>;
|
|
40
|
+
blurInteraction?: WithDefault<boolean, true>;
|
|
41
|
+
|
|
37
42
|
// Boolean properties - match defaults from TrueSheet.types.ts
|
|
38
43
|
grabber?: WithDefault<boolean, true>;
|
|
39
44
|
dismissible?: WithDefault<boolean, true>;
|
|
45
|
+
draggable?: WithDefault<boolean, true>;
|
|
40
46
|
dimmed?: WithDefault<boolean, true>;
|
|
41
47
|
initialDetentAnimated?: WithDefault<boolean, true>;
|
|
42
48
|
edgeToEdgeFullScreen?: WithDefault<boolean, false>;
|
|
43
|
-
|
|
49
|
+
scrollable?: WithDefault<boolean, false>;
|
|
44
50
|
pageSizing?: WithDefault<boolean, true>;
|
|
45
51
|
|
|
46
52
|
// Event handlers
|
|
@@ -54,6 +60,10 @@ export interface NativeProps extends ViewProps {
|
|
|
54
60
|
onDragChange?: DirectEventHandler<DetentInfoEventPayload>;
|
|
55
61
|
onDragEnd?: DirectEventHandler<DetentInfoEventPayload>;
|
|
56
62
|
onPositionChange?: DirectEventHandler<PositionChangeEventPayload>;
|
|
63
|
+
onWillFocus?: DirectEventHandler<null>;
|
|
64
|
+
onDidFocus?: DirectEventHandler<null>;
|
|
65
|
+
onWillBlur?: DirectEventHandler<null>;
|
|
66
|
+
onDidBlur?: DirectEventHandler<null>;
|
|
57
67
|
}
|
|
58
68
|
|
|
59
69
|
export default codegenNativeComponent<NativeProps>('TrueSheetView', {
|
package/src/index.ts
CHANGED
|
@@ -70,24 +70,29 @@ const AnimatedTrueSheet = Animated.createAnimatedComponent(TrueSheet);
|
|
|
70
70
|
export const ReanimatedTrueSheet = forwardRef<TrueSheet, ReanimatedTrueSheetProps>((props, ref) => {
|
|
71
71
|
const { onPositionChange, ...rest } = props;
|
|
72
72
|
|
|
73
|
-
const { animatedPosition, animatedIndex } = useReanimatedTrueSheet();
|
|
73
|
+
const { animatedPosition, animatedIndex, animatedDetent } = useReanimatedTrueSheet();
|
|
74
74
|
|
|
75
75
|
const positionChangeHandler = useReanimatedPositionChangeHandler((payload) => {
|
|
76
76
|
'worklet';
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
if (payload.realtime) {
|
|
79
|
+
// Update directly when we have real-time values (during drag or animation tracking)
|
|
80
|
+
animatedPosition.value = payload.position;
|
|
81
|
+
animatedIndex.value = payload.index;
|
|
82
|
+
animatedDetent.value = payload.detent;
|
|
83
|
+
} else {
|
|
84
|
+
// Animate position, index, and detent when not real-time
|
|
81
85
|
if (Platform.OS === 'android') {
|
|
82
86
|
animatedPosition.value = withTiming(payload.position, TIMING_CONFIG);
|
|
87
|
+
animatedIndex.value = withTiming(payload.index, TIMING_CONFIG);
|
|
88
|
+
animatedDetent.value = withTiming(payload.detent, TIMING_CONFIG);
|
|
83
89
|
} else {
|
|
84
90
|
animatedPosition.value = withSpring(payload.position, SPRING_CONFIG);
|
|
91
|
+
animatedIndex.value = withSpring(payload.index, SPRING_CONFIG);
|
|
92
|
+
animatedDetent.value = withSpring(payload.detent, SPRING_CONFIG);
|
|
85
93
|
}
|
|
86
|
-
} else {
|
|
87
|
-
animatedPosition.value = payload.position;
|
|
88
94
|
}
|
|
89
95
|
|
|
90
|
-
animatedIndex.value = payload.index;
|
|
91
96
|
onPositionChange?.({ nativeEvent: payload } as PositionChangeEvent);
|
|
92
97
|
});
|
|
93
98
|
|
|
@@ -4,13 +4,19 @@ import { useSharedValue, type SharedValue } from 'react-native-reanimated';
|
|
|
4
4
|
|
|
5
5
|
export interface ReanimatedTrueSheetContextValue {
|
|
6
6
|
/**
|
|
7
|
-
* Shared value representing the current sheet position (Y offset from
|
|
7
|
+
* Shared value representing the current sheet position (Y offset from top of screen)
|
|
8
8
|
*/
|
|
9
9
|
animatedPosition: SharedValue<number>;
|
|
10
10
|
/**
|
|
11
|
-
* Shared value representing the current detent index
|
|
11
|
+
* Shared value representing the current detent index as a continuous float.
|
|
12
|
+
* Interpolates smoothly between -1 (off-screen) and the target detent index.
|
|
12
13
|
*/
|
|
13
14
|
animatedIndex: SharedValue<number>;
|
|
15
|
+
/**
|
|
16
|
+
* Shared value representing the current detent value (0-1 fraction of screen height).
|
|
17
|
+
* Interpolates smoothly between detent values as the sheet is dragged.
|
|
18
|
+
*/
|
|
19
|
+
animatedDetent: SharedValue<number>;
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
const ReanimatedTrueSheetContext = createContext<ReanimatedTrueSheetContextValue | null>(null);
|
|
@@ -40,13 +46,15 @@ export const ReanimatedTrueSheetProvider = ({ children }: ReanimatedTrueSheetPro
|
|
|
40
46
|
const { height } = useWindowDimensions();
|
|
41
47
|
const animatedPosition = useSharedValue(height);
|
|
42
48
|
const animatedIndex = useSharedValue(-1);
|
|
49
|
+
const animatedDetent = useSharedValue(0);
|
|
43
50
|
|
|
44
51
|
const value = useMemo(
|
|
45
52
|
() => ({
|
|
46
53
|
animatedPosition,
|
|
47
54
|
animatedIndex,
|
|
55
|
+
animatedDetent,
|
|
48
56
|
}),
|
|
49
|
-
[animatedPosition, animatedIndex]
|
|
57
|
+
[animatedPosition, animatedIndex, animatedDetent]
|
|
50
58
|
);
|
|
51
59
|
|
|
52
60
|
return (
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
package com.lodev09.truesheet.events
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.Arguments
|
|
4
|
-
import com.facebook.react.bridge.WritableMap
|
|
5
|
-
import com.facebook.react.uimanager.events.Event
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Fired when the active detent changes
|
|
9
|
-
* Payload: { index: number, position: number }
|
|
10
|
-
*/
|
|
11
|
-
class DetentChangeEvent(surfaceId: Int, viewId: Int, private val index: Int, private val position: Float) :
|
|
12
|
-
Event<DetentChangeEvent>(surfaceId, viewId) {
|
|
13
|
-
|
|
14
|
-
override fun getEventName(): String = EVENT_NAME
|
|
15
|
-
|
|
16
|
-
override fun getEventData(): WritableMap =
|
|
17
|
-
Arguments.createMap().apply {
|
|
18
|
-
putInt("index", index)
|
|
19
|
-
putDouble("position", position.toDouble())
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
companion object {
|
|
23
|
-
const val EVENT_NAME = "topDetentChange"
|
|
24
|
-
const val REGISTRATION_NAME = "onDetentChange"
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
package com.lodev09.truesheet.events
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.Arguments
|
|
4
|
-
import com.facebook.react.bridge.WritableMap
|
|
5
|
-
import com.facebook.react.uimanager.events.Event
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Fired after the sheet dismissal is complete
|
|
9
|
-
*/
|
|
10
|
-
class DidDismissEvent(surfaceId: Int, viewId: Int) : Event<DidDismissEvent>(surfaceId, viewId) {
|
|
11
|
-
|
|
12
|
-
override fun getEventName(): String = EVENT_NAME
|
|
13
|
-
|
|
14
|
-
override fun getEventData(): WritableMap = Arguments.createMap()
|
|
15
|
-
|
|
16
|
-
companion object {
|
|
17
|
-
const val EVENT_NAME = "topDidDismiss"
|
|
18
|
-
const val REGISTRATION_NAME = "onDidDismiss"
|
|
19
|
-
}
|
|
20
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
package com.lodev09.truesheet.events
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.Arguments
|
|
4
|
-
import com.facebook.react.bridge.WritableMap
|
|
5
|
-
import com.facebook.react.uimanager.events.Event
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Fired after the sheet presentation is complete
|
|
9
|
-
* Payload: { index: number, position: number }
|
|
10
|
-
*/
|
|
11
|
-
class DidPresentEvent(surfaceId: Int, viewId: Int, private val index: Int, private val position: Float) :
|
|
12
|
-
Event<DidPresentEvent>(surfaceId, viewId) {
|
|
13
|
-
|
|
14
|
-
override fun getEventName(): String = EVENT_NAME
|
|
15
|
-
|
|
16
|
-
override fun getEventData(): WritableMap =
|
|
17
|
-
Arguments.createMap().apply {
|
|
18
|
-
putInt("index", index)
|
|
19
|
-
putDouble("position", position.toDouble())
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
companion object {
|
|
23
|
-
const val EVENT_NAME = "topDidPresent"
|
|
24
|
-
const val REGISTRATION_NAME = "onDidPresent"
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
package com.lodev09.truesheet.events
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.Arguments
|
|
4
|
-
import com.facebook.react.bridge.WritableMap
|
|
5
|
-
import com.facebook.react.uimanager.events.Event
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Fired when user starts dragging the sheet
|
|
9
|
-
* Payload: { index: number, position: number }
|
|
10
|
-
*/
|
|
11
|
-
class DragBeginEvent(surfaceId: Int, viewId: Int, private val index: Int, private val position: Float) :
|
|
12
|
-
Event<DragBeginEvent>(surfaceId, viewId) {
|
|
13
|
-
|
|
14
|
-
override fun getEventName(): String = EVENT_NAME
|
|
15
|
-
|
|
16
|
-
override fun getEventData(): WritableMap =
|
|
17
|
-
Arguments.createMap().apply {
|
|
18
|
-
putInt("index", index)
|
|
19
|
-
putDouble("position", position.toDouble())
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
companion object {
|
|
23
|
-
const val EVENT_NAME = "topDragBegin"
|
|
24
|
-
const val REGISTRATION_NAME = "onDragBegin"
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
package com.lodev09.truesheet.events
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.Arguments
|
|
4
|
-
import com.facebook.react.bridge.WritableMap
|
|
5
|
-
import com.facebook.react.uimanager.events.Event
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Fired continuously while user is dragging the sheet
|
|
9
|
-
* Payload: { index: number, position: number }
|
|
10
|
-
*/
|
|
11
|
-
class DragChangeEvent(surfaceId: Int, viewId: Int, private val index: Int, private val position: Float) :
|
|
12
|
-
Event<DragChangeEvent>(surfaceId, viewId) {
|
|
13
|
-
|
|
14
|
-
override fun getEventName(): String = EVENT_NAME
|
|
15
|
-
|
|
16
|
-
override fun getEventData(): WritableMap =
|
|
17
|
-
Arguments.createMap().apply {
|
|
18
|
-
putInt("index", index)
|
|
19
|
-
putDouble("position", position.toDouble())
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
companion object {
|
|
23
|
-
const val EVENT_NAME = "topDragChange"
|
|
24
|
-
const val REGISTRATION_NAME = "onDragChange"
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
package com.lodev09.truesheet.events
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.Arguments
|
|
4
|
-
import com.facebook.react.bridge.WritableMap
|
|
5
|
-
import com.facebook.react.uimanager.events.Event
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Fired when user stops dragging the sheet
|
|
9
|
-
* Payload: { index: number, position: number }
|
|
10
|
-
*/
|
|
11
|
-
class DragEndEvent(surfaceId: Int, viewId: Int, private val index: Int, private val position: Float) :
|
|
12
|
-
Event<DragEndEvent>(surfaceId, viewId) {
|
|
13
|
-
|
|
14
|
-
override fun getEventName(): String = EVENT_NAME
|
|
15
|
-
|
|
16
|
-
override fun getEventData(): WritableMap =
|
|
17
|
-
Arguments.createMap().apply {
|
|
18
|
-
putInt("index", index)
|
|
19
|
-
putDouble("position", position.toDouble())
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
companion object {
|
|
23
|
-
const val EVENT_NAME = "topDragEnd"
|
|
24
|
-
const val REGISTRATION_NAME = "onDragEnd"
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
package com.lodev09.truesheet.events
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.Arguments
|
|
4
|
-
import com.facebook.react.bridge.WritableMap
|
|
5
|
-
import com.facebook.react.uimanager.events.Event
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Fired when the sheet component is mounted and ready
|
|
9
|
-
*/
|
|
10
|
-
class MountEvent(surfaceId: Int, viewId: Int) : Event<MountEvent>(surfaceId, viewId) {
|
|
11
|
-
|
|
12
|
-
override fun getEventName(): String = EVENT_NAME
|
|
13
|
-
|
|
14
|
-
override fun getEventData(): WritableMap = Arguments.createMap()
|
|
15
|
-
|
|
16
|
-
companion object {
|
|
17
|
-
const val EVENT_NAME = "topMount"
|
|
18
|
-
const val REGISTRATION_NAME = "onMount"
|
|
19
|
-
}
|
|
20
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
package com.lodev09.truesheet.events
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.Arguments
|
|
4
|
-
import com.facebook.react.bridge.WritableMap
|
|
5
|
-
import com.facebook.react.uimanager.events.Event
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Fired continuously for position updates during drag and animation
|
|
9
|
-
* Payload: { index: number, position: number, transitioning: boolean }
|
|
10
|
-
*/
|
|
11
|
-
class PositionChangeEvent(
|
|
12
|
-
surfaceId: Int,
|
|
13
|
-
viewId: Int,
|
|
14
|
-
private val index: Int,
|
|
15
|
-
private val position: Float,
|
|
16
|
-
private val transitioning: Boolean = false
|
|
17
|
-
) : Event<PositionChangeEvent>(surfaceId, viewId) {
|
|
18
|
-
|
|
19
|
-
override fun getEventName(): String = EVENT_NAME
|
|
20
|
-
|
|
21
|
-
override fun getEventData(): WritableMap =
|
|
22
|
-
Arguments.createMap().apply {
|
|
23
|
-
putInt("index", index)
|
|
24
|
-
putDouble("position", position.toDouble())
|
|
25
|
-
putBoolean("transitioning", transitioning)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
companion object {
|
|
29
|
-
const val EVENT_NAME = "topPositionChange"
|
|
30
|
-
const val REGISTRATION_NAME = "onPositionChange"
|
|
31
|
-
}
|
|
32
|
-
}
|