Skip to content

Commit

Permalink
refactor: separate Screen native props and public API (#2423)
Browse files Browse the repository at this point in the history
## Description

Separating native types and public API for Screen component. The core
idea behind this change is that I removed hardcoded as ScreenProps and
try to conform public API to NativeProps accepted by Codegen, with some
transformations if necessary.

## Changes

The biggest change is not casting Native to Component with ScreenProps. 

## Screenshots / GIFs

N/A

## Checklist

- [ ] Included code example that can be used to test this change
- [ ] Updated TS types
- [ ] Updated documentation: <!-- For adding new props to native-stack
-->
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx
- [ ] Ensured that CI passes
  • Loading branch information
maciekstosio authored Oct 22, 2024
1 parent b1c9e40 commit 19866ef
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 21 deletions.
52 changes: 32 additions & 20 deletions src/components/Screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,20 @@ import {
} from '../core';

// Native components
import ScreenNativeComponent from '../fabric/ScreenNativeComponent';
import ModalScreenNativeComponent from '../fabric/ModalScreenNativeComponent';
import ScreenNativeComponent, {
NativeProps as ScreenNativeComponentProps,
} from '../fabric/ScreenNativeComponent';
import ModalScreenNativeComponent, {
NativeProps as ModalScreenNativeComponentProps,
} from '../fabric/ModalScreenNativeComponent';
import { usePrevious } from './helpers/usePrevious';

type NativeScreenProps = Omit<
ScreenProps,
'sheetInitialDetentIndex' | 'sheetLargestUndimmedDetentIndex'
> & {
sheetInitialDetent: number;
sheetLargestUndimmedDetent: number;
};

const NativeScreen: React.ComponentType<NativeScreenProps> =
ScreenNativeComponent as React.ComponentType<NativeScreenProps>;
const AnimatedNativeScreen = Animated.createAnimatedComponent(NativeScreen);
type NativeProps = ScreenNativeComponentProps | ModalScreenNativeComponentProps;
const AnimatedNativeScreen = Animated.createAnimatedComponent(
ScreenNativeComponent,
);
const AnimatedNativeModalScreen = Animated.createAnimatedComponent(
ModalScreenNativeComponent as React.ComponentType<NativeScreenProps>,
ModalScreenNativeComponent,
);

// Incomplete type, all accessible properties available at:
Expand Down Expand Up @@ -196,6 +193,11 @@ export const InnerScreen = React.forwardRef<View, ScreenProps>(
sheetInitialDetentIndex = 0,
// Other
stackPresentation,
// Events for override
onAppear,
onDisappear,
onWillAppear,
onWillDisappear,
} = rest;

if (enabled && isNativePlatformSupported) {
Expand Down Expand Up @@ -273,6 +275,22 @@ export const InnerScreen = React.forwardRef<View, ScreenProps>(
<DelayedFreeze freeze={freezeOnBlur && activityState === 0}>
<AnimatedScreen
{...props}
/**
* This messy override is to conform NativeProps used by codegen and
* our Public API. To see reasoning go to this PR:
* https://github.com/software-mansion/react-native-screens/pull/2423#discussion_r1810616995
*/
onAppear={onAppear as NativeProps['onAppear']}
onDisappear={onDisappear as NativeProps['onDisappear']}
onWillAppear={onWillAppear as NativeProps['onWillAppear']}
onWillDisappear={onWillDisappear as NativeProps['onWillDisappear']}
onGestureCancel={
(onGestureCancel as NativeProps['onGestureCancel']) ??
(() => {
// for internal use
})
}
//
// Hierarchy of screens is handled on the native side and setting zIndex value causes this issue:
// https://github.com/software-mansion/react-native-screens/issues/2345
// With below change of zIndex, we force RN diffing mechanism to NOT include detaching and attaching mutation in one transaction.
Expand Down Expand Up @@ -310,12 +328,6 @@ export const InnerScreen = React.forwardRef<View, ScreenProps>(
],
{ useNativeDriver: true },
)
}
onGestureCancel={
onGestureCancel ??
(() => {
// for internal use
})
}>
{!isNativeStack ? ( // see comment of this prop in types.tsx for information why it is needed
children
Expand Down
10 changes: 9 additions & 1 deletion src/fabric/ModalScreenNativeComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ type HeaderHeightChangeEvent = Readonly<{
headerHeight: Double;
}>;

type SheetDetentChangedEvent = Readonly<{
index: Int32;
isStable: boolean;
}>;

type GestureResponseDistanceType = Readonly<{
start: Float;
end: Float;
Expand All @@ -53,7 +58,8 @@ type StackAnimation =
| 'slide_from_left'
| 'slide_from_bottom'
| 'fade_from_bottom'
| 'ios';
| 'ios_from_right'
| 'ios_from_left';

type SwipeDirection = 'vertical' | 'horizontal';

Expand All @@ -70,12 +76,14 @@ export interface NativeProps extends ViewProps {
onTransitionProgress?: DirectEventHandler<TransitionProgressEvent>;
onGestureCancel?: DirectEventHandler<ScreenEvent>;
onHeaderBackButtonClicked?: DirectEventHandler<ScreenEvent>;
onSheetDetentChanged?: DirectEventHandler<SheetDetentChangedEvent>;
sheetAllowedDetents?: number[];
sheetLargestUndimmedDetent?: WithDefault<Int32, -1>;
sheetGrabberVisible?: WithDefault<boolean, false>;
sheetCornerRadius?: WithDefault<Float, -1.0>;
sheetExpandsWhenScrolledToEdge?: WithDefault<boolean, false>;
sheetInitialDetent?: WithDefault<Int32, 0>;
sheetElevation?: WithDefault<Int32, 24>;
customAnimationOnSwipe?: boolean;
fullScreenSwipeEnabled?: boolean;
fullScreenSwipeShadowEnabled?: boolean;
Expand Down

0 comments on commit 19866ef

Please sign in to comment.