@blueprintjs/core
Version:
Core styles & components
168 lines (166 loc) • 8.33 kB
JavaScript
/*
* Copyright 2015 Palantir Technologies, Inc. All rights reserved.
* Licensed under the BSD-3 License as modified (the “License”); you may obtain a copy
* of the license at https://github.com/palantir/blueprint/blob/master/LICENSE
* and https://github.com/palantir/blueprint/blob/master/PATENTS
*/
;
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var classNames = require("classnames");
var React = require("react");
var ReactDOM = require("react-dom");
var abstractComponent_1 = require("../../common/abstractComponent");
var Classes = require("../../common/classes");
var Errors = require("../../common/errors");
var position_1 = require("../../common/position");
var popover_1 = require("../popover/popover");
var menu_1 = require("./menu");
var REACT_CONTEXT_TYPES = {
alignLeft: function (obj, key) {
if (obj[key] != null && typeof obj[key] !== "boolean") {
return new Error("[Blueprint] MenuItem context alignLeft must be boolean");
}
return undefined;
},
};
var MenuItem = (function (_super) {
tslib_1.__extends(MenuItem, _super);
function MenuItem() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = {
alignLeft: false,
};
_this.liRefHandler = function (r) { return _this.liElement = r; };
_this.measureSubmenu = function (el) {
if (el != null) {
var submenuRect = ReactDOM.findDOMNode(el).getBoundingClientRect();
var parentWidth = _this.liElement.parentElement.getBoundingClientRect().width;
var adjustmentWidth = submenuRect.width + parentWidth;
// this ensures that the left and right measurements represent a submenu opened to the right
var submenuLeft = submenuRect.left;
var submenuRight = submenuRect.right;
if (_this.state.alignLeft) {
submenuLeft += adjustmentWidth;
submenuRight += adjustmentWidth;
}
var _a = _this.props.submenuViewportMargin.left, left = _a === void 0 ? 0 : _a;
var _b = _this.props.submenuViewportMargin.right, right = _b === void 0 ? 0 : _b;
if (typeof document !== "undefined"
&& typeof document.documentElement !== "undefined"
&& Number(document.documentElement.clientWidth)) {
// we're in a browser context and the clientWidth is available,
// use it to set calculate 'right'
right = document.documentElement.clientWidth - right;
}
// uses context to prioritize the previous positioning
var alignLeft = _this.context.alignLeft || false;
if (alignLeft) {
if ((submenuLeft - adjustmentWidth) <= left) {
alignLeft = false;
}
}
else {
if (submenuRight >= right) {
alignLeft = true;
}
}
_this.setState({ alignLeft: alignLeft });
}
};
_this.renderChildren = function () {
var _a = _this.props, children = _a.children, submenu = _a.submenu;
if (children != null) {
var childProps_1 = _this.cascadeProps();
if (Object.keys(childProps_1).length === 0) {
return children;
}
else {
return React.Children.map(children, function (child) {
return React.cloneElement(child, childProps_1);
});
}
}
else if (submenu != null) {
return submenu.map(_this.cascadeProps).map(renderMenuItem);
}
else {
return undefined;
}
};
/**
* Evalutes this.props and cascades prop values into new props when:
* - submenuViewportMargin is defined, but is undefined for the supplied input.
* - useSmartPositioning is false, but is undefined for the supplied input.
* @param {IMenuItemProps} newProps If supplied, object will be modified, otherwise, defaults to an empty object.
* @returns An object to be used as child props.
*/
_this.cascadeProps = function (newProps) {
if (newProps === void 0) { newProps = {}; }
var _a = _this.props, submenuViewportMargin = _a.submenuViewportMargin, useSmartPositioning = _a.useSmartPositioning;
if (submenuViewportMargin != null && newProps.submenuViewportMargin == null) {
newProps.submenuViewportMargin = submenuViewportMargin;
}
if (useSmartPositioning === false && newProps.useSmartPositioning == null) {
newProps.useSmartPositioning = useSmartPositioning;
}
return newProps;
};
return _this;
}
MenuItem.prototype.render = function () {
var _a = this.props, children = _a.children, disabled = _a.disabled, label = _a.label, submenu = _a.submenu;
var hasSubmenu = children != null || submenu != null;
var liClasses = classNames((_b = {},
_b[Classes.MENU_SUBMENU] = hasSubmenu,
_b));
var anchorClasses = classNames(Classes.MENU_ITEM, Classes.intentClass(this.props.intent), (_c = {},
_c[Classes.DISABLED] = disabled,
// prevent popover from closing when clicking on submenu trigger or disabled item
_c[Classes.POPOVER_DISMISS] = this.props.shouldDismissPopover && !disabled && !hasSubmenu,
_c), Classes.iconClass(this.props.iconName), this.props.className);
var labelElement;
if (label != null) {
labelElement = React.createElement("span", { className: "pt-menu-item-label" }, label);
}
var content = (React.createElement("a", { className: anchorClasses, href: disabled ? undefined : this.props.href, onClick: disabled ? undefined : this.props.onClick, tabIndex: disabled ? undefined : 0, target: this.props.target },
labelElement,
this.props.text));
if (hasSubmenu) {
var measureSubmenu = (this.props.useSmartPositioning) ? this.measureSubmenu : null;
var submenuElement = React.createElement(menu_1.Menu, { ref: measureSubmenu }, this.renderChildren());
var popoverClasses = classNames((_d = {},
_d[Classes.ALIGN_LEFT] = this.state.alignLeft,
_d));
content = (React.createElement(popover_1.Popover, { content: submenuElement, isDisabled: disabled, enforceFocus: false, hoverCloseDelay: 0, inline: true, interactionKind: popover_1.PopoverInteractionKind.HOVER, position: this.state.alignLeft ? position_1.Position.LEFT_TOP : position_1.Position.RIGHT_TOP, popoverClassName: classNames(Classes.MINIMAL, Classes.MENU_SUBMENU, popoverClasses), useSmartArrowPositioning: false }, content));
}
return (React.createElement("li", { className: liClasses, ref: this.liRefHandler }, content));
var _b, _c, _d;
};
MenuItem.prototype.getChildContext = function () {
return { alignLeft: this.state.alignLeft };
};
MenuItem.prototype.validateProps = function (props) {
if (props.children != null && props.submenu != null) {
console.warn(Errors.MENU_WARN_CHILDREN_SUBMENU_MUTEX);
}
};
return MenuItem;
}(abstractComponent_1.AbstractComponent));
MenuItem.defaultProps = {
disabled: false,
shouldDismissPopover: true,
submenuViewportMargin: {},
text: "",
useSmartPositioning: true,
};
MenuItem.displayName = "Blueprint.MenuItem";
MenuItem.contextTypes = REACT_CONTEXT_TYPES;
MenuItem.childContextTypes = REACT_CONTEXT_TYPES;
exports.MenuItem = MenuItem;
function renderMenuItem(props, key) {
return React.createElement(MenuItem, tslib_1.__assign({ key: key }, props));
}
exports.renderMenuItem = renderMenuItem;
exports.MenuItemFactory = React.createFactory(MenuItem);
//# sourceMappingURL=menuItem.js.map