UNPKG

@hitachivantara/uikit-react-pentaho

Version:
233 lines (232 loc) 9.19 kB
import { jsxs, jsx } from "react/jsx-runtime"; import { forwardRef, useState, useMemo } from "react"; import { useResizeDetector } from "react-resize-detector"; import { useDefaultProps, useLabels, useControlled, useForkRef, HvOverflowTooltip, HvDropDownMenu, HvButton, isKey, uniqueId } from "@hitachivantara/uikit-react-core"; import { CloseXS, MoreOptionsHorizontal, AddAlt } from "@hitachivantara/uikit-react-icons"; import { clamp } from "@hitachivantara/uikit-react-utils"; import { ToolbarTabEditor } from "./ToolbarTabEditor.js"; import { useClasses, MAX_TAB_WIDTH, MIN_TAB_WIDTH, DROPDOWN_MENU_WIDTH } from "./ToolbarTabs.styles.js"; import { staticClasses } from "./ToolbarTabs.styles.js"; import { HvCanvasPanelTabs } from "../PanelTabs/PanelTabs.js"; import { HvCanvasPanelTab } from "../PanelTab/PanelTab.js"; const DEFAULT_LABELS = { create: "Create new", undefined: "Undefined", dropdownMenu: "Dropdown menu" }; const HvCanvasToolbarTabs = forwardRef(function HvCanvasToolbarTabs2(props, ref) { const { children, className, selectedTabId: selectedTabIdProp, icon: iconProp, disableTabEdit = false, hideCreateNew = false, tabs: tabsProp, defaultTabs: defaultTabsProp = [], labels: labelsProp, classes: classesProp, onTabChange: onTabChangeProp, onChange: onChangeProp, ...others } = useDefaultProps("HvCanvasToolbarTabs", props); const { classes, cx } = useClasses(classesProp); const labels = useLabels(DEFAULT_LABELS, labelsProp); const { width: actionsWidth = 0, ref: actionsRef } = useResizeDetector({ handleHeight: false }); const { width: rootWidth = 0, ref: rootRef } = useResizeDetector({ handleHeight: false }); const [tabs, setTabs] = useControlled(tabsProp, defaultTabsProp); const [selectedTab, setSelectedTab] = useControlled( selectedTabIdProp, tabs?.[0]?.id ?? "none" ); const [isEditing, setIsEditing] = useState(false); const rootForkedRef = useForkRef(ref, rootRef); const handleChangeTabs = (event, newTabs) => { setTabs(newTabs); onChangeProp?.(event, newTabs); }; const handleChangeSelectedTab = (event, value) => { setSelectedTab(String(value)); onTabChangeProp?.(event, String(value)); }; const handleCreateNew = (event) => { const newTabs = [...tabs]; const newTab = { id: uniqueId(), label: `${labels.undefined} ${newTabs.length + 1}`, icon: iconProp }; newTabs.push(newTab); handleChangeSelectedTab(event, newTab.id); handleChangeTabs?.(event, newTabs); }; const handleEdit = (event, value, tabId) => handleChangeTabs( event, tabs.map((tab) => tab.id === tabId ? { ...tab, label: value } : tab) ); const handleDeleteTab = (event, tabId) => { const newTabs = tabs.filter((tab) => tab.id !== tabId); if (tabId === selectedTab) { const currentIndex = tabs.findIndex((tab) => tab.id === tabId); const newIndex = currentIndex - 1 < 0 ? 0 : currentIndex - 1; handleChangeSelectedTab(event, newTabs[newIndex]?.id ?? "none"); } handleChangeTabs(event, newTabs); }; const handleKeyDownTab = (event, tabId, removable) => { if (removable && (isKey(event, "Delete") || isKey(event, "Backspace"))) { handleDeleteTab(event, tabId); event.stopPropagation(); } else if (isKey(event, "Enter")) { setIsEditing(true); } }; const { tabWidth, hiddenTabs, visibleTabs } = useMemo(() => { let availableWidth = rootWidth - actionsWidth; let calculatedTabWidth = availableWidth / tabs.length; let clamped = clamp(calculatedTabWidth, MAX_TAB_WIDTH, MIN_TAB_WIDTH); if (calculatedTabWidth < MIN_TAB_WIDTH) { availableWidth -= DROPDOWN_MENU_WIDTH; const visibleCount = Math.floor(availableWidth / MIN_TAB_WIDTH); calculatedTabWidth = availableWidth / visibleCount; clamped = clamp(calculatedTabWidth, MAX_TAB_WIDTH, MIN_TAB_WIDTH); const temporaryHiddenTabs = tabs.slice(visibleCount); const selectedTabHiddenIndex = temporaryHiddenTabs.findIndex( (tab) => tab.id === selectedTab ); const excludedTabIndex = visibleCount - 1; const shouldShuffle = selectedTabHiddenIndex !== -1 && visibleCount > 0; if (shouldShuffle) { return { tabWidth: clamped, visibleTabs: [ ...tabs.slice(0, excludedTabIndex), temporaryHiddenTabs[selectedTabHiddenIndex] ].filter(Boolean), hiddenTabs: [ tabs[excludedTabIndex], ...temporaryHiddenTabs.filter( (tab, i) => i !== selectedTabHiddenIndex ) ].filter(Boolean) }; } return { tabWidth: clamped, visibleTabs: tabs.slice(0, visibleCount), hiddenTabs: temporaryHiddenTabs }; } return { tabWidth: clamped, visibleTabs: tabs, hiddenTabs: [] }; }, [actionsWidth, rootWidth, selectedTab, tabs]); return /* @__PURE__ */ jsxs( "div", { ref: rootForkedRef, className: cx(classes.root, className), ...others, children: [ /* @__PURE__ */ jsxs("div", { className: classes.tabsContainer, children: [ visibleTabs.length > 0 && /* @__PURE__ */ jsx( HvCanvasPanelTabs, { classes: { list: classes.tabsList }, value: selectedTab, onChange: handleChangeSelectedTab, children: visibleTabs.map((tab, index) => { const btnSelected = selectedTab === tab.id; const removable = !tab.fixed; return /* @__PURE__ */ jsx( HvCanvasPanelTab, { style: { width: tabWidth }, id: String(tab.id), className: classes.tab, value: tab.id, onKeyDown: (event) => handleKeyDownTab(event, tab.id, removable), children: /* @__PURE__ */ jsxs("div", { className: classes.tabContent, children: [ tab.icon && /* @__PURE__ */ jsx("div", { className: classes.tabIconContainer, children: tab.icon }), !btnSelected || disableTabEdit ? /* @__PURE__ */ jsx( HvOverflowTooltip, { classes: { tooltipAnchor: classes.tabLabel }, data: tab.label } ) : /* @__PURE__ */ jsx( ToolbarTabEditor, { classes: { label: cx(classes.tabLabel, classes.tabLabelEditor) }, value: tab.label, edit: isEditing, onEditChange: setIsEditing, onChange: (event, value) => handleEdit(event, value, tab.id), onBlur: (event, value) => handleEdit(event, value, tab.id), onKeyDown: (e) => e.stopPropagation() } ), removable && /* @__PURE__ */ jsx("div", { className: classes.closeIconContainer, children: /* @__PURE__ */ jsx( CloseXS, { "aria-hidden": true, size: "xs", onClick: (event) => { handleDeleteTab(event, tab.id); event.stopPropagation(); } } ) }), selectedTab !== tab.id && visibleTabs[index + 1]?.id !== selectedTab && /* @__PURE__ */ jsx("div", { className: classes.tabDivider }) ] }) }, tab.id ); }) } ), hiddenTabs.length > 0 && /* @__PURE__ */ jsx("div", { className: classes.dropdownMenuContainer, children: /* @__PURE__ */ jsx( HvDropDownMenu, { classes: { menuListRoot: classes.dropdownMenuListRoot }, dataList: hiddenTabs, icon: /* @__PURE__ */ jsx(MoreOptionsHorizontal, {}), labels: { dropdownMenu: labels.dropdownMenu }, onClick: (event, value) => handleChangeSelectedTab(event, value.id ?? "none") } ) }) ] }), /* @__PURE__ */ jsxs("div", { ref: actionsRef, className: classes.actionsContainer, children: [ children, !hideCreateNew && /* @__PURE__ */ jsx( HvButton, { variant: "primaryGhost", startIcon: /* @__PURE__ */ jsx(AddAlt, {}), onClick: handleCreateNew, children: labels.create } ) ] }) ] } ); }); export { HvCanvasToolbarTabs, staticClasses as canvasToolbarTabsClasses };