Enable React Native strict TypeScript API (#11459)

This commit is contained in:
Samuel Newman
2026-08-25 09:40:14 +03:00
committed by GitHub
parent 5f3d24efab
commit f87fdd2ea2
149 changed files with 506 additions and 623 deletions
+76 -71
View File
@@ -8,7 +8,7 @@ import {
} from 'react'
import {
Keyboard,
type KeyboardEventListener,
type KeyboardEvent,
type LayoutChangeEvent,
type NativeScrollEvent,
type NativeSyntheticEvent,
@@ -203,80 +203,85 @@ export function Inner(props: DialogInnerProps) {
return <ScrollableInner {...props} />
}
export const ScrollableInner = forwardRef<ScrollView, DialogInnerProps>(
function ScrollableInner(
{children, contentContainerStyle, header, footer, style, ...props},
ref,
) {
const {nativeSnapPoint, disableDrag, setDisableDrag, isHeightConstrained} =
useDialogContext()
const isAtMaxSnapPoint = nativeSnapPoint === BottomSheetSnapPoint.Full
const insets = useSafeAreaInsets()
const [keyboardHeight, setKeyboardHeight] = useState(() =>
IS_ANDROID ? (Keyboard.metrics()?.height ?? 0) : 0,
)
export function ScrollableInner({
ref,
children,
contentContainerStyle,
header,
footer,
style,
...props
}: DialogInnerProps & {
ref?: React.Ref<React.ComponentRef<typeof ScrollView>>
}) {
const {nativeSnapPoint, disableDrag, setDisableDrag, isHeightConstrained} =
useDialogContext()
const isAtMaxSnapPoint = nativeSnapPoint === BottomSheetSnapPoint.Full
const insets = useSafeAreaInsets()
const [keyboardHeight, setKeyboardHeight] = useState(() =>
IS_ANDROID ? (Keyboard.metrics()?.height ?? 0) : 0,
)
const keyboardEventHandler = useCallback<KeyboardEventListener>(e => {
setKeyboardHeight(e.endCoordinates.height)
}, [])
useOnKeyboard('keyboardDidShow', keyboardEventHandler)
useOnKeyboard('keyboardDidHide', keyboardEventHandler)
const keyboardEventHandler = useCallback((e: KeyboardEvent) => {
setKeyboardHeight(e.endCoordinates.height)
}, [])
useOnKeyboard('keyboardDidShow', keyboardEventHandler)
useOnKeyboard('keyboardDidHide', keyboardEventHandler)
const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
if (!IS_ANDROID) {
return
}
const {contentOffset} = e.nativeEvent
if (contentOffset.y > 0 && !disableDrag) {
setDisableDrag(true)
} else if (contentOffset.y <= 1 && disableDrag) {
setDisableDrag(false)
}
const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
if (!IS_ANDROID) {
return
}
const {contentOffset} = e.nativeEvent
if (contentOffset.y > 0 && !disableDrag) {
setDisableDrag(true)
} else if (contentOffset.y <= 1 && disableDrag) {
setDisableDrag(false)
}
}
return (
<>
<ScrollView
style={[isHeightConstrained && a.flex_1, style]}
contentContainerStyle={[
a.pt_2xl,
IS_LIQUID_GLASS ? a.px_2xl : a.px_xl,
platform({
ios: a.pb_2xl,
android: {
paddingBottom: keyboardHeight + insets.bottom + tokens.space.xl,
},
}),
contentContainerStyle,
]}
ref={ref}
showsVerticalScrollIndicator={IS_ANDROID ? false : undefined}
contentInsetAdjustmentBehavior={
isAtMaxSnapPoint ? 'automatic' : 'never'
}
automaticallyAdjustKeyboardInsets={isAtMaxSnapPoint}
{...props}
bounces={isAtMaxSnapPoint}
scrollEventThrottle={50}
// set drag state based on scroll on android.
// we want to detect if it's at the top or not, so watch
// scrollEndDrag and momentumScrollEnd as well
onScroll={android(onScroll)}
onScrollEndDrag={android(onScroll)}
onMomentumScrollEnd={android(onScroll)}
keyboardShouldPersistTaps="handled"
// TODO: figure out why this positions the header absolutely (rather than stickily)
// on Android. fine to disable for now, because we don't have any
// dialogs that use this that actually scroll -sfn
stickyHeaderIndices={ios(header ? [0] : undefined)}>
{header}
{children}
</ScrollView>
{footer}
</>
)
},
)
return (
<>
<ScrollView
style={[isHeightConstrained && a.flex_1, style]}
contentContainerStyle={[
a.pt_2xl,
IS_LIQUID_GLASS ? a.px_2xl : a.px_xl,
platform({
ios: a.pb_2xl,
android: {
paddingBottom: keyboardHeight + insets.bottom + tokens.space.xl,
},
}),
contentContainerStyle,
]}
ref={ref}
showsVerticalScrollIndicator={IS_ANDROID ? false : undefined}
contentInsetAdjustmentBehavior={
isAtMaxSnapPoint ? 'automatic' : 'never'
}
automaticallyAdjustKeyboardInsets={isAtMaxSnapPoint}
{...props}
bounces={isAtMaxSnapPoint}
scrollEventThrottle={50}
// set drag state based on scroll on android.
// we want to detect if it's at the top or not, so watch
// scrollEndDrag and momentumScrollEnd as well
onScroll={android(onScroll)}
onScrollEndDrag={android(onScroll)}
onMomentumScrollEnd={android(onScroll)}
keyboardShouldPersistTaps="handled"
// TODO: figure out why this positions the header absolutely (rather than stickily)
// on Android. fine to disable for now, because we don't have any
// dialogs that use this that actually scroll -sfn
stickyHeaderIndices={ios(header ? [0] : undefined)}>
{header}
{children}
</ScrollView>
{footer}
</>
)
}
export const InnerFlatList = forwardRef<
ListMethods,
+3 -2
View File
@@ -193,7 +193,6 @@ export function Inner({
aria-label={label}
aria-labelledby={accessibilityLabelledBy}
aria-describedby={accessibilityDescribedBy}
// @ts-expect-error web only -prf
onClick={stopPropagation}
onStartShouldSetResponder={_ => true}
onTouchEnd={stopPropagation}
@@ -239,7 +238,9 @@ export function Inner({
export function ScrollableInner({
ref: _ref,
...props
}: DialogInnerProps & {ref?: React.Ref<ScrollView>}) {
}: DialogInnerProps & {
ref?: React.Ref<React.ComponentRef<typeof ScrollView>>
}) {
return <Inner {...props} />
}