suomifi-ui-components
Version:
Suomi.fi UI component library
146 lines (143 loc) • 5.32 kB
JavaScript
import { __rest, __spreadArray, __assign } from 'tslib';
import React, { useState, useRef, useEffect, useLayoutEffect, useMemo } from 'react';
import ReactDOM from 'react-dom';
import { useEnhancedEffect } from '../../utils/common/common.js';
import { HtmlDivWithRef } from '../../reset/HtmlDiv/HtmlDiv.js';
import { useFloating, flip, shift, size, autoUpdate } from '@floating-ui/react-dom';
import classnames from 'classnames';
var defaultProviderValue = {
updatePopover: function updatePopover() {
return null;
},
popoverPlacement: 'bottom'
};
var _a = /*#__PURE__*/React.createContext(defaultProviderValue),
PopoverProvider = _a.Provider,
PopoverConsumer = _a.Consumer;
var Popover = function Popover(props) {
var _a = props.placement,
placement = _a === void 0 ? 'bottom' : _a,
_b = props.allowFlip,
allowFlip = _b === void 0 ? true : _b,
_c = props.matchWidth,
matchWidth = _c === void 0 ? true : _c,
children = props.children,
sourceRef = props.sourceRef,
onClickOutside = props.onClickOutside,
_d = props.portal,
portal = _d === void 0 ? true : _d,
className = props.className,
passProps = __rest(props, ["placement", "allowFlip", "matchWidth", "children", "sourceRef", "onClickOutside", "portal", "className"]);
var _e = useState(null),
floatingElement = _e[0],
setFloatingElement = _e[1];
var _f = useState(null),
mountNode = _f[0],
setMountNode = _f[1];
var _g = useState(false),
isPositioned = _g[0],
setIsPositioned = _g[1];
var portalRef = useRef(null);
var _h = useFloating({
open: true,
middleware: __spreadArray(__spreadArray(__spreadArray([], allowFlip ? [flip()] : [], true), [shift()], false), matchWidth ? [size({
apply: function apply(_a) {
var rects = _a.rects,
elements = _a.elements;
var floatingEl = elements.floating;
floatingEl.style.width = "".concat(rects.reference.width, "px");
}
})] : [], true),
whileElementsMounted: autoUpdate,
placement: placement
}),
floatingUiRefs = _h.refs,
floatingStyles = _h.floatingStyles,
resolvedPlacement = _h.placement,
update = _h.update;
useEffect(function () {
if (sourceRef.current) {
floatingUiRefs.setReference(sourceRef.current);
}
}, [floatingUiRefs, sourceRef]);
useEffect(function () {
if (floatingElement) {
floatingUiRefs.setFloating(floatingElement);
}
}, [floatingUiRefs, floatingElement]);
useLayoutEffect(function () {
if (floatingElement && floatingStyles.position) {
requestAnimationFrame(function () {
requestAnimationFrame(function () {
setIsPositioned(true);
});
});
}
}, [floatingElement, floatingStyles.position]);
var _j = useState(placement),
consumerPlacement = _j[0],
setConsumerPlacement = _j[1];
useEffect(function () {
setConsumerPlacement(resolvedPlacement);
}, [resolvedPlacement]);
var providerValue = useMemo(function () {
return {
updatePopover: function updatePopover() {
return update === null || update === void 0 ? void 0 : update();
},
popoverPlacement: consumerPlacement || placement
};
}, [update, consumerPlacement, placement]);
useEffect(function () {
var globalClickHandler = function globalClickHandler(nativeEvent) {
var _a, _b;
if (!((_a = portalRef.current) === null || _a === void 0 ? void 0 : _a.contains(nativeEvent.target)) && !((_b = sourceRef === null || sourceRef === void 0 ? void 0 : sourceRef.current) === null || _b === void 0 ? void 0 : _b.contains(nativeEvent.target)) && !!onClickOutside) {
onClickOutside(nativeEvent);
}
};
document.addEventListener('click', globalClickHandler, {
capture: true
});
return function () {
document.removeEventListener('click', globalClickHandler, {
capture: true
});
};
}, [onClickOutside, sourceRef]);
useEnhancedEffect(function () {
setMountNode(window.document.body);
});
if (portal && !mountNode) {
return null;
}
if (portal && mountNode) {
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/React.createElement("div", {
className: classnames('fi-portal', className),
ref: setFloatingElement,
style: __assign(__assign({}, floatingStyles), {
visibility: isPositioned ? 'visible' : 'hidden'
}),
tabIndex: -1,
role: "presentation"
}, /*#__PURE__*/React.createElement(HtmlDivWithRef, __assign({
forwardedRef: portalRef
}, passProps), /*#__PURE__*/React.createElement(PopoverProvider, {
value: providerValue
}, children))), mountNode));
}
return /*#__PURE__*/React.createElement("div", {
className: className,
ref: setFloatingElement,
style: __assign(__assign({}, floatingStyles), {
visibility: isPositioned ? 'visible' : 'hidden'
}),
tabIndex: -1,
role: "presentation"
}, /*#__PURE__*/React.createElement(HtmlDivWithRef, __assign({
forwardedRef: portalRef
}, passProps), /*#__PURE__*/React.createElement(PopoverProvider, {
value: providerValue
}, children)));
};
export { Popover, PopoverConsumer };
//# sourceMappingURL=Popover.js.map