"use strict"; exports.__esModule = true; exports.default = void 0; var _react = require("react"); var _dequal = require("dequal"); var _useSafeState = _interopRequireDefault(require("@restart/hooks/useSafeState")); var _popper = require("./popper"); const _excluded = ["enabled", "placement", "strategy", "modifiers"]; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } const disabledApplyStylesModifier = { name: 'applyStyles', enabled: false, phase: 'afterWrite', fn: () => undefined }; // until docjs supports type exports... const ariaDescribedByModifier = { name: 'ariaDescribedBy', enabled: true, phase: 'afterWrite', effect: ({ state }) => () => { const { reference, popper } = state.elements; if ('removeAttribute' in reference) { const ids = (reference.getAttribute('aria-describedby') || '').split(',').filter(id => id.trim() !== popper.id); if (!ids.length) reference.removeAttribute('aria-describedby');else reference.setAttribute('aria-describedby', ids.join(',')); } }, fn: ({ state }) => { var _popper$getAttribute; const { popper, reference } = state.elements; const role = (_popper$getAttribute = popper.getAttribute('role')) == null ? void 0 : _popper$getAttribute.toLowerCase(); if (popper.id && role === 'tooltip' && 'setAttribute' in reference) { const ids = reference.getAttribute('aria-describedby'); if (ids && ids.split(',').indexOf(popper.id) !== -1) { return; } reference.setAttribute('aria-describedby', ids ? `${ids},${popper.id}` : popper.id); } } }; const EMPTY_MODIFIERS = []; /** * Position an element relative some reference element using Popper.js * * @param referenceElement * @param 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 {string=} options.strategy the positioning strategy * @param {function=} options.onCreate called when the popper is created * @param {function=} options.onUpdate called when the popper is updated * * @returns {UsePopperState} The popper state */ function usePopper(referenceElement, popperElement, _ref = {}) { let { enabled = true, placement = 'bottom', strategy = 'absolute', modifiers = EMPTY_MODIFIERS } = _ref, config = _objectWithoutPropertiesLoose(_ref, _excluded); const prevModifiers = (0, _react.useRef)(modifiers); const popperInstanceRef = (0, _react.useRef)(); const update = (0, _react.useCallback)(() => { var _popperInstanceRef$cu; (_popperInstanceRef$cu = popperInstanceRef.current) == null ? void 0 : _popperInstanceRef$cu.update(); }, []); const forceUpdate = (0, _react.useCallback)(() => { var _popperInstanceRef$cu2; (_popperInstanceRef$cu2 = popperInstanceRef.current) == null ? void 0 : _popperInstanceRef$cu2.forceUpdate(); }, []); const [popperState, setState] = (0, _useSafeState.default)((0, _react.useState)({ placement, update, forceUpdate, attributes: {}, styles: { popper: {}, arrow: {} } })); const updateModifier = (0, _react.useMemo)(() => ({ name: 'updateStateModifier', enabled: true, phase: 'write', requires: ['computeStyles'], fn: ({ state }) => { const styles = {}; const attributes = {}; Object.keys(state.elements).forEach(element => { styles[element] = state.styles[element]; attributes[element] = state.attributes[element]; }); setState({ state, styles, attributes, update, forceUpdate, placement: state.placement }); } }), [update, forceUpdate, setState]); const nextModifiers = (0, _react.useMemo)(() => { if (!(0, _dequal.dequal)(prevModifiers.current, modifiers)) { prevModifiers.current = modifiers; } return prevModifiers.current; }, [modifiers]); (0, _react.useEffect)(() => { if (!popperInstanceRef.current || !enabled) return; popperInstanceRef.current.setOptions({ placement, strategy, modifiers: [...nextModifiers, updateModifier, disabledApplyStylesModifier] }); }, [strategy, placement, updateModifier, enabled, nextModifiers]); (0, _react.useEffect)(() => { if (!enabled || referenceElement == null || popperElement == null) { return undefined; } popperInstanceRef.current = (0, _popper.createPopper)(referenceElement, popperElement, Object.assign({}, config, { placement, strategy, modifiers: [...nextModifiers, ariaDescribedByModifier, updateModifier] })); return () => { if (popperInstanceRef.current != null) { popperInstanceRef.current.destroy(); popperInstanceRef.current = undefined; setState(s => Object.assign({}, s, { attributes: {}, styles: { popper: {} } })); } }; // This is only run once to _create_ the popper // eslint-disable-next-line react-hooks/exhaustive-deps }, [enabled, referenceElement, popperElement]); return popperState; } var _default = usePopper; exports.default = _default;