123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- "use strict";
-
- exports.__esModule = true;
- exports.default = void 0;
-
- var _matches = _interopRequireDefault(require("dom-helpers/query/matches"));
-
- var _querySelectorAll = _interopRequireDefault(require("dom-helpers/query/querySelectorAll"));
-
- var _react = _interopRequireDefault(require("react"));
-
- var _reactDom = _interopRequireDefault(require("react-dom"));
-
- var _propTypes = _interopRequireDefault(require("prop-types"));
-
- var _uncontrollable = _interopRequireDefault(require("uncontrollable"));
-
- var Popper = _interopRequireWildcard(require("react-popper"));
-
- var _DropdownContext = _interopRequireDefault(require("./DropdownContext"));
-
- var _DropdownMenu = _interopRequireDefault(require("./DropdownMenu"));
-
- var _DropdownToggle = _interopRequireDefault(require("./DropdownToggle"));
-
- function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
-
- 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; }
-
- 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); }
-
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
-
- var propTypes = {
- /**
- * A render prop that returns the root dropdown element. The `props`
- * argument should spread through to an element containing _both_ the
- * menu and toggle in order to handle keyboard events for focus management.
- *
- * @type {Function ({
- * props: {
- * onKeyDown: (SyntheticEvent) => void,
- * },
- * }) => React.Element}
- */
- children: _propTypes.default.func.isRequired,
-
- /**
- * Determines the direction and location of the Menu in relation to it's Toggle.
- */
- drop: _propTypes.default.oneOf(['up', 'left', 'right', 'down']),
-
- /**
- * Controls the focus behavior for when the Dropdown is opened. Set to
- * `true` to always focus the first menu item, `keyboard` to focus only when
- * navigating via the keyboard, or `false` to disable completely
- *
- * The Default behavior is `false` **unless** the Menu has a `role="menu"`
- * where it will default to `keyboard` to match the recommended [ARIA Authoring practices](https://www.w3.org/TR/wai-aria-practices-1.1/#menubutton).
- */
- focusFirstItemOnShow: _propTypes.default.oneOf([false, true, 'keyboard']),
-
- /**
- * A css slector string that will return __focusable__ menu items.
- * Selectors should be relative to the menu component:
- * e.g. ` > li:not('.disabled')`
- */
- itemSelector: _propTypes.default.string.isRequired,
-
- /**
- * Align the menu to the 'end' side of the placement side of the Dropdown toggle. The default placement is `top-start` or `bottom-start`.
- */
- alignEnd: _propTypes.default.bool,
-
- /**
- * Whether or not the Dropdown is visible.
- *
- * @controllable onToggle
- */
- show: _propTypes.default.bool,
-
- /**
- * A callback fired when the Dropdown wishes to change visibility. Called with the requested
- * `show` value, the DOM event, and the source that fired it: `'click'`,`'keydown'`,`'rootClose'`, or `'select'`.
- *
- * ```js
- * function(
- * isOpen: boolean,
- * event: SyntheticEvent,
- * ): void
- * ```
- *
- * @controllable show
- */
- onToggle: _propTypes.default.func
- };
- var defaultProps = {
- itemSelector: '* > *'
- };
- /**
- * `Dropdown` is set of structural components for building, accessible dropdown menus with close-on-click,
- * keyboard navigation, and correct focus handling. As with all the react-overlay's
- * components its BYOS (bring your own styles). Dropdown is primarily
- * built from three base components, you should compose to build your Dropdowns.
- *
- * - `Dropdown`, which wraps the menu and toggle, and handles keyboard navigation
- * - `Dropdown.Toggle` generally a button that triggers the menu opening
- * - `Dropdown.Menu` The overlaid, menu, positioned to the toggle with PopperJs
- */
-
- var Dropdown =
- /*#__PURE__*/
- function (_React$Component) {
- _inheritsLoose(Dropdown, _React$Component);
-
- Dropdown.getDerivedStateFromProps = function getDerivedStateFromProps(_ref, prevState) {
- var drop = _ref.drop,
- alignEnd = _ref.alignEnd,
- show = _ref.show;
- var lastShow = prevState.context.show;
- return {
- lastShow: lastShow,
- context: _extends({}, prevState.context, {
- drop: drop,
- show: show,
- alignEnd: alignEnd
- })
- };
- };
-
- function Dropdown(props, context) {
- var _this;
-
- _this = _React$Component.call(this, props, context) || this;
-
- _this.handleClick = function (event) {
- _this.toggleOpen(event);
- };
-
- _this.handleKeyDown = function (event) {
- var key = event.key,
- target = event.target; // Second only to https://github.com/twbs/bootstrap/blob/8cfbf6933b8a0146ac3fbc369f19e520bd1ebdac/js/src/dropdown.js#L400
- // in inscrutability
-
- var isInput = /input|textarea/i.test(target.tagName);
-
- if (isInput && (key === ' ' || key !== 'Escape' && _this.menu.contains(target))) {
- return;
- }
-
- _this._lastSourceEvent = event.type;
-
- switch (key) {
- case 'ArrowUp':
- {
- var next = _this.getNextFocusedChild(target, -1);
-
- if (next && next.focus) next.focus();
- event.preventDefault();
- return;
- }
-
- case 'ArrowDown':
- event.preventDefault();
-
- if (!_this.props.show) {
- _this.toggleOpen(event);
- } else {
- var _next = _this.getNextFocusedChild(target, 1);
-
- if (_next && _next.focus) _next.focus();
- }
-
- return;
-
- case 'Escape':
- case 'Tab':
- _this.props.onToggle(false, event);
-
- break;
-
- default:
- }
- };
-
- _this._focusInDropdown = false;
- _this.menu = null;
- _this.state = {
- context: {
- close: _this.handleClose,
- toggle: _this.handleClick,
- menuRef: function menuRef(r) {
- _this.menu = r;
- },
- toggleRef: function toggleRef(r) {
- var toggleNode = r && _reactDom.default.findDOMNode(r);
-
- _this.setState(function (_ref2) {
- var context = _ref2.context;
- return {
- context: _extends({}, context, {
- toggleNode: toggleNode
- })
- };
- });
- }
- }
- };
- return _this;
- }
-
- var _proto = Dropdown.prototype;
-
- _proto.componentDidUpdate = function componentDidUpdate(prevProps) {
- var show = this.props.show;
- var prevOpen = prevProps.show;
-
- if (show && !prevOpen) {
- this.maybeFocusFirst();
- }
-
- this._lastSourceEvent = null;
-
- if (!show && prevOpen) {
- // if focus hasn't already moved from the menu let's return it
- // to the toggle
- if (this._focusInDropdown) {
- this._focusInDropdown = false;
- this.focus();
- }
- }
- };
-
- _proto.getNextFocusedChild = function getNextFocusedChild(current, offset) {
- if (!this.menu) return null;
- var itemSelector = this.props.itemSelector;
- var items = (0, _querySelectorAll.default)(this.menu, itemSelector);
- var index = items.indexOf(current) + offset;
- index = Math.max(0, Math.min(index, items.length));
- return items[index];
- };
-
- _proto.hasMenuRole = function hasMenuRole() {
- return this.menu && (0, _matches.default)(this.menu, '[role=menu]');
- };
-
- _proto.focus = function focus() {
- var toggleNode = this.state.context.toggleNode;
-
- if (toggleNode && toggleNode.focus) {
- toggleNode.focus();
- }
- };
-
- _proto.maybeFocusFirst = function maybeFocusFirst() {
- var type = this._lastSourceEvent;
- var focusFirstItemOnShow = this.props.focusFirstItemOnShow;
-
- if (focusFirstItemOnShow == null) {
- focusFirstItemOnShow = this.hasMenuRole() ? 'keyboard' : false;
- }
-
- if (focusFirstItemOnShow === false || focusFirstItemOnShow === 'keyboard' && !/^key.+$/.test(type)) {
- return;
- }
-
- var itemSelector = this.props.itemSelector;
- var first = (0, _querySelectorAll.default)(this.menu, itemSelector)[0];
- if (first && first.focus) first.focus();
- };
-
- _proto.toggleOpen = function toggleOpen(event) {
- var show = !this.props.show;
- this.props.onToggle(show, event);
- };
-
- _proto.render = function render() {
- var _this$props = this.props,
- children = _this$props.children,
- props = _objectWithoutPropertiesLoose(_this$props, ["children"]);
-
- delete props.onToggle;
-
- if (this.menu && this.state.lastShow && !this.props.show) {
- this._focusInDropdown = this.menu.contains(document.activeElement);
- }
-
- return _react.default.createElement(_DropdownContext.default.Provider, {
- value: this.state.context
- }, _react.default.createElement(Popper.Manager, null, children({
- props: {
- onKeyDown: this.handleKeyDown
- }
- })));
- };
-
- return Dropdown;
- }(_react.default.Component);
-
- Dropdown.displayName = 'ReactOverlaysDropdown';
- Dropdown.propTypes = propTypes;
- Dropdown.defaultProps = defaultProps;
- var UncontrolledDropdown = (0, _uncontrollable.default)(Dropdown, {
- show: 'onToggle'
- });
- UncontrolledDropdown.Menu = _DropdownMenu.default;
- UncontrolledDropdown.Toggle = _DropdownToggle.default;
- var _default = UncontrolledDropdown;
- exports.default = _default;
- module.exports = exports.default;
|