@carbon/ibm-security
Version:
Carbon for Cloud & Cognitive IBM Security UI components
400 lines (397 loc) • 20 kB
JavaScript
;
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: []
};