@hitachivantara/uikit-react-pentaho 0.4.3 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Canvas/BottomPanel/BottomPanel.cjs +0 -1
- package/dist/cjs/Canvas/SidePanel/SidePanel.cjs +0 -1
- package/dist/cjs/Canvas/SidePanel/SidePanel.styles.cjs +3 -2
- package/dist/cjs/Canvas/ToolbarTabs/ToolbarTabEditor.cjs +150 -0
- package/dist/cjs/Canvas/ToolbarTabs/ToolbarTabs.cjs +111 -143
- package/dist/cjs/Canvas/ToolbarTabs/ToolbarTabs.styles.cjs +59 -57
- package/dist/esm/Canvas/BottomPanel/BottomPanel.js +0 -1
- package/dist/esm/Canvas/BottomPanel/BottomPanel.js.map +1 -1
- package/dist/esm/Canvas/SidePanel/SidePanel.js +0 -1
- package/dist/esm/Canvas/SidePanel/SidePanel.js.map +1 -1
- package/dist/esm/Canvas/SidePanel/SidePanel.styles.js +4 -3
- package/dist/esm/Canvas/SidePanel/SidePanel.styles.js.map +1 -1
- package/dist/esm/Canvas/ToolbarTabs/ToolbarTabEditor.js +150 -0
- package/dist/esm/Canvas/ToolbarTabs/ToolbarTabEditor.js.map +1 -0
- package/dist/esm/Canvas/ToolbarTabs/ToolbarTabs.js +116 -148
- package/dist/esm/Canvas/ToolbarTabs/ToolbarTabs.js.map +1 -1
- package/dist/esm/Canvas/ToolbarTabs/ToolbarTabs.styles.js +60 -58
- package/dist/esm/Canvas/ToolbarTabs/ToolbarTabs.styles.js.map +1 -1
- package/dist/types/index.d.ts +15 -12
- package/package.json +6 -4
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import { jsxs,
|
|
2
|
-
import { forwardRef,
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useState, useMemo } from "react";
|
|
3
3
|
import { useResizeDetector } from "react-resize-detector";
|
|
4
|
-
import { useDefaultProps, useLabels, useControlled, useForkRef,
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { useDefaultProps, useLabels, useControlled, useForkRef, HvOverflowTooltip, HvDropDownMenu, HvButton, uniqueId, isKey } from "@hitachivantara/uikit-react-core";
|
|
5
|
+
import { CloseXS, MoreOptionsHorizontal, AddAlt } from "@hitachivantara/uikit-react-icons";
|
|
6
|
+
import { clamp } from "@hitachivantara/uikit-react-utils";
|
|
7
|
+
import { ToolbarTabEditor } from "./ToolbarTabEditor.js";
|
|
8
|
+
import { useClasses, MAX_TAB_WIDTH, MIN_TAB_WIDTH, DROPDOWN_MENU_WIDTH } from "./ToolbarTabs.styles.js";
|
|
7
9
|
import { staticClasses } from "./ToolbarTabs.styles.js";
|
|
8
10
|
import { HvCanvasPanelTabs } from "../PanelTabs/PanelTabs.js";
|
|
9
11
|
import { HvCanvasPanelTab } from "../PanelTab/PanelTab.js";
|
|
10
12
|
const DEFAULT_LABELS = {
|
|
11
13
|
create: "Create new",
|
|
12
14
|
undefined: "Undefined",
|
|
13
|
-
close: "Close",
|
|
14
15
|
dropdownMenu: "Dropdown menu"
|
|
15
16
|
};
|
|
16
|
-
const DROPDOWN_MENU_WIDTH = 64;
|
|
17
|
-
const BORDER_WIDTH = 2;
|
|
18
17
|
const HvCanvasToolbarTabs = forwardRef((props, ref) => {
|
|
19
18
|
const {
|
|
20
19
|
children,
|
|
21
20
|
className,
|
|
22
21
|
selectedTabId: selectedTabIdProp,
|
|
23
22
|
icon: iconProp,
|
|
23
|
+
allowTabEdit = true,
|
|
24
24
|
tabs: tabsProp,
|
|
25
25
|
defaultTabs: defaultTabsProp = [],
|
|
26
26
|
labels: labelsProp,
|
|
@@ -31,13 +31,6 @@ const HvCanvasToolbarTabs = forwardRef((props, ref) => {
|
|
|
31
31
|
} = useDefaultProps("HvCanvasToolbarTabs", props);
|
|
32
32
|
const { classes, cx } = useClasses(classesProp);
|
|
33
33
|
const labels = useLabels(DEFAULT_LABELS, labelsProp);
|
|
34
|
-
const { width: tabWidth = 0, ref: tabRef } = useResizeDetector({
|
|
35
|
-
handleHeight: false,
|
|
36
|
-
refreshMode: "debounce",
|
|
37
|
-
refreshOptions: {
|
|
38
|
-
leading: true
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
34
|
const { width: actionsWidth = 0, ref: actionsRef } = useResizeDetector({
|
|
42
35
|
handleHeight: false
|
|
43
36
|
});
|
|
@@ -49,56 +42,7 @@ const HvCanvasToolbarTabs = forwardRef((props, ref) => {
|
|
|
49
42
|
selectedTabIdProp,
|
|
50
43
|
tabs?.[0]?.id ?? "none"
|
|
51
44
|
);
|
|
52
|
-
const
|
|
53
|
-
const groupTabs = useCallback(
|
|
54
|
-
(allTabs) => {
|
|
55
|
-
let fullTabWidth = MIN_TAB_WIDTH;
|
|
56
|
-
const rootScrollWidth = rootRef.current?.scrollWidth ?? 0;
|
|
57
|
-
if (rootScrollWidth - rootWidth >= 1 || rootWidthLimitReached.current) {
|
|
58
|
-
fullTabWidth = tabWidth + BORDER_WIDTH;
|
|
59
|
-
rootWidthLimitReached.current = true;
|
|
60
|
-
}
|
|
61
|
-
const totalWidth = allTabs.length * fullTabWidth + DROPDOWN_MENU_WIDTH;
|
|
62
|
-
if (tabWidth > 0 && totalWidth > rootWidth - actionsWidth) {
|
|
63
|
-
const visibleCount = Math.floor(
|
|
64
|
-
(rootWidth - actionsWidth - DROPDOWN_MENU_WIDTH) / fullTabWidth
|
|
65
|
-
);
|
|
66
|
-
const temporaryHiddenTabs = allTabs.slice(visibleCount);
|
|
67
|
-
const selectedTabHiddenIndex = temporaryHiddenTabs.findIndex(
|
|
68
|
-
(tab) => tab.id === selectedTab
|
|
69
|
-
);
|
|
70
|
-
const excludedTabIndex = visibleCount - 1;
|
|
71
|
-
const shouldShuffle = selectedTabHiddenIndex !== -1 && visibleCount > 0;
|
|
72
|
-
if (shouldShuffle) {
|
|
73
|
-
return {
|
|
74
|
-
visibleTabs: [
|
|
75
|
-
...tabs.slice(0, excludedTabIndex),
|
|
76
|
-
temporaryHiddenTabs[selectedTabHiddenIndex]
|
|
77
|
-
].filter((tab) => tab),
|
|
78
|
-
hiddenTabs: [
|
|
79
|
-
tabs[excludedTabIndex],
|
|
80
|
-
...temporaryHiddenTabs.filter(
|
|
81
|
-
(tab, i) => i !== selectedTabHiddenIndex
|
|
82
|
-
)
|
|
83
|
-
].filter((tab) => tab)
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
return {
|
|
87
|
-
visibleTabs: tabs.slice(0, visibleCount),
|
|
88
|
-
hiddenTabs: temporaryHiddenTabs
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
return {
|
|
92
|
-
visibleTabs: allTabs,
|
|
93
|
-
hiddenTabs: []
|
|
94
|
-
};
|
|
95
|
-
},
|
|
96
|
-
[actionsWidth, rootRef, rootWidth, selectedTab, tabWidth, tabs]
|
|
97
|
-
);
|
|
98
|
-
const { hiddenTabs, visibleTabs } = useMemo(
|
|
99
|
-
() => groupTabs(tabs),
|
|
100
|
-
[groupTabs, tabs]
|
|
101
|
-
);
|
|
45
|
+
const [isEditing, setIsEditing] = useState(false);
|
|
102
46
|
const rootForkedRef = useForkRef(ref, rootRef);
|
|
103
47
|
const handleChangeTabs = (event, newTabs) => {
|
|
104
48
|
setTabs(newTabs);
|
|
@@ -119,20 +63,69 @@ const HvCanvasToolbarTabs = forwardRef((props, ref) => {
|
|
|
119
63
|
handleChangeSelectedTab(event, newTab.id);
|
|
120
64
|
handleChangeTabs?.(event, newTabs);
|
|
121
65
|
};
|
|
122
|
-
const
|
|
66
|
+
const handleEdit = (event, value, tabId) => handleChangeTabs(
|
|
67
|
+
event,
|
|
68
|
+
tabs.map((tab) => tab.id === tabId ? { ...tab, label: value } : tab)
|
|
69
|
+
);
|
|
70
|
+
const handleDeleteTab = (event, tabId) => {
|
|
123
71
|
const newTabs = tabs.filter((tab) => tab.id !== tabId);
|
|
124
72
|
if (tabId === selectedTab) {
|
|
125
73
|
const currentIndex = tabs.findIndex((tab) => tab.id === tabId);
|
|
126
74
|
const newIndex = currentIndex - 1 < 0 ? 0 : currentIndex - 1;
|
|
127
75
|
handleChangeSelectedTab(event, newTabs[newIndex]?.id ?? "none");
|
|
128
76
|
}
|
|
129
|
-
if (hiddenTabs.length === 1) rootWidthLimitReached.current = false;
|
|
130
77
|
handleChangeTabs(event, newTabs);
|
|
131
78
|
};
|
|
132
|
-
const
|
|
133
|
-
event,
|
|
134
|
-
|
|
135
|
-
|
|
79
|
+
const handleKeyDownTab = (event, tabId) => {
|
|
80
|
+
if (isKey(event, "Delete") || isKey(event, "Backspace")) {
|
|
81
|
+
handleDeleteTab(event, tabId);
|
|
82
|
+
event.stopPropagation();
|
|
83
|
+
} else if (isKey(event, "Enter")) {
|
|
84
|
+
setIsEditing(true);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const { tabWidth, hiddenTabs, visibleTabs } = useMemo(() => {
|
|
88
|
+
let availableWidth = rootWidth - actionsWidth;
|
|
89
|
+
let calculatedTabWidth = availableWidth / tabs.length;
|
|
90
|
+
let clamped = clamp(calculatedTabWidth, MAX_TAB_WIDTH, MIN_TAB_WIDTH);
|
|
91
|
+
if (calculatedTabWidth < MIN_TAB_WIDTH) {
|
|
92
|
+
availableWidth -= DROPDOWN_MENU_WIDTH;
|
|
93
|
+
const visibleCount = Math.floor(availableWidth / MIN_TAB_WIDTH);
|
|
94
|
+
calculatedTabWidth = availableWidth / visibleCount;
|
|
95
|
+
clamped = clamp(calculatedTabWidth, MAX_TAB_WIDTH, MIN_TAB_WIDTH);
|
|
96
|
+
const temporaryHiddenTabs = tabs.slice(visibleCount);
|
|
97
|
+
const selectedTabHiddenIndex = temporaryHiddenTabs.findIndex(
|
|
98
|
+
(tab) => tab.id === selectedTab
|
|
99
|
+
);
|
|
100
|
+
const excludedTabIndex = visibleCount - 1;
|
|
101
|
+
const shouldShuffle = selectedTabHiddenIndex !== -1 && visibleCount > 0;
|
|
102
|
+
if (shouldShuffle) {
|
|
103
|
+
return {
|
|
104
|
+
tabWidth: clamped,
|
|
105
|
+
visibleTabs: [
|
|
106
|
+
...tabs.slice(0, excludedTabIndex),
|
|
107
|
+
temporaryHiddenTabs[selectedTabHiddenIndex]
|
|
108
|
+
].filter((tab) => tab),
|
|
109
|
+
hiddenTabs: [
|
|
110
|
+
tabs[excludedTabIndex],
|
|
111
|
+
...temporaryHiddenTabs.filter(
|
|
112
|
+
(tab, i) => i !== selectedTabHiddenIndex
|
|
113
|
+
)
|
|
114
|
+
].filter((tab) => tab)
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
tabWidth: clamped,
|
|
119
|
+
visibleTabs: tabs.slice(0, visibleCount),
|
|
120
|
+
hiddenTabs: temporaryHiddenTabs
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
tabWidth: clamped,
|
|
125
|
+
visibleTabs: tabs,
|
|
126
|
+
hiddenTabs: []
|
|
127
|
+
};
|
|
128
|
+
}, [actionsWidth, rootWidth, selectedTab, tabs]);
|
|
136
129
|
return /* @__PURE__ */ jsxs(
|
|
137
130
|
"div",
|
|
138
131
|
{
|
|
@@ -141,99 +134,74 @@ const HvCanvasToolbarTabs = forwardRef((props, ref) => {
|
|
|
141
134
|
...others,
|
|
142
135
|
children: [
|
|
143
136
|
/* @__PURE__ */ jsxs("div", { className: classes.tabsContainer, children: [
|
|
144
|
-
visibleTabs.length > 0 && /* @__PURE__ */
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
{
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
137
|
+
visibleTabs.length > 0 && /* @__PURE__ */ jsx(
|
|
138
|
+
HvCanvasPanelTabs,
|
|
139
|
+
{
|
|
140
|
+
classes: { list: classes.tabsList },
|
|
141
|
+
value: selectedTab,
|
|
142
|
+
onChange: handleChangeSelectedTab,
|
|
143
|
+
children: visibleTabs.map((tab, index) => {
|
|
144
|
+
const btnSelected = selectedTab === tab.id;
|
|
145
|
+
return /* @__PURE__ */ jsx(
|
|
152
146
|
HvCanvasPanelTab,
|
|
153
147
|
{
|
|
154
|
-
|
|
148
|
+
style: {
|
|
149
|
+
width: tabWidth
|
|
150
|
+
},
|
|
155
151
|
id: String(tab.id),
|
|
156
152
|
className: classes.tab,
|
|
157
153
|
value: tab.id,
|
|
158
|
-
|
|
159
|
-
"aria-label": tab.label,
|
|
154
|
+
onKeyDown: (event) => handleKeyDownTab(event, tab.id),
|
|
160
155
|
children: /* @__PURE__ */ jsxs("div", { className: classes.tabContent, children: [
|
|
161
|
-
/* @__PURE__ */ jsx(
|
|
162
|
-
|
|
156
|
+
tab.icon && /* @__PURE__ */ jsx("div", { className: classes.tabIconContainer, children: tab.icon }),
|
|
157
|
+
!btnSelected || !allowTabEdit ? /* @__PURE__ */ jsx(
|
|
158
|
+
HvOverflowTooltip,
|
|
159
|
+
{
|
|
160
|
+
classes: {
|
|
161
|
+
tooltipAnchor: classes.tabLabel
|
|
162
|
+
},
|
|
163
|
+
data: tab.label
|
|
164
|
+
}
|
|
165
|
+
) : /* @__PURE__ */ jsx(
|
|
166
|
+
ToolbarTabEditor,
|
|
163
167
|
{
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
+
classes: {
|
|
169
|
+
label: cx(classes.tabLabel, classes.tabLabelEditor)
|
|
170
|
+
},
|
|
171
|
+
value: tab.label,
|
|
172
|
+
edit: isEditing,
|
|
173
|
+
onEditChange: setIsEditing,
|
|
174
|
+
onChange: (event, value) => handleEdit(event, value, tab.id),
|
|
175
|
+
onBlur: (event, value) => handleEdit(event, value, tab.id),
|
|
176
|
+
onKeyDown: (e) => e.stopPropagation()
|
|
168
177
|
}
|
|
169
178
|
),
|
|
170
|
-
/* @__PURE__ */ jsx("div", {
|
|
171
|
-
|
|
179
|
+
/* @__PURE__ */ jsx("div", { className: classes.closeIconContainer, children: /* @__PURE__ */ jsx(
|
|
180
|
+
CloseXS,
|
|
181
|
+
{
|
|
182
|
+
"aria-hidden": true,
|
|
183
|
+
iconSize: "XS",
|
|
184
|
+
onClick: (event) => {
|
|
185
|
+
handleDeleteTab(event, tab.id);
|
|
186
|
+
event.stopPropagation();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
) }),
|
|
172
190
|
selectedTab !== tab.id && visibleTabs[index + 1]?.id !== selectedTab && /* @__PURE__ */ jsx("div", { className: classes.tabDivider })
|
|
173
191
|
] })
|
|
174
192
|
},
|
|
175
193
|
tab.id
|
|
176
|
-
)
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const btnDisabled = selectedTab !== tab.id;
|
|
181
|
-
const num = index + 1;
|
|
182
|
-
return /* @__PURE__ */ jsxs(
|
|
183
|
-
"div",
|
|
184
|
-
{
|
|
185
|
-
style: {
|
|
186
|
-
// @ts-ignore
|
|
187
|
-
"--full-tab-width": `calc(${tabWidth}px + ${BORDER_WIDTH}px)`,
|
|
188
|
-
"--right": `calc(${num} * var(--full-tab-width))`,
|
|
189
|
-
"--editor-width": `calc(var(--full-tab-width) - ${tab.icon ? 2 : 1} * ${ICON_WIDTH}px - ${theme.space.xs})`
|
|
190
|
-
},
|
|
191
|
-
children: [
|
|
192
|
-
btnDisabled ? /* @__PURE__ */ jsx(
|
|
193
|
-
"button",
|
|
194
|
-
{
|
|
195
|
-
type: "button",
|
|
196
|
-
className: classes.tabLabel,
|
|
197
|
-
onClick: (event) => handleChangeSelectedTab(event, tab.id),
|
|
198
|
-
"aria-label": tab.label,
|
|
199
|
-
tabIndex: -1,
|
|
200
|
-
children: /* @__PURE__ */ jsx(HvOverflowTooltip, { data: tab.label })
|
|
201
|
-
}
|
|
202
|
-
) : /* @__PURE__ */ jsx(
|
|
203
|
-
HvInlineEditor,
|
|
204
|
-
{
|
|
205
|
-
className: cx(classes.tabLabel, classes.activeTabLabel),
|
|
206
|
-
"aria-label": tab.label,
|
|
207
|
-
value: tab.label,
|
|
208
|
-
buttonProps: { size: "sm" },
|
|
209
|
-
onChange: (event, value) => handleEdit(event, value, tab.id)
|
|
210
|
-
}
|
|
211
|
-
),
|
|
212
|
-
/* @__PURE__ */ jsx(
|
|
213
|
-
HvIconButton,
|
|
214
|
-
{
|
|
215
|
-
style: {
|
|
216
|
-
// @ts-ignore
|
|
217
|
-
"--close-color": btnDisabled ? theme.colors.secondary_60 : theme.colors.primary
|
|
218
|
-
},
|
|
219
|
-
className: classes.closeButton,
|
|
220
|
-
title: labels.close,
|
|
221
|
-
variant: "primaryGhost",
|
|
222
|
-
onClick: (event) => handleClose(event, tab.id),
|
|
223
|
-
children: /* @__PURE__ */ jsx(CloseXS, {})
|
|
224
|
-
},
|
|
225
|
-
tab.id
|
|
226
|
-
)
|
|
227
|
-
]
|
|
228
|
-
},
|
|
229
|
-
tab.id
|
|
230
|
-
);
|
|
231
|
-
})
|
|
232
|
-
] }),
|
|
194
|
+
);
|
|
195
|
+
})
|
|
196
|
+
}
|
|
197
|
+
),
|
|
233
198
|
hiddenTabs.length > 0 && /* @__PURE__ */ jsx(
|
|
234
199
|
HvDropDownMenu,
|
|
235
200
|
{
|
|
236
|
-
|
|
201
|
+
classes: {
|
|
202
|
+
container: classes.dropdownMenuContainer,
|
|
203
|
+
menuListRoot: classes.dropdownMenuListRoot
|
|
204
|
+
},
|
|
237
205
|
dataList: hiddenTabs,
|
|
238
206
|
icon: /* @__PURE__ */ jsx(MoreOptionsHorizontal, {}),
|
|
239
207
|
labels: { dropdownMenu: labels.dropdownMenu },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolbarTabs.js","sources":["../../../../src/Canvas/ToolbarTabs/ToolbarTabs.tsx"],"sourcesContent":["import { forwardRef, useCallback, useMemo, useRef } from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\nimport {\n ExtractNames,\n HvBaseProps,\n HvButton,\n HvButtonProps,\n HvDropDownMenu,\n HvIconButton,\n HvInlineEditor,\n HvOverflowTooltip,\n theme,\n uniqueId,\n useControlled,\n useDefaultProps,\n useForkRef,\n useLabels,\n} from \"@hitachivantara/uikit-react-core\";\nimport {\n AddAlt,\n Close,\n CloseXS,\n MoreOptionsHorizontal,\n} from \"@hitachivantara/uikit-react-icons\";\n\nimport { HvCanvasPanelTab } from \"../PanelTab\";\nimport { HvCanvasPanelTabs, HvCanvasPanelTabsProps } from \"../PanelTabs\";\nimport {\n ICON_WIDTH,\n MIN_TAB_WIDTH,\n staticClasses,\n useClasses,\n} from \"./ToolbarTabs.styles\";\n\nexport { staticClasses as canvasToolbarTabsClasses };\n\nexport type HvCanvasToolbarTabsClasses = ExtractNames<typeof useClasses>;\n\nconst DEFAULT_LABELS = {\n create: \"Create new\",\n undefined: \"Undefined\",\n close: \"Close\",\n dropdownMenu: \"Dropdown menu\",\n};\n\ninterface ToolbarTabsTab {\n id: string;\n label: string;\n icon?: React.ReactNode;\n}\n\nexport interface HvCanvasToolbarTabsProps\n extends HvBaseProps<HTMLDivElement, \"onChange\"> {\n /** When controlled, defines the tabs. */\n tabs?: ToolbarTabsTab[];\n /** When uncontrolled, defines the initial tabs. */\n defaultTabs?: ToolbarTabsTab[];\n /** Id of the selected tab if it needs to be controlled. */\n selectedTabId?: string;\n /** Defines the icon to be placed before the label when a new tab is created. If not defined, no icon is used. */\n icon?: React.ReactNode;\n /** Callback triggered when a tab changes/is clicked. */\n onTabChange?: (\n event: React.SyntheticEvent | null,\n tabId: string | null,\n ) => void;\n /** Callback triggered when the tabs change: new tab added, tab removed, tab reorder, and label updated. */\n onChange?: (\n event: React.MouseEvent<HTMLButtonElement> | React.SyntheticEvent,\n tabs: ToolbarTabsTab[],\n ) => void;\n /** An object containing all the labels. */\n labels?: Partial<typeof DEFAULT_LABELS>;\n /** A Jss Object used to override or extend the styles applied. */\n classes?: HvCanvasToolbarTabsClasses;\n}\n\ninterface GroupedTabs {\n hiddenTabs: ToolbarTabsTab[];\n visibleTabs: ToolbarTabsTab[];\n}\n\nconst DROPDOWN_MENU_WIDTH = 64;\nconst BORDER_WIDTH = 2;\n\n/**\n * A toolbar tabs component to use in a canvas context.\n */\nexport const HvCanvasToolbarTabs = forwardRef<\n HTMLDivElement,\n HvCanvasToolbarTabsProps\n>((props, ref) => {\n const {\n children,\n className,\n selectedTabId: selectedTabIdProp,\n icon: iconProp,\n tabs: tabsProp,\n defaultTabs: defaultTabsProp = [],\n labels: labelsProp,\n classes: classesProp,\n onTabChange: onTabChangeProp,\n onChange: onChangeProp,\n ...others\n } = useDefaultProps(\"HvCanvasToolbarTabs\", props);\n\n const { classes, cx } = useClasses(classesProp);\n\n const labels = useLabels(DEFAULT_LABELS, labelsProp);\n\n // Tab resize detector: to know when to use the dropdown menu\n const { width: tabWidth = 0, ref: tabRef } = useResizeDetector({\n handleHeight: false,\n refreshMode: \"debounce\",\n refreshOptions: {\n leading: true,\n },\n });\n\n // Actions resize detector: to know when to use the dropdown menu\n const { width: actionsWidth = 0, ref: actionsRef } = useResizeDetector({\n handleHeight: false,\n });\n\n // Root resize detector: to know when to use the dropdown menu\n const { width: rootWidth = 0, ref: rootRef } = useResizeDetector({\n handleHeight: false,\n });\n\n const [tabs, setTabs] = useControlled(tabsProp, defaultTabsProp);\n const [selectedTab, setSelectedTab] = useControlled<string | null>(\n selectedTabIdProp,\n tabs?.[0]?.id ?? \"none\",\n );\n\n const rootWidthLimitReached = useRef(false);\n\n const groupTabs = useCallback(\n (allTabs: ToolbarTabsTab[]): GroupedTabs => {\n let fullTabWidth = MIN_TAB_WIDTH;\n\n const rootScrollWidth = rootRef.current?.scrollWidth ?? 0;\n if (rootScrollWidth - rootWidth >= 1 || rootWidthLimitReached.current) {\n fullTabWidth = tabWidth + BORDER_WIDTH;\n rootWidthLimitReached.current = true;\n }\n\n const totalWidth = allTabs.length * fullTabWidth + DROPDOWN_MENU_WIDTH;\n\n if (tabWidth > 0 && totalWidth > rootWidth - actionsWidth) {\n const visibleCount = Math.floor(\n (rootWidth - actionsWidth - DROPDOWN_MENU_WIDTH) / fullTabWidth,\n );\n const temporaryHiddenTabs = allTabs.slice(visibleCount);\n const selectedTabHiddenIndex = temporaryHiddenTabs.findIndex(\n (tab) => tab.id === selectedTab,\n );\n const excludedTabIndex = visibleCount - 1;\n const shouldShuffle = selectedTabHiddenIndex !== -1 && visibleCount > 0;\n\n if (shouldShuffle) {\n return {\n visibleTabs: [\n ...tabs.slice(0, excludedTabIndex),\n temporaryHiddenTabs[selectedTabHiddenIndex],\n ].filter((tab) => tab),\n hiddenTabs: [\n tabs[excludedTabIndex],\n ...temporaryHiddenTabs.filter(\n (tab, i) => i !== selectedTabHiddenIndex,\n ),\n ].filter((tab) => tab),\n };\n }\n return {\n visibleTabs: tabs.slice(0, visibleCount),\n hiddenTabs: temporaryHiddenTabs,\n };\n }\n return {\n visibleTabs: allTabs,\n hiddenTabs: [],\n };\n },\n [actionsWidth, rootRef, rootWidth, selectedTab, tabWidth, tabs],\n );\n\n const { hiddenTabs, visibleTabs } = useMemo(\n () => groupTabs(tabs),\n [groupTabs, tabs],\n );\n\n const rootForkedRef = useForkRef(ref, rootRef);\n\n const handleChangeTabs = (\n event: React.MouseEvent<HTMLButtonElement> | React.SyntheticEvent,\n newTabs: ToolbarTabsTab[],\n ) => {\n setTabs(newTabs);\n onChangeProp?.(event, newTabs);\n };\n\n const handleChangeSelectedTab: HvCanvasPanelTabsProps[\"onChange\"] = (\n event,\n value,\n ) => {\n setSelectedTab(String(value));\n onTabChangeProp?.(event, String(value));\n };\n\n const handleCreateNew: HvButtonProps[\"onClick\"] = (event) => {\n const newTabs: ToolbarTabsTab[] = [...tabs];\n const newTab: ToolbarTabsTab = {\n id: uniqueId(),\n label: `${labels.undefined} ${newTabs.length + 1}`,\n icon: iconProp,\n };\n newTabs.push(newTab);\n handleChangeSelectedTab(event, newTab.id);\n handleChangeTabs?.(event, newTabs);\n };\n\n const handleClose = (\n event: React.MouseEvent<HTMLButtonElement>,\n tabId: string,\n ) => {\n const newTabs = tabs.filter((tab) => tab.id !== tabId);\n\n if (tabId === selectedTab) {\n const currentIndex = tabs.findIndex((tab) => tab.id === tabId);\n const newIndex = currentIndex - 1 < 0 ? 0 : currentIndex - 1;\n handleChangeSelectedTab(event, newTabs[newIndex]?.id ?? \"none\");\n }\n\n if (hiddenTabs.length === 1) rootWidthLimitReached.current = false;\n\n handleChangeTabs(event, newTabs);\n };\n\n const handleEdit = (\n event: React.SyntheticEvent,\n value: string,\n tabId: string,\n ) =>\n handleChangeTabs(\n event,\n tabs.map((tab) => (tab.id === tabId ? { ...tab, label: value } : tab)),\n );\n\n return (\n <div\n ref={rootForkedRef}\n className={cx(classes.root, className)}\n {...others}\n >\n <div className={classes.tabsContainer}>\n {visibleTabs.length > 0 && (\n <>\n <HvCanvasPanelTabs\n classes={{ list: classes.tabsList }}\n value={selectedTab}\n onChange={handleChangeSelectedTab}\n >\n {visibleTabs.map((tab, index) => (\n <HvCanvasPanelTab\n key={tab.id}\n ref={index === 0 ? tabRef : undefined}\n id={String(tab.id)}\n className={classes.tab}\n value={tab.id}\n tabIndex={0}\n aria-label={tab.label}\n >\n <div className={classes.tabContent}>\n <div\n className={cx({\n [classes.tabIcon]: !!tab.icon,\n })}\n >\n {tab.icon}\n </div>\n\n {/* Invisible components added in order for the tab width to go between max/min as some inner components are absolutely positioned */}\n <div role=\"none\">{tab.label}</div>\n <div role=\"none\">\n <Close />\n </div>\n\n {selectedTab !== tab.id &&\n visibleTabs[index + 1]?.id !== selectedTab && (\n <div className={classes.tabDivider} />\n )}\n </div>\n </HvCanvasPanelTab>\n ))}\n </HvCanvasPanelTabs>\n {/* For accessibility purposes, interactive elements cannot be children of a tablist or tab so they are rendered as HvCanvasTabs sibling. */}\n {visibleTabs.map((tab, index) => {\n const btnDisabled = selectedTab !== tab.id;\n const num = index + 1;\n return (\n <div\n key={tab.id}\n style={{\n // @ts-ignore\n \"--full-tab-width\": `calc(${tabWidth}px + ${BORDER_WIDTH}px)`,\n \"--right\": `calc(${num} * var(--full-tab-width))`,\n \"--editor-width\": `calc(var(--full-tab-width) - ${tab.icon ? 2 : 1} * ${ICON_WIDTH}px - ${theme.space.xs})`,\n }}\n >\n {btnDisabled ? (\n <button\n type=\"button\"\n className={classes.tabLabel}\n onClick={(event) =>\n handleChangeSelectedTab(event, tab.id)\n }\n aria-label={tab.label}\n tabIndex={-1}\n >\n <HvOverflowTooltip data={tab.label} />\n </button>\n ) : (\n <HvInlineEditor\n className={cx(classes.tabLabel, classes.activeTabLabel)}\n aria-label={tab.label}\n value={tab.label}\n buttonProps={{ size: \"sm\" }}\n onChange={(event, value) =>\n handleEdit(event, value, tab.id)\n }\n />\n )}\n <HvIconButton\n key={tab.id}\n style={{\n // @ts-ignore\n \"--close-color\": btnDisabled\n ? theme.colors.secondary_60\n : theme.colors.primary,\n }}\n className={classes.closeButton}\n title={labels.close}\n variant=\"primaryGhost\"\n onClick={(event: React.MouseEvent<HTMLButtonElement>) =>\n handleClose(event, tab.id)\n }\n >\n <CloseXS />\n </HvIconButton>\n </div>\n );\n })}\n </>\n )}\n {hiddenTabs.length > 0 && (\n <HvDropDownMenu\n className={classes.dropdownMenu}\n dataList={hiddenTabs}\n icon={<MoreOptionsHorizontal />}\n labels={{ dropdownMenu: labels.dropdownMenu }}\n onClick={(event, value) =>\n handleChangeSelectedTab(event, value.id ?? \"none\")\n }\n />\n )}\n </div>\n <div ref={actionsRef} className={classes.actionsContainer}>\n {children}\n <HvButton\n variant=\"primaryGhost\"\n startIcon={<AddAlt />}\n onClick={handleCreateNew}\n >\n {labels.create}\n </HvButton>\n </div>\n </div>\n );\n});\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ToolbarTabs.js","sources":["../../../../src/Canvas/ToolbarTabs/ToolbarTabs.tsx"],"sourcesContent":["import { forwardRef, useMemo, useState } from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\nimport {\n ExtractNames,\n HvBaseProps,\n HvButton,\n HvButtonProps,\n HvDropDownMenu,\n HvOverflowTooltip,\n isKey,\n uniqueId,\n useControlled,\n useDefaultProps,\n useForkRef,\n useLabels,\n} from \"@hitachivantara/uikit-react-core\";\nimport {\n AddAlt,\n CloseXS,\n MoreOptionsHorizontal,\n} from \"@hitachivantara/uikit-react-icons\";\nimport { clamp } from \"@hitachivantara/uikit-react-utils\";\n\nimport { HvCanvasPanelTab } from \"../PanelTab\";\nimport { HvCanvasPanelTabs, HvCanvasPanelTabsProps } from \"../PanelTabs\";\nimport { ToolbarTabEditor } from \"./ToolbarTabEditor\";\nimport {\n DROPDOWN_MENU_WIDTH,\n MAX_TAB_WIDTH,\n MIN_TAB_WIDTH,\n staticClasses,\n useClasses,\n} from \"./ToolbarTabs.styles\";\n\nexport { staticClasses as canvasToolbarTabsClasses };\n\nexport type HvCanvasToolbarTabsClasses = ExtractNames<typeof useClasses>;\n\nconst DEFAULT_LABELS = {\n create: \"Create new\",\n undefined: \"Undefined\",\n dropdownMenu: \"Dropdown menu\",\n};\n\ninterface ToolbarTabsTab {\n id: string;\n label: string;\n icon?: React.ReactNode;\n}\n\nexport interface HvCanvasToolbarTabsProps\n extends HvBaseProps<HTMLDivElement, \"onChange\"> {\n /** When controlled, defines the tabs. */\n tabs?: ToolbarTabsTab[];\n /** When uncontrolled, defines the initial tabs. */\n defaultTabs?: ToolbarTabsTab[];\n /** Id of the selected tab if it needs to be controlled. */\n selectedTabId?: string;\n /** Defines the icon to be placed before the label when a new tab is created. If not defined, no icon is used. */\n icon?: React.ReactNode;\n /** Defines whether or not the tabs are editable. */\n allowTabEdit?: boolean;\n /** Callback triggered when a tab changes/is clicked. */\n onTabChange?: (\n event: React.SyntheticEvent | null,\n tabId: string | null,\n ) => void;\n /** Callback triggered when the tabs change: new tab added, tab removed, tab reorder, and label updated. */\n onChange?: (\n event: React.MouseEvent<HTMLButtonElement> | React.SyntheticEvent,\n tabs: ToolbarTabsTab[],\n ) => void;\n /** An object containing all the labels. */\n labels?: Partial<typeof DEFAULT_LABELS>;\n /** A Jss Object used to override or extend the styles applied. */\n classes?: HvCanvasToolbarTabsClasses;\n}\n\n/**\n * A toolbar tabs component to use in a canvas context.\n */\nexport const HvCanvasToolbarTabs = forwardRef<\n HTMLDivElement,\n HvCanvasToolbarTabsProps\n>((props, ref) => {\n const {\n children,\n className,\n selectedTabId: selectedTabIdProp,\n icon: iconProp,\n allowTabEdit = true,\n tabs: tabsProp,\n defaultTabs: defaultTabsProp = [],\n labels: labelsProp,\n classes: classesProp,\n onTabChange: onTabChangeProp,\n onChange: onChangeProp,\n ...others\n } = useDefaultProps(\"HvCanvasToolbarTabs\", props);\n\n const { classes, cx } = useClasses(classesProp);\n\n const labels = useLabels(DEFAULT_LABELS, labelsProp);\n\n // Actions resize detector: to know when to use the dropdown menu\n const { width: actionsWidth = 0, ref: actionsRef } = useResizeDetector({\n handleHeight: false,\n });\n\n // Root resize detector: to know when to use the dropdown menu\n const { width: rootWidth = 0, ref: rootRef } = useResizeDetector({\n handleHeight: false,\n });\n\n const [tabs, setTabs] = useControlled(tabsProp, defaultTabsProp);\n const [selectedTab, setSelectedTab] = useControlled<string | null>(\n selectedTabIdProp,\n tabs?.[0]?.id ?? \"none\",\n );\n const [isEditing, setIsEditing] = useState(false);\n\n const rootForkedRef = useForkRef(ref, rootRef);\n\n const handleChangeTabs = (\n event: React.MouseEvent<HTMLButtonElement> | React.SyntheticEvent,\n newTabs: ToolbarTabsTab[],\n ) => {\n setTabs(newTabs);\n onChangeProp?.(event, newTabs);\n };\n\n const handleChangeSelectedTab: HvCanvasPanelTabsProps[\"onChange\"] = (\n event,\n value,\n ) => {\n setSelectedTab(String(value));\n onTabChangeProp?.(event, String(value));\n };\n\n const handleCreateNew: HvButtonProps[\"onClick\"] = (event) => {\n const newTabs: ToolbarTabsTab[] = [...tabs];\n const newTab: ToolbarTabsTab = {\n id: uniqueId(),\n label: `${labels.undefined} ${newTabs.length + 1}`,\n icon: iconProp,\n };\n newTabs.push(newTab);\n handleChangeSelectedTab(event, newTab.id);\n handleChangeTabs?.(event, newTabs);\n };\n\n const handleEdit = (\n event: React.FormEvent<Element>,\n value: string,\n tabId: string,\n ) =>\n handleChangeTabs(\n event,\n tabs.map((tab) => (tab.id === tabId ? { ...tab, label: value } : tab)),\n );\n\n const handleDeleteTab = (event: any, tabId: string) => {\n const newTabs = tabs.filter((tab) => tab.id !== tabId);\n\n if (tabId === selectedTab) {\n const currentIndex = tabs.findIndex((tab) => tab.id === tabId);\n const newIndex = currentIndex - 1 < 0 ? 0 : currentIndex - 1;\n handleChangeSelectedTab(event, newTabs[newIndex]?.id ?? \"none\");\n }\n\n handleChangeTabs(event, newTabs);\n };\n\n const handleKeyDownTab = (event: React.KeyboardEvent, tabId: string) => {\n if (isKey(event, \"Delete\") || isKey(event, \"Backspace\")) {\n handleDeleteTab(event, tabId);\n\n // We don't want the click to also select the tab\n event.stopPropagation();\n } else if (isKey(event, \"Enter\")) {\n // Activate edit label mode\n setIsEditing(true);\n }\n };\n\n const { tabWidth, hiddenTabs, visibleTabs } = useMemo(() => {\n let availableWidth = rootWidth - actionsWidth;\n let calculatedTabWidth = availableWidth / tabs.length;\n let clamped = clamp(calculatedTabWidth, MAX_TAB_WIDTH, MIN_TAB_WIDTH);\n\n // Overflowing\n if (calculatedTabWidth < MIN_TAB_WIDTH) {\n availableWidth -= DROPDOWN_MENU_WIDTH;\n const visibleCount = Math.floor(availableWidth / MIN_TAB_WIDTH);\n calculatedTabWidth = availableWidth / visibleCount;\n clamped = clamp(calculatedTabWidth, MAX_TAB_WIDTH, MIN_TAB_WIDTH);\n\n const temporaryHiddenTabs = tabs.slice(visibleCount);\n const selectedTabHiddenIndex = temporaryHiddenTabs.findIndex(\n (tab) => tab.id === selectedTab,\n );\n const excludedTabIndex = visibleCount - 1;\n const shouldShuffle = selectedTabHiddenIndex !== -1 && visibleCount > 0;\n\n if (shouldShuffle) {\n return {\n tabWidth: clamped,\n visibleTabs: [\n ...tabs.slice(0, excludedTabIndex),\n temporaryHiddenTabs[selectedTabHiddenIndex],\n ].filter((tab) => tab),\n hiddenTabs: [\n tabs[excludedTabIndex],\n ...temporaryHiddenTabs.filter(\n (tab, i) => i !== selectedTabHiddenIndex,\n ),\n ].filter((tab) => tab),\n };\n }\n\n return {\n tabWidth: clamped,\n visibleTabs: tabs.slice(0, visibleCount),\n hiddenTabs: temporaryHiddenTabs,\n };\n }\n\n return {\n tabWidth: clamped,\n visibleTabs: tabs,\n hiddenTabs: [],\n };\n }, [actionsWidth, rootWidth, selectedTab, tabs]);\n\n return (\n <div\n ref={rootForkedRef}\n className={cx(classes.root, className)}\n {...others}\n >\n <div className={classes.tabsContainer}>\n {visibleTabs.length > 0 && (\n <HvCanvasPanelTabs\n classes={{ list: classes.tabsList }}\n value={selectedTab}\n onChange={handleChangeSelectedTab}\n >\n {visibleTabs.map((tab, index) => {\n const btnSelected = selectedTab === tab.id;\n return (\n <HvCanvasPanelTab\n style={{\n width: tabWidth,\n }}\n key={tab.id}\n id={String(tab.id)}\n className={classes.tab}\n value={tab.id}\n onKeyDown={(event) => handleKeyDownTab(event, tab.id)}\n >\n <div className={classes.tabContent}>\n {tab.icon && (\n <div className={classes.tabIconContainer}>{tab.icon}</div>\n )}\n {!btnSelected || !allowTabEdit ? (\n <HvOverflowTooltip\n classes={{\n tooltipAnchor: classes.tabLabel,\n }}\n data={tab.label}\n />\n ) : (\n <ToolbarTabEditor\n classes={{\n label: cx(classes.tabLabel, classes.tabLabelEditor),\n }}\n value={tab.label}\n edit={isEditing}\n onEditChange={setIsEditing}\n onChange={(event, value) =>\n handleEdit(event, value, tab.id)\n }\n onBlur={(event, value) =>\n handleEdit(event, value, tab.id)\n }\n // We don't want the arrow keys to trigger the tab navigation\n onKeyDown={(e) => e.stopPropagation()}\n />\n )}\n <div className={classes.closeIconContainer}>\n <CloseXS\n aria-hidden\n iconSize=\"XS\"\n onClick={(event) => {\n handleDeleteTab(event, tab.id);\n\n // We don't want the click to also select the tab\n event.stopPropagation();\n }}\n />\n </div>\n {selectedTab !== tab.id &&\n visibleTabs[index + 1]?.id !== selectedTab && (\n <div className={classes.tabDivider} />\n )}\n </div>\n </HvCanvasPanelTab>\n );\n })}\n </HvCanvasPanelTabs>\n )}\n {hiddenTabs.length > 0 && (\n <HvDropDownMenu\n classes={{\n container: classes.dropdownMenuContainer,\n menuListRoot: classes.dropdownMenuListRoot,\n }}\n dataList={hiddenTabs}\n icon={<MoreOptionsHorizontal />}\n labels={{ dropdownMenu: labels.dropdownMenu }}\n onClick={(event, value) =>\n handleChangeSelectedTab(event, value.id ?? \"none\")\n }\n />\n )}\n </div>\n <div ref={actionsRef} className={classes.actionsContainer}>\n {children}\n <HvButton\n variant=\"primaryGhost\"\n startIcon={<AddAlt />}\n onClick={handleCreateNew}\n >\n {labels.create}\n </HvButton>\n </div>\n </div>\n );\n});\n"],"names":[],"mappings":";;;;;;;;;;;AAsCA,MAAM,iBAAiB;AAAA,EACrB,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,cAAc;AAChB;AAuCO,MAAM,sBAAsB,WAGjC,CAAC,OAAO,QAAQ;AACV,QAAA;AAAA,IACJ;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,MAAM;AAAA,IACN,eAAe;AAAA,IACf,MAAM;AAAA,IACN,aAAa,kBAAkB,CAAC;AAAA,IAChC,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,aAAa;AAAA,IACb,UAAU;AAAA,IACV,GAAG;AAAA,EAAA,IACD,gBAAgB,uBAAuB,KAAK;AAEhD,QAAM,EAAE,SAAS,GAAG,IAAI,WAAW,WAAW;AAExC,QAAA,SAAS,UAAU,gBAAgB,UAAU;AAGnD,QAAM,EAAE,OAAO,eAAe,GAAG,KAAK,eAAe,kBAAkB;AAAA,IACrE,cAAc;AAAA,EAAA,CACf;AAGD,QAAM,EAAE,OAAO,YAAY,GAAG,KAAK,YAAY,kBAAkB;AAAA,IAC/D,cAAc;AAAA,EAAA,CACf;AAED,QAAM,CAAC,MAAM,OAAO,IAAI,cAAc,UAAU,eAAe;AACzD,QAAA,CAAC,aAAa,cAAc,IAAI;AAAA,IACpC;AAAA,IACA,OAAO,CAAC,GAAG,MAAM;AAAA,EAAA;AAEnB,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAE1C,QAAA,gBAAgB,WAAW,KAAK,OAAO;AAEvC,QAAA,mBAAmB,CACvB,OACA,YACG;AACH,YAAQ,OAAO;AACf,mBAAe,OAAO,OAAO;AAAA,EAAA;AAGzB,QAAA,0BAA8D,CAClE,OACA,UACG;AACY,mBAAA,OAAO,KAAK,CAAC;AACV,sBAAA,OAAO,OAAO,KAAK,CAAC;AAAA,EAAA;AAGlC,QAAA,kBAA4C,CAAC,UAAU;AACrD,UAAA,UAA4B,CAAC,GAAG,IAAI;AAC1C,UAAM,SAAyB;AAAA,MAC7B,IAAI,SAAS;AAAA,MACb,OAAO,GAAG,OAAO,SAAS,IAAI,QAAQ,SAAS,CAAC;AAAA,MAChD,MAAM;AAAA,IAAA;AAER,YAAQ,KAAK,MAAM;AACK,4BAAA,OAAO,OAAO,EAAE;AACxC,uBAAmB,OAAO,OAAO;AAAA,EAAA;AAGnC,QAAM,aAAa,CACjB,OACA,OACA,UAEA;AAAA,IACE;AAAA,IACA,KAAK,IAAI,CAAC,QAAS,IAAI,OAAO,QAAQ,EAAE,GAAG,KAAK,OAAO,MAAA,IAAU,GAAI;AAAA,EAAA;AAGnE,QAAA,kBAAkB,CAAC,OAAY,UAAkB;AACrD,UAAM,UAAU,KAAK,OAAO,CAAC,QAAQ,IAAI,OAAO,KAAK;AAErD,QAAI,UAAU,aAAa;AACzB,YAAM,eAAe,KAAK,UAAU,CAAC,QAAQ,IAAI,OAAO,KAAK;AAC7D,YAAM,WAAW,eAAe,IAAI,IAAI,IAAI,eAAe;AAC3D,8BAAwB,OAAO,QAAQ,QAAQ,GAAG,MAAM,MAAM;AAAA,IAChE;AAEA,qBAAiB,OAAO,OAAO;AAAA,EAAA;AAG3B,QAAA,mBAAmB,CAAC,OAA4B,UAAkB;AACtE,QAAI,MAAM,OAAO,QAAQ,KAAK,MAAM,OAAO,WAAW,GAAG;AACvD,sBAAgB,OAAO,KAAK;AAG5B,YAAM,gBAAgB;AAAA,IACb,WAAA,MAAM,OAAO,OAAO,GAAG;AAEhC,mBAAa,IAAI;AAAA,IACnB;AAAA,EAAA;AAGF,QAAM,EAAE,UAAU,YAAY,YAAY,IAAI,QAAQ,MAAM;AAC1D,QAAI,iBAAiB,YAAY;AAC7B,QAAA,qBAAqB,iBAAiB,KAAK;AAC/C,QAAI,UAAU,MAAM,oBAAoB,eAAe,aAAa;AAGpE,QAAI,qBAAqB,eAAe;AACpB,wBAAA;AAClB,YAAM,eAAe,KAAK,MAAM,iBAAiB,aAAa;AAC9D,2BAAqB,iBAAiB;AAC5B,gBAAA,MAAM,oBAAoB,eAAe,aAAa;AAE1D,YAAA,sBAAsB,KAAK,MAAM,YAAY;AACnD,YAAM,yBAAyB,oBAAoB;AAAA,QACjD,CAAC,QAAQ,IAAI,OAAO;AAAA,MAAA;AAEtB,YAAM,mBAAmB,eAAe;AAClC,YAAA,gBAAgB,2BAA2B,MAAM,eAAe;AAEtE,UAAI,eAAe;AACV,eAAA;AAAA,UACL,UAAU;AAAA,UACV,aAAa;AAAA,YACX,GAAG,KAAK,MAAM,GAAG,gBAAgB;AAAA,YACjC,oBAAoB,sBAAsB;AAAA,UAAA,EAC1C,OAAO,CAAC,QAAQ,GAAG;AAAA,UACrB,YAAY;AAAA,YACV,KAAK,gBAAgB;AAAA,YACrB,GAAG,oBAAoB;AAAA,cACrB,CAAC,KAAK,MAAM,MAAM;AAAA,YACpB;AAAA,UAAA,EACA,OAAO,CAAC,QAAQ,GAAG;AAAA,QAAA;AAAA,MAEzB;AAEO,aAAA;AAAA,QACL,UAAU;AAAA,QACV,aAAa,KAAK,MAAM,GAAG,YAAY;AAAA,QACvC,YAAY;AAAA,MAAA;AAAA,IAEhB;AAEO,WAAA;AAAA,MACL,UAAU;AAAA,MACV,aAAa;AAAA,MACb,YAAY,CAAC;AAAA,IAAA;AAAA,KAEd,CAAC,cAAc,WAAW,aAAa,IAAI,CAAC;AAG7C,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAW,GAAG,QAAQ,MAAM,SAAS;AAAA,MACpC,GAAG;AAAA,MAEJ,UAAA;AAAA,QAAC,qBAAA,OAAA,EAAI,WAAW,QAAQ,eACrB,UAAA;AAAA,UAAA,YAAY,SAAS,KACpB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAS,EAAE,MAAM,QAAQ,SAAS;AAAA,cAClC,OAAO;AAAA,cACP,UAAU;AAAA,cAET,UAAY,YAAA,IAAI,CAAC,KAAK,UAAU;AACzB,sBAAA,cAAc,gBAAgB,IAAI;AAEtC,uBAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,OAAO;AAAA,sBACL,OAAO;AAAA,oBACT;AAAA,oBAEA,IAAI,OAAO,IAAI,EAAE;AAAA,oBACjB,WAAW,QAAQ;AAAA,oBACnB,OAAO,IAAI;AAAA,oBACX,WAAW,CAAC,UAAU,iBAAiB,OAAO,IAAI,EAAE;AAAA,oBAEpD,UAAC,qBAAA,OAAA,EAAI,WAAW,QAAQ,YACrB,UAAA;AAAA,sBAAA,IAAI,QACF,oBAAA,OAAA,EAAI,WAAW,QAAQ,kBAAmB,cAAI,KAAK,CAAA;AAAA,sBAErD,CAAC,eAAe,CAAC,eAChB;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,SAAS;AAAA,4BACP,eAAe,QAAQ;AAAA,0BACzB;AAAA,0BACA,MAAM,IAAI;AAAA,wBAAA;AAAA,sBAAA,IAGZ;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,SAAS;AAAA,4BACP,OAAO,GAAG,QAAQ,UAAU,QAAQ,cAAc;AAAA,0BACpD;AAAA,0BACA,OAAO,IAAI;AAAA,0BACX,MAAM;AAAA,0BACN,cAAc;AAAA,0BACd,UAAU,CAAC,OAAO,UAChB,WAAW,OAAO,OAAO,IAAI,EAAE;AAAA,0BAEjC,QAAQ,CAAC,OAAO,UACd,WAAW,OAAO,OAAO,IAAI,EAAE;AAAA,0BAGjC,WAAW,CAAC,MAAM,EAAE,gBAAgB;AAAA,wBAAA;AAAA,sBACtC;AAAA,sBAED,oBAAA,OAAA,EAAI,WAAW,QAAQ,oBACtB,UAAA;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,eAAW;AAAA,0BACX,UAAS;AAAA,0BACT,SAAS,CAAC,UAAU;AACF,4CAAA,OAAO,IAAI,EAAE;AAG7B,kCAAM,gBAAgB;AAAA,0BACxB;AAAA,wBAAA;AAAA,sBAAA,GAEJ;AAAA,sBACC,gBAAgB,IAAI,MACnB,YAAY,QAAQ,CAAC,GAAG,OAAO,eAC7B,oBAAC,OAAI,EAAA,WAAW,QAAQ,WAAY,CAAA;AAAA,oBAAA,GAE1C;AAAA,kBAAA;AAAA,kBAnDK,IAAI;AAAA,gBAAA;AAAA,cAoDX,CAEH;AAAA,YAAA;AAAA,UACH;AAAA,UAED,WAAW,SAAS,KACnB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAS;AAAA,gBACP,WAAW,QAAQ;AAAA,gBACnB,cAAc,QAAQ;AAAA,cACxB;AAAA,cACA,UAAU;AAAA,cACV,0BAAO,uBAAsB,EAAA;AAAA,cAC7B,QAAQ,EAAE,cAAc,OAAO,aAAa;AAAA,cAC5C,SAAS,CAAC,OAAO,UACf,wBAAwB,OAAO,MAAM,MAAM,MAAM;AAAA,YAAA;AAAA,UAErD;AAAA,QAAA,GAEJ;AAAA,6BACC,OAAI,EAAA,KAAK,YAAY,WAAW,QAAQ,kBACtC,UAAA;AAAA,UAAA;AAAA,UACD;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,+BAAY,QAAO,EAAA;AAAA,cACnB,SAAS;AAAA,cAER,UAAO,OAAA;AAAA,YAAA;AAAA,UACV;AAAA,QAAA,GACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;"}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { tabClasses } from "@mui/base/Tab";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { theme, createClasses } from "@hitachivantara/uikit-react-core";
|
|
3
|
+
import { toolbarTabEditorClasses as staticClasses$1 } from "./ToolbarTabEditor.js";
|
|
4
4
|
const MIN_TAB_WIDTH = 120;
|
|
5
5
|
const MAX_TAB_WIDTH = 220;
|
|
6
|
+
const DROPDOWN_MENU_WIDTH = 64;
|
|
6
7
|
const TAB_HEIGHT = 32;
|
|
7
|
-
const
|
|
8
|
+
const CLOSE_ICON_SIZE = 32;
|
|
9
|
+
const TAB_ICON_SIZE = 16;
|
|
10
|
+
const TAB_PADDING = theme.space.xs;
|
|
11
|
+
const TAB_COLOR = theme.palette.blue[50];
|
|
8
12
|
const { staticClasses, useClasses } = createClasses(
|
|
9
13
|
"HvCanvasToolbarTabs",
|
|
10
14
|
{
|
|
@@ -16,85 +20,77 @@ const { staticClasses, useClasses } = createClasses(
|
|
|
16
20
|
backgroundColor: theme.colors.atmo1,
|
|
17
21
|
boxShadow: theme.colors.shadow,
|
|
18
22
|
borderRadius: `0px 0px ${theme.radii.base} ${theme.radii.base}`,
|
|
19
|
-
gap: theme.space.sm,
|
|
20
23
|
transition: "width 0.3s ease"
|
|
21
24
|
},
|
|
22
25
|
tabsContainer: {
|
|
23
|
-
position: "relative",
|
|
24
26
|
display: "flex"
|
|
25
27
|
},
|
|
26
28
|
tabsList: {
|
|
27
29
|
height: TAB_HEIGHT,
|
|
28
|
-
background: theme.colors.atmo1
|
|
30
|
+
background: theme.colors.atmo1,
|
|
31
|
+
borderEndStartRadius: theme.radii.base
|
|
29
32
|
},
|
|
30
33
|
tab: {
|
|
31
|
-
|
|
34
|
+
boxSizing: "border-box",
|
|
32
35
|
border: `1px solid ${theme.colors.atmo1}`,
|
|
33
36
|
borderBottom: "none",
|
|
34
37
|
borderRadius: "10px 10px 0 0",
|
|
35
38
|
boxShadow: "none",
|
|
36
39
|
backgroundColor: theme.colors.atmo1,
|
|
40
|
+
"&:first-of-type": { borderEndStartRadius: theme.radii.base },
|
|
37
41
|
[`&.${tabClasses.selected}`]: {
|
|
38
42
|
color: theme.colors.primary,
|
|
39
|
-
backgroundColor:
|
|
43
|
+
backgroundColor: TAB_COLOR,
|
|
40
44
|
borderColor: theme.colors.atmo4
|
|
45
|
+
},
|
|
46
|
+
[`&:hover:not(.${tabClasses.selected}), &:focus:not(.${tabClasses.selected})`]: {
|
|
47
|
+
borderRadius: 0,
|
|
48
|
+
backgroundColor: TAB_COLOR,
|
|
49
|
+
borderColor: TAB_COLOR,
|
|
50
|
+
"&:first-of-type": { borderEndStartRadius: theme.radii.base }
|
|
51
|
+
},
|
|
52
|
+
// Hide icon when editor is hovered and focused
|
|
53
|
+
[`&:has($tabLabelEditor:hover) $tabIconContainer, &:has(.${staticClasses$1.edit}) $tabIconContainer`]: {
|
|
54
|
+
display: "none"
|
|
55
|
+
},
|
|
56
|
+
// Hide close when editor is focused
|
|
57
|
+
[`&:has(.${staticClasses$1.edit}) $closeIconContainer`]: {
|
|
58
|
+
display: "none"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
tabLabel: {
|
|
62
|
+
"&:not($tabLabelEditor)": {
|
|
63
|
+
margin: theme.spacing(0, "xs")
|
|
41
64
|
}
|
|
42
65
|
},
|
|
66
|
+
tabLabelEditor: {
|
|
67
|
+
color: theme.colors.primary
|
|
68
|
+
},
|
|
43
69
|
tabContent: {
|
|
70
|
+
position: "relative",
|
|
44
71
|
height: TAB_HEIGHT,
|
|
45
72
|
display: "flex",
|
|
46
|
-
justifyContent: "
|
|
47
|
-
|
|
73
|
+
justifyContent: "flex-start",
|
|
74
|
+
alignItems: "center",
|
|
48
75
|
width: "100%",
|
|
49
|
-
padding:
|
|
50
|
-
"& > div:first-of-type:not($tabIcon)": {
|
|
51
|
-
visibility: "hidden"
|
|
52
|
-
},
|
|
53
|
-
"& > div:nth-of-type(2)": {
|
|
54
|
-
visibility: "hidden",
|
|
55
|
-
minWidth: `calc(${MIN_TAB_WIDTH}px - ${theme.space.xs} - 2 * ${ICON_WIDTH}px)`,
|
|
56
|
-
maxWidth: `calc(${MAX_TAB_WIDTH}px - ${theme.space.xs} - 2 * ${ICON_WIDTH}px)`
|
|
57
|
-
},
|
|
58
|
-
"& > div:nth-of-type(3)": {
|
|
59
|
-
visibility: "hidden",
|
|
60
|
-
marginRight: `calc(-1 * ${theme.space.xs})`
|
|
61
|
-
}
|
|
76
|
+
padding: TAB_PADDING
|
|
62
77
|
},
|
|
63
|
-
|
|
78
|
+
tabIconContainer: {
|
|
64
79
|
display: "flex",
|
|
65
80
|
justifyContent: "center",
|
|
66
|
-
alignItems: "center"
|
|
67
|
-
|
|
68
|
-
closeButton: {
|
|
69
|
-
position: "absolute",
|
|
70
|
-
top: 0,
|
|
71
|
-
right: "calc(100% - var(--right))",
|
|
72
|
-
color: "var(--close-color)"
|
|
73
|
-
},
|
|
74
|
-
tabLabel: {
|
|
75
|
-
position: "absolute",
|
|
76
|
-
width: "var(--editor-width)",
|
|
77
|
-
right: `calc(100% - var(--right) + ${ICON_WIDTH}px)`,
|
|
78
|
-
height: TAB_LABEL_HEIGHT,
|
|
79
|
-
top: 4.5,
|
|
80
|
-
"&:not($activeTabLabel)": {
|
|
81
|
-
...theme.typography.body,
|
|
82
|
-
color: theme.colors.secondary_60,
|
|
83
|
-
background: "none",
|
|
84
|
-
cursor: "pointer"
|
|
85
|
-
}
|
|
81
|
+
alignItems: "center",
|
|
82
|
+
width: TAB_ICON_SIZE
|
|
86
83
|
},
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
minHeight: TAB_LABEL_HEIGHT
|
|
84
|
+
closeIconContainer: {
|
|
85
|
+
display: "flex",
|
|
86
|
+
justifyContent: "center",
|
|
87
|
+
alignItems: "center",
|
|
88
|
+
marginLeft: "auto",
|
|
89
|
+
marginRight: theme.spacing(-1),
|
|
90
|
+
width: CLOSE_ICON_SIZE,
|
|
91
|
+
"&:hover": {
|
|
92
|
+
backgroundColor: theme.colors.containerBackgroundHover,
|
|
93
|
+
borderRadius: theme.radii.circle
|
|
98
94
|
}
|
|
99
95
|
},
|
|
100
96
|
tabDivider: {
|
|
@@ -110,13 +106,19 @@ const { staticClasses, useClasses } = createClasses(
|
|
|
110
106
|
alignItems: "center",
|
|
111
107
|
gap: theme.space.sm
|
|
112
108
|
},
|
|
113
|
-
|
|
114
|
-
|
|
109
|
+
dropdownMenuContainer: {
|
|
110
|
+
width: DROPDOWN_MENU_WIDTH,
|
|
111
|
+
display: "flex",
|
|
112
|
+
justifyContent: "center"
|
|
113
|
+
},
|
|
114
|
+
dropdownMenuListRoot: {
|
|
115
|
+
maxHeight: 220
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
118
|
);
|
|
118
119
|
export {
|
|
119
|
-
|
|
120
|
+
DROPDOWN_MENU_WIDTH,
|
|
121
|
+
MAX_TAB_WIDTH,
|
|
120
122
|
MIN_TAB_WIDTH,
|
|
121
123
|
staticClasses,
|
|
122
124
|
useClasses
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolbarTabs.styles.js","sources":["../../../../src/Canvas/ToolbarTabs/ToolbarTabs.styles.tsx"],"sourcesContent":["import { tabClasses } from \"@mui/base/Tab\";\nimport {
|
|
1
|
+
{"version":3,"file":"ToolbarTabs.styles.js","sources":["../../../../src/Canvas/ToolbarTabs/ToolbarTabs.styles.tsx"],"sourcesContent":["import { tabClasses } from \"@mui/base/Tab\";\nimport { createClasses, theme } from \"@hitachivantara/uikit-react-core\";\n\nimport { toolbarTabEditorClasses } from \"./ToolbarTabEditor\";\n\nexport const MIN_TAB_WIDTH = 120;\nexport const MAX_TAB_WIDTH = 220;\nexport const DROPDOWN_MENU_WIDTH = 64;\nconst TAB_HEIGHT = 32;\nconst CLOSE_ICON_SIZE = 32;\nconst TAB_ICON_SIZE = 16;\nconst TAB_PADDING = theme.space.xs;\nconst TAB_COLOR = theme.palette.blue[50]; // TODO - dark theme color\n\nexport const { staticClasses, useClasses } = createClasses(\n \"HvCanvasToolbarTabs\",\n {\n root: {\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n width: \"100%\",\n backgroundColor: theme.colors.atmo1,\n boxShadow: theme.colors.shadow,\n borderRadius: `0px 0px ${theme.radii.base} ${theme.radii.base}`,\n transition: \"width 0.3s ease\",\n },\n tabsContainer: {\n display: \"flex\",\n },\n tabsList: {\n height: TAB_HEIGHT,\n background: theme.colors.atmo1,\n borderEndStartRadius: theme.radii.base,\n },\n tab: {\n boxSizing: \"border-box\",\n border: `1px solid ${theme.colors.atmo1}`,\n borderBottom: \"none\",\n borderRadius: \"10px 10px 0 0\",\n boxShadow: \"none\",\n backgroundColor: theme.colors.atmo1,\n \"&:first-of-type\": { borderEndStartRadius: theme.radii.base },\n [`&.${tabClasses.selected}`]: {\n color: theme.colors.primary,\n backgroundColor: TAB_COLOR,\n borderColor: theme.colors.atmo4,\n },\n [`&:hover:not(.${tabClasses.selected}), &:focus:not(.${tabClasses.selected})`]:\n {\n borderRadius: 0,\n backgroundColor: TAB_COLOR,\n borderColor: TAB_COLOR,\n \"&:first-of-type\": { borderEndStartRadius: theme.radii.base },\n },\n\n // Hide icon when editor is hovered and focused\n [`&:has($tabLabelEditor:hover) $tabIconContainer, &:has(.${toolbarTabEditorClasses.edit}) $tabIconContainer`]:\n {\n display: \"none\",\n },\n // Hide close when editor is focused\n [`&:has(.${toolbarTabEditorClasses.edit}) $closeIconContainer`]: {\n display: \"none\",\n },\n },\n tabLabel: {\n \"&:not($tabLabelEditor)\": {\n margin: theme.spacing(0, \"xs\"),\n },\n },\n tabLabelEditor: {\n color: theme.colors.primary,\n },\n tabContent: {\n position: \"relative\",\n height: TAB_HEIGHT,\n display: \"flex\",\n justifyContent: \"flex-start\",\n alignItems: \"center\",\n width: \"100%\",\n padding: TAB_PADDING,\n },\n tabIconContainer: {\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n width: TAB_ICON_SIZE,\n },\n closeIconContainer: {\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n marginLeft: \"auto\",\n marginRight: theme.spacing(-1),\n width: CLOSE_ICON_SIZE,\n \"&:hover\": {\n backgroundColor: theme.colors.containerBackgroundHover,\n borderRadius: theme.radii.circle,\n },\n },\n tabDivider: {\n position: \"absolute\",\n height: 18,\n width: 1,\n backgroundColor: theme.colors.atmo3,\n right: 0,\n },\n actionsContainer: {\n display: \"flex\",\n justifyContent: \"flex-end\",\n alignItems: \"center\",\n gap: theme.space.sm,\n },\n dropdownMenuContainer: {\n width: DROPDOWN_MENU_WIDTH,\n display: \"flex\",\n justifyContent: \"center\",\n },\n dropdownMenuListRoot: {\n maxHeight: 220,\n },\n },\n);\n"],"names":["toolbarTabEditorClasses"],"mappings":"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"}
|