@hitachivantara/uikit-react-pentaho
Version:
UI Kit Pentaho React components.
233 lines (232 loc) • 9.19 kB
JavaScript
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
};