diff --git a/src/RNGestureHandlerModule.native.ts b/src/RNGestureHandlerModule.native.ts new file mode 100644 index 0000000000..b32050b354 --- /dev/null +++ b/src/RNGestureHandlerModule.native.ts @@ -0,0 +1,5 @@ +// 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 b32050b354..bdf885f988 100644 --- a/src/RNGestureHandlerModule.ts +++ b/src/RNGestureHandlerModule.ts @@ -1,5 +1,105 @@ -// 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 React from 'react'; -import Module from './specs/NativeRNGestureHandlerModule'; -export default Module; +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/RNGestureHandlerModule.web.ts b/src/RNGestureHandlerModule.web.ts deleted file mode 100644 index bdf885f988..0000000000 --- a/src/RNGestureHandlerModule.web.ts +++ /dev/null @@ -1,105 +0,0 @@ -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 new file mode 100644 index 0000000000..7a585b64c0 --- /dev/null +++ b/src/RNRenderer.native.ts @@ -0,0 +1,3 @@ +// 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 7a585b64c0..d46b825958 100644 --- a/src/RNRenderer.ts +++ b/src/RNRenderer.ts @@ -1,3 +1,3 @@ -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck -export { default as RNRenderer } from 'react-native/Libraries/Renderer/shims/ReactNative'; +export const RNRenderer = { + findHostInstance_DEPRECATED: (_ref: any) => null, +}; diff --git a/src/RNRenderer.web.ts b/src/RNRenderer.web.ts deleted file mode 100644 index d46b825958..0000000000 --- a/src/RNRenderer.web.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const RNRenderer = { - findHostInstance_DEPRECATED: (_ref: any) => null, -}; diff --git a/src/components/GestureComponents.native.tsx b/src/components/GestureComponents.native.tsx new file mode 100644 index 0000000000..2a551b058d --- /dev/null +++ b/src/components/GestureComponents.native.tsx @@ -0,0 +1,148 @@ +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 2a551b058d..6ab8ba63ef 100644 --- a/src/components/GestureComponents.tsx +++ b/src/components/GestureComponents.tsx @@ -1,148 +1,41 @@ import * as React from 'react'; import { - PropsWithChildren, - ForwardedRef, - RefAttributes, - ReactElement, -} from 'react'; -import { - ScrollView as RNScrollView, - ScrollViewProps as RNScrollViewProps, + FlatList as RNFlatList, 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, + ScrollView as RNScrollView, + FlatListProps, + View, } 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, +export const ScrollView = createNativeWrapper(RNScrollView, { + disallowInterruption: 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, { +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 +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) => ( ( - - )} - // @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 - } + {...props} + renderScrollComponent={(scrollProps) => } /> - ); -}) 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 deleted file mode 100644 index 6ab8ba63ef..0000000000 --- a/src/components/GestureComponents.web.tsx +++ /dev/null @@ -1,41 +0,0 @@ -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 new file mode 100644 index 0000000000..1b85c23a30 --- /dev/null +++ b/src/components/GestureHandlerButton.native.tsx @@ -0,0 +1,5 @@ +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 1b85c23a30..4126c7cb90 100644 --- a/src/components/GestureHandlerButton.tsx +++ b/src/components/GestureHandlerButton.tsx @@ -1,5 +1,6 @@ -import { HostComponent } from 'react-native'; -import { RawButtonProps } from './GestureButtons'; -import RNGestureHandlerButtonNativeComponent from '../specs/RNGestureHandlerButtonNativeComponent'; +import * as React from 'react'; +import { View } from 'react-native'; -export default RNGestureHandlerButtonNativeComponent as HostComponent; +export default React.forwardRef((props, ref) => ( + +)); diff --git a/src/components/GestureHandlerButton.web.tsx b/src/components/GestureHandlerButton.web.tsx deleted file mode 100644 index 4126c7cb90..0000000000 --- a/src/components/GestureHandlerButton.web.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import * as React from 'react'; -import { View } from 'react-native'; - -export default React.forwardRef((props, ref) => ( - -)); diff --git a/src/components/GestureHandlerRootView.web.tsx b/src/components/GestureHandlerRootView.native.tsx similarity index 71% rename from src/components/GestureHandlerRootView.web.tsx rename to src/components/GestureHandlerRootView.native.tsx index 965f29f4af..d668562599 100644 --- a/src/components/GestureHandlerRootView.web.tsx +++ b/src/components/GestureHandlerRootView.native.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.tsx b/src/components/GestureHandlerRootView.tsx index d668562599..965f29f4af 100644 --- a/src/components/GestureHandlerRootView.tsx +++ b/src/components/GestureHandlerRootView.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 new file mode 100644 index 0000000000..fd1cf9464d --- /dev/null +++ b/src/getReactNativeVersion.native.ts @@ -0,0 +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() { + return REACT_NATIVE_VERSION; +} diff --git a/src/getReactNativeVersion.ts b/src/getReactNativeVersion.ts index fd1cf9464d..6acdea8371 100644 --- a/src/getReactNativeVersion.ts +++ b/src/getReactNativeVersion.ts @@ -1,11 +1,3 @@ -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; + throw new Error('getReactNativeVersion is not supported on web'); } diff --git a/src/getReactNativeVersion.web.ts b/src/getReactNativeVersion.web.ts deleted file mode 100644 index 6acdea8371..0000000000 --- a/src/getReactNativeVersion.web.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function getReactNativeVersion() { - throw new Error('getReactNativeVersion is not supported on web'); -} diff --git a/src/getShadowNodeFromRef.native.ts b/src/getShadowNodeFromRef.native.ts new file mode 100644 index 0000000000..f97a913faf --- /dev/null +++ b/src/getShadowNodeFromRef.native.ts @@ -0,0 +1,44 @@ +// 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 f97a913faf..af1cf978a2 100644 --- a/src/getShadowNodeFromRef.ts +++ b/src/getShadowNodeFromRef.ts @@ -1,44 +1,7 @@ // Used by GestureDetector (unsupported on web at the moment) to check whether the -// attached view may get flattened on Fabric. This implementation causes errors +// 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. 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; +// the conditional importing. +export function getShadowNodeFromRef(_ref: any) { + return null; } diff --git a/src/getShadowNodeFromRef.web.ts b/src/getShadowNodeFromRef.web.ts deleted file mode 100644 index af1cf978a2..0000000000 --- a/src/getShadowNodeFromRef.web.ts +++ /dev/null @@ -1,7 +0,0 @@ -// 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 new file mode 100644 index 0000000000..44f8bcdbcd --- /dev/null +++ b/src/handlers/PressabilityDebugView.native.tsx @@ -0,0 +1,2 @@ +// @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 44f8bcdbcd..73e56c2bc4 100644 --- a/src/handlers/PressabilityDebugView.tsx +++ b/src/handlers/PressabilityDebugView.tsx @@ -1,2 +1,4 @@ -// @ts-ignore it's not exported so we need to import it from path -export { PressabilityDebugView } from 'react-native/Libraries/Pressability/PressabilityDebug'; +// PressabilityDebugView is not implemented in react-native-web +export function PressabilityDebugView() { + return null; +} diff --git a/src/handlers/PressabilityDebugView.web.tsx b/src/handlers/PressabilityDebugView.web.tsx deleted file mode 100644 index 73e56c2bc4..0000000000 --- a/src/handlers/PressabilityDebugView.web.tsx +++ /dev/null @@ -1,4 +0,0 @@ -// 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 new file mode 100644 index 0000000000..3848dac64c --- /dev/null +++ b/src/handlers/customDirectEventTypes.native.ts @@ -0,0 +1,2 @@ +// @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 3848dac64c..b7867a663b 100644 --- a/src/handlers/customDirectEventTypes.ts +++ b/src/handlers/customDirectEventTypes.ts @@ -1,2 +1,5 @@ -// @ts-ignore - its taken straight from RN -export { customDirectEventTypes } from 'react-native/Libraries/Renderer/shims/ReactNativeViewConfigRegistry'; +// 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/customDirectEventTypes.web.ts b/src/handlers/customDirectEventTypes.web.ts deleted file mode 100644 index b7867a663b..0000000000 --- a/src/handlers/customDirectEventTypes.web.ts +++ /dev/null @@ -1,5 +0,0 @@ -// 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 569b0b76e1..ba72c2adbb 100644 --- a/src/handlers/gestures/GestureDetector.tsx +++ b/src/handlers/gestures/GestureDetector.tsx @@ -42,7 +42,6 @@ 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'; @@ -50,6 +49,14 @@ 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 }; @@ -220,9 +227,7 @@ function attachHandlers({ : ActionType.JS_FUNCTION_NEW_API; if (Platform.OS === 'web') { - ( - RNGestureHandlerModule.attachGestureHandler as typeof RNGestureHandlerModuleWeb.attachGestureHandler - )( + (RNGestureHandlerModule.attachGestureHandler as AttachGestureHandlerWeb)( gesture.handlerTag, viewTag, ActionType.JS_FUNCTION_OLD_API, // ignored on web diff --git a/tsconfig.json b/tsconfig.json index e3fe5c53b1..7fbc758390 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,7 +19,9 @@ "forceConsistentCasingInFileNames": true, "noImplicitUseStrict": false, "noUnusedParameters": true, - "noUnusedLocals": true + "noUnusedLocals": true, + + "moduleSuffixes": [".native", ""] }, - "include": ["src/**/*.ts", "src/**/*.tsx", "jestSetup.js"], + "include": ["src/**/*.ts", "src/**/*.tsx", "jestSetup.js"] }