123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637 |
- 'use strict';
- Object.defineProperty(exports, '__esModule', { value: true });
- function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
- var React = require('react');
- var React__default = _interopDefault(React);
- var ReactDOM = _interopDefault(require('react-dom'));
- function _extends() {
- _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;
- };
- return _extends.apply(this, arguments);
- }
- var useOnEscape = function useOnEscape(handler, active) {
- if (active === void 0) {
- active = true;
- }
- React.useEffect(function () {
- if (!active) return;
- var listener = function listener(event) {
- // check if key is an Escape
- if (event.key === 'Escape') handler(event);
- };
- document.addEventListener('keyup', listener);
- return function () {
- if (!active) return;
- document.removeEventListener('keyup', listener);
- };
- }, [handler, active]);
- };
- var useRepositionOnResize = function useRepositionOnResize(handler, active) {
- if (active === void 0) {
- active = true;
- }
- React.useEffect(function () {
- if (!active) return;
- var listener = function listener() {
- handler();
- };
- window.addEventListener('resize', listener);
- return function () {
- if (!active) return;
- window.removeEventListener('resize', listener);
- };
- }, [handler, active]);
- };
- var useOnClickOutside = function useOnClickOutside(ref, handler, active) {
- if (active === void 0) {
- active = true;
- }
- React.useEffect(function () {
- if (!active) return;
- var listener = function listener(event) {
- // Do nothing if clicking ref's element or descendent elements
- var refs = Array.isArray(ref) ? ref : [ref];
- var contains = false;
- refs.forEach(function (r) {
- if (!r.current || r.current.contains(event.target)) {
- contains = true;
- return;
- }
- });
- event.stopPropagation();
- if (!contains) handler(event);
- };
- document.addEventListener('mousedown', listener);
- document.addEventListener('touchstart', listener);
- return function () {
- if (!active) return;
- document.removeEventListener('mousedown', listener);
- document.removeEventListener('touchstart', listener);
- };
- }, [ref, handler, active]);
- }; // Make sure that user is not able TAB out of the Modal content on Open
- var useTabbing = function useTabbing(contentRef, active) {
- if (active === void 0) {
- active = true;
- }
- React.useEffect(function () {
- if (!active) return;
- var listener = function listener(event) {
- // check if key is an Tab
- if (event.keyCode === 9) {
- var _contentRef$current;
- var els = contentRef === null || contentRef === void 0 ? void 0 : (_contentRef$current = contentRef.current) === null || _contentRef$current === void 0 ? void 0 : _contentRef$current.querySelectorAll('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex="0"]');
- var focusableEls = Array.prototype.slice.call(els);
- if (focusableEls.length === 1) {
- event.preventDefault();
- return;
- }
- var firstFocusableEl = focusableEls[0];
- var lastFocusableEl = focusableEls[focusableEls.length - 1];
- if (event.shiftKey && document.activeElement === firstFocusableEl) {
- event.preventDefault();
- lastFocusableEl.focus();
- } else if (document.activeElement === lastFocusableEl) {
- event.preventDefault();
- firstFocusableEl.focus();
- }
- }
- };
- document.addEventListener('keydown', listener);
- return function () {
- if (!active) return;
- document.removeEventListener('keydown', listener);
- };
- }, [contentRef, active]);
- };
- var useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
- var Style = {
- popupContent: {
- tooltip: {
- position: 'absolute',
- zIndex: 999
- },
- modal: {
- position: 'relative',
- margin: 'auto'
- }
- },
- popupArrow: {
- height: '8px',
- width: '16px',
- position: 'absolute',
- background: 'transparent',
- color: '#FFF',
- zIndex: -1
- },
- overlay: {
- tooltip: {
- position: 'fixed',
- top: '0',
- bottom: '0',
- left: '0',
- right: '0',
- zIndex: 999
- },
- modal: {
- position: 'fixed',
- top: '0',
- bottom: '0',
- left: '0',
- right: '0',
- display: 'flex',
- zIndex: 999
- }
- }
- };
- var POSITION_TYPES = ['top left', 'top center', 'top right', 'right top', 'right center', 'right bottom', 'bottom left', 'bottom center', 'bottom right', 'left top', 'left center', 'left bottom'];
- var getCoordinatesForPosition = function getCoordinatesForPosition(triggerBounding, ContentBounding, position, //PopupPosition | PopupPosition[],
- arrow, _ref) {
- var offsetX = _ref.offsetX,
- offsetY = _ref.offsetY;
- var margin = arrow ? 8 : 0;
- var args = position.split(' '); // the step N 1 : center the popup content => ok
- var CenterTop = triggerBounding.top + triggerBounding.height / 2;
- var CenterLeft = triggerBounding.left + triggerBounding.width / 2;
- var height = ContentBounding.height,
- width = ContentBounding.width;
- var top = CenterTop - height / 2;
- var left = CenterLeft - width / 2;
- var transform = '';
- var arrowTop = '0%';
- var arrowLeft = '0%'; // the step N 2 : => ok
- switch (args[0]) {
- case 'top':
- top -= height / 2 + triggerBounding.height / 2 + margin;
- transform = "rotate(180deg) translateX(50%)";
- arrowTop = '100%';
- arrowLeft = '50%';
- break;
- case 'bottom':
- top += height / 2 + triggerBounding.height / 2 + margin;
- transform = "rotate(0deg) translateY(-100%) translateX(-50%)";
- arrowLeft = '50%';
- break;
- case 'left':
- left -= width / 2 + triggerBounding.width / 2 + margin;
- transform = " rotate(90deg) translateY(50%) translateX(-25%)";
- arrowLeft = '100%';
- arrowTop = '50%';
- break;
- case 'right':
- left += width / 2 + triggerBounding.width / 2 + margin;
- transform = "rotate(-90deg) translateY(-150%) translateX(25%)";
- arrowTop = '50%';
- break;
- }
- switch (args[1]) {
- case 'top':
- top = triggerBounding.top;
- arrowTop = triggerBounding.height / 2 + "px";
- break;
- case 'bottom':
- top = triggerBounding.top - height + triggerBounding.height;
- arrowTop = height - triggerBounding.height / 2 + "px";
- break;
- case 'left':
- left = triggerBounding.left;
- arrowLeft = triggerBounding.width / 2 + "px";
- break;
- case 'right':
- left = triggerBounding.left - width + triggerBounding.width;
- arrowLeft = width - triggerBounding.width / 2 + "px";
- break;
- }
- top = args[0] === 'top' ? top - offsetY : top + offsetY;
- left = args[0] === 'left' ? left - offsetX : left + offsetX;
- return {
- top: top,
- left: left,
- transform: transform,
- arrowLeft: arrowLeft,
- arrowTop: arrowTop
- };
- };
- var getTooltipBoundary = function getTooltipBoundary(keepTooltipInside) {
- // add viewport
- var boundingBox = {
- top: 0,
- left: 0,
- /* eslint-disable-next-line no-undef */
- width: window.innerWidth,
- /* eslint-disable-next-line no-undef */
- height: window.innerHeight
- };
- if (typeof keepTooltipInside === 'string') {
- /* eslint-disable-next-line no-undef */
- var selector = document.querySelector(keepTooltipInside);
- {
- if (selector === null) throw new Error(keepTooltipInside + " selector does not exist : keepTooltipInside must be a valid html selector 'class' or 'Id' or a boolean value");
- }
- if (selector !== null) boundingBox = selector.getBoundingClientRect();
- }
- return boundingBox;
- };
- var calculatePosition = function calculatePosition(triggerBounding, ContentBounding, position, arrow, _ref2, keepTooltipInside) {
- var offsetX = _ref2.offsetX,
- offsetY = _ref2.offsetY;
- var bestCoords = {
- arrowLeft: '0%',
- arrowTop: '0%',
- left: 0,
- top: 0,
- transform: 'rotate(135deg)'
- };
- var i = 0;
- var wrapperBox = getTooltipBoundary(keepTooltipInside);
- var positions = Array.isArray(position) ? position : [position]; // keepTooltipInside would be activated if the keepTooltipInside exist or the position is Array
- if (keepTooltipInside || Array.isArray(position)) positions = [].concat(positions, POSITION_TYPES); // add viewPort for WarpperBox
- // wrapperBox.top = wrapperBox.top + window.scrollY;
- // wrapperBox.left = wrapperBox.left + window.scrollX;
- while (i < positions.length) {
- bestCoords = getCoordinatesForPosition(triggerBounding, ContentBounding, positions[i], arrow, {
- offsetX: offsetX,
- offsetY: offsetY
- });
- var contentBox = {
- top: bestCoords.top,
- left: bestCoords.left,
- width: ContentBounding.width,
- height: ContentBounding.height
- };
- if (contentBox.top <= wrapperBox.top || contentBox.left <= wrapperBox.left || contentBox.top + contentBox.height >= wrapperBox.top + wrapperBox.height || contentBox.left + contentBox.width >= wrapperBox.left + wrapperBox.width) {
- i++;
- } else {
- break;
- }
- }
- return bestCoords;
- };
- var popupIdCounter = 0;
- var getRootPopup = function getRootPopup() {
- var PopupRoot = document.getElementById('popup-root');
- if (PopupRoot === null) {
- PopupRoot = document.createElement('div');
- PopupRoot.setAttribute('id', 'popup-root');
- document.body.appendChild(PopupRoot);
- }
- return PopupRoot;
- };
- var Popup = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
- var _ref$trigger = _ref.trigger,
- trigger = _ref$trigger === void 0 ? null : _ref$trigger,
- _ref$onOpen = _ref.onOpen,
- onOpen = _ref$onOpen === void 0 ? function () {} : _ref$onOpen,
- _ref$onClose = _ref.onClose,
- onClose = _ref$onClose === void 0 ? function () {} : _ref$onClose,
- _ref$defaultOpen = _ref.defaultOpen,
- defaultOpen = _ref$defaultOpen === void 0 ? false : _ref$defaultOpen,
- _ref$open = _ref.open,
- open = _ref$open === void 0 ? undefined : _ref$open,
- _ref$disabled = _ref.disabled,
- disabled = _ref$disabled === void 0 ? false : _ref$disabled,
- _ref$nested = _ref.nested,
- nested = _ref$nested === void 0 ? false : _ref$nested,
- _ref$closeOnDocumentC = _ref.closeOnDocumentClick,
- closeOnDocumentClick = _ref$closeOnDocumentC === void 0 ? true : _ref$closeOnDocumentC,
- _ref$repositionOnResi = _ref.repositionOnResize,
- repositionOnResize = _ref$repositionOnResi === void 0 ? true : _ref$repositionOnResi,
- _ref$closeOnEscape = _ref.closeOnEscape,
- closeOnEscape = _ref$closeOnEscape === void 0 ? true : _ref$closeOnEscape,
- _ref$on = _ref.on,
- on = _ref$on === void 0 ? ['click'] : _ref$on,
- _ref$contentStyle = _ref.contentStyle,
- contentStyle = _ref$contentStyle === void 0 ? {} : _ref$contentStyle,
- _ref$arrowStyle = _ref.arrowStyle,
- arrowStyle = _ref$arrowStyle === void 0 ? {} : _ref$arrowStyle,
- _ref$overlayStyle = _ref.overlayStyle,
- overlayStyle = _ref$overlayStyle === void 0 ? {} : _ref$overlayStyle,
- _ref$className = _ref.className,
- className = _ref$className === void 0 ? '' : _ref$className,
- _ref$position = _ref.position,
- position = _ref$position === void 0 ? 'bottom center' : _ref$position,
- _ref$modal = _ref.modal,
- modal = _ref$modal === void 0 ? false : _ref$modal,
- _ref$lockScroll = _ref.lockScroll,
- lockScroll = _ref$lockScroll === void 0 ? false : _ref$lockScroll,
- _ref$arrow = _ref.arrow,
- arrow = _ref$arrow === void 0 ? true : _ref$arrow,
- _ref$offsetX = _ref.offsetX,
- offsetX = _ref$offsetX === void 0 ? 0 : _ref$offsetX,
- _ref$offsetY = _ref.offsetY,
- offsetY = _ref$offsetY === void 0 ? 0 : _ref$offsetY,
- _ref$mouseEnterDelay = _ref.mouseEnterDelay,
- mouseEnterDelay = _ref$mouseEnterDelay === void 0 ? 100 : _ref$mouseEnterDelay,
- _ref$mouseLeaveDelay = _ref.mouseLeaveDelay,
- mouseLeaveDelay = _ref$mouseLeaveDelay === void 0 ? 100 : _ref$mouseLeaveDelay,
- _ref$keepTooltipInsid = _ref.keepTooltipInside,
- keepTooltipInside = _ref$keepTooltipInsid === void 0 ? false : _ref$keepTooltipInsid,
- children = _ref.children;
- var _useState = React.useState(open || defaultOpen),
- isOpen = _useState[0],
- setIsOpen = _useState[1];
- var triggerRef = React.useRef(null);
- var contentRef = React.useRef(null);
- var arrowRef = React.useRef(null);
- var focusedElBeforeOpen = React.useRef(null);
- var popupId = React.useRef("popup-" + ++popupIdCounter);
- var isModal = modal ? true : !trigger;
- var timeOut = React.useRef(0);
- useIsomorphicLayoutEffect(function () {
- if (isOpen) {
- focusedElBeforeOpen.current = document.activeElement;
- setPosition();
- focusContentOnOpen(); // for accessibility
- lockScrolll();
- } else {
- resetScroll();
- }
- return function () {
- clearTimeout(timeOut.current);
- };
- }, [isOpen]); // for uncontrolled popup we need to sync isOpen with open prop
- React.useEffect(function () {
- if (typeof open === 'boolean') {
- if (open) openPopup();else closePopup();
- }
- }, [open, disabled]);
- var openPopup = function openPopup(event) {
- if (isOpen || disabled) return;
- setIsOpen(true);
- setTimeout(function () {
- return onOpen(event);
- }, 0);
- };
- var closePopup = function closePopup(event) {
- var _focusedElBeforeOpen$;
- if (!isOpen || disabled) return;
- setIsOpen(false);
- if (isModal) (_focusedElBeforeOpen$ = focusedElBeforeOpen.current) === null || _focusedElBeforeOpen$ === void 0 ? void 0 : _focusedElBeforeOpen$.focus();
- setTimeout(function () {
- return onClose(event);
- }, 0);
- };
- var togglePopup = function togglePopup(event) {
- event === null || event === void 0 ? void 0 : event.stopPropagation();
- if (!isOpen) openPopup(event);else closePopup(event);
- };
- var onMouseEnter = function onMouseEnter(event) {
- clearTimeout(timeOut.current);
- timeOut.current = setTimeout(function () {
- return openPopup(event);
- }, mouseEnterDelay);
- };
- var onContextMenu = function onContextMenu(event) {
- event === null || event === void 0 ? void 0 : event.preventDefault();
- togglePopup();
- };
- var onMouseLeave = function onMouseLeave(event) {
- clearTimeout(timeOut.current);
- timeOut.current = setTimeout(function () {
- return closePopup(event);
- }, mouseLeaveDelay);
- };
- var lockScrolll = function lockScrolll() {
- if (isModal && lockScroll) document.getElementsByTagName('body')[0].style.overflow = 'hidden'; // migrate to document.body
- };
- var resetScroll = function resetScroll() {
- if (isModal && lockScroll) document.getElementsByTagName('body')[0].style.overflow = 'auto';
- };
- var focusContentOnOpen = function focusContentOnOpen() {
- var _contentRef$current;
- var focusableEls = contentRef === null || contentRef === void 0 ? void 0 : (_contentRef$current = contentRef.current) === null || _contentRef$current === void 0 ? void 0 : _contentRef$current.querySelectorAll('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex="0"]');
- var firstEl = Array.prototype.slice.call(focusableEls)[0];
- firstEl === null || firstEl === void 0 ? void 0 : firstEl.focus();
- };
- React.useImperativeHandle(ref, function () {
- return {
- open: function open() {
- openPopup();
- },
- close: function close() {
- closePopup();
- },
- toggle: function toggle() {
- togglePopup();
- }
- };
- }); // set Position
- var setPosition = function setPosition() {
- if (isModal || !isOpen) return;
- if (!(triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.current) || !(triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.current) || !(contentRef === null || contentRef === void 0 ? void 0 : contentRef.current)) return; /// show error as one of ref is undefined
- var trigger = triggerRef.current.getBoundingClientRect();
- var content = contentRef.current.getBoundingClientRect();
- var cords = calculatePosition(trigger, content, position, arrow, {
- offsetX: offsetX,
- offsetY: offsetY
- }, keepTooltipInside);
- contentRef.current.style.top = cords.top + window.scrollY + "px";
- contentRef.current.style.left = cords.left + window.scrollX + "px";
- if (arrow && !!arrowRef.current) {
- var _arrowStyle$top, _arrowStyle$left;
- arrowRef.current.style.transform = cords.transform;
- arrowRef.current.style.setProperty('-ms-transform', cords.transform);
- arrowRef.current.style.setProperty('-webkit-transform', cords.transform);
- arrowRef.current.style.top = ((_arrowStyle$top = arrowStyle.top) === null || _arrowStyle$top === void 0 ? void 0 : _arrowStyle$top.toString()) || cords.arrowTop;
- arrowRef.current.style.left = ((_arrowStyle$left = arrowStyle.left) === null || _arrowStyle$left === void 0 ? void 0 : _arrowStyle$left.toString()) || cords.arrowLeft;
- }
- }; // hooks
- useOnEscape(closePopup, closeOnEscape); // can be optimized if we disabled for hover
- useTabbing(contentRef, isOpen && isModal);
- useRepositionOnResize(setPosition, repositionOnResize);
- useOnClickOutside(!!trigger ? [contentRef, triggerRef] : [contentRef], closePopup, closeOnDocumentClick && !nested); // we need to add a ne
- // render the trigger element and add events
- var renderTrigger = function renderTrigger() {
- var triggerProps = {
- key: 'T',
- ref: triggerRef,
- 'aria-describedby': popupId.current
- };
- var onAsArray = Array.isArray(on) ? on : [on];
- for (var i = 0, len = onAsArray.length; i < len; i++) {
- switch (onAsArray[i]) {
- case 'click':
- triggerProps.onClick = togglePopup;
- break;
- case 'right-click':
- triggerProps.onContextMenu = onContextMenu;
- break;
- case 'hover':
- triggerProps.onMouseEnter = onMouseEnter;
- triggerProps.onMouseLeave = onMouseLeave;
- break;
- case 'focus':
- triggerProps.onFocus = onMouseEnter;
- triggerProps.onBlur = onMouseLeave;
- break;
- }
- }
- if (typeof trigger === 'function') {
- var comp = trigger(isOpen);
- return !!trigger && React__default.cloneElement(comp, triggerProps);
- }
- return !!trigger && React__default.cloneElement(trigger, triggerProps);
- };
- var addWarperAction = function addWarperAction() {
- var popupContentStyle = isModal ? Style.popupContent.modal : Style.popupContent.tooltip;
- var childrenElementProps = {
- className: "popup-content " + (className !== '' ? className.split(' ').map(function (c) {
- return c + "-content";
- }).join(' ') : ''),
- style: _extends({}, popupContentStyle, contentStyle, {
- pointerEvents: 'auto'
- }),
- ref: contentRef,
- onClick: function onClick(e) {
- e.stopPropagation();
- }
- };
- if (!modal && on.indexOf('hover') >= 0) {
- childrenElementProps.onMouseEnter = onMouseEnter;
- childrenElementProps.onMouseLeave = onMouseLeave;
- }
- return childrenElementProps;
- };
- var renderContent = function renderContent() {
- return React__default.createElement("div", Object.assign({}, addWarperAction(), {
- key: "C",
- role: isModal ? 'dialog' : 'tooltip',
- id: popupId.current
- }), arrow && !isModal && React__default.createElement("div", {
- ref: arrowRef,
- style: Style.popupArrow
- }, React__default.createElement("svg", {
- "data-testid": "arrow",
- className: "popup-arrow " + (className !== '' ? className.split(' ').map(function (c) {
- return c + "-arrow";
- }).join(' ') : ''),
- viewBox: "0 0 32 16",
- style: _extends({
- position: 'absolute'
- }, arrowStyle)
- }, React__default.createElement("path", {
- d: "M16 0l16 16H0z",
- fill: "currentcolor"
- }))), children && typeof children === 'function' ? children(closePopup, isOpen) : children);
- };
- var overlay = !(on.indexOf('hover') >= 0);
- var ovStyle = isModal ? Style.overlay.modal : Style.overlay.tooltip;
- var content = [overlay && React__default.createElement("div", {
- key: "O",
- "data-testid": "overlay",
- "data-popup": isModal ? 'modal' : 'tooltip',
- className: "popup-overlay " + (className !== '' ? className.split(' ').map(function (c) {
- return c + "-overlay";
- }).join(' ') : ''),
- style: _extends({}, ovStyle, overlayStyle, {
- pointerEvents: closeOnDocumentClick && nested || isModal ? 'auto' : 'none'
- }),
- onClick: closeOnDocumentClick && nested ? closePopup : undefined,
- tabIndex: -1
- }, isModal && renderContent()), !isModal && renderContent()];
- return React__default.createElement(React__default.Fragment, null, renderTrigger(), isOpen && ReactDOM.createPortal(content, getRootPopup()));
- });
- exports.Popup = Popup;
- exports.default = Popup;
- //# sourceMappingURL=reactjs-popup.cjs.development.js.map
|