125 lines
4.5 KiB
JavaScript
125 lines
4.5 KiB
JavaScript
|
"use strict";
|
||
|
|
||
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
|
||
|
exports.__esModule = true;
|
||
|
exports["default"] = usePopper;
|
||
|
|
||
|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
||
|
|
||
|
var _popper = _interopRequireDefault(require("popper.js"));
|
||
|
|
||
|
var _react = require("react");
|
||
|
|
||
|
var initialPopperStyles = {
|
||
|
position: 'absolute',
|
||
|
top: '0',
|
||
|
left: '0',
|
||
|
opacity: '0',
|
||
|
pointerEvents: 'none'
|
||
|
};
|
||
|
var initialArrowStyles = {};
|
||
|
/**
|
||
|
* Position an element relative some reference element using Popper.js
|
||
|
*
|
||
|
* @param {HTMLElement} referenceElement The element
|
||
|
* @param {HTMLElement} popperElement
|
||
|
* @param {Object} options
|
||
|
* @param {Object} options.modifiers Popper.js modifiers
|
||
|
* @param {Boolean} options.enabled toggle the popper functionality on/off
|
||
|
* @param {String} options.placement The popper element placement relative to the reference element
|
||
|
* @param {Boolean} options.positionFixed use fixed positioning
|
||
|
* @param {Boolean} options.eventsEnabled have Popper listen on window resize events to reposition the element
|
||
|
*/
|
||
|
|
||
|
function usePopper(referenceElement, popperElement, _temp) {
|
||
|
var _ref = _temp === void 0 ? {} : _temp,
|
||
|
_ref$enabled = _ref.enabled,
|
||
|
enabled = _ref$enabled === void 0 ? true : _ref$enabled,
|
||
|
_ref$placement = _ref.placement,
|
||
|
placement = _ref$placement === void 0 ? 'bottom' : _ref$placement,
|
||
|
_ref$positionFixed = _ref.positionFixed,
|
||
|
positionFixed = _ref$positionFixed === void 0 ? false : _ref$positionFixed,
|
||
|
_ref$eventsEnabled = _ref.eventsEnabled,
|
||
|
eventsEnabled = _ref$eventsEnabled === void 0 ? true : _ref$eventsEnabled,
|
||
|
_ref$modifiers = _ref.modifiers,
|
||
|
modifiers = _ref$modifiers === void 0 ? {} : _ref$modifiers;
|
||
|
|
||
|
var popperInstanceRef = (0, _react.useRef)();
|
||
|
var hasArrow = !!(modifiers.arrow && modifiers.arrow.element);
|
||
|
var scheduleUpdate = (0, _react.useCallback)(function () {
|
||
|
if (popperInstanceRef.current) {
|
||
|
popperInstanceRef.current.scheduleUpdate();
|
||
|
}
|
||
|
}, []);
|
||
|
|
||
|
var _useState = (0, _react.useState)({
|
||
|
placement: placement,
|
||
|
scheduleUpdate: scheduleUpdate,
|
||
|
outOfBoundaries: false,
|
||
|
styles: initialPopperStyles,
|
||
|
arrowStyles: initialArrowStyles
|
||
|
}),
|
||
|
state = _useState[0],
|
||
|
setState = _useState[1]; // A placement difference in state means popper determined a new placement
|
||
|
// apart from the props value. By the time the popper element is rendered with
|
||
|
// the new position Popper has already measured it, if the place change triggers
|
||
|
// a size change it will result in a misaligned popper. So we schedule an update to be sure.
|
||
|
|
||
|
|
||
|
(0, _react.useEffect)(function () {
|
||
|
scheduleUpdate();
|
||
|
}, [state.placement, scheduleUpdate]);
|
||
|
/** Toggle Events */
|
||
|
|
||
|
(0, _react.useEffect)(function () {
|
||
|
if (popperInstanceRef.current) {
|
||
|
// eslint-disable-next-line no-unused-expressions
|
||
|
eventsEnabled ? popperInstanceRef.current.enableEventListeners() : popperInstanceRef.current.disableEventListeners();
|
||
|
}
|
||
|
}, [eventsEnabled]);
|
||
|
(0, _react.useEffect)(function () {
|
||
|
if (!enabled || referenceElement == null || popperElement == null) {
|
||
|
return undefined;
|
||
|
}
|
||
|
|
||
|
var arrow = modifiers.arrow && (0, _extends2["default"])({}, modifiers.arrow, {
|
||
|
element: modifiers.arrow.element
|
||
|
});
|
||
|
popperInstanceRef.current = new _popper["default"](referenceElement, popperElement, {
|
||
|
placement: placement,
|
||
|
positionFixed: positionFixed,
|
||
|
modifiers: (0, _extends2["default"])({}, modifiers, {
|
||
|
arrow: arrow,
|
||
|
applyStyle: {
|
||
|
enabled: false
|
||
|
},
|
||
|
updateStateModifier: {
|
||
|
enabled: true,
|
||
|
order: 900,
|
||
|
fn: function fn(data) {
|
||
|
setState({
|
||
|
scheduleUpdate: scheduleUpdate,
|
||
|
styles: (0, _extends2["default"])({
|
||
|
position: data.offsets.popper.position
|
||
|
}, data.styles),
|
||
|
arrowStyles: data.arrowStyles,
|
||
|
outOfBoundaries: data.hide,
|
||
|
placement: data.placement
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
});
|
||
|
return function () {
|
||
|
if (popperInstanceRef.current !== null) {
|
||
|
popperInstanceRef.current.destroy();
|
||
|
popperInstanceRef.current = null;
|
||
|
}
|
||
|
}; // intentionally NOT re-running on new modifiers
|
||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||
|
}, [enabled, placement, positionFixed, referenceElement, popperElement, hasArrow]);
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
module.exports = exports.default;
|