Add withMouseHover HOC

This commit is contained in:
Chi Vinh Le
2018-07-16 18:02:50 -03:00
parent f24c21c94e
commit 2c2213893e
4 changed files with 75 additions and 7 deletions
+1
View File
@@ -1,2 +1,3 @@
export { default as withStyles } from "./withStyles";
export { default as withKeyboardFocus } from "./withKeyboardFocus";
export { default as withMouseHover } from "./withMouseHover";
@@ -3,10 +3,10 @@ import { FocusEvent, MouseEvent } from "react";
import { hoistStatics } from "recompose";
interface InjectedProps {
onFocus?: React.EventHandler<FocusEvent<any>>;
onBlur?: React.EventHandler<FocusEvent<any>>;
onMouseDown?: React.EventHandler<MouseEvent<any>>;
keyboardFocus?: boolean;
onFocus: React.EventHandler<FocusEvent<any>>;
onBlur: React.EventHandler<FocusEvent<any>>;
onMouseDown: React.EventHandler<MouseEvent<any>>;
keyboardFocus: boolean;
}
/**
@@ -61,4 +61,5 @@ export default hoistStatics<InjectedProps>(
return WithKeyboardFocus as React.ComponentType<any>;
}
);
// TODO: workaround, add bug link.
) as <T>(WrappedComponent: T) => T;
@@ -0,0 +1,65 @@
import * as React from "react";
import { MouseEvent, TouchEvent } from "react";
import { hoistStatics } from "recompose";
interface InjectedProps {
onMouseOver: React.EventHandler<MouseEvent<any>>;
onMouseOut: React.EventHandler<MouseEvent<any>>;
onTouchEnd: React.EventHandler<TouchEvent<any>>;
mouseHover: boolean;
}
/**
* withMouseHover provides a property `MouseHover: boolean`
* to indicate a focus on the element, that wasn't triggered by mouse
* or touch.
*/
export default hoistStatics<InjectedProps>(
<T extends InjectedProps>(WrappedComponent: React.ComponentType<T>) => {
class WithMouseHover extends React.Component<any> {
public state = {
mouseHover: false,
lastTouchEndTime: 0,
};
private handleTouchEnd: React.EventHandler<TouchEvent<any>> = event => {
if (this.props.onTouchEnd) {
this.props.onTouchEnd(event);
}
this.setState({ lastTouchEndTime: new Date().getTime() });
};
private handleMouseOver: React.EventHandler<MouseEvent<any>> = event => {
if (this.props.onMouseOver) {
this.props.onMouseOver(event);
}
const now = new Date().getTime();
if (now - this.state.lastTouchEndTime > 750) {
this.setState({ mouseHover: true });
}
};
private handleMouseOut: React.EventHandler<MouseEvent<any>> = event => {
if (this.props.onMouseOut) {
this.props.onMouseOut(event);
}
this.setState({ mouseHover: false });
};
public render() {
return (
<WrappedComponent
{...this.props}
onMouseOver={this.handleMouseOver}
onMouseOut={this.handleMouseOut}
onTouchEnd={this.handleTouchEnd}
mouseHover={this.state.mouseHover}
/>
);
}
}
return WithMouseHover as React.ComponentType<any>;
}
// TODO: workaround, add bug link.
) as <T>(WrappedComponent: T) => T;
+3 -2
View File
@@ -13,17 +13,18 @@ function withStyles<T>(
): DefaultingInferableComponentEnhancer<{ classes?: Partial<T> }> {
const classes = { ...(styles as any) };
return withPropsOnChange<any, any>(["classes"], props => {
const resolvedClasses = { ...classes };
if (props.classes) {
Object.keys(props.classes).forEach(k => {
if (classes[k]) {
classes[k] += ` ${props.classes[k]}`;
resolvedClasses[k] += ` ${props.classes[k]}`;
} else if (process.env.NODE_ENV !== "production") {
// tslint:disable:next-line: no-console
console.warn("Extending non existant className", k);
}
});
}
return { classes };
return { classes: resolvedClasses };
});
}