@coreui/react
Version:
UI Components Library for React.js
159 lines (156 loc) • 7.6 kB
JavaScript
import { __rest, __assign } from '../../node_modules/tslib/tslib.es6.js';
import React, { forwardRef, useRef, useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import classNames from '../../_virtual/index.js';
import { CDropdownContext } from './CDropdownContext.js';
import { useForkedRef } from '../../hooks/useForkedRef.js';
import { usePopper } from '../../hooks/usePopper.js';
import { placementPropType } from '../../props.js';
import getNextActiveElement from '../../utils/getNextActiveElement.js';
import isRTL from '../../utils/isRTL.js';
import { getPlacement } from './utils.js';
var CDropdown = forwardRef(function (_a, ref) {
var _b;
var children = _a.children, alignment = _a.alignment, _c = _a.as, as = _c === void 0 ? 'div' : _c, _d = _a.autoClose, autoClose = _d === void 0 ? true : _d, className = _a.className, container = _a.container, dark = _a.dark, direction = _a.direction, _e = _a.offset, offset = _e === void 0 ? [0, 2] : _e, onHide = _a.onHide, onShow = _a.onShow, _f = _a.placement, placement = _f === void 0 ? 'bottom-start' : _f, _g = _a.popper, popper = _g === void 0 ? true : _g, popperConfig = _a.popperConfig, _h = _a.portal, portal = _h === void 0 ? false : _h, _j = _a.variant, variant = _j === void 0 ? 'btn-group' : _j, _k = _a.visible, visible = _k === void 0 ? false : _k, rest = __rest(_a, ["children", "alignment", "as", "autoClose", "className", "container", "dark", "direction", "offset", "onHide", "onShow", "placement", "popper", "popperConfig", "portal", "variant", "visible"]);
var dropdownRef = useRef(null);
var dropdownToggleRef = useRef(null);
var dropdownMenuRef = useRef(null);
var forkedRef = useForkedRef(ref, dropdownRef);
var _l = useState(visible), _visible = _l[0], setVisible = _l[1];
var _m = usePopper(), initPopper = _m.initPopper, destroyPopper = _m.destroyPopper;
var Component = variant === 'nav-item' ? 'li' : as;
// Disable popper if responsive aligment is set.
if (typeof alignment === 'object') {
popper = false;
}
var contextValues = {
alignment: alignment,
container: container,
dark: dark,
dropdownToggleRef: dropdownToggleRef,
dropdownMenuRef: dropdownMenuRef,
popper: popper,
portal: portal,
variant: variant,
visible: _visible,
setVisible: setVisible,
};
var defaultPopperConfig = {
modifiers: [
{
name: 'offset',
options: {
offset: offset,
},
},
],
placement: getPlacement(placement, direction, alignment, isRTL(dropdownMenuRef.current)),
};
var computedPopperConfig = __assign(__assign({}, defaultPopperConfig), (typeof popperConfig === 'function' ? popperConfig(defaultPopperConfig) : popperConfig));
useEffect(function () {
setVisible(visible);
}, [visible]);
useEffect(function () {
var toggleElement = dropdownToggleRef.current;
var menuElement = dropdownMenuRef.current;
if (_visible && toggleElement && menuElement) {
if (popper) {
initPopper(toggleElement, menuElement, computedPopperConfig);
}
toggleElement.focus();
toggleElement.addEventListener('keydown', handleKeydown);
menuElement.addEventListener('keydown', handleKeydown);
window.addEventListener('mouseup', handleMouseUp);
window.addEventListener('keyup', handleKeyup);
onShow === null || onShow === void 0 ? void 0 : onShow();
}
return function () {
if (popper) {
destroyPopper();
}
toggleElement === null || toggleElement === void 0 ? void 0 : toggleElement.removeEventListener('keydown', handleKeydown);
menuElement === null || menuElement === void 0 ? void 0 : menuElement.removeEventListener('keydown', handleKeydown);
window.removeEventListener('mouseup', handleMouseUp);
window.removeEventListener('keyup', handleKeyup);
onHide === null || onHide === void 0 ? void 0 : onHide();
};
}, [
computedPopperConfig,
destroyPopper,
dropdownMenuRef,
dropdownToggleRef,
initPopper,
_visible,
]);
var handleKeydown = function (event) {
if (_visible &&
dropdownMenuRef.current &&
(event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
event.preventDefault();
var target = event.target;
var items = Array.from(dropdownMenuRef.current.querySelectorAll('.dropdown-item:not(.disabled):not(:disabled)'));
getNextActiveElement(items, target, event.key === 'ArrowDown', true).focus();
}
};
var handleKeyup = function (event) {
if (autoClose === false) {
return;
}
if (event.key === 'Escape') {
setVisible(false);
}
};
var handleMouseUp = function (event) {
if (!dropdownToggleRef.current || !dropdownMenuRef.current) {
return;
}
if (dropdownToggleRef.current.contains(event.target)) {
return;
}
if (autoClose === true ||
(autoClose === 'inside' && dropdownMenuRef.current.contains(event.target)) ||
(autoClose === 'outside' && !dropdownMenuRef.current.contains(event.target))) {
setTimeout(function () { return setVisible(false); }, 1);
return;
}
};
return (React.createElement(CDropdownContext.Provider, { value: contextValues }, variant === 'input-group' ? (React.createElement(React.Fragment, null, children)) : (React.createElement(Component, __assign({ className: classNames(variant === 'nav-item' ? 'nav-item dropdown' : variant, (_b = {
'dropdown-center': direction === 'center',
'dropup dropup-center': direction === 'dropup-center'
},
_b["".concat(direction)] = direction && direction !== 'center' && direction !== 'dropup-center',
_b), className) }, rest, { ref: forkedRef }), children))));
});
var alignmentDirection = PropTypes.oneOf(['start', 'end']);
CDropdown.propTypes = {
alignment: PropTypes.oneOfType([
alignmentDirection,
PropTypes.shape({ xs: alignmentDirection.isRequired }),
PropTypes.shape({ sm: alignmentDirection.isRequired }),
PropTypes.shape({ md: alignmentDirection.isRequired }),
PropTypes.shape({ lg: alignmentDirection.isRequired }),
PropTypes.shape({ xl: alignmentDirection.isRequired }),
PropTypes.shape({ xxl: alignmentDirection.isRequired }),
]),
as: PropTypes.elementType,
autoClose: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.oneOf(['inside', 'outside']),
]),
children: PropTypes.node,
className: PropTypes.string,
dark: PropTypes.bool,
direction: PropTypes.oneOf(['center', 'dropup', 'dropup-center', 'dropend', 'dropstart']),
offset: PropTypes.any, // TODO: find good proptype
onHide: PropTypes.func,
onShow: PropTypes.func,
placement: placementPropType,
popper: PropTypes.bool,
popperConfig: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
portal: PropTypes.bool,
variant: PropTypes.oneOf(['btn-group', 'dropdown', 'input-group', 'nav-item']),
visible: PropTypes.bool,
};
CDropdown.displayName = 'CDropdown';
export { CDropdown };
//# sourceMappingURL=CDropdown.js.map