diff --git a/change/react-native-windows-2020-08-14-09-57-33-fix-touchable-mouse.json b/change/react-native-windows-2020-08-14-09-57-33-fix-touchable-mouse.json
new file mode 100644
index 00000000000..956ab190ced
--- /dev/null
+++ b/change/react-native-windows-2020-08-14-09-57-33-fix-touchable-mouse.json
@@ -0,0 +1,8 @@
+{
+ "type": "patch",
+ "comment": "Restore Previous Behavior Allowing onMouseEnter and onMouseLeave on Touchables",
+ "packageName": "react-native-windows",
+ "email": "ngerlem@microsoft.com",
+ "dependentChangeType": "patch",
+ "date": "2020-08-14T16:57:33.938Z"
+}
diff --git a/packages/playground/windows/playground/MainPage.xaml b/packages/playground/windows/playground/MainPage.xaml
index a4824be9fba..3c055e45a2c 100644
--- a/packages/playground/windows/playground/MainPage.xaml
+++ b/packages/playground/windows/playground/MainPage.xaml
@@ -68,7 +68,6 @@
-
diff --git a/vnext/.flowconfig b/vnext/.flowconfig
index a4b73ab4f67..227e661cd79 100644
--- a/vnext/.flowconfig
+++ b/vnext/.flowconfig
@@ -43,6 +43,8 @@
/Libraries/StyleSheet/processColor.js
/Libraries/StyleSheet/processColorArray.js
/Libraries/StyleSheet/StyleSheetTypes.js
+/Libraries/Pressability/Pressability.js
+/Libraries/Types/CoreEventTypes.js
/RNTester/js/components/ListExampleShared.js
/RNTester/js/components/RNTesterExampleList.js
/RNTester/js/examples/ScrollView/ScrollViewExample.js
diff --git a/vnext/src/Libraries/Components/Touchable/TouchableHighlight.windows.js b/vnext/src/Libraries/Components/Touchable/TouchableHighlight.windows.js
index 2e14386084a..f465c4641fd 100644
--- a/vnext/src/Libraries/Components/Touchable/TouchableHighlight.windows.js
+++ b/vnext/src/Libraries/Components/Touchable/TouchableHighlight.windows.js
@@ -176,6 +176,8 @@ class TouchableHighlight extends React.Component {
getPressOutDelayMS: () => this.props.delayPressOut,
getPressRectOffset: () => this.props.pressRetentionOffset,
getTouchSoundDisabled: () => this.props.touchSoundDisabled,
+ onMouseEnter: this.props.onMouseEnter, // [Windows]
+ onMouseLeave: this.props.onMouseLeave, // [Windows]
onBlur: event => {
if (Platform.isTV) {
this._hideUnderlay();
diff --git a/vnext/src/Libraries/Components/Touchable/TouchableOpacity.windows.js b/vnext/src/Libraries/Components/Touchable/TouchableOpacity.windows.js
index 35d5339180f..f0a4f286382 100644
--- a/vnext/src/Libraries/Components/Touchable/TouchableOpacity.windows.js
+++ b/vnext/src/Libraries/Components/Touchable/TouchableOpacity.windows.js
@@ -150,6 +150,8 @@ class TouchableOpacity extends React.Component {
getPressDelayMS: () => this.props.delayPressIn,
getPressOutDelayMS: () => this.props.delayPressOut,
getPressRectOffset: () => this.props.pressRetentionOffset,
+ onMouseEnter: this.props.onMouseEnter, // [Windows]
+ onMouseLeave: this.props.onMouseLeave, // [Windows]
onBlur: event => {
if (Platform.isTV) {
this._opacityInactive(250);
diff --git a/vnext/src/Libraries/Components/Touchable/TouchableWithoutFeedback.windows.js b/vnext/src/Libraries/Components/Touchable/TouchableWithoutFeedback.windows.js
index bcd4de3adba..b94fa9cbed8 100644
--- a/vnext/src/Libraries/Components/Touchable/TouchableWithoutFeedback.windows.js
+++ b/vnext/src/Libraries/Components/Touchable/TouchableWithoutFeedback.windows.js
@@ -27,6 +27,7 @@ import type {
BlurEvent,
FocusEvent,
LayoutEvent,
+ MouseEvent, // [Windows]
PressEvent,
} from '../../Types/CoreEventTypes';
import Platform from '../../Utilities/Platform';
@@ -70,8 +71,8 @@ type Props = $ReadOnly<{|
accessibilityPosInSet?: ?number, // [Windows]
accessibilitySetSize?: ?number, // [Windows]
onAccessibilityTap?: ?() => void, // [Windows]
- onMouseEnter?: ?(event: SyntheticEvent<{}>) => void, // [Windows]
- onMouseLeave?: ?(event: SyntheticEvent<{}>) => void, // [Windows]
+ onMouseEnter?: ?(event: MouseEvent) => void, // [Windows]
+ onMouseLeave?: ?(event: MouseEvent) => void, // [Windows]
tabIndex?: ?number, // [Windows]
tooltip?: ?Stringish, // [Windows]
|}>;
@@ -127,6 +128,8 @@ class TouchableWithoutFeedback extends React.Component {
getPressOutDelayMS: () => this.props.delayPressOut,
getPressRectOffset: () => this.props.pressRetentionOffset,
getTouchSoundDisabled: () => this.props.touchSoundDisabled,
+ onMouseEnter: this.props.onMouseEnter, // [Windows]
+ onMouseLeave: this.props.onMouseLeave, // [Windows]
onBlur: event => {
if (this.props.onBlur != null) {
this.props.onBlur(event);
diff --git a/vnext/src/Libraries/Components/View/ViewPropTypes.windows.js b/vnext/src/Libraries/Components/View/ViewPropTypes.windows.js
index 8a50a858811..f3f09713c9c 100644
--- a/vnext/src/Libraries/Components/View/ViewPropTypes.windows.js
+++ b/vnext/src/Libraries/Components/View/ViewPropTypes.windows.js
@@ -434,8 +434,8 @@ type WindowsViewProps = $ReadOnly<{|
onFocus?: ?(event: FocusEvent) => mixed,
onBlur?: ?(event: FocusEvent) => mixed,
- onMouseLeave?: ?(event: SyntheticEvent<{}>) => mixed,
- onMouseEnter?: ?(event: SyntheticEvent<{}>) => mixed,
+ onMouseLeave?: ?(event: MouseEvent) => mixed,
+ onMouseEnter?: ?(event: MouseEvent) => mixed,
|}>;
// Windows]
diff --git a/vnext/src/Libraries/Pressability/Pressability.windows.js b/vnext/src/Libraries/Pressability/Pressability.windows.js
index 31883d6d352..4f64a0a20c1 100644
--- a/vnext/src/Libraries/Pressability/Pressability.windows.js
+++ b/vnext/src/Libraries/Pressability/Pressability.windows.js
@@ -20,7 +20,7 @@ import type {
PressEvent,
MouseEvent,
KeyEvent, // [Windows]
-} from '../Types/CoreEventTypes.js';
+} from '../Types/CoreEventTypes'; // [Windows] remove explicit .js
import Platform from '../Utilities/Platform';
import UIManager from '../ReactNative/UIManager';
import type {HostComponent} from '../Renderer/shims/ReactNativeTypes';
@@ -129,6 +129,22 @@ export type PressabilityConfig = $ReadOnly<{|
* Returns whether to start a press gesture.
*/
onStartShouldSetResponder?: ?() => boolean,
+
+ // [Windows
+ /**
+ * Raw handler for onMouseEnter that will be preferred if set over hover
+ * events. This is to preserve compatibility with pre-0.62 behavior which
+ * allowed attaching mouse event handlers to Touchables
+ */
+ onMouseEnter?: ?(event: MouseEvent) => mixed,
+
+ /**
+ * Raw handler for onMouseLeave that will be preferred if set over hover
+ * events. This is to preserve compatibility with pre-0.62 behavior which
+ * allowed attaching mouse event handlers to Touchables
+ */
+ onMouseLeave?: ?(event: MouseEvent) => mixed,
+ // Windows]
|}>;
type EventHandlers = $ReadOnly<{|
@@ -528,6 +544,12 @@ export default class Pressability {
? null
: {
onMouseEnter: (event: MouseEvent): void => {
+ // [Windows Add attached raw mouse event handler for compat
+ if (this._config.onMouseEnter) {
+ this._config.onMouseEnter(event);
+ }
+ // Windows]
+
if (isHoverEnabled()) {
this._isHovered = true;
this._cancelHoverOutDelayTimeout();
@@ -546,6 +568,12 @@ export default class Pressability {
},
onMouseLeave: (event: MouseEvent): void => {
+ // [Windows Add attached raw mouse event handler for compat
+ if (this._config.onMouseLeave) {
+ this._config.onMouseLeave(event);
+ }
+ // Windows]
+
if (this._isHovered) {
this._isHovered = false;
this._cancelHoverInDelayTimeout();
diff --git a/vnext/src/Libraries/Types/CoreEventTypes.js b/vnext/src/Libraries/Types/CoreEventTypes.windows.js
similarity index 86%
rename from vnext/src/Libraries/Types/CoreEventTypes.js
rename to vnext/src/Libraries/Types/CoreEventTypes.windows.js
index 3758e8356fc..cdb4d305025 100644
--- a/vnext/src/Libraries/Types/CoreEventTypes.js
+++ b/vnext/src/Libraries/Types/CoreEventTypes.windows.js
@@ -151,15 +151,32 @@ export type FocusEvent = SyntheticEvent<
|}>,
>;
+// [Windows Mouse events on Windows don't match up with the version in core
+// introduced for react-native-web. Replace typings with our values to catch
+// anything dependent on react-native-web specific values
export type MouseEvent = SyntheticEvent<
$ReadOnly<{|
- clientX: number,
- clientY: number,
+ target: number,
+ identifier: number,
pageX: number,
pageY: number,
+ locationX: number,
+ locationY: number,
timestamp: number,
+ pointerType: string,
+ force: number,
+ isLeftButton: boolean,
+ isRightButton: boolean,
+ isMiddleButton: boolean,
+ isBarrelButtonPressed: boolean,
+ isHorizontalScrollWheel: boolean,
+ isEraser: boolean,
+ shiftKey: boolean,
+ ctrlKey: boolean,
+ altKey: boolean,
|}>,
>;
+// Windows]
// [Windows
export type KeyEvent = SyntheticEvent<
diff --git a/packages/playground/Samples/mouse.tsx b/vnext/src/RNTester/js/examples-win/Mouse/MouseExample.windows.js
similarity index 88%
rename from packages/playground/Samples/mouse.tsx
rename to vnext/src/RNTester/js/examples-win/Mouse/MouseExample.windows.js
index b2a4f0f6902..993887fa2e7 100644
--- a/packages/playground/Samples/mouse.tsx
+++ b/vnext/src/RNTester/js/examples-win/Mouse/MouseExample.windows.js
@@ -3,16 +3,31 @@
* Licensed under the MIT License.
* @format
*/
-import * as React from 'react';
-import {
- AppRegistry,
+
+'use strict';
+
+const React = require('react');
+
+const {
StyleSheet,
View,
Text,
GestureResponderEvent,
TouchableHighlight,
BackHandler,
-} from 'react-native';
+} = require('react-native');
+
+exports.displayName = 'MouseExample';
+exports.title = 'Mouse Events';
+exports.description = 'Tests that mouse events can be observed';
+exports.examples = [
+ {
+ title: 'onMouseEnter and onMouseLeave affect style\n',
+ render: function(): React.Node {
+ return ;
+ },
+ },
+];
const styles = StyleSheet.create({
page: {
@@ -68,16 +83,16 @@ const styles = StyleSheet.create({
},
});
-export default class Bootstrap extends React.Component<
+export default class ExampleComponent extends React.Component<
{},
{
- clicked: number;
- pageHover: boolean;
- contentHover: boolean;
- contentChildHover: boolean;
- overlayHover: boolean;
- overlayChildHover: boolean;
- }
+ clicked: number,
+ pageHover: boolean,
+ contentHover: boolean,
+ contentChildHover: boolean,
+ overlayHover: boolean,
+ overlayChildHover: boolean,
+ },
> {
constructor(props: {}) {
super(props);
@@ -225,5 +240,3 @@ export default class Bootstrap extends React.Component<
return true;
};
}
-
-AppRegistry.registerComponent('Bootstrap', () => Bootstrap);
diff --git a/vnext/src/RNTester/js/utils/RNTesterList.windows.ts b/vnext/src/RNTester/js/utils/RNTesterList.windows.ts
index a554aaeb707..d472f6c8736 100644
--- a/vnext/src/RNTester/js/utils/RNTesterList.windows.ts
+++ b/vnext/src/RNTester/js/utils/RNTesterList.windows.ts
@@ -203,6 +203,10 @@ const APIExamples: Array = [
key: 'LayoutExample',
module: require('react-native/RNTester/js/examples/Layout/LayoutExample'),
},
+ {
+ key: 'MouseExample',
+ module: require('./../examples-win/Mouse/MouseExample'),
+ },
{
key: 'NativeAnimationsExample',
module: require('react-native/RNTester/js/examples/NativeAnimation/NativeAnimationsExample'),
diff --git a/vnext/src/overrides.json b/vnext/src/overrides.json
index c02cfcdb585..cbc34ac6551 100644
--- a/vnext/src/overrides.json
+++ b/vnext/src/overrides.json
@@ -674,7 +674,7 @@
},
{
"type": "patch",
- "file": "Libraries\\Types\\CoreEventTypes.js",
+ "file": "Libraries\\Types\\CoreEventTypes.windows.js",
"baseFile": "Libraries\\Types\\CoreEventTypes.js",
"baseVersion": "0.62.0-rc.3",
"baseHash": "83b203d547d9bdc57a8f3346ecee6f6e34b25f5d",