@cimpress/react-components
Version:
React components to support the MCP styleguide
73 lines • 3.92 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import React, { useState, useEffect } from 'react';
import { css, cx } from '@emotion/css';
import TabGroup from './TabGroup';
import Tab from './Tab';
import cvar from '../theme/cvar';
const generateTabMap = (tabs) => tabs.reduce((tabAcc, tab) => (Object.assign(Object.assign({}, tabAcc), { [tab.id]: tab })), {});
const validateIcons = (tabs) => {
const tabsWithIcons = tabs.filter((tab) => Boolean(tab.icon));
const isValid = !tabsWithIcons.length || tabsWithIcons.length === tabs.length;
if (!isValid) {
console.warn('TabMenu: All tabs must have icons for them to render. Ignoring icons for all tabs...');
}
return isValid;
};
const validateDescriptions = (tabs) => {
const tabsWithDescriptions = tabs.filter((tab) => Boolean(tab.description));
const isValid = !tabsWithDescriptions.length || tabsWithDescriptions.length === tabs.length;
if (!isValid) {
console.warn('TabMenu: All tabs must have descriptions for them to render. Ignoring descriptions for all tabs...');
}
return isValid;
};
const tabMenuStyle = css `
display: flex;
`;
const tabsBaseStyle = css `
display: flex;
flex-direction: column;
min-width: 250px;
`;
const activeTabBodyStyle = css `
padding-left: ${cvar('spacing-24')};
flex-grow: 3;
`;
export const TabMenu = (_a) => {
var { className = '', activeTabId, tabs, tabGroups = [], onTabClick = () => { }, bodyStyle = {}, tabStyle = {}, style = {}, alwaysShowTabGroups = false } = _a, rest = __rest(_a, ["className", "activeTabId", "tabs", "tabGroups", "onTabClick", "bodyStyle", "tabStyle", "style", "alwaysShowTabGroups"]);
const [tabMap, setTabMap] = useState(generateTabMap(tabs));
const [showIcons, setShowIcons] = useState(validateIcons(tabs));
const [showDescriptions, setShowDescriptions] = useState(validateDescriptions(tabs));
useEffect(() => {
// Create a lookup mapping of tabs by id to optimize
setTabMap(generateTabMap(tabs));
setShowIcons(validateIcons(tabs));
setShowDescriptions(validateDescriptions(tabs));
}, [tabs]);
if (!tabs || !tabs.length) {
return null;
}
let activeTab = tabs[0];
if (activeTabId) {
activeTab = tabMap[activeTabId] || activeTab;
}
return (React.createElement("div", Object.assign({ className: cx('crc-tab-menu', tabMenuStyle, className), style: style }, rest),
React.createElement("div", { className: tabsBaseStyle, style: tabStyle }, tabGroups.length > 1 || alwaysShowTabGroups
? tabGroups.map(({ label, tabIds = [] }) => (React.createElement(TabGroup, { key: `${label}-${tabIds.join('-')}`, label: label }, tabIds.map(tabId => {
const { id, title, description, icon } = tabMap[tabId];
return (React.createElement(Tab, Object.assign({ key: id, id: id, title: title, onTabClick: onTabClick, isActive: activeTab.id === id }, (showIcons ? { icon } : {}), (showDescriptions ? { description } : {}))));
}))))
: tabs.map(({ id, title, description, icon }) => (React.createElement(Tab, Object.assign({ key: id, id: id, title: title, onTabClick: onTabClick, isActive: activeTab.id === id }, (showIcons ? { icon } : {}), (showDescriptions ? { description } : {})))))),
React.createElement("div", { className: activeTabBodyStyle, style: bodyStyle }, activeTab && activeTab.body)));
};
//# sourceMappingURL=TabMenu.js.map