UNPKG

@helpscout/hsds-react

Version:

React component library for Help Scout's Design System

424 lines (343 loc) 13 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = void 0; var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose")); var _react = _interopRequireDefault(require("react")); var _wedux = require("@helpscout/wedux"); var _Keys = _interopRequireDefault(require("../../constants/Keys")); var _KeypressListener = _interopRequireDefault(require("../KeypressListener")); var _Dropdown = require("./Dropdown.actions"); var _Dropdown2 = require("./Dropdown.utils"); var _Dropdown3 = require("./Dropdown.renderUtils"); var _lodash = _interopRequireDefault(require("lodash.isnil")); var _scrolling = require("../../utilities/scrolling"); var _jsxRuntime = require("react/jsx-runtime"); // Deprecated /* istanbul ignore file */ function noop() {} var DropdownRenderer = /*#__PURE__*/function (_React$PureComponent) { (0, _inheritsLoose2.default)(DropdownRenderer, _React$PureComponent); function DropdownRenderer() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _React$PureComponent.call.apply(_React$PureComponent, [this].concat(args)) || this; _this.modifier = 1; _this.handleTab = function (event) { var _this$props = _this.props, closeDropdown = _this$props.closeDropdown, enableTabNavigation = _this$props.enableTabNavigation, items = _this$props.items, index = _this$props.index; if (!enableTabNavigation) { closeDropdown(); return; } requestAnimationFrame(function () { var target = document.activeElement; var isLastItem = parseInt(index, 10) === items.length - 1; if (isLastItem) { closeDropdown(); return; } if (!(0, _Dropdown3.isDOMNodeValidItem)(target)) return; event.preventDefault(); if (event.shiftKey) { _this.moveUp(); } else { _this.moveDown(); } }); }; _this.handleOnKeyDown = function (event) { var _this$props2 = _this.props, dropRight = _this$props2.dropRight, enableLeftRightArrowNavigation = _this$props2.enableLeftRightArrowNavigation; switch (event.keyCode) { case _Keys.default.UP_ARROW: event.preventDefault(); _this.moveUp(); break; case _Keys.default.DOWN_ARROW: event.preventDefault(); _this.moveDown(); break; case _Keys.default.LEFT_ARROW: event.preventDefault(); if (enableLeftRightArrowNavigation) { _this.moveUp(); } else { if (dropRight) { _this.closeSubMenu(); } else { _this.openSubMenu(); } } break; case _Keys.default.RIGHT_ARROW: event.preventDefault(); if (enableLeftRightArrowNavigation) { _this.moveDown(); } else { if (dropRight) { _this.openSubMenu(); } else { _this.closeSubMenu(); } } break; case _Keys.default.TAB: _this.handleTab(event); break; case _Keys.default.ENTER: event.preventDefault(); _this.props.selectItemFromIndex(event); break; default: break; } }; _this.setNextIndex = function (nextIndex) { var envNode = _this.props.envNode; if ((0, _lodash.default)(nextIndex)) return; var target = (0, _Dropdown3.findItemDOMNode)(nextIndex, envNode); if (target) { _this.props.focusItem({ target: target }); _this.scrollIntoView(target); } }; _this.scrollIntoView = function (node) { if (node) { (0, _scrolling.scrollIntoView)(node); } }; return _this; } var _proto = DropdownRenderer.prototype; _proto.moveUp = function moveUp() { this.props.decrementIndex(this.modifier); }; _proto.moveDown = function moveDown() { this.props.incrementIndex(this.modifier); }; _proto.openSubMenu = function openSubMenu() { var _this$props3 = this.props, index = _this$props3.index, isOpen = _this$props3.isOpen; if (!isOpen || (0, _lodash.default)(index)) return; var nextIndex = (0, _Dropdown2.getNextChildPath)(index); this.setNextIndex(nextIndex); }; _proto.closeSubMenu = function closeSubMenu() { var _this$props4 = this.props, index = _this$props4.index, isOpen = _this$props4.isOpen; if (!isOpen || (0, _lodash.default)(index)) return; var nextIndex = (0, _Dropdown2.getParentPath)(index); this.setNextIndex(nextIndex); }; _proto.shouldRenderDOM = function shouldRenderDOM() { var _this$props5 = this.props, index = _this$props5.index, selectedItem = _this$props5.selectedItem; return index || selectedItem; }; _proto.renderSubMenus = function renderSubMenus() { var _this$props6 = this.props, envNode = _this$props6.envNode, focusClassName = _this$props6.focusClassName, index = _this$props6.index, openClassName = _this$props6.openClassName; if (!this.shouldRenderDOM()) return; var openNodes = (0, _Dropdown3.findOpenItemDOMNodes)(envNode, openClassName); Array.from(openNodes).forEach(function (node) { var nodeIndex = (0, _Dropdown3.getIndexFromItemDOMNode)(node); var isOpen = (0, _Dropdown3.isOpenFromIndex)(index, nodeIndex); if (isOpen) { node.classList.add(openClassName); } else { node.classList.remove(openClassName); node.classList.remove(focusClassName); } }); }; _proto.renderPreviousInteraction = function renderPreviousInteraction() { var _this$props7 = this.props, envNode = _this$props7.envNode, focusClassName = _this$props7.focusClassName, previousIndex = _this$props7.previousIndex, index = _this$props7.index, openClassName = _this$props7.openClassName; if (!this.shouldRenderDOM()) return; var previousNode = (0, _Dropdown3.findItemDOMNode)(previousIndex, envNode); if (!previousNode) return; var isOpen = (0, _Dropdown3.isOpenFromIndex)(index, previousIndex); if (isOpen) { previousNode.classList.add(openClassName); } else { Array.from((0, _Dropdown3.findFocusedItemDOMNodes)(envNode, focusClassName)).forEach(function (node) { if (!node.classList.contains(openClassName)) { node.classList.remove(focusClassName); } }); (0, _Dropdown3.resetSubMenuScrollPositionFromItemNode)(previousNode); } }; _proto.renderNextInteraction = function renderNextInteraction() { var _this$props8 = this.props, envNode = _this$props8.envNode, focusClassName = _this$props8.focusClassName, lastInteractionWasKeyboard = _this$props8.lastInteractionWasKeyboard, index = _this$props8.index, openClassName = _this$props8.openClassName, previousIndex = _this$props8.previousIndex; if (!this.shouldRenderDOM()) return; var nextNode = (0, _Dropdown3.findItemDOMNode)(index, envNode); if (!nextNode) return; nextNode.classList.add(focusClassName); if (lastInteractionWasKeyboard) { this.scrollIntoView(nextNode); } var closedSubMenu = (0, _Dropdown3.didCloseSubMenu)(previousIndex, index); if (closedSubMenu) { nextNode.classList.remove(openClassName); } }; _proto.renderSelectedItem = function renderSelectedItem() { var _this$props9 = this.props, activeClassName = _this$props9.activeClassName, allowMultipleSelection = _this$props9.allowMultipleSelection, envNode = _this$props9.envNode, index = _this$props9.index, indexMap = _this$props9.indexMap, previousSelectedItem = _this$props9.previousSelectedItem, selectedItem = _this$props9.selectedItem; if (!this.shouldRenderDOM()) return; if (allowMultipleSelection) { var selectedNode = (0, _Dropdown3.findItemDOMNode)(index, envNode); var itemId = indexMap[index - 1]; var nodeIsSelected = (0, _Dropdown2.itemIsActive)(selectedItem, { id: itemId, // Fallback matcher, for items without `id` value: itemId }); if (selectedNode) { if (nodeIsSelected) { selectedNode.classList.add(activeClassName); (0, _Dropdown3.setAriaActiveOnMenuFromItemNode)(selectedNode); } else { selectedNode.classList.remove(activeClassName); } } } else { // Render selected (active) styles var previousSelectedNode = (0, _Dropdown3.findItemDOMNodeById)(previousSelectedItem, envNode); var _selectedNode = (0, _Dropdown3.findItemDOMNodeById)(selectedItem, envNode); if (previousSelectedNode) { previousSelectedNode.classList.remove(activeClassName); } if (_selectedNode) { _selectedNode.classList.add(activeClassName); (0, _Dropdown3.setAriaActiveOnMenuFromItemNode)(_selectedNode); } } }; _proto.optimizedItemRenderFromProps = function optimizedItemRenderFromProps() { if (!this.shouldRenderDOM()) return; // Render (recursive) sub-menu interactions this.renderSubMenus(); // Render previous interactions this.renderPreviousInteraction(); // Render next interactions this.renderNextInteraction(); // Render selected item this.renderSelectedItem(); }; _proto.optimizedRender = function optimizedRender() { var _this2 = this; requestAnimationFrame(function () { _this2.optimizedItemRenderFromProps(); }); }; _proto.render = function render() { var _this$props10 = this.props, envNode = _this$props10.envNode, dataCy = _this$props10['data-cy']; // We'll update the DOM for every render cycle // It may feel "wrong"... But, this is FAR cheaper than // relying on React to do it. // That is because we're doing with a single (more or less) calculation // rather than spreading the work throughout the menu/item tree. // This is especially important if item nesting is going to be a thing. this.optimizedRender(); return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: "c-DropdownRendererNode", "data-cy": dataCy, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_KeypressListener.default, { handler: this.handleOnKeyDown, type: "keydown", scope: envNode }) }); }; return DropdownRenderer; }(_react.default.PureComponent); DropdownRenderer.defaultProps = { activeClassName: 'is-active', 'data-cy': 'DropdownRenderer', decrementIndex: noop, enableLeftRightArrowNavigation: false, enableTabNavigation: true, focusClassName: 'is-focused', focusItem: noop, incrementIndex: noop, items: [], openClassName: 'is-open', selectItemFromIndex: noop }; var ConnectedRenderer = (0, _wedux.connect)( // mapStateToProps function (state) { var activeClassName = state.activeClassName, allowMultipleSelection = state.allowMultipleSelection, enableLeftRightArrowNavigation = state.enableLeftRightArrowNavigation, enableTabNavigation = state.enableTabNavigation, envNode = state.envNode, focusClassName = state.focusClassName, index = state.index, indexMap = state.indexMap, inputValue = state.inputValue, isOpen = state.isOpen, items = state.items, lastInteractionType = state.lastInteractionType, openClassName = state.openClassName, previousIndex = state.previousIndex, previousSelectedItem = state.previousSelectedItem, selectedItem = state.selectedItem; return { activeClassName: activeClassName, allowMultipleSelection: allowMultipleSelection, enableLeftRightArrowNavigation: enableLeftRightArrowNavigation, enableTabNavigation: enableTabNavigation, envNode: envNode, dropRight: (0, _Dropdown2.isDropRight)(state), focusClassName: focusClassName, index: index, indexMap: indexMap, inputValue: inputValue, isOpen: isOpen, items: items, lastInteractionWasKeyboard: lastInteractionType === 'keyboard', openClassName: openClassName, previousIndex: previousIndex, previousSelectedItem: previousSelectedItem, selectedItem: selectedItem }; }, // mapDispatchToProps { closeDropdown: _Dropdown.closeDropdown, focusItem: _Dropdown.focusItem, incrementIndex: _Dropdown.incrementIndex, decrementIndex: _Dropdown.decrementIndex, selectItemFromIndex: _Dropdown.selectItemFromIndex })(DropdownRenderer); var _default = ConnectedRenderer; exports.default = _default;