@d8660091/react-popper
Version:
A React component for displaying popper based on popper.js
131 lines (124 loc) • 3.68 kB
JavaScript
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
import React from 'react';
import PropTypes from 'prop-types';
import Popper from 'popper.js';
import { compose, lifecycle, setDisplayName, setPropTypes, withHandlers, withStateHandlers } from 'recompose';
var enhance = compose(setDisplayName('Popper'), setPropTypes({
renderRef: PropTypes.any.isRequired,
renderPop: PropTypes.func,
children: PropTypes.any,
options: PropTypes.object,
defaultIsOpened: PropTypes.bool,
canClickOutside: PropTypes.bool
}), withStateHandlers({
reference: null
}, {
setReference: function setReference() {
return function (reference) {
if (reference) {
return {
reference: reference
};
}
};
}
}), withStateHandlers({
pop: null,
popper: null
}, {
setPop: function setPop(_ref, props) {
var prevPopper = _ref.popper;
return function (pop) {
if (prevPopper) {
prevPopper.destroy();
}
var popper = pop ? new Popper(props.reference, pop, props.options) : null;
return { pop: pop, popper: popper };
};
}
}), withStateHandlers(function (_ref2) {
var _ref2$defaultIsOpened = _ref2.defaultIsOpened,
defaultIsOpened = _ref2$defaultIsOpened === undefined ? false : _ref2$defaultIsOpened;
return {
isOpened: defaultIsOpened
};
}, {
open: function open(_, props) {
return function () {
return {
isOpened: true
};
};
},
close: function close() {
return function () {
return {
isOpened: false
};
};
},
toggle: function toggle(_ref3, props) {
var isOpened = _ref3.isOpened;
return function () {
return {
isOpened: !isOpened
};
};
}
}), withHandlers({
onClick: function onClick(props) {
return function (e) {
if (props.reference && !props.canClickOutside && !e.canBeIgnoredByReactPopper) {
var isInsidePop = props.pop && props.pop.contains(e.target);
if (!props.reference.contains(e.target) && !isInsidePop) {
// click outside
props.close();
}
}
};
}
}), lifecycle({
componentDidUpdate: function componentDidUpdate() {
if (this.props.popper) {
this.props.popper.scheduleUpdate();
}
},
componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
if (this.props.options != nextProps.options && this.props.pop) {
this.props.setPop(this.props.pop);
}
},
componentWillMount: function componentWillMount() {
document.addEventListener('mousedown', this.props.onClick);
},
componentWillUnmount: function componentWillUnmount() {
document.removeEventListener('mousedown', this.props.onClick);
if (this.props.popper) {
this.props.popper.destroy();
}
}
}));
export default enhance(function (props) {
return React.createElement(
React.Fragment,
null,
props.renderRef(_extends({}, props)),
props.isOpened && (props.renderPop ? props.renderPop(_extends({}, props)) : React.createElement(
'div',
{ ref: props.setPop, style: props.style, className: props.className },
props.children
))
);
});
export var ClickableArea = function ClickableArea(props) {
return React.createElement(
'div',
{ ref: function ref(el) {
return el && el.addEventListener('mousedown', ignoreEvent);
} },
props.children
);
};
function ignoreEvent(e) {
e.canBeIgnoredByReactPopper = true;
}