Merge branch 'next' into permalink

This commit is contained in:
Chi Vinh Le
2018-08-03 16:05:43 +02:00
127 changed files with 3521 additions and 1363 deletions
@@ -3,7 +3,14 @@ import React from "react";
import simulant from "simulant";
import sinon from "sinon";
import ClickOutside from "./ClickOutside";
import UIContext from "../UIContext";
import {
ClickFarAwayCallback,
ClickFarAwayRegister,
ClickOutside,
default as ClickOutsideWithContext,
} from "./ClickOutside";
let container: HTMLElement;
@@ -60,3 +67,57 @@ it("should ignore click inside", () => {
expect(onClickOutside.calledOnce).toEqual(false);
wrapper.unmount();
});
it("should detect click far away", () => {
let emitFarAwayClick: ClickFarAwayCallback = Function;
const unlisten = sinon.spy();
const registerClickFarAway: ClickFarAwayRegister = cb => {
emitFarAwayClick = cb;
return unlisten;
};
const onClickOutside = sinon.spy();
const wrapper = mount(
<ClickOutside
onClickOutside={onClickOutside}
registerClickFarAway={registerClickFarAway}
>
<button id="click-outside-test-button">Push Me</button>
</ClickOutside>,
{
attachTo: container,
}
);
expect(onClickOutside.calledOnce).toEqual(false);
emitFarAwayClick();
expect(onClickOutside.calledOnce).toEqual(true);
expect(unlisten.calledOnce).toEqual(false);
wrapper.unmount();
expect(unlisten.calledOnce).toEqual(true);
});
it("should get registerClickFarAway from context", () => {
const registerClickFarAway: ClickFarAwayRegister = sinon.spy();
const onClickOutside = sinon.spy();
const context: any = {
registerClickFarAway,
};
const wrapper = mount(
<UIContext.Provider value={context}>
<ClickOutsideWithContext
onClickOutside={onClickOutside}
registerClickFarAway={registerClickFarAway}
>
<button id="click-outside-test-button">Push Me</button>
</ClickOutsideWithContext>
</UIContext.Provider>,
{
attachTo: container,
}
);
expect(wrapper.find(ClickOutside).prop("registerClickFarAway")).toEqual(
registerClickFarAway
);
wrapper.unmount();
});
@@ -1,13 +1,30 @@
import React from "react";
import React, { StatelessComponent } from "react";
import { findDOMNode } from "react-dom";
import UIContext from "../UIContext";
export type ClickFarAwayCallback = () => void;
export type ClickFarAwayUnlistenCallback = () => void;
export type ClickFarAwayRegister = (
callback: ClickFarAwayCallback
) => ClickFarAwayUnlistenCallback;
export interface ClickOutsideProps {
onClickOutside: (e?: MouseEvent) => void;
/**
* A way to listen for clicks that are e.g. outside of the
* current frame for `ClickOutside`
*/
registerClickFarAway?: ClickFarAwayRegister;
children: React.ReactNode;
}
class ClickOutside extends React.Component<ClickOutsideProps> {
export class ClickOutside extends React.Component<ClickOutsideProps> {
public domNode: Element | null = null;
private unlisten?: ClickFarAwayUnlistenCallback;
public handleClick = (e: MouseEvent) => {
const { onClickOutside } = this.props;
@@ -17,13 +34,30 @@ class ClickOutside extends React.Component<ClickOutsideProps> {
}
};
public handleClickFarAway = () => {
const { onClickOutside } = this.props;
// tslint:disable-next-line:no-unused-expression
onClickOutside && onClickOutside();
};
public componentDidMount() {
this.domNode = findDOMNode(this) as Element;
document.addEventListener("click", this.handleClick, true);
// Listen to far away clicks.
if (this.props.registerClickFarAway) {
this.unlisten = this.props.registerClickFarAway(this.handleClickFarAway);
}
}
public componentWillUnmount() {
document.removeEventListener("click", this.handleClick, true);
// Unlisten to far away clicks.
if (this.unlisten) {
this.unlisten();
this.unlisten = undefined;
}
}
public render() {
@@ -31,4 +65,12 @@ class ClickOutside extends React.Component<ClickOutsideProps> {
}
}
export default ClickOutside;
const ClickOutsideWithContext: StatelessComponent<Props> = props => (
<UIContext.Consumer>
{({ registerClickFarAway }) => (
<ClickOutside {...props} registerClickFarAway={registerClickFarAway} />
)}
</UIContext.Consumer>
);
export default ClickOutsideWithContext;
@@ -1 +1 @@
export { default } from "./ClickOutside";
export { default as ClickOutside, ClickFarAwayRegister } from "./ClickOutside";