UNPKG

@salesforce/design-system-react

Version:

Salesforce Lightning Design System for React

249 lines (214 loc) 9.72 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _react = require("react"); var _react2 = _interopRequireDefault(_react); var _propTypes = require("prop-types"); var _propTypes2 = _interopRequireDefault(_propTypes); var _lodash = require("lodash.isequal"); var _lodash2 = _interopRequireDefault(_lodash); var _classnames = require("classnames"); var _classnames2 = _interopRequireDefault(_classnames); var _icon = require("../../icon"); var _icon2 = _interopRequireDefault(_icon); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* Copyright (c) 2015-present, salesforce.com, inc. All rights reserved */ /* Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license */ /* eslint-disable jsx-a11y/interactive-supports-focus */ var propTypes = { /* * Active descendant in menu */ activeOption: _propTypes2.default.object, /* * Index of active descendant in menu */ activeOptionIndex: _propTypes2.default.number, /** * CSS classes to be added to container `div` tag. Uses `classNames` [API](https://github.com/JedWatson/classnames). */ className: _propTypes2.default.oneOfType([_propTypes2.default.array, _propTypes2.default.object, _propTypes2.default.string]), /** * CSS classes to be added to tag with `.slds-dropdown`. Uses `classNames` [API](https://github.com/JedWatson/classnames). */ classNameMenu: _propTypes2.default.oneOfType([_propTypes2.default.array, _propTypes2.default.object, _propTypes2.default.string]), /** * CSS classes to be added to menu sub header `span` tag. Uses `classNames` [API](https://github.com/JedWatson/classnames). */ classNameMenuSubHeader: _propTypes2.default.oneOfType([_propTypes2.default.array, _propTypes2.default.object, _propTypes2.default.string]), /** * Sets the dialog width to the width of one of the following: * `target`: (Menus attached to `input` typically follow this UX pattern), * `menu`: Consider setting a menuMaxWidth if using this value. If not, width will be set to width of largest menu item. * 'none' */ inheritWidthOf: _propTypes2.default.oneOf(['target', 'menu', 'none']), /* * Id used for assistive technology */ inputId: _propTypes2.default.string, /** * Determines the height of the menu based on SLDS CSS classes. */ itemVisibleLength: _propTypes2.default.oneOf([5, 7, 10]), /** * **Text labels for internationalization** * This object is merged with the default props object on every render. * * `noOptionsFound`: Custom message that renders when no matches found. The default empty state is just text that says, 'No matches found.'. */ labels: _propTypes2.default.shape({ noOptionsFound: _propTypes2.default.oneOfType([_propTypes2.default.node, _propTypes2.default.string]).isRequired }), /** * Accepts a custom menu item rendering function that becomes a custom component and is passed in the following props: * * `assistiveText`: Object, `assistiveText` prop that is passed into Combobox * * `option`: Object, option data for item being rendered that is passed into Combobox * * `selected`: Boolean, allows rendering of `assistiveText.optionSelectedInMenu` in Readonly Combobox * * _Tested with snapshot testing._ */ menuItem: _propTypes2.default.func, /* * Sets a maximum width that the menu will be if `inheritWidthOf` is menu. */ maxWidth: _propTypes2.default.string, /* * Menu options */ options: _propTypes2.default.array, /* * Callback to remove active descendent */ resetActiveOption: _propTypes2.default.func, /* * Callback when option is selected with keyboard or mouse */ onSelect: _propTypes2.default.func, /* * Selected options */ selection: _propTypes2.default.array, /** * Changes styles of the menu option */ variant: _propTypes2.default.oneOf(['icon-title-subtitle', 'checkbox']), isSelected: _propTypes2.default.func, assistiveText: _propTypes2.default.object }; var defaultProps = {}; var Menu = function Menu(props) { var maxWidth = props.inheritWidthOf === 'menu' ? 'inherit' : undefined; maxWidth = props.inheritWidthOf === 'menu' && props.maxWidth ? props.maxWidth : maxWidth; // .slds-dropdown sets the menu to absolute positioning, since it has a relative parent. Absolute positioning removes clientHeight and clientWidth which Popper.js needs to absolute position the menu's wrapping div. Absolute positioning an already absolute positioned element doesn't work. Setting the menu's position to relative allows PopperJS to work it's magic. var menuOptions = props.options.map(function (optionData, index) { var active = index === props.activeOptionIndex && (0, _lodash2.default)(optionData, props.activeOption); var selected = props.isSelected({ selection: props.selection, option: optionData }); var MenuItem = props.menuItem; if (optionData.type === 'separator') { return optionData.label ? _react2.default.createElement("li", { className: "slds-dropdown__header slds-truncate", title: optionData.label, role: "separator", key: "menu-separator-".concat(optionData.id) }, _react2.default.createElement("span", { className: (0, _classnames2.default)('slds-text-title_caps', props.classNameMenuSubHeader) }, optionData.label)) : _react2.default.createElement("li", { className: "slds-has-divider_top-space", role: "separator", key: "menu-separator-".concat(optionData.id) }); } return _react2.default.createElement("li", { className: "slds-listbox__item", key: "menu-option-".concat(optionData.id), role: "presentation" }, { 'icon-title-subtitle': _react2.default.createElement("span", { // eslint-disable-line jsx-a11y/no-static-element-interactions "aria-selected": active, id: "".concat(props.inputId, "-listbox-option-").concat(optionData.id), className: (0, _classnames2.default)('slds-media slds-listbox__option', 'slds-listbox__option_entity slds-listbox__option_has-meta', { 'slds-has-focus': active }), onClick: function onClick(event) { props.onSelect(event, { option: optionData }); }, role: "option" }, optionData.icon && !props.menuItem ? _react2.default.createElement("span", { className: "slds-media__figure" }, optionData.icon) : null, props.menuItem ? _react2.default.createElement(MenuItem, { assistiveText: props.assistiveText, selected: selected, option: optionData }) : _react2.default.createElement("span", { className: "slds-media__body" }, _react2.default.createElement("span", { className: "slds-listbox__option-text slds-listbox__option-text_entity" }, optionData.label), _react2.default.createElement("span", { className: "slds-listbox__option-meta slds-listbox__option-meta_entity" }, optionData.subTitle))), checkbox: _react2.default.createElement("span", { // eslint-disable-line jsx-a11y/no-static-element-interactions "aria-selected": selected, id: "".concat(props.inputId, "-listbox-option-").concat(optionData.id), className: (0, _classnames2.default)('slds-media slds-listbox__option', ' slds-listbox__option_plain slds-media_small slds-media_center', { 'slds-has-focus': active, 'slds-is-selected': selected }), onClick: function onClick(event) { props.onSelect(event, { selection: props.selection, option: optionData }); }, role: "option" }, _react2.default.createElement("span", { className: "slds-media__figure" }, _react2.default.createElement(_icon2.default, { className: "slds-listbox__icon-selected", category: "utility", name: "check", size: "x-small" })), _react2.default.createElement("span", { className: "slds-media__body" }, props.menuItem ? _react2.default.createElement(MenuItem, { assistiveText: props.assistiveText, selected: selected, option: optionData }) : _react2.default.createElement("span", { className: "slds-truncate", title: optionData.label }, selected ? _react2.default.createElement("span", { className: "slds-assistive-text" }, props.assistiveText.optionSelectedInMenu) : null, ' ', optionData.label))) }[props.variant]); }); return _react2.default.createElement("ul", { className: (0, _classnames2.default)('slds-listbox slds-listbox_vertical slds-dropdown slds-dropdown_fluid', { 'slds-dropdown_length-with-icon-5': props.itemVisibleLength === 5, 'slds-dropdown_length-with-icon-7': props.itemVisibleLength === 7, 'slds-dropdown_length-with-icon-10': props.itemVisibleLength === 10 }, props.classNameMenu), role: "presentation", style: { width: props.inheritWidthOf === 'menu' ? 'auto' : undefined, maxWidth: maxWidth, position: props.menuPosition !== 'relative' ? 'relative' : undefined } }, menuOptions.length ? menuOptions : _react2.default.createElement("li", { className: "slds-listbox__item slds-listbox__status", role: "status", "aria-live": "polite" }, _react2.default.createElement("span", { className: "slds-m-left--x-large slds-p-vertical--medium" }, props.labels.noOptionsFound))); }; Menu.displayName = 'Menu'; Menu.propTypes = propTypes; Menu.defaultProps = defaultProps; exports.default = Menu;