diff --git a/src/components/Swipeable.tsx b/src/components/Swipeable.tsx index b3ae488ab2..e464540e5a 100644 --- a/src/components/Swipeable.tsx +++ b/src/components/Swipeable.tsx @@ -541,6 +541,7 @@ export default class Swipeable extends Component< return ( @@ -551,6 +552,7 @@ export default class Swipeable extends Component< {right} > { @@ -156,6 +174,7 @@ export type CommonGestureConfig = { activeCursor?: ActiveCursor; mouseButton?: MouseButton; enableContextMenu?: boolean; + touchAction?: TouchAction; }; // Events payloads are types instead of interfaces due to TS limitation. diff --git a/src/handlers/gestures/GestureDetector.tsx b/src/handlers/gestures/GestureDetector.tsx index 5f55b5eeab..569b0b76e1 100644 --- a/src/handlers/gestures/GestureDetector.tsx +++ b/src/handlers/gestures/GestureDetector.tsx @@ -19,6 +19,7 @@ import { HandlerStateChangeEvent, scheduleFlushOperations, UserSelect, + TouchAction, } from '../gestureHandlerCommon'; import { GestureStateManager, @@ -614,11 +615,21 @@ const applyEnableContextMenuProp = ( } }; +const applyTouchActionProp = ( + touchAction: TouchAction, + gesture: ComposedGesture | GestureType +): void => { + for (const g of gesture.toGestureArray()) { + g.config.touchAction = touchAction; + } +}; + interface GestureDetectorProps { gesture: ComposedGesture | GestureType; children?: React.ReactNode; userSelect?: UserSelect; enableContextMenu?: boolean; + touchAction?: TouchAction; } interface GestureDetectorState { firstRender: boolean; @@ -644,6 +655,10 @@ export const GestureDetector = (props: GestureDetectorProps) => { applyEnableContextMenuProp(props.enableContextMenu, gestureConfig); } + if (props.touchAction !== undefined) { + applyTouchActionProp(props.touchAction, gestureConfig); + } + const gesture = gestureConfig.toGestureArray(); const useReanimatedHook = gesture.some((g) => g.shouldUseReanimated); diff --git a/src/web/interfaces.ts b/src/web/interfaces.ts index 9f3ef3d1d8..0b83e4641e 100644 --- a/src/web/interfaces.ts +++ b/src/web/interfaces.ts @@ -1,4 +1,8 @@ -import { UserSelect, ActiveCursor } from '../handlers/gestureHandlerCommon'; +import { + UserSelect, + ActiveCursor, + TouchAction, +} from '../handlers/gestureHandlerCommon'; import { Directions } from '../Directions'; import { State } from '../State'; import { PointerType } from '../PointerType'; @@ -23,6 +27,7 @@ type ConfigArgs = | boolean | HitSlop | UserSelect + | TouchAction | ActiveCursor | Directions | Handler[] @@ -40,6 +45,7 @@ export interface Config extends Record { activeCursor?: ActiveCursor; mouseButton?: MouseButton; enableContextMenu?: boolean; + touchAction?: TouchAction; activateAfterLongPress?: number; failOffsetXStart?: number; diff --git a/src/web/tools/GestureHandlerWebDelegate.ts b/src/web/tools/GestureHandlerWebDelegate.ts index fad27df38c..5e10e445e8 100644 --- a/src/web/tools/GestureHandlerWebDelegate.ts +++ b/src/web/tools/GestureHandlerWebDelegate.ts @@ -32,10 +32,6 @@ export class GestureHandlerWebDelegate this.gestureHandler = handler; this.view = findNodeHandle(viewRef) as unknown as HTMLElement; - this.view.style['touchAction'] = 'none'; - //@ts-ignore This one disables default events on Safari - this.view.style['WebkitTouchCallout'] = 'none'; - const config = handler.getConfig(); this.addContextMenuListeners(config); @@ -48,6 +44,10 @@ export class GestureHandlerWebDelegate this.view.style['userSelect'] = config.userSelect; } + this.view.style['touchAction'] = config.touchAction ?? 'none'; + //@ts-ignore This one disables default events on Safari + this.view.style['WebkitTouchCallout'] = 'none'; + this.eventManagers.push(new PointerEventManager(this.view)); this.eventManagers.push(new TouchEventManager(this.view));