@pega/cosmos-react-core 10.0.0-build.5.2 → 10.0.0-build.5.21

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.
Files changed (131) hide show
  1. package/lib/components/AIRewrite/AIRewrite.styles.d.ts +19 -3
  2. package/lib/components/AIRewrite/AIRewrite.styles.d.ts.map +1 -1
  3. package/lib/components/AppShell/AppHeader.styles.d.ts.map +1 -1
  4. package/lib/components/AppShell/AppHeader.styles.js +8 -3
  5. package/lib/components/AppShell/AppHeader.styles.js.map +1 -1
  6. package/lib/components/AppShell/AppShell.d.ts.map +1 -1
  7. package/lib/components/AppShell/AppShell.js +16 -6
  8. package/lib/components/AppShell/AppShell.js.map +1 -1
  9. package/lib/components/AppShell/AppShell.styles.d.ts +3 -0
  10. package/lib/components/AppShell/AppShell.styles.d.ts.map +1 -1
  11. package/lib/components/AppShell/AppShell.styles.js +33 -17
  12. package/lib/components/AppShell/AppShell.styles.js.map +1 -1
  13. package/lib/components/AppShell/AppShell.types.d.ts +33 -0
  14. package/lib/components/AppShell/AppShell.types.d.ts.map +1 -1
  15. package/lib/components/AppShell/AppShell.types.js.map +1 -1
  16. package/lib/components/AppShell/DocumentTabs.d.ts +6 -0
  17. package/lib/components/AppShell/DocumentTabs.d.ts.map +1 -0
  18. package/lib/components/AppShell/DocumentTabs.js +409 -0
  19. package/lib/components/AppShell/DocumentTabs.js.map +1 -0
  20. package/lib/components/AppShell/DocumentTabs.styles.d.ts +231 -0
  21. package/lib/components/AppShell/DocumentTabs.styles.d.ts.map +1 -0
  22. package/lib/components/AppShell/DocumentTabs.styles.js +562 -0
  23. package/lib/components/AppShell/DocumentTabs.styles.js.map +1 -0
  24. package/lib/components/AppShell/NavigationListItemWrapper.d.ts.map +1 -1
  25. package/lib/components/AppShell/NavigationListItemWrapper.js +6 -5
  26. package/lib/components/AppShell/NavigationListItemWrapper.js.map +1 -1
  27. package/lib/components/AppShell/Operator.d.ts.map +1 -1
  28. package/lib/components/AppShell/Operator.js +8 -5
  29. package/lib/components/AppShell/Operator.js.map +1 -1
  30. package/lib/components/AppShell/ThemeSwitcher.d.ts.map +1 -1
  31. package/lib/components/AppShell/ThemeSwitcher.js +1 -0
  32. package/lib/components/AppShell/ThemeSwitcher.js.map +1 -1
  33. package/lib/components/AppShell/index.d.ts +1 -1
  34. package/lib/components/AppShell/index.d.ts.map +1 -1
  35. package/lib/components/AppShell/index.js.map +1 -1
  36. package/lib/components/Backdrop/Backdrop.js +2 -2
  37. package/lib/components/Backdrop/Backdrop.js.map +1 -1
  38. package/lib/components/DateTime/Input/DateInput.d.ts.map +1 -1
  39. package/lib/components/DateTime/Input/DateInput.js +15 -9
  40. package/lib/components/DateTime/Input/DateInput.js.map +1 -1
  41. package/lib/components/DateTime/Input/DateTime.styles.d.ts +3 -0
  42. package/lib/components/DateTime/Input/DateTime.styles.d.ts.map +1 -1
  43. package/lib/components/DateTime/Input/DateTime.styles.js +25 -0
  44. package/lib/components/DateTime/Input/DateTime.styles.js.map +1 -1
  45. package/lib/components/DateTime/Input/DateTimeInput.d.ts.map +1 -1
  46. package/lib/components/DateTime/Input/DateTimeInput.js +27 -18
  47. package/lib/components/DateTime/Input/DateTimeInput.js.map +1 -1
  48. package/lib/components/DateTime/Input/TimeInput.d.ts +6 -3
  49. package/lib/components/DateTime/Input/TimeInput.d.ts.map +1 -1
  50. package/lib/components/DateTime/Input/TimeInput.js +54 -24
  51. package/lib/components/DateTime/Input/TimeInput.js.map +1 -1
  52. package/lib/components/DateTime/Input/WeekInput.d.ts +6 -3
  53. package/lib/components/DateTime/Input/WeekInput.d.ts.map +1 -1
  54. package/lib/components/DateTime/Input/WeekInput.js +29 -16
  55. package/lib/components/DateTime/Input/WeekInput.js.map +1 -1
  56. package/lib/components/DateTime/Picker/Calendar.styles.d.ts.map +1 -1
  57. package/lib/components/DateTime/Picker/Calendar.styles.js +5 -0
  58. package/lib/components/DateTime/Picker/Calendar.styles.js.map +1 -1
  59. package/lib/components/DateTime/Picker/DatePicker.styles.d.ts.map +1 -1
  60. package/lib/components/DateTime/Picker/DatePicker.styles.js +32 -7
  61. package/lib/components/DateTime/Picker/DatePicker.styles.js.map +1 -1
  62. package/lib/components/DateTime/Picker/TimePicker.d.ts.map +1 -1
  63. package/lib/components/DateTime/Picker/TimePicker.js +10 -2
  64. package/lib/components/DateTime/Picker/TimePicker.js.map +1 -1
  65. package/lib/components/Dialog/Dialog.types.d.ts +23 -13
  66. package/lib/components/Dialog/Dialog.types.d.ts.map +1 -1
  67. package/lib/components/Dialog/Dialog.types.js.map +1 -1
  68. package/lib/components/Dialog/FormDialog.d.ts.map +1 -1
  69. package/lib/components/Dialog/FormDialog.js +50 -18
  70. package/lib/components/Dialog/FormDialog.js.map +1 -1
  71. package/lib/components/Dialog/InfoDialog.d.ts.map +1 -1
  72. package/lib/components/Dialog/InfoDialog.js +6 -4
  73. package/lib/components/Dialog/InfoDialog.js.map +1 -1
  74. package/lib/components/Dialog/TouchDialog.js +1 -1
  75. package/lib/components/Dialog/TouchDialog.js.map +1 -1
  76. package/lib/components/Dialog/TouchDialog.styles.d.ts.map +1 -1
  77. package/lib/components/Dialog/TouchDialog.styles.js +2 -1
  78. package/lib/components/Dialog/TouchDialog.styles.js.map +1 -1
  79. package/lib/components/InlineEdit/InlineEdit.d.ts +6 -0
  80. package/lib/components/InlineEdit/InlineEdit.d.ts.map +1 -1
  81. package/lib/components/InlineEdit/InlineEdit.js +45 -4
  82. package/lib/components/InlineEdit/InlineEdit.js.map +1 -1
  83. package/lib/components/InlineEdit/InlineEdit.styles.d.ts +19 -3
  84. package/lib/components/InlineEdit/InlineEdit.styles.d.ts.map +1 -1
  85. package/lib/components/InlineEdit/InlineEdit.styles.js +38 -20
  86. package/lib/components/InlineEdit/InlineEdit.styles.js.map +1 -1
  87. package/lib/components/Link/Link.d.ts +7 -2
  88. package/lib/components/Link/Link.d.ts.map +1 -1
  89. package/lib/components/Link/Link.js +45 -20
  90. package/lib/components/Link/Link.js.map +1 -1
  91. package/lib/components/Link/Link.test-ids.d.ts +1 -1
  92. package/lib/components/Link/Link.test-ids.d.ts.map +1 -1
  93. package/lib/components/Link/Link.test-ids.js +2 -1
  94. package/lib/components/Link/Link.test-ids.js.map +1 -1
  95. package/lib/components/ListToolbar/ListToolbar.styles.d.ts +19 -3
  96. package/lib/components/ListToolbar/ListToolbar.styles.d.ts.map +1 -1
  97. package/lib/components/Menu/FlyoutMenuList.d.ts.map +1 -1
  98. package/lib/components/Menu/FlyoutMenuList.js +1 -1
  99. package/lib/components/Menu/FlyoutMenuList.js.map +1 -1
  100. package/lib/components/Menu/Menu.js +2 -1
  101. package/lib/components/Menu/Menu.js.map +1 -1
  102. package/lib/components/MenuButton/MenuButton.d.ts.map +1 -1
  103. package/lib/components/MenuButton/MenuButton.js +5 -1
  104. package/lib/components/MenuButton/MenuButton.js.map +1 -1
  105. package/lib/components/Popover/getResolvedTarget.d.ts +11 -0
  106. package/lib/components/Popover/getResolvedTarget.d.ts.map +1 -0
  107. package/lib/components/Popover/getResolvedTarget.js +13 -0
  108. package/lib/components/Popover/getResolvedTarget.js.map +1 -0
  109. package/lib/components/Popover/index.d.ts +1 -0
  110. package/lib/components/Popover/index.d.ts.map +1 -1
  111. package/lib/components/Popover/index.js +1 -0
  112. package/lib/components/Popover/index.js.map +1 -1
  113. package/lib/components/QRCode/QRCode.d.ts.map +1 -1
  114. package/lib/components/QRCode/QRCode.js +2 -0
  115. package/lib/components/QRCode/QRCode.js.map +1 -1
  116. package/lib/components/Tooltip/Tooltip.d.ts.map +1 -1
  117. package/lib/components/Tooltip/Tooltip.js +8 -2
  118. package/lib/components/Tooltip/Tooltip.js.map +1 -1
  119. package/lib/hooks/useI18n.d.ts +18 -0
  120. package/lib/hooks/useI18n.d.ts.map +1 -1
  121. package/lib/i18n/default.d.ts +18 -0
  122. package/lib/i18n/default.d.ts.map +1 -1
  123. package/lib/i18n/default.js +23 -3
  124. package/lib/i18n/default.js.map +1 -1
  125. package/lib/i18n/i18n.d.ts +18 -0
  126. package/lib/i18n/i18n.d.ts.map +1 -1
  127. package/lib/theme/theme.d.ts +25 -0
  128. package/lib/theme/theme.d.ts.map +1 -1
  129. package/lib/theme/themeDefinition.json +18 -3
  130. package/lib/theme/themeOverrides.schema.json +16 -0
  131. package/package.json +1 -1
@@ -0,0 +1,409 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
3
+ import Icon, { registerIcon } from '../Icon';
4
+ import * as homeIcon from '../Icon/icons/home.icon';
5
+ import * as timesIcon from '../Icon/icons/times.icon';
6
+ import Tooltip from '../Tooltip';
7
+ import { useElement, useDirection, useI18n, useRefMap, useUID } from '../../hooks';
8
+ import { cap, createStringMatcher } from '../../utils';
9
+ import { StyledDocumentTabsContainer, StyledDocumentTabButton, StyledDocumentTabClose, StyledDocumentTabCloseAnchor, StyledDocumentTabItem, StyledDocumentTabLabel, StyledDocumentTabList, StyledDocumentTabAnchor, StyledOverflowTabMenu } from './DocumentTabs.styles';
10
+ registerIcon(homeIcon, timesIcon);
11
+ const OVERFLOW_SEARCH_THRESHOLD = 8;
12
+ const GROUP_ORDER = ['page', 'case', 'data'];
13
+ const getTabLabel = (tab) => tab.label || tab.id;
14
+ // tab.id may be an application key (e.g. `ON8TTL-C11NGALL-WORK D-23074`)
15
+ // containing spaces or other characters that break CSS selectors and
16
+ // aria-controls resolution. `encodeURIComponent` percent-encodes disallowed
17
+ // characters 1:1, so different tab ids can never collapse to the same DOM
18
+ // id — collisions would break aria-labelledby / aria-controls and confuse
19
+ // screen readers.
20
+ const sanitizeIdSegment = (id) => encodeURIComponent(id);
21
+ export const getTabPanelId = (id) => `document-tab-panel-${sanitizeIdSegment(id)}`;
22
+ export const getTabElementId = (id) => `document-tab-${sanitizeIdSegment(id)}`;
23
+ const reorderTabs = (tabs, fromId, toIndex) => {
24
+ const fromIndex = tabs.findIndex(tab => tab.id === fromId);
25
+ if (fromIndex < 0 || fromIndex === toIndex) {
26
+ return tabs;
27
+ }
28
+ const nextTabs = [...tabs];
29
+ const [movedTab] = nextTabs.splice(fromIndex, 1);
30
+ const insertIndex = fromIndex < toIndex ? toIndex - 1 : toIndex;
31
+ nextTabs.splice(insertIndex, 0, movedTab);
32
+ return nextTabs;
33
+ };
34
+ const isTabReorderable = (tab) => tab.reorderable !== false;
35
+ const DocumentTabItem = ({ tab, label, isActive, isTabStop, closeable, reorderable, isDragging, isDropBefore, setTabRef, onTabClick, onTabClose, onDragStart, onDragOver, onDrop, onDragEnd, onKeyUp }) => {
36
+ const [tabEl, setTabEl] = useElement();
37
+ const t = useI18n();
38
+ return (_jsxs(StyledDocumentTabItem, { isActive: isActive, isDragging: isDragging, isDropBefore: isDropBefore, onDragOver: event => onDragOver(tab.id, event), onDrop: event => onDrop(tab.id, event), children: [_jsx(StyledDocumentTabButton, { ref: el => {
39
+ setTabEl(el);
40
+ setTabRef(el);
41
+ }, role: 'tab', id: getTabElementId(tab.id), hasClose: closeable, "aria-selected": isActive, "aria-controls": isActive ? getTabPanelId(tab.id) : undefined, tabIndex: isTabStop ? 0 : -1, draggable: reorderable, onClick: () => onTabClick(tab.id), onDragStart: event => onDragStart(tab.id, event), onDragEnd: onDragEnd, onKeyDown: (e) => {
42
+ const { key } = e;
43
+ if (key === 'ArrowRight' ||
44
+ key === 'ArrowDown' ||
45
+ key === 'ArrowLeft' ||
46
+ key === 'ArrowUp' ||
47
+ key === 'Enter' ||
48
+ key === ' ' ||
49
+ key === 'Delete' ||
50
+ key === 'Backspace') {
51
+ e.preventDefault();
52
+ }
53
+ }, onKeyUp: onKeyUp, onAuxClick: (e) => {
54
+ if (e.button === 1 && closeable) {
55
+ e.preventDefault();
56
+ onTabClose(tab.id, e);
57
+ }
58
+ }, children: _jsxs(StyledDocumentTabAnchor, { children: [tab.icon && _jsx(Icon, { name: tab.icon }), _jsx(StyledDocumentTabLabel, { children: label })] }) }), closeable && (_jsx(StyledDocumentTabCloseAnchor, { children: _jsx(StyledDocumentTabClose, { icon: true, compact: true, variant: 'simple', draggable: false, tabIndex: isTabStop ? 0 : -1, onClick: (e) => onTabClose(tab.id, e), "aria-label": t('close_noun', [label]), children: _jsx(Icon, { name: 'times' }) }) })), _jsx(Tooltip, { target: tabEl, placement: 'bottom', showDelay: 'long', hideDelay: 'none', children: label })] }));
59
+ };
60
+ const DocumentTabs = ({ items, currentTabId, onTabClick, onTabClose, onTabCloseAll, onTabReorder }) => {
61
+ const [orderedItems, setOrderedItems] = useState(items);
62
+ const [isOverflowing, setIsOverflowing] = useState(false);
63
+ const [draggedTabId, setDraggedTabId] = useState(null);
64
+ const [dropBeforeId, setDropBeforeId] = useState(null);
65
+ const [overflowSearch, setOverflowSearch] = useState('');
66
+ // The tab that owns the keyboard tabstop. Updated synchronously on user
67
+ // interaction so Tab-away/Tab-back returns to the tab the user chose,
68
+ // regardless of async `currentTabId` propagation from the parent.
69
+ const [focusedTabId, setFocusedTabId] = useState(null);
70
+ const tabListRef = useRef(null);
71
+ const [tabRefs, getTabRef] = useRefMap();
72
+ const overflowMenuId = useUID();
73
+ const { rtl, end: endDirection, start: startDirection } = useDirection();
74
+ const t = useI18n();
75
+ useEffect(() => {
76
+ setOrderedItems(previousItems => {
77
+ const previousOrder = previousItems.map(tab => tab.id);
78
+ const itemMap = new Map(items.map(tab => [tab.id, tab]));
79
+ const nextItems = [];
80
+ previousOrder.forEach(id => {
81
+ const tab = itemMap.get(id);
82
+ if (tab) {
83
+ nextItems.push(tab);
84
+ itemMap.delete(id);
85
+ }
86
+ });
87
+ itemMap.forEach(tab => {
88
+ nextItems.push(tab);
89
+ });
90
+ return nextItems;
91
+ });
92
+ }, [items]);
93
+ useEffect(() => {
94
+ if (focusedTabId && !items.some(tab => tab.id === focusedTabId)) {
95
+ setFocusedTabId(null);
96
+ }
97
+ }, [items, focusedTabId]);
98
+ // Keyboard a11y: when the active tab switches AND the switch was triggered
99
+ // from outside the tablist (e.g. Recents drawer, search results), move
100
+ // focus onto the newly active tab so Tab can advance to its close (X)
101
+ // button. Without this, focus stays wherever the caller left it (typically
102
+ // returned to the drawer trigger via onAfterClose).
103
+ //
104
+ // Skip if focus is already inside the tablist — that means the user
105
+ // switched tabs via the tab strip itself (click/keyboard nav) and we
106
+ // shouldn't yank focus onto a different tab button.
107
+ const isFirstCurrentTabIdRenderRef = useRef(true);
108
+ useEffect(() => {
109
+ if (isFirstCurrentTabIdRenderRef.current) {
110
+ isFirstCurrentTabIdRenderRef.current = false;
111
+ return;
112
+ }
113
+ if (!currentTabId)
114
+ return;
115
+ const activeAtChange = document.activeElement;
116
+ if (activeAtChange?.closest('[role="tablist"]'))
117
+ return;
118
+ const focusTab = () => {
119
+ document.getElementById(getTabElementId(currentTabId))?.focus();
120
+ setFocusedTabId(currentTabId);
121
+ };
122
+ const raf = requestAnimationFrame(focusTab);
123
+ const timer = setTimeout(focusTab, 500);
124
+ return () => {
125
+ cancelAnimationFrame(raf);
126
+ clearTimeout(timer);
127
+ };
128
+ }, [currentTabId]);
129
+ const applyReorder = useCallback((nextTabs) => {
130
+ setOrderedItems(nextTabs);
131
+ onTabReorder?.(nextTabs.map(tab => tab.id));
132
+ }, [onTabReorder]);
133
+ const handleTabClick = (id) => {
134
+ setFocusedTabId(id);
135
+ onTabClick?.(id);
136
+ };
137
+ const handleTabClose = (id, e) => {
138
+ e.stopPropagation();
139
+ // Move focus to the previous sibling (or next, if closing the leftmost)
140
+ // so keyboard/screen-reader users don't get dropped to <body> when the
141
+ // close button unmounts.
142
+ const closingIndex = orderedItems.findIndex(tab => tab.id === id);
143
+ const neighbor = orderedItems[closingIndex - 1] ?? orderedItems[closingIndex + 1];
144
+ if (neighbor) {
145
+ setFocusedTabId(neighbor.id);
146
+ tabRefs.get(neighbor.id)?.focus();
147
+ }
148
+ else {
149
+ setFocusedTabId(null);
150
+ }
151
+ onTabClose?.(id);
152
+ };
153
+ const moveTabByOffset = useCallback((tabId, offset) => {
154
+ const fromIndex = orderedItems.findIndex(tab => tab.id === tabId);
155
+ if (fromIndex < 0) {
156
+ return;
157
+ }
158
+ const tab = orderedItems[fromIndex];
159
+ if (!isTabReorderable(tab)) {
160
+ return;
161
+ }
162
+ const toIndex = fromIndex + offset;
163
+ if (toIndex < 0 || toIndex >= orderedItems.length) {
164
+ return;
165
+ }
166
+ if (!isTabReorderable(orderedItems[toIndex])) {
167
+ return;
168
+ }
169
+ applyReorder(reorderTabs(orderedItems, tabId, toIndex + (offset > 0 ? 1 : 0)));
170
+ }, [applyReorder, orderedItems]);
171
+ const handleDragStart = (tabId, event) => {
172
+ const tab = orderedItems.find(item => item.id === tabId);
173
+ if (!tab || !isTabReorderable(tab) || !onTabReorder) {
174
+ event.preventDefault();
175
+ return;
176
+ }
177
+ setDraggedTabId(tabId);
178
+ event.dataTransfer.effectAllowed = 'move';
179
+ event.dataTransfer.setData('text/plain', tabId);
180
+ };
181
+ const handleDragOver = (tabId, event) => {
182
+ if (!draggedTabId || draggedTabId === tabId) {
183
+ return;
184
+ }
185
+ // A drop on a non-reorderable target would insert the dragged tab
186
+ // before it, which is exactly what makes the target "reorderable" —
187
+ // reject so pinned tabs stay pinned.
188
+ const target = orderedItems.find(tab => tab.id === tabId);
189
+ if (!target || !isTabReorderable(target)) {
190
+ return;
191
+ }
192
+ event.preventDefault();
193
+ event.dataTransfer.dropEffect = 'move';
194
+ setDropBeforeId(tabId);
195
+ };
196
+ const handleDrop = (tabId, event) => {
197
+ event.preventDefault();
198
+ if (!draggedTabId || draggedTabId === tabId) {
199
+ setDraggedTabId(null);
200
+ setDropBeforeId(null);
201
+ return;
202
+ }
203
+ const target = orderedItems.find(tab => tab.id === tabId);
204
+ if (!target || !isTabReorderable(target)) {
205
+ setDraggedTabId(null);
206
+ setDropBeforeId(null);
207
+ return;
208
+ }
209
+ const fromIndex = orderedItems.findIndex(tab => tab.id === draggedTabId);
210
+ const toIndex = orderedItems.findIndex(tab => tab.id === tabId);
211
+ if (fromIndex >= 0 && toIndex >= 0) {
212
+ // Dropping on the immediate right neighbor swaps the two tabs; every
213
+ // other target uses the standard "insert before" semantics.
214
+ const dropIndex = toIndex === fromIndex + 1 ? toIndex + 1 : toIndex;
215
+ applyReorder(reorderTabs(orderedItems, draggedTabId, dropIndex));
216
+ }
217
+ setDraggedTabId(null);
218
+ setDropBeforeId(null);
219
+ };
220
+ const handleDragEnd = () => {
221
+ setDraggedTabId(null);
222
+ setDropBeforeId(null);
223
+ };
224
+ const checkAndUpdateIsOverflowing = useCallback(() => {
225
+ if (tabListRef.current) {
226
+ const value = tabListRef.current.scrollWidth > tabListRef.current.clientWidth;
227
+ setIsOverflowing(current => (current === value ? current : value));
228
+ return value;
229
+ }
230
+ return isOverflowing;
231
+ }, [isOverflowing]);
232
+ useEffect(() => {
233
+ const resizeObserver = new ResizeObserver(() => {
234
+ checkAndUpdateIsOverflowing();
235
+ });
236
+ if (tabListRef.current) {
237
+ resizeObserver.observe(tabListRef.current);
238
+ }
239
+ return () => {
240
+ resizeObserver.disconnect();
241
+ };
242
+ }, [checkAndUpdateIsOverflowing, orderedItems.length]);
243
+ useLayoutEffect(() => {
244
+ if (!checkAndUpdateIsOverflowing()) {
245
+ return;
246
+ }
247
+ const activeTabRef = currentTabId ? tabRefs.get(currentTabId) : undefined;
248
+ if (activeTabRef && tabListRef.current) {
249
+ const activeTabRect = activeTabRef.getBoundingClientRect();
250
+ const tabListRect = tabListRef.current.getBoundingClientRect();
251
+ // Compare both edges in the same (viewport) coordinate space so the
252
+ // check works regardless of where the tablist sits horizontally.
253
+ if (activeTabRect.left < tabListRect.left || activeTabRect.right > tabListRect.right) {
254
+ tabListRef.current.scrollLeft = rtl
255
+ ? -(tabListRect.width - (activeTabRef.offsetLeft + activeTabRect.width))
256
+ : activeTabRef.offsetLeft;
257
+ }
258
+ }
259
+ }, [orderedItems, currentTabId, rtl, checkAndUpdateIsOverflowing]);
260
+ const changeTabFocus = (event, index) => {
261
+ const { key, altKey } = event;
262
+ const tab = orderedItems[index];
263
+ if (altKey && (key === 'ArrowLeft' || key === 'ArrowRight')) {
264
+ event.preventDefault();
265
+ if (tab && isTabReorderable(tab) && onTabReorder) {
266
+ const offset = key === `Arrow${cap(endDirection)}` ? 1 : -1;
267
+ moveTabByOffset(tab.id, offset);
268
+ }
269
+ return;
270
+ }
271
+ if (key === `Arrow${cap(endDirection)}`) {
272
+ event.preventDefault();
273
+ const nextIndex = (index + 1) % orderedItems.length;
274
+ setFocusedTabId(orderedItems[nextIndex].id);
275
+ tabRefs.get(orderedItems[nextIndex].id)?.focus();
276
+ }
277
+ else if (key === `Arrow${cap(startDirection)}`) {
278
+ event.preventDefault();
279
+ const prevIndex = index === 0 ? orderedItems.length - 1 : index - 1;
280
+ setFocusedTabId(orderedItems[prevIndex].id);
281
+ tabRefs.get(orderedItems[prevIndex].id)?.focus();
282
+ }
283
+ else if (key === 'Enter' || key === ' ') {
284
+ event.preventDefault();
285
+ handleTabClick(tab.id);
286
+ }
287
+ else if ((key === 'Delete' || key === 'Backspace') && tab && tab.closeable !== false) {
288
+ event.preventDefault();
289
+ const neighbor = orderedItems[index - 1] ?? orderedItems[index + 1];
290
+ setFocusedTabId(neighbor ? neighbor.id : null);
291
+ onTabClose?.(tab.id);
292
+ if (neighbor) {
293
+ tabRefs.get(neighbor.id)?.focus();
294
+ }
295
+ }
296
+ };
297
+ const overflowSearchRegex = createStringMatcher(overflowSearch);
298
+ const hasCloseableTabs = orderedItems.some(tab => tab.closeable !== false);
299
+ const overflowMenuItems = useMemo(() => {
300
+ const closeAllMenuItem = hasCloseableTabs && onTabCloseAll
301
+ ? {
302
+ id: 'document-tabs-close-all',
303
+ primary: t('document_tabs_close_all'),
304
+ onClick: () => {
305
+ onTabCloseAll();
306
+ }
307
+ }
308
+ : undefined;
309
+ const prependCloseAll = (menuItems) => {
310
+ if (!closeAllMenuItem) {
311
+ return menuItems;
312
+ }
313
+ if (menuItems.length === 0) {
314
+ return [closeAllMenuItem];
315
+ }
316
+ return [closeAllMenuItem, ...menuItems];
317
+ };
318
+ const filteredTabs = orderedItems.filter(tab => {
319
+ const label = getTabLabel(tab);
320
+ return (overflowSearchRegex.test(label) ||
321
+ (tab.secondary && overflowSearchRegex.test(tab.secondary)));
322
+ });
323
+ const groupedTabs = GROUP_ORDER.map(group => ({
324
+ group,
325
+ tabs: filteredTabs.filter(tab => tab.group === group)
326
+ })).filter(entry => entry.tabs.length > 0);
327
+ const ungroupedTabs = filteredTabs.filter(tab => !tab.group || !GROUP_ORDER.includes(tab.group));
328
+ const toMenuItem = (tab) => {
329
+ const label = getTabLabel(tab);
330
+ return {
331
+ id: tab.id,
332
+ primary: label,
333
+ secondary: tab.secondary ? [tab.secondary] : undefined,
334
+ selected: tab.id === currentTabId,
335
+ visual: tab.icon ? _jsx(Icon, { name: tab.icon }) : undefined,
336
+ onClick: () => {
337
+ onTabClick?.(tab.id);
338
+ tabRefs.get(tab.id)?.focus();
339
+ }
340
+ };
341
+ };
342
+ const groupLabels = {
343
+ page: t('document_tabs_pages'),
344
+ case: t('document_tabs_cases'),
345
+ data: t('document_tabs_data')
346
+ };
347
+ const menuCategories = groupedTabs.map(({ group, tabs }) => ({
348
+ id: `document-tabs-${group}`,
349
+ label: groupLabels[group],
350
+ items: tabs.map(toMenuItem)
351
+ }));
352
+ if (ungroupedTabs.length > 0) {
353
+ if (menuCategories.length > 0) {
354
+ menuCategories.push({
355
+ id: 'document-tabs-other',
356
+ label: t('document_tabs_all'),
357
+ items: ungroupedTabs.map(toMenuItem)
358
+ });
359
+ }
360
+ else {
361
+ return prependCloseAll(ungroupedTabs.map(toMenuItem));
362
+ }
363
+ }
364
+ if (menuCategories.length === 0 && filteredTabs.length > 0) {
365
+ return prependCloseAll(filteredTabs.map(toMenuItem));
366
+ }
367
+ return prependCloseAll(menuCategories);
368
+ }, [
369
+ orderedItems,
370
+ overflowSearchRegex,
371
+ currentTabId,
372
+ onTabClick,
373
+ onTabCloseAll,
374
+ hasCloseableTabs,
375
+ t
376
+ ]);
377
+ const showOverflowSearch = isOverflowing && orderedItems.length > OVERFLOW_SEARCH_THRESHOLD;
378
+ if (orderedItems.length === 0) {
379
+ return null;
380
+ }
381
+ return (_jsxs(StyledDocumentTabsContainer, { container: { alignItems: 'center', gap: 0.5 }, "data-overflowing": isOverflowing || undefined, children: [_jsx(StyledOverflowTabMenu, { menu: {
382
+ listId: overflowMenuId,
383
+ mode: 'single-select',
384
+ items: overflowMenuItems,
385
+ ...(showOverflowSearch && {
386
+ filterInputProps: {
387
+ value: overflowSearch,
388
+ onChange: (e) => setOverflowSearch(e.target.value)
389
+ }
390
+ })
391
+ }, icon: 'caret-down', iconOnly: true, variant: 'simple', text: t('document_tabs_overflow_menu'), popover: {
392
+ onHide: () => {
393
+ setOverflowSearch('');
394
+ }
395
+ } }), _jsx(StyledDocumentTabList, { role: 'tablist', ref: tabListRef, "aria-label": t('document_tabs_all'), children: (() => {
396
+ // If nothing has been clicked/focused yet, the active tab (or
397
+ // first tab as a fallback) holds the initial tabstop so keyboard
398
+ // users can Tab in.
399
+ const initialTabStopId = focusedTabId ??
400
+ orderedItems.find(tab => tab.id === currentTabId)?.id ??
401
+ orderedItems[0]?.id ??
402
+ null;
403
+ return orderedItems.map((tab, index) => (_jsx(DocumentTabItem, { tab: tab, label: getTabLabel(tab), isActive: tab.id === currentTabId, isTabStop: tab.id === initialTabStopId, closeable: tab.closeable !== false, reorderable: isTabReorderable(tab) && !!onTabReorder, isDragging: draggedTabId === tab.id, isDropBefore: dropBeforeId === tab.id, setTabRef: getTabRef(tab.id), onTabClick: handleTabClick, onTabClose: handleTabClose, onDragStart: handleDragStart, onDragOver: handleDragOver, onDrop: handleDrop, onDragEnd: handleDragEnd, onKeyUp: (e) => {
404
+ changeTabFocus(e, index);
405
+ } }, tab.id)));
406
+ })() })] }));
407
+ };
408
+ export default DocumentTabs;
409
+ //# sourceMappingURL=DocumentTabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocumentTabs.js","sourceRoot":"","sources":["../../../src/components/AppShell/DocumentTabs.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type KeyboardEvent,\n type MouseEvent,\n type DragEvent\n} from 'react';\n\nimport Icon, { registerIcon } from '../Icon';\nimport * as homeIcon from '../Icon/icons/home.icon';\nimport * as timesIcon from '../Icon/icons/times.icon';\nimport Tooltip from '../Tooltip';\nimport { useElement, useDirection, useI18n, useRefMap, useUID } from '../../hooks';\nimport { cap, createStringMatcher } from '../../utils';\nimport type { MenuItemProps, MenuProps } from '../Menu';\n\nimport type { DocumentTabsProps, DocumentTab, DocumentTabGroup } from './AppShell.types';\nimport {\n StyledDocumentTabsContainer,\n StyledDocumentTabButton,\n StyledDocumentTabClose,\n StyledDocumentTabCloseAnchor,\n StyledDocumentTabItem,\n StyledDocumentTabLabel,\n StyledDocumentTabList,\n StyledDocumentTabAnchor,\n StyledOverflowTabMenu\n} from './DocumentTabs.styles';\n\nregisterIcon(homeIcon, timesIcon);\n\nconst OVERFLOW_SEARCH_THRESHOLD = 8;\nconst GROUP_ORDER: DocumentTabGroup[] = ['page', 'case', 'data'];\n\nconst getTabLabel = (tab: DocumentTab): string => tab.label || tab.id;\n\n// tab.id may be an application key (e.g. `ON8TTL-C11NGALL-WORK D-23074`)\n// containing spaces or other characters that break CSS selectors and\n// aria-controls resolution. `encodeURIComponent` percent-encodes disallowed\n// characters 1:1, so different tab ids can never collapse to the same DOM\n// id — collisions would break aria-labelledby / aria-controls and confuse\n// screen readers.\nconst sanitizeIdSegment = (id: string): string => encodeURIComponent(id);\n\nexport const getTabPanelId = (id: string): string => `document-tab-panel-${sanitizeIdSegment(id)}`;\n\nexport const getTabElementId = (id: string): string => `document-tab-${sanitizeIdSegment(id)}`;\n\nconst reorderTabs = (tabs: DocumentTab[], fromId: string, toIndex: number): DocumentTab[] => {\n const fromIndex = tabs.findIndex(tab => tab.id === fromId);\n if (fromIndex < 0 || fromIndex === toIndex) {\n return tabs;\n }\n\n const nextTabs = [...tabs];\n const [movedTab] = nextTabs.splice(fromIndex, 1);\n const insertIndex = fromIndex < toIndex ? toIndex - 1 : toIndex;\n nextTabs.splice(insertIndex, 0, movedTab);\n return nextTabs;\n};\n\nconst isTabReorderable = (tab: DocumentTab): boolean => tab.reorderable !== false;\n\ninterface DocumentTabItemProps {\n tab: DocumentTab;\n label: string;\n isActive: boolean;\n isTabStop: boolean;\n closeable: boolean;\n reorderable: boolean;\n isDragging: boolean;\n isDropBefore: boolean;\n setTabRef: (el: HTMLButtonElement | null) => void;\n onTabClick: (id: string) => void;\n onTabClose: (id: string, e: MouseEvent<HTMLElement>) => void;\n onDragStart: (tabId: string, event: DragEvent<HTMLButtonElement>) => void;\n onDragOver: (tabId: string, event: DragEvent<HTMLDivElement>) => void;\n onDrop: (tabId: string, event: DragEvent<HTMLDivElement>) => void;\n onDragEnd: () => void;\n onKeyUp: (e: KeyboardEvent) => void;\n}\n\nconst DocumentTabItem = ({\n tab,\n label,\n isActive,\n isTabStop,\n closeable,\n reorderable,\n isDragging,\n isDropBefore,\n setTabRef,\n onTabClick,\n onTabClose,\n onDragStart,\n onDragOver,\n onDrop,\n onDragEnd,\n onKeyUp\n}: DocumentTabItemProps) => {\n const [tabEl, setTabEl] = useElement<HTMLButtonElement>();\n const t = useI18n();\n\n return (\n <StyledDocumentTabItem\n isActive={isActive}\n isDragging={isDragging}\n isDropBefore={isDropBefore}\n onDragOver={event => onDragOver(tab.id, event)}\n onDrop={event => onDrop(tab.id, event)}\n >\n <StyledDocumentTabButton\n ref={el => {\n setTabEl(el);\n setTabRef(el);\n }}\n role='tab'\n id={getTabElementId(tab.id)}\n hasClose={closeable}\n aria-selected={isActive}\n /* Only the active tab's panel is rendered, so only reference it from\n the active tab. Dangling aria-controls on inactive tabs point to\n non-existent nodes and confuse screen readers. */\n aria-controls={isActive ? getTabPanelId(tab.id) : undefined}\n tabIndex={isTabStop ? 0 : -1}\n draggable={reorderable}\n onClick={() => onTabClick(tab.id)}\n onDragStart={event => onDragStart(tab.id, event)}\n onDragEnd={onDragEnd}\n onKeyDown={(e: KeyboardEvent<HTMLButtonElement>) => {\n const { key } = e;\n if (\n key === 'ArrowRight' ||\n key === 'ArrowDown' ||\n key === 'ArrowLeft' ||\n key === 'ArrowUp' ||\n key === 'Enter' ||\n key === ' ' ||\n key === 'Delete' ||\n key === 'Backspace'\n ) {\n e.preventDefault();\n }\n }}\n onKeyUp={onKeyUp}\n onAuxClick={(e: MouseEvent<HTMLButtonElement>) => {\n if (e.button === 1 && closeable) {\n e.preventDefault();\n onTabClose(tab.id, e);\n }\n }}\n >\n <StyledDocumentTabAnchor>\n {tab.icon && <Icon name={tab.icon} />}\n <StyledDocumentTabLabel>{label}</StyledDocumentTabLabel>\n </StyledDocumentTabAnchor>\n </StyledDocumentTabButton>\n {closeable && (\n <StyledDocumentTabCloseAnchor>\n <StyledDocumentTabClose\n icon\n compact\n variant='simple'\n draggable={false}\n tabIndex={isTabStop ? 0 : -1}\n onClick={(e: MouseEvent<HTMLButtonElement>) => onTabClose(tab.id, e)}\n aria-label={t('close_noun', [label])}\n >\n <Icon name='times' />\n </StyledDocumentTabClose>\n </StyledDocumentTabCloseAnchor>\n )}\n <Tooltip target={tabEl} placement='bottom' showDelay='long' hideDelay='none'>\n {label}\n </Tooltip>\n </StyledDocumentTabItem>\n );\n};\n\nconst DocumentTabs = ({\n items,\n currentTabId,\n onTabClick,\n onTabClose,\n onTabCloseAll,\n onTabReorder\n}: DocumentTabsProps) => {\n const [orderedItems, setOrderedItems] = useState<DocumentTab[]>(items);\n const [isOverflowing, setIsOverflowing] = useState(false);\n const [draggedTabId, setDraggedTabId] = useState<string | null>(null);\n const [dropBeforeId, setDropBeforeId] = useState<string | null>(null);\n const [overflowSearch, setOverflowSearch] = useState('');\n // The tab that owns the keyboard tabstop. Updated synchronously on user\n // interaction so Tab-away/Tab-back returns to the tab the user chose,\n // regardless of async `currentTabId` propagation from the parent.\n const [focusedTabId, setFocusedTabId] = useState<string | null>(null);\n\n const tabListRef = useRef<HTMLDivElement>(null);\n const [tabRefs, getTabRef] = useRefMap<HTMLButtonElement>();\n const overflowMenuId = useUID();\n\n const { rtl, end: endDirection, start: startDirection } = useDirection();\n const t = useI18n();\n\n useEffect(() => {\n setOrderedItems(previousItems => {\n const previousOrder = previousItems.map(tab => tab.id);\n const itemMap = new Map(items.map(tab => [tab.id, tab]));\n const nextItems: DocumentTab[] = [];\n\n previousOrder.forEach(id => {\n const tab = itemMap.get(id);\n if (tab) {\n nextItems.push(tab);\n itemMap.delete(id);\n }\n });\n\n itemMap.forEach(tab => {\n nextItems.push(tab);\n });\n\n return nextItems;\n });\n }, [items]);\n\n useEffect(() => {\n if (focusedTabId && !items.some(tab => tab.id === focusedTabId)) {\n setFocusedTabId(null);\n }\n }, [items, focusedTabId]);\n\n // Keyboard a11y: when the active tab switches AND the switch was triggered\n // from outside the tablist (e.g. Recents drawer, search results), move\n // focus onto the newly active tab so Tab can advance to its close (X)\n // button. Without this, focus stays wherever the caller left it (typically\n // returned to the drawer trigger via onAfterClose).\n //\n // Skip if focus is already inside the tablist — that means the user\n // switched tabs via the tab strip itself (click/keyboard nav) and we\n // shouldn't yank focus onto a different tab button.\n const isFirstCurrentTabIdRenderRef = useRef(true);\n useEffect(() => {\n if (isFirstCurrentTabIdRenderRef.current) {\n isFirstCurrentTabIdRenderRef.current = false;\n return;\n }\n if (!currentTabId) return;\n const activeAtChange = document.activeElement;\n if (activeAtChange?.closest('[role=\"tablist\"]')) return;\n const focusTab = () => {\n document.getElementById(getTabElementId(currentTabId))?.focus();\n setFocusedTabId(currentTabId);\n };\n const raf = requestAnimationFrame(focusTab);\n const timer = setTimeout(focusTab, 500);\n return () => {\n cancelAnimationFrame(raf);\n clearTimeout(timer);\n };\n }, [currentTabId]);\n\n const applyReorder = useCallback(\n (nextTabs: DocumentTab[]) => {\n setOrderedItems(nextTabs);\n onTabReorder?.(nextTabs.map(tab => tab.id));\n },\n [onTabReorder]\n );\n\n const handleTabClick = (id: string) => {\n setFocusedTabId(id);\n onTabClick?.(id);\n };\n\n const handleTabClose = (id: string, e: MouseEvent<HTMLElement>) => {\n e.stopPropagation();\n // Move focus to the previous sibling (or next, if closing the leftmost)\n // so keyboard/screen-reader users don't get dropped to <body> when the\n // close button unmounts.\n const closingIndex = orderedItems.findIndex(tab => tab.id === id);\n const neighbor = orderedItems[closingIndex - 1] ?? orderedItems[closingIndex + 1];\n if (neighbor) {\n setFocusedTabId(neighbor.id);\n tabRefs.get(neighbor.id)?.focus();\n } else {\n setFocusedTabId(null);\n }\n onTabClose?.(id);\n };\n\n const moveTabByOffset = useCallback(\n (tabId: string, offset: number) => {\n const fromIndex = orderedItems.findIndex(tab => tab.id === tabId);\n if (fromIndex < 0) {\n return;\n }\n\n const tab = orderedItems[fromIndex];\n if (!isTabReorderable(tab)) {\n return;\n }\n\n const toIndex = fromIndex + offset;\n if (toIndex < 0 || toIndex >= orderedItems.length) {\n return;\n }\n\n if (!isTabReorderable(orderedItems[toIndex])) {\n return;\n }\n\n applyReorder(reorderTabs(orderedItems, tabId, toIndex + (offset > 0 ? 1 : 0)));\n },\n [applyReorder, orderedItems]\n );\n\n const handleDragStart = (tabId: string, event: DragEvent<HTMLButtonElement>) => {\n const tab = orderedItems.find(item => item.id === tabId);\n if (!tab || !isTabReorderable(tab) || !onTabReorder) {\n event.preventDefault();\n return;\n }\n\n setDraggedTabId(tabId);\n event.dataTransfer.effectAllowed = 'move';\n event.dataTransfer.setData('text/plain', tabId);\n };\n\n const handleDragOver = (tabId: string, event: DragEvent<HTMLDivElement>) => {\n if (!draggedTabId || draggedTabId === tabId) {\n return;\n }\n\n // A drop on a non-reorderable target would insert the dragged tab\n // before it, which is exactly what makes the target \"reorderable\" —\n // reject so pinned tabs stay pinned.\n const target = orderedItems.find(tab => tab.id === tabId);\n if (!target || !isTabReorderable(target)) {\n return;\n }\n\n event.preventDefault();\n event.dataTransfer.dropEffect = 'move';\n setDropBeforeId(tabId);\n };\n\n const handleDrop = (tabId: string, event: DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n\n if (!draggedTabId || draggedTabId === tabId) {\n setDraggedTabId(null);\n setDropBeforeId(null);\n return;\n }\n\n const target = orderedItems.find(tab => tab.id === tabId);\n if (!target || !isTabReorderable(target)) {\n setDraggedTabId(null);\n setDropBeforeId(null);\n return;\n }\n\n const fromIndex = orderedItems.findIndex(tab => tab.id === draggedTabId);\n const toIndex = orderedItems.findIndex(tab => tab.id === tabId);\n\n if (fromIndex >= 0 && toIndex >= 0) {\n // Dropping on the immediate right neighbor swaps the two tabs; every\n // other target uses the standard \"insert before\" semantics.\n const dropIndex = toIndex === fromIndex + 1 ? toIndex + 1 : toIndex;\n applyReorder(reorderTabs(orderedItems, draggedTabId, dropIndex));\n }\n\n setDraggedTabId(null);\n setDropBeforeId(null);\n };\n\n const handleDragEnd = () => {\n setDraggedTabId(null);\n setDropBeforeId(null);\n };\n\n const checkAndUpdateIsOverflowing = useCallback(() => {\n if (tabListRef.current) {\n const value = tabListRef.current.scrollWidth > tabListRef.current.clientWidth;\n setIsOverflowing(current => (current === value ? current : value));\n return value;\n }\n return isOverflowing;\n }, [isOverflowing]);\n\n useEffect(() => {\n const resizeObserver = new ResizeObserver(() => {\n checkAndUpdateIsOverflowing();\n });\n\n if (tabListRef.current) {\n resizeObserver.observe(tabListRef.current);\n }\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [checkAndUpdateIsOverflowing, orderedItems.length]);\n\n useLayoutEffect(() => {\n if (!checkAndUpdateIsOverflowing()) {\n return;\n }\n\n const activeTabRef = currentTabId ? tabRefs.get(currentTabId) : undefined;\n\n if (activeTabRef && tabListRef.current) {\n const activeTabRect = activeTabRef.getBoundingClientRect();\n const tabListRect = tabListRef.current.getBoundingClientRect();\n\n // Compare both edges in the same (viewport) coordinate space so the\n // check works regardless of where the tablist sits horizontally.\n if (activeTabRect.left < tabListRect.left || activeTabRect.right > tabListRect.right) {\n tabListRef.current.scrollLeft = rtl\n ? -(tabListRect.width - (activeTabRef.offsetLeft + activeTabRect.width))\n : activeTabRef.offsetLeft;\n }\n }\n }, [orderedItems, currentTabId, rtl, checkAndUpdateIsOverflowing]);\n\n const changeTabFocus = (event: KeyboardEvent, index: number): void => {\n const { key, altKey } = event;\n const tab = orderedItems[index];\n\n if (altKey && (key === 'ArrowLeft' || key === 'ArrowRight')) {\n event.preventDefault();\n if (tab && isTabReorderable(tab) && onTabReorder) {\n const offset = key === `Arrow${cap(endDirection)}` ? 1 : -1;\n moveTabByOffset(tab.id, offset);\n }\n return;\n }\n\n if (key === `Arrow${cap(endDirection)}`) {\n event.preventDefault();\n const nextIndex = (index + 1) % orderedItems.length;\n setFocusedTabId(orderedItems[nextIndex].id);\n tabRefs.get(orderedItems[nextIndex].id)?.focus();\n } else if (key === `Arrow${cap(startDirection)}`) {\n event.preventDefault();\n const prevIndex = index === 0 ? orderedItems.length - 1 : index - 1;\n setFocusedTabId(orderedItems[prevIndex].id);\n tabRefs.get(orderedItems[prevIndex].id)?.focus();\n } else if (key === 'Enter' || key === ' ') {\n event.preventDefault();\n handleTabClick(tab.id);\n } else if ((key === 'Delete' || key === 'Backspace') && tab && tab.closeable !== false) {\n event.preventDefault();\n const neighbor = orderedItems[index - 1] ?? orderedItems[index + 1];\n setFocusedTabId(neighbor ? neighbor.id : null);\n onTabClose?.(tab.id);\n if (neighbor) {\n tabRefs.get(neighbor.id)?.focus();\n }\n }\n };\n\n const overflowSearchRegex = createStringMatcher(overflowSearch);\n\n const hasCloseableTabs = orderedItems.some(tab => tab.closeable !== false);\n\n const overflowMenuItems = useMemo((): MenuProps['items'] => {\n const closeAllMenuItem: MenuItemProps | undefined =\n hasCloseableTabs && onTabCloseAll\n ? {\n id: 'document-tabs-close-all',\n primary: t('document_tabs_close_all'),\n onClick: () => {\n onTabCloseAll();\n }\n }\n : undefined;\n\n const prependCloseAll = (menuItems: MenuProps['items']): MenuProps['items'] => {\n if (!closeAllMenuItem) {\n return menuItems;\n }\n if (menuItems.length === 0) {\n return [closeAllMenuItem];\n }\n return [closeAllMenuItem, ...menuItems];\n };\n\n const filteredTabs = orderedItems.filter(tab => {\n const label = getTabLabel(tab);\n return (\n overflowSearchRegex.test(label) ||\n (tab.secondary && overflowSearchRegex.test(tab.secondary))\n );\n });\n\n const groupedTabs = GROUP_ORDER.map(group => ({\n group,\n tabs: filteredTabs.filter(tab => tab.group === group)\n })).filter(entry => entry.tabs.length > 0);\n\n const ungroupedTabs = filteredTabs.filter(\n tab => !tab.group || !GROUP_ORDER.includes(tab.group)\n );\n\n const toMenuItem = (tab: DocumentTab): MenuItemProps => {\n const label = getTabLabel(tab);\n return {\n id: tab.id,\n primary: label,\n secondary: tab.secondary ? [tab.secondary] : undefined,\n selected: tab.id === currentTabId,\n visual: tab.icon ? <Icon name={tab.icon} /> : undefined,\n onClick: () => {\n onTabClick?.(tab.id);\n tabRefs.get(tab.id)?.focus();\n }\n };\n };\n\n const groupLabels: Record<DocumentTabGroup, string> = {\n page: t('document_tabs_pages'),\n case: t('document_tabs_cases'),\n data: t('document_tabs_data')\n };\n\n const menuCategories: MenuProps['items'] = groupedTabs.map(({ group, tabs }) => ({\n id: `document-tabs-${group}`,\n label: groupLabels[group],\n items: tabs.map(toMenuItem)\n }));\n\n if (ungroupedTabs.length > 0) {\n if (menuCategories.length > 0) {\n menuCategories.push({\n id: 'document-tabs-other',\n label: t('document_tabs_all'),\n items: ungroupedTabs.map(toMenuItem)\n });\n } else {\n return prependCloseAll(ungroupedTabs.map(toMenuItem));\n }\n }\n\n if (menuCategories.length === 0 && filteredTabs.length > 0) {\n return prependCloseAll(filteredTabs.map(toMenuItem));\n }\n\n return prependCloseAll(menuCategories);\n }, [\n orderedItems,\n overflowSearchRegex,\n currentTabId,\n onTabClick,\n onTabCloseAll,\n hasCloseableTabs,\n t\n ]);\n\n const showOverflowSearch = isOverflowing && orderedItems.length > OVERFLOW_SEARCH_THRESHOLD;\n\n if (orderedItems.length === 0) {\n return null;\n }\n\n return (\n <StyledDocumentTabsContainer\n container={{ alignItems: 'center', gap: 0.5 }}\n data-overflowing={isOverflowing || undefined}\n >\n <StyledOverflowTabMenu\n menu={{\n listId: overflowMenuId,\n mode: 'single-select',\n items: overflowMenuItems,\n ...(showOverflowSearch && {\n filterInputProps: {\n value: overflowSearch,\n onChange: (e: ChangeEvent<HTMLInputElement>) => setOverflowSearch(e.target.value)\n }\n })\n }}\n icon='caret-down'\n iconOnly\n variant='simple'\n text={t('document_tabs_overflow_menu')}\n popover={{\n onHide: () => {\n setOverflowSearch('');\n }\n }}\n />\n <StyledDocumentTabList role='tablist' ref={tabListRef} aria-label={t('document_tabs_all')}>\n {(() => {\n // If nothing has been clicked/focused yet, the active tab (or\n // first tab as a fallback) holds the initial tabstop so keyboard\n // users can Tab in.\n const initialTabStopId =\n focusedTabId ??\n orderedItems.find(tab => tab.id === currentTabId)?.id ??\n orderedItems[0]?.id ??\n null;\n return orderedItems.map((tab, index) => (\n <DocumentTabItem\n key={tab.id}\n tab={tab}\n label={getTabLabel(tab)}\n isActive={tab.id === currentTabId}\n isTabStop={tab.id === initialTabStopId}\n closeable={tab.closeable !== false}\n reorderable={isTabReorderable(tab) && !!onTabReorder}\n isDragging={draggedTabId === tab.id}\n isDropBefore={dropBeforeId === tab.id}\n setTabRef={getTabRef(tab.id)}\n onTabClick={handleTabClick}\n onTabClose={handleTabClose}\n onDragStart={handleDragStart}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n onDragEnd={handleDragEnd}\n onKeyUp={(e: KeyboardEvent) => {\n changeTabFocus(e, index);\n }}\n />\n ));\n })()}\n </StyledDocumentTabList>\n </StyledDocumentTabsContainer>\n );\n};\n\nexport default DocumentTabs;\n"]}