From 8b2470acf99f90236999a021768761378236fd69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Bert?= <63123542+m-bert@users.noreply.github.com> Date: Tue, 7 May 2024 13:15:36 +0200 Subject: [PATCH] Revert "Change `.web` files to default and add `.native` (#2835)" (#2896) ## Description This reverts commit e3e0b79a3d3a622ec65a9c9509e8b5b12b01ff6e. #2835 was the first PR that was meant to introduce compatibility with `Next.js`. Unfortunately, it broke types outside of our repository. Our `tsconfig.json` has special flag, i.e. `moduleSuffixes`, which allows `tsc` to look for `.native` files first. Most of our users do not have this flag and they've run into `ts` problems, like this one: ``` 'TextInput' refers to a value, but is being used as a type here. Did you mean 'typeof TextInput'? ``` Given that removing `moduleSuffixes` from `tsconfig` results in a bunch of errors (and there are more of them that we may not be aware of), we decided that it will be better to revert this change for now. It is not necessary since we only need it to support `Next.js`. At first I thought that #2873 may help, but unfortunately it doesn't. Fixes #2889 ## Test plan 1. Check that web, Android and iOS work as they did before 2. Check that code from [this comment](https://github.com/software-mansion/react-native-gesture-handler/pull/2835#issuecomment-2086176342) now does not throw any errors --- src/RNGestureHandlerModule.native.ts | 5 - src/RNGestureHandlerModule.ts | 108 +----------- src/RNGestureHandlerModule.web.ts | 105 ++++++++++++ src/RNRenderer.native.ts | 3 - src/RNRenderer.ts | 6 +- src/RNRenderer.web.ts | 3 + src/components/GestureComponents.native.tsx | 148 ----------------- src/components/GestureComponents.tsx | 155 +++++++++++++++--- src/components/GestureComponents.web.tsx | 41 +++++ .../GestureHandlerButton.native.tsx | 5 - src/components/GestureHandlerButton.tsx | 9 +- src/components/GestureHandlerButton.web.tsx | 6 + src/components/GestureHandlerRootView.tsx | 6 + ...ive.tsx => GestureHandlerRootView.web.tsx} | 6 - src/getReactNativeVersion.native.ts | 11 -- src/getReactNativeVersion.ts | 10 +- src/getReactNativeVersion.web.ts | 3 + src/getShadowNodeFromRef.native.ts | 44 ----- src/getShadowNodeFromRef.ts | 45 ++++- src/getShadowNodeFromRef.web.ts | 7 + src/handlers/PressabilityDebugView.native.tsx | 2 - src/handlers/PressabilityDebugView.tsx | 6 +- src/handlers/PressabilityDebugView.web.tsx | 4 + src/handlers/customDirectEventTypes.native.ts | 2 - src/handlers/customDirectEventTypes.ts | 7 +- src/handlers/customDirectEventTypes.web.ts | 5 + src/handlers/gestures/GestureDetector.tsx | 13 +- tsconfig.json | 6 +- 28 files changed, 382 insertions(+), 389 deletions(-) delete mode 100644 src/RNGestureHandlerModule.native.ts create mode 100644 src/RNGestureHandlerModule.web.ts delete mode 100644 src/RNRenderer.native.ts create mode 100644 src/RNRenderer.web.ts delete mode 100644 src/components/GestureComponents.native.tsx create mode 100644 src/components/GestureComponents.web.tsx delete mode 100644 src/components/GestureHandlerButton.native.tsx create mode 100644 src/components/GestureHandlerButton.web.tsx rename src/components/{GestureHandlerRootView.native.tsx => GestureHandlerRootView.web.tsx} (71%) delete mode 100644 src/getReactNativeVersion.native.ts create mode 100644 src/getReactNativeVersion.web.ts delete mode 100644 src/getShadowNodeFromRef.native.ts create mode 100644 src/getShadowNodeFromRef.web.ts delete mode 100644 src/handlers/PressabilityDebugView.native.tsx create mode 100644 src/handlers/PressabilityDebugView.web.tsx delete mode 100644 src/handlers/customDirectEventTypes.native.ts create mode 100644 src/handlers/customDirectEventTypes.web.ts diff --git a/src/RNGestureHandlerModule.native.ts b/src/RNGestureHandlerModule.native.ts deleted file mode 100644 index b32050b354..0000000000 --- a/src/RNGestureHandlerModule.native.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Reexport the native module spec used by codegen. The relevant files are inluded on Android -// to ensure the compatibility with the old arch, while iOS doesn't require those at all. - -import Module from './specs/NativeRNGestureHandlerModule'; -export default Module; diff --git a/src/RNGestureHandlerModule.ts b/src/RNGestureHandlerModule.ts index bdf885f988..b32050b354 100644 --- a/src/RNGestureHandlerModule.ts +++ b/src/RNGestureHandlerModule.ts @@ -1,105 +1,5 @@ -import React from 'react'; +// Reexport the native module spec used by codegen. The relevant files are inluded on Android +// to ensure the compatibility with the old arch, while iOS doesn't require those at all. -import type { ActionType } from './ActionType'; -import { isNewWebImplementationEnabled } from './EnableNewWebImplementation'; -import { Gestures, HammerGestures } from './web/Gestures'; -import type { Config } from './web/interfaces'; -import InteractionManager from './web/tools/InteractionManager'; -import NodeManager from './web/tools/NodeManager'; -import * as HammerNodeManager from './web_hammer/NodeManager'; -import { GestureHandlerWebDelegate } from './web/tools/GestureHandlerWebDelegate'; - -export default { - handleSetJSResponder(tag: number, blockNativeResponder: boolean) { - console.warn('handleSetJSResponder: ', tag, blockNativeResponder); - }, - handleClearJSResponder() { - console.warn('handleClearJSResponder: '); - }, - createGestureHandler( - handlerName: keyof typeof Gestures, - handlerTag: number, - config: T - ) { - if (isNewWebImplementationEnabled()) { - if (!(handlerName in Gestures)) { - throw new Error( - `react-native-gesture-handler: ${handlerName} is not supported on web.` - ); - } - - const GestureClass = Gestures[handlerName]; - NodeManager.createGestureHandler( - handlerTag, - new GestureClass(new GestureHandlerWebDelegate()) - ); - InteractionManager.getInstance().configureInteractions( - NodeManager.getHandler(handlerTag), - config as unknown as Config - ); - } else { - if (!(handlerName in HammerGestures)) { - throw new Error( - `react-native-gesture-handler: ${handlerName} is not supported on web.` - ); - } - - // @ts-ignore If it doesn't exist, the error is thrown - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const GestureClass = HammerGestures[handlerName]; - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - HammerNodeManager.createGestureHandler(handlerTag, new GestureClass()); - } - - this.updateGestureHandler(handlerTag, config as unknown as Config); - }, - attachGestureHandler( - handlerTag: number, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - newView: any, - _actionType: ActionType, - propsRef: React.RefObject - ) { - if ( - !(newView instanceof HTMLElement || newView instanceof React.Component) - ) { - return; - } - - if (isNewWebImplementationEnabled()) { - //@ts-ignore Types should be HTMLElement or React.Component - NodeManager.getHandler(handlerTag).init(newView, propsRef); - } else { - //@ts-ignore Types should be HTMLElement or React.Component - HammerNodeManager.getHandler(handlerTag).setView(newView, propsRef); - } - }, - updateGestureHandler(handlerTag: number, newConfig: Config) { - if (isNewWebImplementationEnabled()) { - NodeManager.getHandler(handlerTag).updateGestureConfig(newConfig); - - InteractionManager.getInstance().configureInteractions( - NodeManager.getHandler(handlerTag), - newConfig - ); - } else { - HammerNodeManager.getHandler(handlerTag).updateGestureConfig(newConfig); - } - }, - getGestureHandlerNode(handlerTag: number) { - if (isNewWebImplementationEnabled()) { - return NodeManager.getHandler(handlerTag); - } else { - return HammerNodeManager.getHandler(handlerTag); - } - }, - dropGestureHandler(handlerTag: number) { - if (isNewWebImplementationEnabled()) { - NodeManager.dropGestureHandler(handlerTag); - } else { - HammerNodeManager.dropGestureHandler(handlerTag); - } - }, - // eslint-disable-next-line @typescript-eslint/no-empty-function - flushOperations() {}, -}; +import Module from './specs/NativeRNGestureHandlerModule'; +export default Module; diff --git a/src/RNGestureHandlerModule.web.ts b/src/RNGestureHandlerModule.web.ts new file mode 100644 index 0000000000..bdf885f988 --- /dev/null +++ b/src/RNGestureHandlerModule.web.ts @@ -0,0 +1,105 @@ +import React from 'react'; + +import type { ActionType } from './ActionType'; +import { isNewWebImplementationEnabled } from './EnableNewWebImplementation'; +import { Gestures, HammerGestures } from './web/Gestures'; +import type { Config } from './web/interfaces'; +import InteractionManager from './web/tools/InteractionManager'; +import NodeManager from './web/tools/NodeManager'; +import * as HammerNodeManager from './web_hammer/NodeManager'; +import { GestureHandlerWebDelegate } from './web/tools/GestureHandlerWebDelegate'; + +export default { + handleSetJSResponder(tag: number, blockNativeResponder: boolean) { + console.warn('handleSetJSResponder: ', tag, blockNativeResponder); + }, + handleClearJSResponder() { + console.warn('handleClearJSResponder: '); + }, + createGestureHandler( + handlerName: keyof typeof Gestures, + handlerTag: number, + config: T + ) { + if (isNewWebImplementationEnabled()) { + if (!(handlerName in Gestures)) { + throw new Error( + `react-native-gesture-handler: ${handlerName} is not supported on web.` + ); + } + + const GestureClass = Gestures[handlerName]; + NodeManager.createGestureHandler( + handlerTag, + new GestureClass(new GestureHandlerWebDelegate()) + ); + InteractionManager.getInstance().configureInteractions( + NodeManager.getHandler(handlerTag), + config as unknown as Config + ); + } else { + if (!(handlerName in HammerGestures)) { + throw new Error( + `react-native-gesture-handler: ${handlerName} is not supported on web.` + ); + } + + // @ts-ignore If it doesn't exist, the error is thrown + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const GestureClass = HammerGestures[handlerName]; + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + HammerNodeManager.createGestureHandler(handlerTag, new GestureClass()); + } + + this.updateGestureHandler(handlerTag, config as unknown as Config); + }, + attachGestureHandler( + handlerTag: number, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + newView: any, + _actionType: ActionType, + propsRef: React.RefObject + ) { + if ( + !(newView instanceof HTMLElement || newView instanceof React.Component) + ) { + return; + } + + if (isNewWebImplementationEnabled()) { + //@ts-ignore Types should be HTMLElement or React.Component + NodeManager.getHandler(handlerTag).init(newView, propsRef); + } else { + //@ts-ignore Types should be HTMLElement or React.Component + HammerNodeManager.getHandler(handlerTag).setView(newView, propsRef); + } + }, + updateGestureHandler(handlerTag: number, newConfig: Config) { + if (isNewWebImplementationEnabled()) { + NodeManager.getHandler(handlerTag).updateGestureConfig(newConfig); + + InteractionManager.getInstance().configureInteractions( + NodeManager.getHandler(handlerTag), + newConfig + ); + } else { + HammerNodeManager.getHandler(handlerTag).updateGestureConfig(newConfig); + } + }, + getGestureHandlerNode(handlerTag: number) { + if (isNewWebImplementationEnabled()) { + return NodeManager.getHandler(handlerTag); + } else { + return HammerNodeManager.getHandler(handlerTag); + } + }, + dropGestureHandler(handlerTag: number) { + if (isNewWebImplementationEnabled()) { + NodeManager.dropGestureHandler(handlerTag); + } else { + HammerNodeManager.dropGestureHandler(handlerTag); + } + }, + // eslint-disable-next-line @typescript-eslint/no-empty-function + flushOperations() {}, +}; diff --git a/src/RNRenderer.native.ts b/src/RNRenderer.native.ts deleted file mode 100644 index 7a585b64c0..0000000000 --- a/src/RNRenderer.native.ts +++ /dev/null @@ -1,3 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck -export { default as RNRenderer } from 'react-native/Libraries/Renderer/shims/ReactNative'; diff --git a/src/RNRenderer.ts b/src/RNRenderer.ts index d46b825958..7a585b64c0 100644 --- a/src/RNRenderer.ts +++ b/src/RNRenderer.ts @@ -1,3 +1,3 @@ -export const RNRenderer = { - findHostInstance_DEPRECATED: (_ref: any) => null, -}; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-nocheck +export { default as RNRenderer } from 'react-native/Libraries/Renderer/shims/ReactNative'; diff --git a/src/RNRenderer.web.ts b/src/RNRenderer.web.ts new file mode 100644 index 0000000000..d46b825958 --- /dev/null +++ b/src/RNRenderer.web.ts @@ -0,0 +1,3 @@ +export const RNRenderer = { + findHostInstance_DEPRECATED: (_ref: any) => null, +}; diff --git a/src/components/GestureComponents.native.tsx b/src/components/GestureComponents.native.tsx deleted file mode 100644 index 2a551b058d..0000000000 --- a/src/components/GestureComponents.native.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import * as React from 'react'; -import { - PropsWithChildren, - ForwardedRef, - RefAttributes, - ReactElement, -} from 'react'; -import { - ScrollView as RNScrollView, - ScrollViewProps as RNScrollViewProps, - Switch as RNSwitch, - SwitchProps as RNSwitchProps, - TextInput as RNTextInput, - TextInputProps as RNTextInputProps, - DrawerLayoutAndroid as RNDrawerLayoutAndroid, - DrawerLayoutAndroidProps as RNDrawerLayoutAndroidProps, - FlatList as RNFlatList, - FlatListProps as RNFlatListProps, - RefreshControl as RNRefreshControl, -} from 'react-native'; - -import createNativeWrapper from '../handlers/createNativeWrapper'; - -import { - NativeViewGestureHandlerProps, - nativeViewProps, -} from '../handlers/NativeViewGestureHandler'; - -import { toArray } from '../utils'; - -export const RefreshControl = createNativeWrapper(RNRefreshControl, { - disallowInterruption: true, - shouldCancelWhenOutside: false, -}); -// eslint-disable-next-line @typescript-eslint/no-redeclare -export type RefreshControl = typeof RefreshControl & RNRefreshControl; - -const GHScrollView = createNativeWrapper>( - RNScrollView, - { - disallowInterruption: true, - shouldCancelWhenOutside: false, - } -); -export const ScrollView = React.forwardRef< - RNScrollView, - RNScrollViewProps & NativeViewGestureHandlerProps ->((props, ref) => { - const refreshControlGestureRef = React.useRef(null); - const { refreshControl, waitFor, ...rest } = props; - - return ( - - ); -}); -// backward type compatibility with https://github.com/software-mansion/react-native-gesture-handler/blob/db78d3ca7d48e8ba57482d3fe9b0a15aa79d9932/react-native-gesture-handler.d.ts#L440-L457 -// include methods of wrapped components by creating an intersection type with the RN component instead of duplicating them. -// eslint-disable-next-line @typescript-eslint/no-redeclare -export type ScrollView = typeof GHScrollView & RNScrollView; - -export const Switch = createNativeWrapper(RNSwitch, { - shouldCancelWhenOutside: false, - shouldActivateOnStart: true, - disallowInterruption: true, -}); -// eslint-disable-next-line @typescript-eslint/no-redeclare -export type Switch = typeof Switch & RNSwitch; - -export const TextInput = createNativeWrapper(RNTextInput); -// eslint-disable-next-line @typescript-eslint/no-redeclare -export type TextInput = typeof TextInput & RNTextInput; - -export const DrawerLayoutAndroid = createNativeWrapper< - PropsWithChildren ->(RNDrawerLayoutAndroid, { disallowInterruption: true }); -// eslint-disable-next-line @typescript-eslint/no-redeclare -export type DrawerLayoutAndroid = typeof DrawerLayoutAndroid & - RNDrawerLayoutAndroid; - -export const FlatList = React.forwardRef((props, ref) => { - const refreshControlGestureRef = React.useRef(null); - - const { waitFor, refreshControl, ...rest } = props; - - const flatListProps = {}; - const scrollViewProps = {}; - for (const [propName, value] of Object.entries(rest)) { - // https://github.com/microsoft/TypeScript/issues/26255 - if ((nativeViewProps as readonly string[]).includes(propName)) { - // @ts-ignore - this function cannot have generic type so we have to ignore this error - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - scrollViewProps[propName] = value; - } else { - // @ts-ignore - this function cannot have generic type so we have to ignore this error - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - flatListProps[propName] = value; - } - } - - return ( - // @ts-ignore - this function cannot have generic type so we have to ignore this error - ( - - )} - // @ts-ignore we don't pass `refreshing` prop as we only want to override the ref - refreshControl={ - refreshControl - ? React.cloneElement(refreshControl, { - // @ts-ignore for reasons unknown to me, `ref` doesn't exist on the type inferred by TS - ref: refreshControlGestureRef, - }) - : undefined - } - /> - ); -}) as ( - props: PropsWithChildren< - RNFlatListProps & - RefAttributes> & - NativeViewGestureHandlerProps - >, - ref: ForwardedRef> -) => ReactElement | null; -// eslint-disable-next-line @typescript-eslint/no-redeclare -export type FlatList = typeof FlatList & RNFlatList; diff --git a/src/components/GestureComponents.tsx b/src/components/GestureComponents.tsx index 6ab8ba63ef..2a551b058d 100644 --- a/src/components/GestureComponents.tsx +++ b/src/components/GestureComponents.tsx @@ -1,41 +1,148 @@ import * as React from 'react'; import { - FlatList as RNFlatList, + PropsWithChildren, + ForwardedRef, + RefAttributes, + ReactElement, +} from 'react'; +import { + ScrollView as RNScrollView, + ScrollViewProps as RNScrollViewProps, Switch as RNSwitch, + SwitchProps as RNSwitchProps, TextInput as RNTextInput, - ScrollView as RNScrollView, - FlatListProps, - View, + TextInputProps as RNTextInputProps, + DrawerLayoutAndroid as RNDrawerLayoutAndroid, + DrawerLayoutAndroidProps as RNDrawerLayoutAndroidProps, + FlatList as RNFlatList, + FlatListProps as RNFlatListProps, + RefreshControl as RNRefreshControl, } from 'react-native'; import createNativeWrapper from '../handlers/createNativeWrapper'; -export const ScrollView = createNativeWrapper(RNScrollView, { - disallowInterruption: false, +import { + NativeViewGestureHandlerProps, + nativeViewProps, +} from '../handlers/NativeViewGestureHandler'; + +import { toArray } from '../utils'; + +export const RefreshControl = createNativeWrapper(RNRefreshControl, { + disallowInterruption: true, + shouldCancelWhenOutside: false, }); +// eslint-disable-next-line @typescript-eslint/no-redeclare +export type RefreshControl = typeof RefreshControl & RNRefreshControl; + +const GHScrollView = createNativeWrapper>( + RNScrollView, + { + disallowInterruption: true, + shouldCancelWhenOutside: false, + } +); +export const ScrollView = React.forwardRef< + RNScrollView, + RNScrollViewProps & NativeViewGestureHandlerProps +>((props, ref) => { + const refreshControlGestureRef = React.useRef(null); + const { refreshControl, waitFor, ...rest } = props; -export const Switch = createNativeWrapper(RNSwitch, { + return ( + + ); +}); +// backward type compatibility with https://github.com/software-mansion/react-native-gesture-handler/blob/db78d3ca7d48e8ba57482d3fe9b0a15aa79d9932/react-native-gesture-handler.d.ts#L440-L457 +// include methods of wrapped components by creating an intersection type with the RN component instead of duplicating them. +// eslint-disable-next-line @typescript-eslint/no-redeclare +export type ScrollView = typeof GHScrollView & RNScrollView; + +export const Switch = createNativeWrapper(RNSwitch, { shouldCancelWhenOutside: false, shouldActivateOnStart: true, disallowInterruption: true, }); -export const TextInput = createNativeWrapper(RNTextInput); -export const DrawerLayoutAndroid = () => { - console.warn('DrawerLayoutAndroid is not supported on web!'); - return ; -}; - -// RefreshControl is implemented as a functional component, rendering a View -// NativeViewGestureHandler needs to set a ref on its child, which cannot be done -// on functional components -export const RefreshControl = createNativeWrapper(View); - -export const FlatList = React.forwardRef( - (props: FlatListProps, ref: any) => ( +// eslint-disable-next-line @typescript-eslint/no-redeclare +export type Switch = typeof Switch & RNSwitch; + +export const TextInput = createNativeWrapper(RNTextInput); +// eslint-disable-next-line @typescript-eslint/no-redeclare +export type TextInput = typeof TextInput & RNTextInput; + +export const DrawerLayoutAndroid = createNativeWrapper< + PropsWithChildren +>(RNDrawerLayoutAndroid, { disallowInterruption: true }); +// eslint-disable-next-line @typescript-eslint/no-redeclare +export type DrawerLayoutAndroid = typeof DrawerLayoutAndroid & + RNDrawerLayoutAndroid; + +export const FlatList = React.forwardRef((props, ref) => { + const refreshControlGestureRef = React.useRef(null); + + const { waitFor, refreshControl, ...rest } = props; + + const flatListProps = {}; + const scrollViewProps = {}; + for (const [propName, value] of Object.entries(rest)) { + // https://github.com/microsoft/TypeScript/issues/26255 + if ((nativeViewProps as readonly string[]).includes(propName)) { + // @ts-ignore - this function cannot have generic type so we have to ignore this error + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + scrollViewProps[propName] = value; + } else { + // @ts-ignore - this function cannot have generic type so we have to ignore this error + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + flatListProps[propName] = value; + } + } + + return ( + // @ts-ignore - this function cannot have generic type so we have to ignore this error } + {...flatListProps} + renderScrollComponent={(scrollProps) => ( + + )} + // @ts-ignore we don't pass `refreshing` prop as we only want to override the ref + refreshControl={ + refreshControl + ? React.cloneElement(refreshControl, { + // @ts-ignore for reasons unknown to me, `ref` doesn't exist on the type inferred by TS + ref: refreshControlGestureRef, + }) + : undefined + } /> - ) -); + ); +}) as ( + props: PropsWithChildren< + RNFlatListProps & + RefAttributes> & + NativeViewGestureHandlerProps + >, + ref: ForwardedRef> +) => ReactElement | null; +// eslint-disable-next-line @typescript-eslint/no-redeclare +export type FlatList = typeof FlatList & RNFlatList; diff --git a/src/components/GestureComponents.web.tsx b/src/components/GestureComponents.web.tsx new file mode 100644 index 0000000000..6ab8ba63ef --- /dev/null +++ b/src/components/GestureComponents.web.tsx @@ -0,0 +1,41 @@ +import * as React from 'react'; +import { + FlatList as RNFlatList, + Switch as RNSwitch, + TextInput as RNTextInput, + ScrollView as RNScrollView, + FlatListProps, + View, +} from 'react-native'; + +import createNativeWrapper from '../handlers/createNativeWrapper'; + +export const ScrollView = createNativeWrapper(RNScrollView, { + disallowInterruption: false, +}); + +export const Switch = createNativeWrapper(RNSwitch, { + shouldCancelWhenOutside: false, + shouldActivateOnStart: true, + disallowInterruption: true, +}); +export const TextInput = createNativeWrapper(RNTextInput); +export const DrawerLayoutAndroid = () => { + console.warn('DrawerLayoutAndroid is not supported on web!'); + return ; +}; + +// RefreshControl is implemented as a functional component, rendering a View +// NativeViewGestureHandler needs to set a ref on its child, which cannot be done +// on functional components +export const RefreshControl = createNativeWrapper(View); + +export const FlatList = React.forwardRef( + (props: FlatListProps, ref: any) => ( + } + /> + ) +); diff --git a/src/components/GestureHandlerButton.native.tsx b/src/components/GestureHandlerButton.native.tsx deleted file mode 100644 index 1b85c23a30..0000000000 --- a/src/components/GestureHandlerButton.native.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { HostComponent } from 'react-native'; -import { RawButtonProps } from './GestureButtons'; -import RNGestureHandlerButtonNativeComponent from '../specs/RNGestureHandlerButtonNativeComponent'; - -export default RNGestureHandlerButtonNativeComponent as HostComponent; diff --git a/src/components/GestureHandlerButton.tsx b/src/components/GestureHandlerButton.tsx index 4126c7cb90..1b85c23a30 100644 --- a/src/components/GestureHandlerButton.tsx +++ b/src/components/GestureHandlerButton.tsx @@ -1,6 +1,5 @@ -import * as React from 'react'; -import { View } from 'react-native'; +import { HostComponent } from 'react-native'; +import { RawButtonProps } from './GestureButtons'; +import RNGestureHandlerButtonNativeComponent from '../specs/RNGestureHandlerButtonNativeComponent'; -export default React.forwardRef((props, ref) => ( - -)); +export default RNGestureHandlerButtonNativeComponent as HostComponent; diff --git a/src/components/GestureHandlerButton.web.tsx b/src/components/GestureHandlerButton.web.tsx new file mode 100644 index 0000000000..4126c7cb90 --- /dev/null +++ b/src/components/GestureHandlerButton.web.tsx @@ -0,0 +1,6 @@ +import * as React from 'react'; +import { View } from 'react-native'; + +export default React.forwardRef((props, ref) => ( + +)); diff --git a/src/components/GestureHandlerRootView.tsx b/src/components/GestureHandlerRootView.tsx index 965f29f4af..d668562599 100644 --- a/src/components/GestureHandlerRootView.tsx +++ b/src/components/GestureHandlerRootView.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { PropsWithChildren } from 'react'; import { View, ViewProps, StyleSheet } from 'react-native'; +import { maybeInitializeFabric } from '../init'; import GestureHandlerRootViewContext from '../GestureHandlerRootViewContext'; export interface GestureHandlerRootViewProps @@ -10,6 +11,11 @@ export default function GestureHandlerRootView({ style, ...rest }: GestureHandlerRootViewProps) { + // try initialize fabric on the first render, at this point we can + // reliably check if fabric is enabled (the function contains a flag + // to make sure it's called only once) + maybeInitializeFabric(); + return ( diff --git a/src/components/GestureHandlerRootView.native.tsx b/src/components/GestureHandlerRootView.web.tsx similarity index 71% rename from src/components/GestureHandlerRootView.native.tsx rename to src/components/GestureHandlerRootView.web.tsx index d668562599..965f29f4af 100644 --- a/src/components/GestureHandlerRootView.native.tsx +++ b/src/components/GestureHandlerRootView.web.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { PropsWithChildren } from 'react'; import { View, ViewProps, StyleSheet } from 'react-native'; -import { maybeInitializeFabric } from '../init'; import GestureHandlerRootViewContext from '../GestureHandlerRootViewContext'; export interface GestureHandlerRootViewProps @@ -11,11 +10,6 @@ export default function GestureHandlerRootView({ style, ...rest }: GestureHandlerRootViewProps) { - // try initialize fabric on the first render, at this point we can - // reliably check if fabric is enabled (the function contains a flag - // to make sure it's called only once) - maybeInitializeFabric(); - return ( diff --git a/src/getReactNativeVersion.native.ts b/src/getReactNativeVersion.native.ts deleted file mode 100644 index fd1cf9464d..0000000000 --- a/src/getReactNativeVersion.native.ts +++ /dev/null @@ -1,11 +0,0 @@ -import pack from 'react-native/package.json'; - -const [majorStr, minorStr] = pack.version.split('.'); -const REACT_NATIVE_VERSION = { - major: parseInt(majorStr, 10), - minor: parseInt(minorStr, 10), -}; - -export function getReactNativeVersion() { - return REACT_NATIVE_VERSION; -} diff --git a/src/getReactNativeVersion.ts b/src/getReactNativeVersion.ts index 6acdea8371..fd1cf9464d 100644 --- a/src/getReactNativeVersion.ts +++ b/src/getReactNativeVersion.ts @@ -1,3 +1,11 @@ +import pack from 'react-native/package.json'; + +const [majorStr, minorStr] = pack.version.split('.'); +const REACT_NATIVE_VERSION = { + major: parseInt(majorStr, 10), + minor: parseInt(minorStr, 10), +}; + export function getReactNativeVersion() { - throw new Error('getReactNativeVersion is not supported on web'); + return REACT_NATIVE_VERSION; } diff --git a/src/getReactNativeVersion.web.ts b/src/getReactNativeVersion.web.ts new file mode 100644 index 0000000000..6acdea8371 --- /dev/null +++ b/src/getReactNativeVersion.web.ts @@ -0,0 +1,3 @@ +export function getReactNativeVersion() { + throw new Error('getReactNativeVersion is not supported on web'); +} diff --git a/src/getShadowNodeFromRef.native.ts b/src/getShadowNodeFromRef.native.ts deleted file mode 100644 index f97a913faf..0000000000 --- a/src/getShadowNodeFromRef.native.ts +++ /dev/null @@ -1,44 +0,0 @@ -// Used by GestureDetector (unsupported on web at the moment) to check whether the -// attached view may get flattened on Fabric. This implementation causes errors -// on web due to the static resolution of `require` statements by webpack breaking -// the conditional importing. Solved by making .web file. -let findHostInstance_DEPRECATED: (ref: unknown) => void; -let getInternalInstanceHandleFromPublicInstance: (ref: unknown) => { - stateNode: { node: unknown }; -}; - -export function getShadowNodeFromRef(ref: unknown) { - // load findHostInstance_DEPRECATED lazily because it may not be available before render - if (findHostInstance_DEPRECATED === undefined) { - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - findHostInstance_DEPRECATED = - // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-member-access - require('react-native/Libraries/Renderer/shims/ReactFabric').findHostInstance_DEPRECATED; - } catch (e) { - findHostInstance_DEPRECATED = (_ref: unknown) => null; - } - } - - // load findHostInstance_DEPRECATED lazily because it may not be available before render - if (getInternalInstanceHandleFromPublicInstance === undefined) { - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - getInternalInstanceHandleFromPublicInstance = - // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-member-access - require('react-native/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricPublicInstance') - .getInternalInstanceHandleFromPublicInstance ?? - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return - ((ref: any) => ref._internalInstanceHandle); - } catch (e) { - getInternalInstanceHandleFromPublicInstance = (ref: any) => - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return - ref._internalInstanceHandle; - } - } - - // @ts-ignore Fabric - return getInternalInstanceHandleFromPublicInstance( - findHostInstance_DEPRECATED(ref) - ).stateNode.node; -} diff --git a/src/getShadowNodeFromRef.ts b/src/getShadowNodeFromRef.ts index af1cf978a2..f97a913faf 100644 --- a/src/getShadowNodeFromRef.ts +++ b/src/getShadowNodeFromRef.ts @@ -1,7 +1,44 @@ // Used by GestureDetector (unsupported on web at the moment) to check whether the -// attached view may get flattened on Fabric. Original implementation causes errors +// attached view may get flattened on Fabric. This implementation causes errors // on web due to the static resolution of `require` statements by webpack breaking -// the conditional importing. -export function getShadowNodeFromRef(_ref: any) { - return null; +// the conditional importing. Solved by making .web file. +let findHostInstance_DEPRECATED: (ref: unknown) => void; +let getInternalInstanceHandleFromPublicInstance: (ref: unknown) => { + stateNode: { node: unknown }; +}; + +export function getShadowNodeFromRef(ref: unknown) { + // load findHostInstance_DEPRECATED lazily because it may not be available before render + if (findHostInstance_DEPRECATED === undefined) { + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + findHostInstance_DEPRECATED = + // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-member-access + require('react-native/Libraries/Renderer/shims/ReactFabric').findHostInstance_DEPRECATED; + } catch (e) { + findHostInstance_DEPRECATED = (_ref: unknown) => null; + } + } + + // load findHostInstance_DEPRECATED lazily because it may not be available before render + if (getInternalInstanceHandleFromPublicInstance === undefined) { + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + getInternalInstanceHandleFromPublicInstance = + // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-member-access + require('react-native/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricPublicInstance') + .getInternalInstanceHandleFromPublicInstance ?? + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return + ((ref: any) => ref._internalInstanceHandle); + } catch (e) { + getInternalInstanceHandleFromPublicInstance = (ref: any) => + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return + ref._internalInstanceHandle; + } + } + + // @ts-ignore Fabric + return getInternalInstanceHandleFromPublicInstance( + findHostInstance_DEPRECATED(ref) + ).stateNode.node; } diff --git a/src/getShadowNodeFromRef.web.ts b/src/getShadowNodeFromRef.web.ts new file mode 100644 index 0000000000..af1cf978a2 --- /dev/null +++ b/src/getShadowNodeFromRef.web.ts @@ -0,0 +1,7 @@ +// Used by GestureDetector (unsupported on web at the moment) to check whether the +// attached view may get flattened on Fabric. Original implementation causes errors +// on web due to the static resolution of `require` statements by webpack breaking +// the conditional importing. +export function getShadowNodeFromRef(_ref: any) { + return null; +} diff --git a/src/handlers/PressabilityDebugView.native.tsx b/src/handlers/PressabilityDebugView.native.tsx deleted file mode 100644 index 44f8bcdbcd..0000000000 --- a/src/handlers/PressabilityDebugView.native.tsx +++ /dev/null @@ -1,2 +0,0 @@ -// @ts-ignore it's not exported so we need to import it from path -export { PressabilityDebugView } from 'react-native/Libraries/Pressability/PressabilityDebug'; diff --git a/src/handlers/PressabilityDebugView.tsx b/src/handlers/PressabilityDebugView.tsx index 73e56c2bc4..44f8bcdbcd 100644 --- a/src/handlers/PressabilityDebugView.tsx +++ b/src/handlers/PressabilityDebugView.tsx @@ -1,4 +1,2 @@ -// PressabilityDebugView is not implemented in react-native-web -export function PressabilityDebugView() { - return null; -} +// @ts-ignore it's not exported so we need to import it from path +export { PressabilityDebugView } from 'react-native/Libraries/Pressability/PressabilityDebug'; diff --git a/src/handlers/PressabilityDebugView.web.tsx b/src/handlers/PressabilityDebugView.web.tsx new file mode 100644 index 0000000000..73e56c2bc4 --- /dev/null +++ b/src/handlers/PressabilityDebugView.web.tsx @@ -0,0 +1,4 @@ +// PressabilityDebugView is not implemented in react-native-web +export function PressabilityDebugView() { + return null; +} diff --git a/src/handlers/customDirectEventTypes.native.ts b/src/handlers/customDirectEventTypes.native.ts deleted file mode 100644 index 3848dac64c..0000000000 --- a/src/handlers/customDirectEventTypes.native.ts +++ /dev/null @@ -1,2 +0,0 @@ -// @ts-ignore - its taken straight from RN -export { customDirectEventTypes } from 'react-native/Libraries/Renderer/shims/ReactNativeViewConfigRegistry'; diff --git a/src/handlers/customDirectEventTypes.ts b/src/handlers/customDirectEventTypes.ts index b7867a663b..3848dac64c 100644 --- a/src/handlers/customDirectEventTypes.ts +++ b/src/handlers/customDirectEventTypes.ts @@ -1,5 +1,2 @@ -// customDirectEventTypes doesn't exist in react-native-web, therefore importing it -// directly in createHandler.tsx would end in crash. -const customDirectEventTypes = {}; - -export { customDirectEventTypes }; +// @ts-ignore - its taken straight from RN +export { customDirectEventTypes } from 'react-native/Libraries/Renderer/shims/ReactNativeViewConfigRegistry'; diff --git a/src/handlers/customDirectEventTypes.web.ts b/src/handlers/customDirectEventTypes.web.ts new file mode 100644 index 0000000000..b7867a663b --- /dev/null +++ b/src/handlers/customDirectEventTypes.web.ts @@ -0,0 +1,5 @@ +// customDirectEventTypes doesn't exist in react-native-web, therefore importing it +// directly in createHandler.tsx would end in crash. +const customDirectEventTypes = {}; + +export { customDirectEventTypes }; diff --git a/src/handlers/gestures/GestureDetector.tsx b/src/handlers/gestures/GestureDetector.tsx index f6a582c252..45d927c230 100644 --- a/src/handlers/gestures/GestureDetector.tsx +++ b/src/handlers/gestures/GestureDetector.tsx @@ -42,6 +42,7 @@ import { isFabric, isJestEnv, tagMessage } from '../../utils'; import { getReactNativeVersion } from '../../getReactNativeVersion'; import { getShadowNodeFromRef } from '../../getShadowNodeFromRef'; import { Platform } from 'react-native'; +import type RNGestureHandlerModuleWeb from '../../RNGestureHandlerModule.web'; import { onGestureHandlerEvent } from './eventReceiver'; import { RNRenderer } from '../../RNRenderer'; import { isNewWebImplementationEnabled } from '../../EnableNewWebImplementation'; @@ -49,14 +50,6 @@ import { nativeViewGestureHandlerProps } from '../NativeViewGestureHandler'; import GestureHandlerRootViewContext from '../../GestureHandlerRootViewContext'; import { ghQueueMicrotask } from '../../ghQueueMicrotask'; -type AttachGestureHandlerWeb = ( - handlerTag: number, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - newView: any, - _actionType: ActionType, - propsRef: React.RefObject -) => void; - declare const global: { isFormsStackingContext: (node: unknown) => boolean | null; // JSI function }; @@ -227,7 +220,9 @@ function attachHandlers({ : ActionType.JS_FUNCTION_NEW_API; if (Platform.OS === 'web') { - (RNGestureHandlerModule.attachGestureHandler as AttachGestureHandlerWeb)( + ( + RNGestureHandlerModule.attachGestureHandler as typeof RNGestureHandlerModuleWeb.attachGestureHandler + )( gesture.handlerTag, viewTag, ActionType.JS_FUNCTION_OLD_API, // ignored on web diff --git a/tsconfig.json b/tsconfig.json index 7fbc758390..e3fe5c53b1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,9 +19,7 @@ "forceConsistentCasingInFileNames": true, "noImplicitUseStrict": false, "noUnusedParameters": true, - "noUnusedLocals": true, - - "moduleSuffixes": [".native", ""] + "noUnusedLocals": true }, - "include": ["src/**/*.ts", "src/**/*.tsx", "jestSetup.js"] + "include": ["src/**/*.ts", "src/**/*.tsx", "jestSetup.js"], }