@helpscout/hsds-react
Version:
React component library for Help Scout's Design System
424 lines (343 loc) • 13 kB
JavaScript
"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;