@skbkontur/ui-kit
Version:
201 lines • 8.07 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var React = tslib_1.__importStar(require("react"));
var react_dom_1 = tslib_1.__importDefault(require("react-dom"));
var ScrollContainer_1 = tslib_1.__importDefault(require("../../ScrollContainer/ScrollContainer"));
var utils_1 = require("./utils");
var InternalMenuView_1 = require("./InternalMenuView");
var InternalMenu = /** @class */ (function (_super) {
tslib_1.__extends(InternalMenu, _super);
function InternalMenu() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = {
highlightedIndex: -1
};
_this.scrollContainer = null;
_this.highlighted = null;
_this.rootElement = null;
_this.focusWithScrollRestore = function () {
if (_this.rootElement && window) {
var scrollX_1 = window.scrollX;
var scrollY_1 = window.scrollY;
_this.rootElement.focus();
window.scrollTo(scrollX_1, scrollY_1);
}
};
_this.setInitialSelection = function () {
if (_this.props.initialSelectedItemIndex === undefined) {
return;
}
for (var i = _this.props.initialSelectedItemIndex; i > -1; i--) {
_this.moveDown();
}
};
_this.refScrollContainer = function (scrollContainer) {
_this.scrollContainer = scrollContainer;
};
_this.scrollToSelected = function () {
if (_this.scrollContainer && _this.highlighted) {
var highlightedDomNode = react_dom_1.default.findDOMNode(_this.highlighted);
if (highlightedDomNode instanceof HTMLElement) {
_this.scrollContainer.scrollTo(highlightedDomNode);
}
}
};
_this.highlightItem = function (index) {
_this.setState({ highlightedIndex: index });
if (_this.rootElement && _this.rootElement.focus) {
_this.rootElement.focus();
}
};
_this.unhighlight = function () {
_this.setState({ highlightedIndex: -1 });
};
_this.moveUp = function () {
_this.move(-1);
};
_this.moveDown = function () {
_this.move(1);
};
_this.handleKeyDown = function (event) {
if (typeof _this.props.onKeyDown === 'function') {
_this.props.onKeyDown(event);
}
if (event.defaultPrevented) {
return;
}
switch (event.key) {
case 'ArrowUp':
event.preventDefault();
_this.moveUp();
break;
case 'ArrowDown':
event.preventDefault();
_this.moveDown();
break;
case 'Enter':
event.preventDefault();
_this.select(_this.state.highlightedIndex, false, event);
break;
default:
break;
}
};
return _this;
}
InternalMenu.prototype.componentDidMount = function () {
this.focusWithScrollRestore();
this.setInitialSelection();
};
InternalMenu.prototype.render = function () {
var _this = this;
var enableIconPadding = React.Children.toArray(this.props.children).some(function (x) { return x && typeof x === 'object' && x.props.icon; });
if (this.isEmpty()) {
return null;
}
return (React.createElement(InternalMenuView_1.InternalMenuStyledWrapper, { style: { width: this.props.width, maxHeight: this.props.maxHeight }, onKeyDown: this.handleKeyDown, innerRef: function (element) {
_this.rootElement = element;
}, tabIndex: 0 },
React.createElement(ScrollContainer_1.default, { ref: this.refScrollContainer, maxHeight: this.props.maxHeight, preventWindowScroll: this.props.preventWindowScroll }, React.Children.map(this.props.children, function (child, index) {
if (!React.isValidElement(child)) {
return child;
}
if (enableIconPadding && (utils_1.isMenuItem(child) || utils_1.isMenuHeader(child))) {
child = React.cloneElement(child, {
_enableIconPadding: true
});
}
if (utils_1.isActiveElement(child)) {
var isHighlightedMenuItem_1 = _this.state.highlightedIndex === index;
return React.cloneElement(child, {
ref: function (element) {
if (isHighlightedMenuItem_1) {
_this.highlighted = element;
}
return element;
},
state: isHighlightedMenuItem_1 ? 'hover' : child.props.state,
onClick: _this.select.bind(_this, index, false),
onMouseEnter: function () { return _this.highlightItem(index); },
onMouseLeave: _this.unhighlight
});
}
return child;
}))));
};
InternalMenu.prototype.select = function (index, shouldHandleHref, event) {
var item = childrenToArray(this.props.children)[index];
if (utils_1.isActiveElement(item)) {
if (shouldHandleHref && item.props.href) {
if (item.props.target) {
window.open(item.props.href, item.props.target);
}
else {
location.href = item.props.href;
}
}
if (item.props.onClick) {
item.props.onClick(event);
}
if (this.props.onItemClick) {
this.props.onItemClick(event.type);
}
return true;
}
return false;
};
InternalMenu.prototype.move = function (step) {
var _this = this;
this.setState(function (state) {
var children = childrenToArray(_this.props.children);
if (!children.some(utils_1.isActiveElement)) {
return null;
}
var index = state.highlightedIndex;
do {
index += step;
if (!_this.props.cyclicSelection && (index < 0 || index > children.length)) {
return null;
}
if (index < 0) {
index = children.length - 1;
}
else if (index > children.length) {
index = 0;
}
var child = children[index];
if (utils_1.isActiveElement(child)) {
return { highlightedIndex: index };
}
} while (index !== state.highlightedIndex);
return null;
}, this.scrollToSelected);
};
InternalMenu.prototype.isEmpty = function () {
var children = this.props.children;
return !children || !childrenToArray(children).filter(isExist).length;
};
InternalMenu.defaultProps = {
width: 'auto',
maxHeight: 301,
hasShadow: true,
preventWindowScroll: true,
cyclicSelection: true,
initialSelectedItemIndex: -1
};
return InternalMenu;
}(React.Component));
exports.default = InternalMenu;
function isExist(value) {
return value !== null && value !== undefined;
}
function childrenToArray(children) {
var ret = [];
// Use forEach instead of map to avoid cloning for key unifying.
React.Children.toArray(children).forEach(function (child) {
ret.push(child);
});
return ret;
}
//# sourceMappingURL=InternalMenu.js.map
;