UNPKG

@carbon/ibm-security

Version:

Carbon for Cloud & Cognitive IBM Security UI components

400 lines (397 loc) 20 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.namespace = exports.default = void 0; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _iconsReact = require("@carbon/icons-react"); var _classnames5 = _interopRequireDefault(require("classnames")); var _propTypes = _interopRequireDefault(require("prop-types")); var _react = _interopRequireWildcard(require("react")); var _capabilities = require("../../globals/utils/capabilities"); var _globalRoot = _interopRequireDefault(require("../../globals/utils/globalRoot")); var _Component2 = _interopRequireDefault(require("../Component")); var _IconButton = _interopRequireDefault(require("../IconButton")); var _Nav = _interopRequireDefault(require("../Nav")); var _NavList = _interopRequireDefault(require("../Nav/NavList")); var _NavItem = _interopRequireDefault(require("../Nav/NavItem")); var _Transition = _interopRequireDefault(require("../Transition")); var _namespace = require("../../globals/namespace"); var _excluded = ["children", "href", "content", "icon", "id", "title"], _excluded2 = ["href", "element", "content", "id", "title"]; function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } /** * @file Toolbar. * @copyright IBM Security 2019 - 2021 */ var namespace = exports.namespace = (0, _namespace.getComponentNamespace)('toolbar'); /** * Toolbar component. * @param {Record<string, any>} htmlContent Toolbar props. * @returns {Toolbar} Toolbar instance. */ var Toolbar = exports.default = /*#__PURE__*/function (_Component) { function Toolbar() { var _this; (0, _classCallCheck2.default)(this, Toolbar); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _callSuper(this, Toolbar, [].concat(args)); (0, _defineProperty2.default)(_this, "state", { isActive: { menu: false, settings: false, support: false }, content: undefined, showContent: false }); (0, _defineProperty2.default)(_this, "wrapper", /*#__PURE__*/_react.default.createRef()); /** * Handle a click outside of the Toolbar wrapper. * @param {Event} event A click event. */ (0, _defineProperty2.default)(_this, "handleClickOutside", function (event) { var activeElement = event.target.getRootNode().activeElement || document.activeElement; if (event.target !== activeElement && event.target.nodeName !== 'SHELL-COMPONENT' && _this.wrapper && !_this.wrapper.current.contains(event.target)) { _this.setState({ isActive: { menu: false, settings: false, support: false } }); _this.props.onToggle(false); } }); (0, _defineProperty2.default)(_this, "toggleContent", function () { var htmlContent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined; _this.setState({ content: htmlContent, showContent: !_this.state.showContent }); }); return _this; } (0, _inherits2.default)(Toolbar, _Component); return (0, _createClass2.default)(Toolbar, [{ key: "componentDidMount", value: function componentDidMount() { if ((0, _capabilities.isClient)() && _globalRoot.default.document) { _globalRoot.default.document.addEventListener('click', this.handleClickOutside); } } }, { key: "componentWillUnmount", value: function componentWillUnmount() { if ((0, _capabilities.isClient)() && _globalRoot.default.document) { _globalRoot.default.document.removeEventListener('click', this.handleClickOutside); } } }, { key: "toggleIcon", value: /** * Toggles the appropriate icon button based on whether the relevant panel is open. * @param {string} label The icon label. * @param {Function} renderIcon The icon to use. * @param {string} type The panel to check. * @returns {IconButton} The icon button to return. */ function toggleIcon(label, renderIcon, type) { var _this2 = this; var isActiveItem = this.state.isActive[type]; var iconButtonClass = "".concat(namespace, "__button"); var iconButtonClasses = (0, _classnames5.default)(iconButtonClass, (0, _defineProperty2.default)({}, "".concat(iconButtonClass, "--active"), isActiveItem)); return /*#__PURE__*/_react.default.createElement(_IconButton.default, (0, _extends2.default)({ className: iconButtonClasses, "aria-expanded": isActiveItem }, isActiveItem ? (0, _defineProperty2.default)({}, "aria-controls", "".concat(namespace, "--toolbar--").concat(type)) : {}, { "aria-label": label, iconClassName: "".concat(namespace, "__icon"), label: label, onClick: function onClick() { return _this2.togglePanel(type); }, renderIcon: isActiveItem ? _iconsReact.Close20 : renderIcon, state: isActiveItem, tooltip: !isActiveItem, tooltipDirection: _IconButton.default.TooltipDirection.RIGHT })); } /** * Toggles the panel and applies the appropriate class to the body. * @param {string} type The type of panel to toggle. */ }, { key: "togglePanel", value: function togglePanel(type) { var _this3 = this; _Component2.default.call(this, type, function (state) { var isToggled = state[type]; _this3.props.onToggle(isToggled); _globalRoot.default.dispatchEvent(new CustomEvent("".concat(namespace, ":toggle"), { detail: { isToggled: isToggled } })); }); } }, { key: "renderContent", value: /** * Renders the panel content. * @param {string} type The type of panel to render. * @returns {React.Element} The rendered panel. */ function renderContent(type) { var _this4 = this; var navigationType = this.props[type]; var isActiveItem = this.state.isActive[type]; return isActiveItem && navigationType.length > 0 && navigationType.map(function (_ref2) { var id = _ref2.id, navigation = _ref2.navigation, title = _ref2.title; return /*#__PURE__*/_react.default.createElement(_Nav.default, { key: id, heading: title, label: title }, navigation.filter(function (item) { return item !== null && item !== undefined; }).map(function (_ref3) { var children = _ref3.children, href = _ref3.href, content = _ref3.content, icon = _ref3.icon, navigationItemId = _ref3.id, navigationItemTitle = _ref3.title, props = (0, _objectWithoutProperties2.default)(_ref3, _excluded); var hasIcon = icon !== undefined; return children ? /*#__PURE__*/_react.default.createElement(_NavList.default, { className: (0, _classnames5.default)((0, _defineProperty2.default)({}, "".concat(namespace, "__nav__list__title--icon"), hasIcon)), renderIcon: hasIcon, icon: icon, key: navigationItemId, navigationItemTitle: navigationItemTitle, title: navigationItemTitle }, children.map(function (_ref4) { var navigationListItemHref = _ref4.href, navigationListItemElement = _ref4.element, content = _ref4.content, navigationListItemId = _ref4.id, navigationListItemTitle = _ref4.title, props = (0, _objectWithoutProperties2.default)(_ref4, _excluded2); return /*#__PURE__*/_react.default.createElement(_NavItem.default, (0, _extends2.default)({ key: navigationListItemId, onClick: function onClick() { return _this4.togglePanel(type); }, id: navigationListItemId, href: navigationListItemHref, element: navigationListItemElement, link: content === undefined, handleItemSelect: function handleItemSelect() { return _this4.toggleContent(content); } }, props), navigationListItemTitle); })) : /*#__PURE__*/_react.default.createElement(_NavItem.default, (0, _extends2.default)({ key: navigationItemId, id: navigationItemId, onClick: function onClick() { return _this4.togglePanel(type); }, href: href, link: content === undefined, handleItemSelect: function handleItemSelect() { return _this4.toggleContent(content); } }, props), hasIcon && /*#__PURE__*/_react.default.createElement("img", { alt: navigationItemTitle, className: "".concat(namespace, "__nav__item__icon"), src: icon }), /*#__PURE__*/_react.default.createElement("div", { className: (0, _classnames5.default)("".concat(namespace, "__nav__item__title"), (0, _defineProperty2.default)({}, "".concat(namespace, "__nav__item__title--icon"), hasIcon)) }, navigationItemTitle)); })); }); } }, { key: "render", value: function render() { var _this5 = this; var _this$props = this.props, className = _this$props.className, _this$props$labels = _this$props.labels, _this$props$labels$ma = _this$props$labels.mainNavigation, _this$props$labels$ma2 = _this$props$labels$ma === void 0 ? {} : _this$props$labels$ma, _this$props$labels$ma3 = _this$props$labels$ma2.ariaLabel, ariaLabel = _this$props$labels$ma3 === void 0 ? null : _this$props$labels$ma3, menu = _this$props$labels.menu, settings = _this$props$labels.settings, support = _this$props$labels.support, _this$props$renderAdd = _this$props.renderAddons, renderAddons = _this$props$renderAdd === void 0 ? [] : _this$props$renderAdd; var renderSupport = this.props.support.length > 0; var renderSettings = this.props.settings.length > 0; var classes = (0, _classnames5.default)(namespace, className, (0, _defineProperty2.default)({}, "".concat(namespace, "__minimized"), !renderSupport && !renderSettings)); var isActive = this.state.isActive; var activeItems = Object.entries(isActive) // eslint-disable-next-line no-unused-vars .filter(function (_ref5) { var _ref6 = (0, _slicedToArray2.default)(_ref5, 2), type = _ref6[0], isActiveItem = _ref6[1]; return isActiveItem; }); var currentType = ''; var isPanelActive = false; if (activeItems.length > 0) { var _activeItems = (0, _slicedToArray2.default)(activeItems, 1); var _activeItems$ = (0, _slicedToArray2.default)(_activeItems[0], 2); currentType = _activeItems$[0]; isPanelActive = _activeItems$[1]; } return /*#__PURE__*/_react.default.createElement("div", { ref: this.wrapper }, /*#__PURE__*/_react.default.createElement("nav", { "aria-label": ariaLabel, className: classes }, /*#__PURE__*/_react.default.createElement("ul", { className: "".concat(namespace, "__group") }, /*#__PURE__*/_react.default.createElement("li", null, this.toggleIcon(menu.button, _iconsReact.Menu20, 'menu')), renderSettings && /*#__PURE__*/_react.default.createElement("li", null, this.toggleIcon(settings.button, _iconsReact.Settings20, 'settings')), renderSupport && /*#__PURE__*/_react.default.createElement("li", null, this.toggleIcon(support.button, _iconsReact.Help20, 'support')), renderAddons.map(function (_ref7) { var id = _ref7.id, render = _ref7.render; return /*#__PURE__*/_react.default.createElement("li", { key: id }, render({ className: "".concat(namespace, "__button"), iconClassName: "".concat(namespace, "__icon") })); }))), /*#__PURE__*/_react.default.createElement(_Transition.default, { className: namespace, component: "span" }, isPanelActive && this.state.showContent ? /*#__PURE__*/_react.default.createElement("div", { role: "navigation", "aria-label": currentType, id: "".concat(namespace, "--toolbar--").concat(currentType), className: "".concat(namespace, "__panel") }, /*#__PURE__*/_react.default.createElement(_IconButton.default, { onClick: this.toggleContent, renderIcon: _iconsReact.ArrowLeft20 }), /*#__PURE__*/_react.default.createElement("div", { className: "".concat(namespace, "__content"), dangerouslySetInnerHTML: { __html: this.state.content } // eslint-disable-line react/no-danger })) : isPanelActive && /*#__PURE__*/_react.default.createElement("div", { role: "navigation", "aria-label": currentType, id: "".concat(namespace, "--toolbar--").concat(currentType), className: "".concat(namespace, "__panel") }, Object.keys(isActive).map(function (type) { return /*#__PURE__*/_react.default.createElement(_Transition.default, { key: type, className: "".concat(namespace, "__content"), component: "span" }, _this5.renderContent(type)); })))); } }]); }(_react.Component); var href = _propTypes.default.string.isRequired; var navigation = { /** @type {string} The ID of the navigation. */ id: _propTypes.default.string.isRequired, /** @type {string} The title of the navigation. */ title: _propTypes.default.node.isRequired, /** @type {node} Content. */ content: _propTypes.default.node, /** @type {string} Icon. */ icon: _propTypes.default.string }; var panel = function panel() { return /** @type {Array<Object.*>} An array list of navigation lists and sub-navigation. */_propTypes.default.arrayOf(/** @type {Record<object, object>} An object list of navigation. */ _propTypes.default.shape(_objectSpread(_objectSpread({}, navigation), {}, { /** @type {Array<Object.*>} An array list of navigation items. */ navigation: _propTypes.default.arrayOf(/** @type {Record<object, object>} An object list of navigation. */ _propTypes.default.shape(Object.assign({}, navigation, { /** @type {Array<Object.*>} An array list of sub-navigation items. */ children: _propTypes.default.arrayOf(/** @type {Record<object, object>} An object list of sub-navigation. */ _propTypes.default.shape(Object.assign({}, navigation, href))), href: href }))).isRequired })).isRequired); }; Toolbar.propTypes = { /** @type {string} Extra classes to add. */ className: _propTypes.default.string, /** @type {Record<object, object>} An object list of labels. */ labels: _propTypes.default.shape({ /** @type {Record<string, string>} An object list of navigation labels for the top level navigation item. */ mainNavigation: _propTypes.default.shape({ /** Specify the `aria-label` for the primary navigation */ ariaLabel: _propTypes.default.string.isRequired }).isRequired, /** @type {Record<string, string>} An object list of menu labels. */ menu: _propTypes.default.shape({ /** @type {string} The button label. */ button: _propTypes.default.string.isRequired, /** @type {string} The tooltip label. */ tooltip: _propTypes.default.string }).isRequired, /** @type {Record<string, string>} An object list of settings labels. */ settings: _propTypes.default.shape({ /** @type {string} The button label. */ button: _propTypes.default.string.isRequired, /** @type {string} The tooltip label. */ tooltip: _propTypes.default.string }), /** @type {Record<string, string>} An object list of support labels. */ support: _propTypes.default.shape({ /** @type {string} The button label. */ button: _propTypes.default.string.isRequired, /** @type {string} The tooltip label. */ tooltip: _propTypes.default.string }) }).isRequired, // eslint-disable-next-line react/no-unused-prop-types menu: panel(), /** @type {Function} Toggle handler. */ onToggle: _propTypes.default.func, /** @type {Array<{id: string, tooltip: string, render: Function: React.Element}>} An object list to render custom addon icons. */ renderAddons: _propTypes.default.arrayOf(_propTypes.default.shape({ id: _propTypes.default.string.isRequired, render: _propTypes.default.func.isRequired, tooltip: _propTypes.default.string })), // eslint-disable-next-line react/no-unused-prop-types settings: panel(), // eslint-disable-next-line react/no-unused-prop-types support: panel() }; Toolbar.defaultProps = { className: null, menu: [], onToggle: function onToggle(isToggled) { return isToggled; }, renderAddons: [], settings: [], support: [] };