@sap-ux/ui-components
Version:
SAP UI Components Library
241 lines • 9.42 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UIContextualMenu = exports.UIContextualMenuLayoutType = exports.UIContextualMenuItemType = void 0;
exports.getUIcontextualMenuStyles = getUIcontextualMenuStyles;
exports.getUIContextualMenuItemStyles = getUIContextualMenuItemStyles;
exports.getUIcontextualMenuCalloutStyles = getUIcontextualMenuCalloutStyles;
const react_1 = __importDefault(require("react"));
const react_2 = require("@fluentui/react");
Object.defineProperty(exports, "UIContextualMenuItemType", { enumerable: true, get: function () { return react_2.ContextualMenuItemType; } });
const Icons_1 = require("../Icons");
var UIContextualMenuLayoutType;
(function (UIContextualMenuLayoutType) {
UIContextualMenuLayoutType["DropdownMenu"] = "DropdownMenu";
UIContextualMenuLayoutType["ContextualMenu"] = "ContextualMenu";
})(UIContextualMenuLayoutType || (exports.UIContextualMenuLayoutType = UIContextualMenuLayoutType = {}));
require("./UIContextualMenu.scss");
const DEFAULT_ZINDEX = 1000000;
/* Method receives callout style and extracts into raw styles object.
*
* @param {IStyleFunctionOrObject<ICalloutContentStyleProps, ICalloutContentStyles> | undefined} styles Callout styles.
* @param {keyof ICalloutContentStyles} name Callout style type.
* @returns {IRawStyle} Raw style object.
*/
const extractRawStyles = (styles, name) => {
if (typeof styles === 'object' && typeof styles[name] === 'object') {
return styles[name];
}
return {};
};
const submenuIconProps = { iconName: Icons_1.UiIcons.ArrowDown };
/**
* ContextualMenu styles prop generator.
*
* @returns - consumable styles property for ContextualMenu
*/
function getUIcontextualMenuStyles() {
return {
root: {
minWidth: 190,
maxWidth: 300,
background: 'var(--vscode-input-background)',
border: 0
}
};
}
/**
* ContextualMenu subcomponent styles prop generator.
*
* @param props Contextual menu properties.
* @param currentItemHasSubmenu Item has submenu.
* @param itemsHaveSubMenu At least one of sibling item has submenu.
* @returns - consumable styles property for ContextualMenuItem
*/
function getUIContextualMenuItemStyles(props, currentItemHasSubmenu, itemsHaveSubMenu) {
const { iconToLeft } = props ?? {};
const padding = {};
if (iconToLeft && itemsHaveSubMenu) {
padding.label = currentItemHasSubmenu ? 10 : 19;
padding.root = '0 3px !important';
}
else if (!iconToLeft && currentItemHasSubmenu) {
padding.rootRight = '3px !important';
}
return {
root: {
padding: padding.root,
paddingRight: padding.rootRight
},
checkmarkIcon: {
color: 'var(--vscode-foreground)',
maxHeight: 18,
fontSize: 16,
lineHeight: 18,
margin: 0
},
icon: {
marginLeft: 0,
marginRight: 6
},
label: {
fontFamily: 'var(--vscode-font-family)',
lineHeight: 18,
height: 18,
paddingLeft: padding.label
},
linkContent: {
fontSize: 13,
height: 'auto'
},
subMenuIcon: {
height: 16,
width: 16,
transform: iconToLeft ? 'rotate(90deg)' : 'rotate(-90deg)',
transformOrigin: '50% 50%',
lineHeight: 0
}
};
}
/**
* ContextualMenu sub-component styles prop generator.
*
* @param styles External styles of contextual menu.
* @param maxWidth Maximal width of callout
* @returns consumable styles property for Callout
*/
function getUIcontextualMenuCalloutStyles(styles, maxWidth) {
return {
root: {
maxWidth: maxWidth,
...(styles ? extractRawStyles(styles, 'root') : undefined)
}
};
}
/**
* Recursively applies corresponding styles generator to each,
* IContextualMenuItem, ICallourProps and IContxualMenuProps item in props tree.
*
* @param props Contextual menu properties.
* @returns - mutated IContextualMenuItem prop with styles props generators applied to each menu tree node
*/
function injectContextualMenuItemsStyle(props) {
const { items, iconToLeft } = props;
const renderMenuWithIcons = items.some((item) => item.iconProps);
const itemsHaveSubMenu = items.some((item) => item.subMenuProps);
return items.map((item) => {
if (!item.itemProps) {
item.itemProps = {};
}
const submenu = !!item.subMenuProps;
if (item.itemProps.styles) {
item.itemProps.styles = {
...getUIContextualMenuItemStyles(props, submenu, itemsHaveSubMenu),
...item.itemProps.styles
};
}
else {
item.itemProps.styles = getUIContextualMenuItemStyles(props, submenu, itemsHaveSubMenu);
}
if (!item.submenuIconProps) {
item.submenuIconProps = submenuIconProps;
}
if (item.iconProps || renderMenuWithIcons) {
item.onRenderContent = (props, renderers) => {
return (react_1.default.createElement(react_1.default.Fragment, null,
renderers.renderItemName(props),
item.iconProps && renderers.renderItemIcon(props)));
};
}
else if (iconToLeft) {
item.onRenderContent = (props, defaultRenders) => {
return (react_1.default.createElement(react_1.default.Fragment, null,
defaultRenders.renderSubMenuIcon(props),
defaultRenders.renderCheckMarkIcon(props),
defaultRenders.renderItemIcon(props),
defaultRenders.renderItemName(props),
defaultRenders.renderSecondaryText(props)));
};
}
return item;
});
}
/**
* Method returns class names string depending on props and component state.
*
* @param props Contextual menu properties.
* @returns Class names of root element.
*/
function getClassNames(props) {
const classNames = ['ts-ContextualMenu'];
const { layoutType = UIContextualMenuLayoutType.DropdownMenu, iconToLeft } = props;
const layoutClassName = layoutType === UIContextualMenuLayoutType.DropdownMenu
? 'ts-ContextualMenu--dropdown'
: 'ts-ContextualMenu--contextual';
classNames.push(layoutClassName);
if (props.className) {
classNames.push(props.className);
}
if (iconToLeft) {
classNames.push('ts-ContextualMenu--reverse');
}
return classNames.join(' ');
}
/**
* Method returns class names string for callout element depending on props and component state.
*
* @param props Contextual menu properties.
* @param isSubmenu Is submenu.
* @returns Class names of callout element.
*/
function getCalloutClassName(props, isSubmenu) {
const classNames = ['ts-ContextualMenu-callout'];
const { layoutType = UIContextualMenuLayoutType.DropdownMenu } = props;
const layoutClassName = layoutType === UIContextualMenuLayoutType.DropdownMenu
? 'ts-ContextualMenu-callout--dropdown'
: 'ts-ContextualMenu-callout--contextual';
classNames.push(layoutClassName);
if (isSubmenu && props.showSubmenuBeneath) {
classNames.push('ts-ContextualMenu-callout--submenu-beneath');
}
if (props.calloutProps?.className) {
classNames.push(props.calloutProps.className);
}
return classNames.join(' ');
}
const UIContextualMenu = (props) => {
const { showSubmenuBeneath } = props;
const zIndex = showSubmenuBeneath ? DEFAULT_ZINDEX - 1 : undefined;
return (react_1.default.createElement(react_2.ContextualMenu, { isBeakVisible: false, beakWidth: 8, onRenderSubMenu: getSubMenu.bind(undefined, props, zIndex), ...props, className: getClassNames(props), items: injectContextualMenuItemsStyle(props), calloutProps: {
styles: getUIcontextualMenuCalloutStyles(props.styles, props.maxWidth),
...props.calloutProps,
className: getCalloutClassName(props)
}, styles: { ...getUIcontextualMenuStyles(), ...props.styles } }));
};
exports.UIContextualMenu = UIContextualMenu;
/**
* Method returns element for submenu of contextual menu.
*
* @param rootMenuProps Root contextual menu props.
* @param zIndex z-index to apply for layer of submenu.
* @param subMenuProps Submenu properties.
* @returns Element for submenu of contextual menu.
*/
function getSubMenu(rootMenuProps, zIndex, subMenuProps) {
if (!subMenuProps) {
return null;
}
const { iconToLeft } = rootMenuProps;
const zIndexOfSubmenu = zIndex !== undefined ? zIndex - 1 : undefined;
return (react_1.default.createElement(exports.UIContextualMenu, { iconToLeft: iconToLeft, ...subMenuProps, calloutProps: {
gapSpace: 10,
layerProps: {
styles: { root: { zIndex } }
},
...subMenuProps.calloutProps,
className: getCalloutClassName(rootMenuProps, true)
}, onRenderSubMenu: getSubMenu.bind(undefined, rootMenuProps, zIndexOfSubmenu) }));
}
//# sourceMappingURL=UIContextualMenu.js.map