@harborclient/sdk 1.0.67 → 1.0.68
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/components/FooterIcon/index.d.ts +2 -1
- package/dist/components/FooterIcon/index.d.ts.map +1 -1
- package/dist/components/FooterIcon/index.js +3 -2
- package/dist/components/TabBar/ClosingTabShell.d.ts +20 -0
- package/dist/components/TabBar/ClosingTabShell.d.ts.map +1 -0
- package/dist/components/TabBar/ClosingTabShell.js +126 -0
- package/dist/components/TabBar/TabBarShell.d.ts +58 -0
- package/dist/components/TabBar/TabBarShell.d.ts.map +1 -0
- package/dist/components/TabBar/TabBarShell.js +37 -0
- package/dist/components/TabBar/TabContextMenu.d.ts +32 -0
- package/dist/components/TabBar/TabContextMenu.d.ts.map +1 -0
- package/dist/components/TabBar/TabContextMenu.js +133 -0
- package/dist/components/TabBar/TabNewButton.d.ts +26 -0
- package/dist/components/TabBar/TabNewButton.d.ts.map +1 -0
- package/dist/components/TabBar/TabNewButton.js +14 -0
- package/dist/components/TabBar/index.d.ts +92 -0
- package/dist/components/TabBar/index.d.ts.map +1 -0
- package/dist/components/TabBar/index.js +224 -0
- package/dist/components/TabBar/tabCloseMenuHelpers.d.ts +41 -0
- package/dist/components/TabBar/tabCloseMenuHelpers.d.ts.map +1 -0
- package/dist/components/TabBar/tabCloseMenuHelpers.js +48 -0
- package/dist/components/TabBar/types.d.ts +60 -0
- package/dist/components/TabBar/types.d.ts.map +1 -0
- package/dist/components/TabBar/types.js +1 -0
- package/dist/components/TabBar/useExitingTabItems.d.ts +73 -0
- package/dist/components/TabBar/useExitingTabItems.d.ts.map +1 -0
- package/dist/components/TabBar/useExitingTabItems.js +103 -0
- package/dist/components/TabBar/useSortableTabItem.d.ts +31 -0
- package/dist/components/TabBar/useSortableTabItem.d.ts.map +1 -0
- package/dist/components/TabBar/useSortableTabItem.js +29 -0
- package/dist/components/Toolbar/index.d.ts.map +1 -1
- package/dist/components/Toolbar/index.js +21 -5
- package/dist/components/classes.d.ts +9 -0
- package/dist/components/classes.d.ts.map +1 -1
- package/dist/components/classes.js +15 -2
- package/dist/components/footerBarUtils.d.ts +11 -0
- package/dist/components/footerBarUtils.d.ts.map +1 -0
- package/dist/components/footerBarUtils.js +10 -0
- package/dist/components/index.d.ts +3 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +3 -1
- package/dist/styles.css +12 -0
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -1
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@harborclient/sdk/jsx-runtime";
|
|
2
|
+
import { DndContext as DndContextBase, DragOverlay as DragOverlayBase, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors } from '@dnd-kit/core';
|
|
3
|
+
import { SortableContext, arrayMove, horizontalListSortingStrategy, rectSortingStrategy, sortableKeyboardCoordinates } from '@dnd-kit/sortable';
|
|
4
|
+
import { useEffect, useMemo, useState } from '@harborclient/sdk/react';
|
|
5
|
+
import { cn, resolveTabListKeyAction } from '../utils.js';
|
|
6
|
+
import { ClosingTabShell } from './ClosingTabShell.js';
|
|
7
|
+
import { TabBarShell } from './TabBarShell.js';
|
|
8
|
+
import { TabContextMenu } from './TabContextMenu.js';
|
|
9
|
+
import { TabNewButton } from './TabNewButton.js';
|
|
10
|
+
import { useExitingTabItems } from './useExitingTabItems.js';
|
|
11
|
+
const DndContext = DndContextBase;
|
|
12
|
+
const DragOverlay = DragOverlayBase;
|
|
13
|
+
/**
|
|
14
|
+
* Builds a stable dnd-kit sortable id for a tab row.
|
|
15
|
+
*
|
|
16
|
+
* @param prefix - Sortable id prefix.
|
|
17
|
+
* @param id - Open tab id.
|
|
18
|
+
*/
|
|
19
|
+
function tabSortableId(prefix, id) {
|
|
20
|
+
return `${prefix}${String(id)}`;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Parses a sortable drag id back to its tab id string.
|
|
24
|
+
*
|
|
25
|
+
* @param prefix - Sortable id prefix.
|
|
26
|
+
* @param dragId - Sortable id from dnd-kit.
|
|
27
|
+
*/
|
|
28
|
+
function parseTabSortableId(prefix, dragId) {
|
|
29
|
+
if (!dragId.startsWith(prefix)) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return dragId.slice(prefix.length);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Resolves the tab list index for arrow-key navigation from keyboard focus.
|
|
36
|
+
*
|
|
37
|
+
* @param tabs - Open tabs in display order.
|
|
38
|
+
* @param activeId - Currently selected tab id.
|
|
39
|
+
* @param tabIdPrefix - Prefix for tab element ids.
|
|
40
|
+
* @returns Index into `tabs`, or `-1` when the list is empty.
|
|
41
|
+
*/
|
|
42
|
+
function resolveFocusedTabIndex(tabs, activeId, tabIdPrefix) {
|
|
43
|
+
const activeElement = document.activeElement;
|
|
44
|
+
if (activeElement instanceof HTMLElement) {
|
|
45
|
+
const tabElement = activeElement.closest('[role="tab"]');
|
|
46
|
+
if (tabElement instanceof HTMLElement && tabElement.id.startsWith(tabIdPrefix)) {
|
|
47
|
+
const tabId = tabElement.id.slice(tabIdPrefix.length);
|
|
48
|
+
const focusedIndex = tabs.findIndex((tab) => String(tab.id) === tabId);
|
|
49
|
+
if (focusedIndex >= 0) {
|
|
50
|
+
return focusedIndex;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return tabs.findIndex((tab) => tab.id === activeId);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Document-style tab bar with drag reorder, keyboard navigation, close animation,
|
|
58
|
+
* optional context menu, and a new-tab control.
|
|
59
|
+
*/
|
|
60
|
+
export function TabBar({ tabs, activeId, wrap, ariaLabel, tabIdPrefix, panelIdPrefix, sortablePrefix, newTab, onSelect, onClose, onReorder, buildContextMenuGroups, onArrowDownIntoPanel, onFocusTab, renderScrollContainer, maxTabWidthClass, sortableCursor, className }) {
|
|
61
|
+
const resolvedSortablePrefix = sortablePrefix ?? `${tabIdPrefix}sort:`;
|
|
62
|
+
const [activeDragId, setActiveDragId] = useState(null);
|
|
63
|
+
const [contextMenu, setContextMenu] = useState(null);
|
|
64
|
+
const getId = useMemo(() => (item) => item.id, []);
|
|
65
|
+
const sortableEnabled = tabs.length >= 2;
|
|
66
|
+
const { completeExit, getExitingBefore, removedIds } = useExitingTabItems(tabs, getId);
|
|
67
|
+
/**
|
|
68
|
+
* Stable sortable ids for open tabs.
|
|
69
|
+
*/
|
|
70
|
+
const sortableIds = useMemo(() => tabs.map((tab) => tabSortableId(resolvedSortablePrefix, tab.id)), [tabs, resolvedSortablePrefix]);
|
|
71
|
+
/**
|
|
72
|
+
* Stable tab ids in display order for context menu close actions.
|
|
73
|
+
*/
|
|
74
|
+
const orderedIds = useMemo(() => tabs.map((tab) => tab.id), [tabs]);
|
|
75
|
+
/**
|
|
76
|
+
* Menu groups for the open tab context menu, when one is visible.
|
|
77
|
+
*/
|
|
78
|
+
const contextMenuGroups = useMemo(() => {
|
|
79
|
+
if (contextMenu == null || buildContextMenuGroups == null) {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
return buildContextMenuGroups(contextMenu.targetId, orderedIds);
|
|
83
|
+
}, [buildContextMenuGroups, contextMenu, orderedIds]);
|
|
84
|
+
/**
|
|
85
|
+
* Moves focus to the active tab when the focused tab row was just removed.
|
|
86
|
+
*/
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (removedIds.length === 0 || onFocusTab == null) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const focusedTab = document.activeElement?.closest('[role="tab"]');
|
|
92
|
+
if (!(focusedTab instanceof HTMLElement) || !focusedTab.id.startsWith(tabIdPrefix)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const focusedTabId = focusedTab.id.slice(tabIdPrefix.length);
|
|
96
|
+
if (!removedIds.some((id) => String(id) === focusedTabId)) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
requestAnimationFrame(() => {
|
|
100
|
+
onFocusTab(activeId);
|
|
101
|
+
});
|
|
102
|
+
}, [activeId, onFocusTab, removedIds, tabIdPrefix]);
|
|
103
|
+
const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 6 } }), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }));
|
|
104
|
+
/**
|
|
105
|
+
* Tab currently being dragged for overlay preview.
|
|
106
|
+
*/
|
|
107
|
+
const activeDragTab = useMemo(() => {
|
|
108
|
+
if (activeDragId == null) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
return tabs.find((tab) => tab.id === activeDragId) ?? null;
|
|
112
|
+
}, [activeDragId, tabs]);
|
|
113
|
+
/**
|
|
114
|
+
* Records the tab being dragged for overlay preview.
|
|
115
|
+
*/
|
|
116
|
+
const handleDragStart = (event) => {
|
|
117
|
+
const tabId = parseTabSortableId(resolvedSortablePrefix, String(event.active.id));
|
|
118
|
+
if (tabId == null) {
|
|
119
|
+
setActiveDragId(null);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const match = tabs.find((tab) => String(tab.id) === tabId);
|
|
123
|
+
setActiveDragId(match?.id ?? null);
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Persists a new tab order when a tab is dropped.
|
|
127
|
+
*/
|
|
128
|
+
const handleDragEnd = (event) => {
|
|
129
|
+
const { active, over } = event;
|
|
130
|
+
setActiveDragId(null);
|
|
131
|
+
if (!over || !sortableEnabled) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const activeTabIdFromDrag = parseTabSortableId(resolvedSortablePrefix, String(active.id));
|
|
135
|
+
const overTabId = parseTabSortableId(resolvedSortablePrefix, String(over.id));
|
|
136
|
+
if (activeTabIdFromDrag == null || overTabId == null || activeTabIdFromDrag === overTabId) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const tabIds = tabs.map((tab) => tab.id);
|
|
140
|
+
const oldIndex = tabIds.findIndex((id) => String(id) === activeTabIdFromDrag);
|
|
141
|
+
const newIndex = tabIds.findIndex((id) => String(id) === overTabId);
|
|
142
|
+
if (oldIndex < 0 || newIndex < 0) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
onReorder(arrayMove(tabIds, oldIndex, newIndex));
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Moves focus and selection across open tabs with arrow, Home, and End keys.
|
|
149
|
+
*/
|
|
150
|
+
const handleTabListKeyDown = (event) => {
|
|
151
|
+
if (event.key === 'ArrowDown' && onArrowDownIntoPanel != null) {
|
|
152
|
+
const activeElement = document.activeElement;
|
|
153
|
+
if (activeElement instanceof HTMLElement) {
|
|
154
|
+
const tabElement = activeElement.closest('[role="tab"]');
|
|
155
|
+
if (tabElement instanceof HTMLElement && tabElement.id.startsWith(tabIdPrefix)) {
|
|
156
|
+
const tabId = tabElement.id.slice(tabIdPrefix.length);
|
|
157
|
+
const match = tabs.find((tab) => String(tab.id) === tabId);
|
|
158
|
+
if (match != null && onArrowDownIntoPanel(match.id)) {
|
|
159
|
+
event.preventDefault();
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const currentIndex = resolveFocusedTabIndex(tabs, activeId, tabIdPrefix);
|
|
166
|
+
if (currentIndex < 0) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const nextIndex = resolveTabListKeyAction(event.key, currentIndex, tabs.length);
|
|
170
|
+
if (nextIndex === null) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
event.preventDefault();
|
|
174
|
+
const nextTab = tabs[nextIndex];
|
|
175
|
+
onSelect(nextTab.id);
|
|
176
|
+
if (onFocusTab != null) {
|
|
177
|
+
requestAnimationFrame(() => {
|
|
178
|
+
onFocusTab(nextTab.id);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
const tabRowClassName = wrap ? 'w-full min-w-0 py-1' : 'flex w-max flex-nowrap items-end py-1';
|
|
183
|
+
const tabListClassName = wrap
|
|
184
|
+
? 'flex min-w-0 w-full flex-wrap items-end gap-y-2'
|
|
185
|
+
: 'flex items-end';
|
|
186
|
+
const sortStrategy = wrap ? rectSortingStrategy : horizontalListSortingStrategy;
|
|
187
|
+
const newTabButton = (_jsx(TabNewButton, { wrapped: wrap, ariaLabel: newTab.ariaLabel, title: newTab.title, onClick: newTab.onClick }));
|
|
188
|
+
/**
|
|
189
|
+
* Renders one tab shell, optionally inside a close-animation wrapper.
|
|
190
|
+
*/
|
|
191
|
+
const renderTabShell = (item, options) => (_jsx(TabBarShell, { item: item, tabIndex: options.tabIndex, sortableId: tabSortableId(resolvedSortablePrefix, item.id), sortableDisabled: options.sortableDisabled, exiting: options.exiting, tabIdPrefix: tabIdPrefix, panelIdPrefix: panelIdPrefix, maxTabWidthClass: maxTabWidthClass, sortableCursor: sortableCursor, onSelect: onSelect, onClose: onClose, onContextMenu: options.onContextMenu }));
|
|
192
|
+
const tabRow = (_jsxs("div", { className: tabRowClassName, children: [_jsxs(DndContext, { sensors: sensors, collisionDetection: closestCenter, onDragStart: handleDragStart, onDragEnd: handleDragEnd, onDragCancel: () => setActiveDragId(null), children: [_jsxs("div", { role: "tablist", "aria-label": ariaLabel, className: tabListClassName, onKeyDown: handleTabListKeyDown, children: [_jsxs(SortableContext, { items: sortableIds, strategy: sortStrategy, children: [tabs.flatMap((tab) => {
|
|
193
|
+
const nodes = getExitingBefore(tab.id).map((exitingTab) => (_jsx(ClosingTabShell, { onComplete: () => completeExit(exitingTab.exitKey), children: renderTabShell(exitingTab.item, {
|
|
194
|
+
tabIndex: -1,
|
|
195
|
+
sortableDisabled: true,
|
|
196
|
+
exiting: true
|
|
197
|
+
}) }, exitingTab.exitKey)));
|
|
198
|
+
nodes.push(_jsx(TabBarShell, { item: tab, tabIndex: 0, sortableId: tabSortableId(resolvedSortablePrefix, tab.id), sortableDisabled: !sortableEnabled, tabIdPrefix: tabIdPrefix, panelIdPrefix: panelIdPrefix, maxTabWidthClass: maxTabWidthClass, sortableCursor: sortableCursor, onSelect: onSelect, onClose: onClose, onContextMenu: buildContextMenuGroups == null
|
|
199
|
+
? undefined
|
|
200
|
+
: (id, event) => {
|
|
201
|
+
setContextMenu({
|
|
202
|
+
targetId: id,
|
|
203
|
+
x: event.clientX,
|
|
204
|
+
y: event.clientY
|
|
205
|
+
});
|
|
206
|
+
} }, `live-${String(tab.id)}`));
|
|
207
|
+
return nodes;
|
|
208
|
+
}), getExitingBefore(null).map((exitingTab) => (_jsx(ClosingTabShell, { onComplete: () => completeExit(exitingTab.exitKey), children: renderTabShell(exitingTab.item, {
|
|
209
|
+
tabIndex: -1,
|
|
210
|
+
sortableDisabled: true,
|
|
211
|
+
exiting: true
|
|
212
|
+
}) }, exitingTab.exitKey)))] }), wrap ? newTabButton : null] }), _jsx(DragOverlay, { children: activeDragTab ? (_jsx("div", { className: "rounded-t-lg border border-separator bg-surface px-3 py-2 text-[14px] font-medium shadow-md", children: activeDragTab.dragLabel })) : null })] }), wrap ? null : newTabButton] }));
|
|
213
|
+
const defaultScrollContainer = (row) => (_jsx("div", { className: "min-w-0 flex-1 overflow-x-auto", children: row }));
|
|
214
|
+
const scrollContainer = renderScrollContainer ?? defaultScrollContainer;
|
|
215
|
+
const containerClassName = cn('app-no-drag flex shrink-0 items-end border-b border-separator bg-sidebar px-2', className);
|
|
216
|
+
return (_jsxs("div", { className: containerClassName, children: [wrap ? _jsx("div", { className: "min-w-0 flex-1", children: tabRow }) : scrollContainer(tabRow), contextMenu != null && buildContextMenuGroups != null && (_jsx(TabContextMenu, { groups: contextMenuGroups, position: { x: contextMenu.x, y: contextMenu.y }, onClose: () => setContextMenu(null) }))] }));
|
|
217
|
+
}
|
|
218
|
+
export { TabNewButton } from './TabNewButton.js';
|
|
219
|
+
export { TabContextMenu } from './TabContextMenu.js';
|
|
220
|
+
export { ClosingTabShell } from './ClosingTabShell.js';
|
|
221
|
+
export { TabBarShell } from './TabBarShell.js';
|
|
222
|
+
export { useSortableTabItem } from './useSortableTabItem.js';
|
|
223
|
+
export { useExitingTabItems, detectRemovedTabItems, resolveInsertBeforeId } from './useExitingTabItems.js';
|
|
224
|
+
export { buildTabCloseMenuGroups, tabIdsToCloseOthers, tabIdsToCloseToTheRight } from './tabCloseMenuHelpers.js';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { MenuItem } from '../RowActionsMenu/index.js';
|
|
2
|
+
interface TabCloseMenuActions<T extends string | number> {
|
|
3
|
+
/**
|
|
4
|
+
* Closes a single tab.
|
|
5
|
+
*/
|
|
6
|
+
onClose: (id: T) => void;
|
|
7
|
+
/**
|
|
8
|
+
* Closes every tab in `ids`.
|
|
9
|
+
*/
|
|
10
|
+
onCloseMany: (ids: T[]) => void;
|
|
11
|
+
/**
|
|
12
|
+
* Closes tabs that are considered saved (non-dirty for requests, with messages for AI).
|
|
13
|
+
*/
|
|
14
|
+
onCloseSaved: () => void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Builds grouped context menu items shared by request and AI tab bars.
|
|
18
|
+
*
|
|
19
|
+
* @param orderedIds - Tab ids in display order.
|
|
20
|
+
* @param targetId - Tab that was right-clicked.
|
|
21
|
+
* @param actions - Close handlers for single, bulk, and saved-only operations.
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildTabCloseMenuGroups<T extends string | number>(orderedIds: readonly T[], targetId: T, actions: TabCloseMenuActions<T>): MenuItem[][];
|
|
24
|
+
/**
|
|
25
|
+
* Returns tab ids for every tab except the one at `targetId`.
|
|
26
|
+
*
|
|
27
|
+
* @param orderedIds - Tab ids in display order.
|
|
28
|
+
* @param targetId - Tab that should remain open.
|
|
29
|
+
* @returns Ids of all other tabs.
|
|
30
|
+
*/
|
|
31
|
+
export declare function tabIdsToCloseOthers<T extends string | number>(orderedIds: readonly T[], targetId: T): T[];
|
|
32
|
+
/**
|
|
33
|
+
* Returns tab ids positioned to the right of `targetId` in display order.
|
|
34
|
+
*
|
|
35
|
+
* @param orderedIds - Tab ids in display order.
|
|
36
|
+
* @param targetId - Tab whose right-hand neighbors should be closed.
|
|
37
|
+
* @returns Ids of tabs after `targetId`, or an empty array when not found.
|
|
38
|
+
*/
|
|
39
|
+
export declare function tabIdsToCloseToTheRight<T extends string | number>(orderedIds: readonly T[], targetId: T): T[];
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=tabCloseMenuHelpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tabCloseMenuHelpers.d.ts","sourceRoot":"","sources":["../../../src/components/TabBar/tabCloseMenuHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAE3D,UAAU,mBAAmB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACrD;;OAEG;IACH,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC;IAEzB;;OAEG;IACH,WAAW,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC;IAEhC;;OAEG;IACH,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC/D,UAAU,EAAE,SAAS,CAAC,EAAE,EACxB,QAAQ,EAAE,CAAC,EACX,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAC9B,QAAQ,EAAE,EAAE,CAuBd;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC3D,UAAU,EAAE,SAAS,CAAC,EAAE,EACxB,QAAQ,EAAE,CAAC,GACV,CAAC,EAAE,CAEL;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC/D,UAAU,EAAE,SAAS,CAAC,EAAE,EACxB,QAAQ,EAAE,CAAC,GACV,CAAC,EAAE,CAML"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds grouped context menu items shared by request and AI tab bars.
|
|
3
|
+
*
|
|
4
|
+
* @param orderedIds - Tab ids in display order.
|
|
5
|
+
* @param targetId - Tab that was right-clicked.
|
|
6
|
+
* @param actions - Close handlers for single, bulk, and saved-only operations.
|
|
7
|
+
*/
|
|
8
|
+
export function buildTabCloseMenuGroups(orderedIds, targetId, actions) {
|
|
9
|
+
const targetIndex = orderedIds.indexOf(targetId);
|
|
10
|
+
const others = tabIdsToCloseOthers(orderedIds, targetId);
|
|
11
|
+
const toTheRight = tabIdsToCloseToTheRight(orderedIds, targetId);
|
|
12
|
+
const items = [{ label: 'Close', onSelect: () => actions.onClose(targetId) }];
|
|
13
|
+
if (orderedIds.length > 1) {
|
|
14
|
+
items.push({ label: 'Close others', onSelect: () => actions.onCloseMany(others) });
|
|
15
|
+
}
|
|
16
|
+
if (targetIndex >= 0 && targetIndex < orderedIds.length - 1) {
|
|
17
|
+
items.push({
|
|
18
|
+
label: 'Close to the right',
|
|
19
|
+
onSelect: () => actions.onCloseMany(toTheRight)
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
items.push({ label: 'Close saved', onSelect: () => actions.onCloseSaved() }, { label: 'Close all', onSelect: () => actions.onCloseMany([...orderedIds]) });
|
|
23
|
+
return [items];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns tab ids for every tab except the one at `targetId`.
|
|
27
|
+
*
|
|
28
|
+
* @param orderedIds - Tab ids in display order.
|
|
29
|
+
* @param targetId - Tab that should remain open.
|
|
30
|
+
* @returns Ids of all other tabs.
|
|
31
|
+
*/
|
|
32
|
+
export function tabIdsToCloseOthers(orderedIds, targetId) {
|
|
33
|
+
return orderedIds.filter((id) => id !== targetId);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Returns tab ids positioned to the right of `targetId` in display order.
|
|
37
|
+
*
|
|
38
|
+
* @param orderedIds - Tab ids in display order.
|
|
39
|
+
* @param targetId - Tab whose right-hand neighbors should be closed.
|
|
40
|
+
* @returns Ids of tabs after `targetId`, or an empty array when not found.
|
|
41
|
+
*/
|
|
42
|
+
export function tabIdsToCloseToTheRight(orderedIds, targetId) {
|
|
43
|
+
const index = orderedIds.indexOf(targetId);
|
|
44
|
+
if (index < 0) {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
return orderedIds.slice(index + 1);
|
|
48
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Data for a single tab row rendered by {@link TabBar}.
|
|
4
|
+
*/
|
|
5
|
+
export interface TabBarItem<TId extends string | number> {
|
|
6
|
+
/**
|
|
7
|
+
* Stable tab identifier used for selection, close, and reorder callbacks.
|
|
8
|
+
*/
|
|
9
|
+
id: TId;
|
|
10
|
+
/**
|
|
11
|
+
* Whether this tab is the currently selected tab.
|
|
12
|
+
*/
|
|
13
|
+
active: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Label and icon content rendered inside the tab shell.
|
|
16
|
+
*/
|
|
17
|
+
content: ReactNode;
|
|
18
|
+
/**
|
|
19
|
+
* Accessible name for the tab control, including unsaved or status suffixes.
|
|
20
|
+
*/
|
|
21
|
+
accessibleName: string;
|
|
22
|
+
/**
|
|
23
|
+
* Accessible name for the close button, typically including the tab title.
|
|
24
|
+
*/
|
|
25
|
+
closeAccessibleName: string;
|
|
26
|
+
/**
|
|
27
|
+
* Native tooltip text when the label is truncated.
|
|
28
|
+
*/
|
|
29
|
+
title?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Plain-text or element preview shown in the drag overlay.
|
|
32
|
+
*/
|
|
33
|
+
dragLabel: ReactNode;
|
|
34
|
+
/**
|
|
35
|
+
* When true, uses active styling even when not selected (for example tab group edit).
|
|
36
|
+
*/
|
|
37
|
+
highlighted?: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Configuration for the new-tab "+" control at the end of the tab bar.
|
|
41
|
+
*/
|
|
42
|
+
export interface TabBarNewTab {
|
|
43
|
+
/**
|
|
44
|
+
* Accessible name for the new-tab control.
|
|
45
|
+
*/
|
|
46
|
+
ariaLabel: string;
|
|
47
|
+
/**
|
|
48
|
+
* Native tooltip text for the new-tab control.
|
|
49
|
+
*/
|
|
50
|
+
title: string;
|
|
51
|
+
/**
|
|
52
|
+
* Called when the user opens a new tab or chat.
|
|
53
|
+
*/
|
|
54
|
+
onClick: () => void;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Cursor style applied to draggable tab rows when reordering is enabled.
|
|
58
|
+
*/
|
|
59
|
+
export type TabBarSortableCursor = 'pointer' | 'grab';
|
|
60
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/TabBar/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IACrD;;OAEG;IACH,EAAE,EAAE,GAAG,CAAC;IAER;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;OAEG;IACH,OAAO,EAAE,SAAS,CAAC;IAEnB;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,SAAS,EAAE,SAAS,CAAC;IAErB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,MAAM,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snapshot of a tab row kept in the DOM while its close animation plays.
|
|
3
|
+
*/
|
|
4
|
+
export interface ExitingTabItem<T, TId> {
|
|
5
|
+
/**
|
|
6
|
+
* Tab data captured at removal time.
|
|
7
|
+
*/
|
|
8
|
+
item: T;
|
|
9
|
+
/**
|
|
10
|
+
* Id of the live tab immediately to the right before removal, or null when
|
|
11
|
+
* this tab was last in the row.
|
|
12
|
+
*/
|
|
13
|
+
insertBeforeId: TId | null;
|
|
14
|
+
/**
|
|
15
|
+
* Stable React key for this exit animation instance.
|
|
16
|
+
*/
|
|
17
|
+
exitKey: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolves the anchor id for an exiting tab: the first still-open tab that was
|
|
21
|
+
* to its right in the previous list, or null when none remain on the right.
|
|
22
|
+
*
|
|
23
|
+
* @param previousItems - Tab list before removal.
|
|
24
|
+
* @param removedIndex - Index of the tab being removed.
|
|
25
|
+
* @param currentIds - Ids that remain open after removal.
|
|
26
|
+
* @param getId - Reads a stable id from a tab item.
|
|
27
|
+
* @returns Anchor id for render placement, or null for end-of-row placement.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveInsertBeforeId<T, TId>(previousItems: T[], removedIndex: number, currentIds: Set<TId>, getId: (item: T) => TId): TId | null;
|
|
30
|
+
/**
|
|
31
|
+
* Detects tabs removed between two list snapshots and their render anchors.
|
|
32
|
+
*
|
|
33
|
+
* @param previousItems - Tab list before removal.
|
|
34
|
+
* @param currentItems - Tab list after removal.
|
|
35
|
+
* @param getId - Reads a stable id from a tab item.
|
|
36
|
+
* @returns Removed tabs with placement anchors for exit animation.
|
|
37
|
+
*/
|
|
38
|
+
export declare function detectRemovedTabItems<T, TId>(previousItems: T[], currentItems: T[], getId: (item: T) => TId): Array<{
|
|
39
|
+
item: T;
|
|
40
|
+
insertBeforeId: TId | null;
|
|
41
|
+
}>;
|
|
42
|
+
interface UseExitingTabItemsResult<T, TId> {
|
|
43
|
+
/**
|
|
44
|
+
* Tabs currently playing their close animation.
|
|
45
|
+
*/
|
|
46
|
+
exiting: ExitingTabItem<T, TId>[];
|
|
47
|
+
/**
|
|
48
|
+
* Ids removed in the latest list update (cleared on the next stable render).
|
|
49
|
+
*/
|
|
50
|
+
removedIds: TId[];
|
|
51
|
+
/**
|
|
52
|
+
* Drops a finished exit snapshot from local state.
|
|
53
|
+
*
|
|
54
|
+
* @param exitKey - Key returned with the exiting tab entry.
|
|
55
|
+
*/
|
|
56
|
+
completeExit: (exitKey: string) => void;
|
|
57
|
+
/**
|
|
58
|
+
* Returns exit snapshots that should render immediately before an anchor tab.
|
|
59
|
+
*
|
|
60
|
+
* @param anchorId - Live tab id to the right of the snapshot, or null for end-of-row.
|
|
61
|
+
*/
|
|
62
|
+
getExitingBefore: (anchorId: TId | null) => ExitingTabItem<T, TId>[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Tracks tab rows removed from a live list and keeps snapshots for exit animation.
|
|
66
|
+
*
|
|
67
|
+
* @param items - Current open tabs from Redux or parent state.
|
|
68
|
+
* @param getId - Reads a stable id from a tab item.
|
|
69
|
+
* @returns Exiting snapshots, placement helpers, and ids removed last update.
|
|
70
|
+
*/
|
|
71
|
+
export declare function useExitingTabItems<T, TId>(items: T[], getId: (item: T) => TId): UseExitingTabItemsResult<T, TId>;
|
|
72
|
+
export {};
|
|
73
|
+
//# sourceMappingURL=useExitingTabItems.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useExitingTabItems.d.ts","sourceRoot":"","sources":["../../../src/components/TabBar/useExitingTabItems.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC,EAAE,GAAG;IACpC;;OAEG;IACH,IAAI,EAAE,CAAC,CAAC;IAER;;;OAGG;IACH,cAAc,EAAE,GAAG,GAAG,IAAI,CAAC;IAE3B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,GAAG,EAC1C,aAAa,EAAE,CAAC,EAAE,EAClB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,GAAG,CAAC,GAAG,CAAC,EACpB,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,GAAG,GACtB,GAAG,GAAG,IAAI,CASZ;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,GAAG,EAC1C,aAAa,EAAE,CAAC,EAAE,EAClB,YAAY,EAAE,CAAC,EAAE,EACjB,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,GAAG,GACtB,KAAK,CAAC;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,cAAc,EAAE,GAAG,GAAG,IAAI,CAAA;CAAE,CAAC,CAkBhD;AAED,UAAU,wBAAwB,CAAC,CAAC,EAAE,GAAG;IACvC;;OAEG;IACH,OAAO,EAAE,cAAc,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;IAElC;;OAEG;IACH,UAAU,EAAE,GAAG,EAAE,CAAC;IAElB;;;;OAIG;IACH,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAExC;;;;OAIG;IACH,gBAAgB,EAAE,CAAC,QAAQ,EAAE,GAAG,GAAG,IAAI,KAAK,cAAc,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;CACtE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,GAAG,EACvC,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,GAAG,GACtB,wBAAwB,CAAC,CAAC,EAAE,GAAG,CAAC,CA8DlC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from '@harborclient/sdk/react';
|
|
2
|
+
/**
|
|
3
|
+
* Resolves the anchor id for an exiting tab: the first still-open tab that was
|
|
4
|
+
* to its right in the previous list, or null when none remain on the right.
|
|
5
|
+
*
|
|
6
|
+
* @param previousItems - Tab list before removal.
|
|
7
|
+
* @param removedIndex - Index of the tab being removed.
|
|
8
|
+
* @param currentIds - Ids that remain open after removal.
|
|
9
|
+
* @param getId - Reads a stable id from a tab item.
|
|
10
|
+
* @returns Anchor id for render placement, or null for end-of-row placement.
|
|
11
|
+
*/
|
|
12
|
+
export function resolveInsertBeforeId(previousItems, removedIndex, currentIds, getId) {
|
|
13
|
+
for (let index = removedIndex + 1; index < previousItems.length; index += 1) {
|
|
14
|
+
const id = getId(previousItems[index]);
|
|
15
|
+
if (currentIds.has(id)) {
|
|
16
|
+
return id;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Detects tabs removed between two list snapshots and their render anchors.
|
|
23
|
+
*
|
|
24
|
+
* @param previousItems - Tab list before removal.
|
|
25
|
+
* @param currentItems - Tab list after removal.
|
|
26
|
+
* @param getId - Reads a stable id from a tab item.
|
|
27
|
+
* @returns Removed tabs with placement anchors for exit animation.
|
|
28
|
+
*/
|
|
29
|
+
export function detectRemovedTabItems(previousItems, currentItems, getId) {
|
|
30
|
+
const currentIds = new Set(currentItems.map(getId));
|
|
31
|
+
const removed = [];
|
|
32
|
+
for (let index = 0; index < previousItems.length; index += 1) {
|
|
33
|
+
const item = previousItems[index];
|
|
34
|
+
const id = getId(item);
|
|
35
|
+
if (currentIds.has(id)) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
removed.push({
|
|
39
|
+
item,
|
|
40
|
+
insertBeforeId: resolveInsertBeforeId(previousItems, index, currentIds, getId)
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return removed;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Tracks tab rows removed from a live list and keeps snapshots for exit animation.
|
|
47
|
+
*
|
|
48
|
+
* @param items - Current open tabs from Redux or parent state.
|
|
49
|
+
* @param getId - Reads a stable id from a tab item.
|
|
50
|
+
* @returns Exiting snapshots, placement helpers, and ids removed last update.
|
|
51
|
+
*/
|
|
52
|
+
export function useExitingTabItems(items, getId) {
|
|
53
|
+
const previousItemsRef = useRef(items);
|
|
54
|
+
const getIdRef = useRef(getId);
|
|
55
|
+
const exitCounterRef = useRef(0);
|
|
56
|
+
const [exiting, setExiting] = useState([]);
|
|
57
|
+
const [removedIds, setRemovedIds] = useState([]);
|
|
58
|
+
/**
|
|
59
|
+
* Keeps the latest id getter available to the removal effect without re-running it.
|
|
60
|
+
*/
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
getIdRef.current = getId;
|
|
63
|
+
}, [getId]);
|
|
64
|
+
/**
|
|
65
|
+
* Captures removed tabs whenever the live list shrinks.
|
|
66
|
+
*/
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
const previousItems = previousItemsRef.current;
|
|
69
|
+
const removed = detectRemovedTabItems(previousItems, items, getIdRef.current);
|
|
70
|
+
if (removed.length > 0) {
|
|
71
|
+
const nextExiting = removed.map(({ item, insertBeforeId }) => {
|
|
72
|
+
exitCounterRef.current += 1;
|
|
73
|
+
return {
|
|
74
|
+
item,
|
|
75
|
+
insertBeforeId,
|
|
76
|
+
exitKey: `${String(getIdRef.current(item))}-exit-${exitCounterRef.current}`
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
setExiting((current) => [...current, ...nextExiting]);
|
|
80
|
+
setRemovedIds(removed.map((entry) => getIdRef.current(entry.item)));
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
setRemovedIds([]);
|
|
84
|
+
}
|
|
85
|
+
previousItemsRef.current = items;
|
|
86
|
+
}, [items]);
|
|
87
|
+
/**
|
|
88
|
+
* Removes a finished exit snapshot after its width transition completes.
|
|
89
|
+
*/
|
|
90
|
+
const completeExit = useCallback((exitKey) => {
|
|
91
|
+
setExiting((current) => current.filter((entry) => entry.exitKey !== exitKey));
|
|
92
|
+
}, []);
|
|
93
|
+
/**
|
|
94
|
+
* Groups exit snapshots by the live tab they should render in front of.
|
|
95
|
+
*/
|
|
96
|
+
const getExitingBefore = useCallback((anchorId) => exiting.filter((entry) => entry.insertBeforeId === anchorId), [exiting]);
|
|
97
|
+
return {
|
|
98
|
+
exiting,
|
|
99
|
+
removedIds,
|
|
100
|
+
completeExit,
|
|
101
|
+
getExitingBefore
|
|
102
|
+
};
|
|
103
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SyntheticListenerMap } from '@dnd-kit/core/dist/hooks/utilities';
|
|
2
|
+
import type { CSSProperties } from 'react';
|
|
3
|
+
interface SortableTabItemResult {
|
|
4
|
+
/**
|
|
5
|
+
* Ref for the sortable tab shell element.
|
|
6
|
+
*/
|
|
7
|
+
setNodeRef: (element: HTMLElement | null) => void;
|
|
8
|
+
/**
|
|
9
|
+
* dnd-kit pointer and keyboard listeners for the tab shell.
|
|
10
|
+
*/
|
|
11
|
+
listeners: SyntheticListenerMap | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Inline styles for transform and drag feedback on the tab shell.
|
|
14
|
+
*/
|
|
15
|
+
style: CSSProperties;
|
|
16
|
+
/**
|
|
17
|
+
* Whether this tab is currently being dragged.
|
|
18
|
+
*/
|
|
19
|
+
isDragging: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Wraps dnd-kit sortable behavior for horizontal tab bar items while keeping
|
|
23
|
+
* the tab element itself as a direct child of the tab list for ARIA compliance.
|
|
24
|
+
*
|
|
25
|
+
* @param id - Stable sortable id for this tab.
|
|
26
|
+
* @param disabled - When true, skips drag behavior (for example a single open tab).
|
|
27
|
+
* @returns Refs, listeners, and styles for the draggable tab shell.
|
|
28
|
+
*/
|
|
29
|
+
export declare function useSortableTabItem(id: string, disabled?: boolean): SortableTabItemResult;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=useSortableTabItem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSortableTabItem.d.ts","sourceRoot":"","sources":["../../../src/components/TabBar/useSortableTabItem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAG/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,UAAU,qBAAqB;IAC7B;;OAEG;IACH,UAAU,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IAElD;;OAEG;IACH,SAAS,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAE5C;;OAEG;IACH,KAAK,EAAE,aAAa,CAAC;IAErB;;OAEG;IACH,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,UAAQ,GAAG,qBAAqB,CAoBtF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useSortable } from '@dnd-kit/sortable';
|
|
2
|
+
import { CSS } from '@dnd-kit/utilities';
|
|
3
|
+
/**
|
|
4
|
+
* Wraps dnd-kit sortable behavior for horizontal tab bar items while keeping
|
|
5
|
+
* the tab element itself as a direct child of the tab list for ARIA compliance.
|
|
6
|
+
*
|
|
7
|
+
* @param id - Stable sortable id for this tab.
|
|
8
|
+
* @param disabled - When true, skips drag behavior (for example a single open tab).
|
|
9
|
+
* @returns Refs, listeners, and styles for the draggable tab shell.
|
|
10
|
+
*/
|
|
11
|
+
export function useSortableTabItem(id, disabled = false) {
|
|
12
|
+
const { listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
|
13
|
+
id,
|
|
14
|
+
disabled
|
|
15
|
+
});
|
|
16
|
+
const style = disabled
|
|
17
|
+
? {}
|
|
18
|
+
: {
|
|
19
|
+
transform: CSS.Transform.toString(transform),
|
|
20
|
+
transition,
|
|
21
|
+
opacity: isDragging ? 0.45 : undefined
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
setNodeRef,
|
|
25
|
+
listeners,
|
|
26
|
+
style,
|
|
27
|
+
isDragging
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Toolbar/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,wBAAwB,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIjG;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,IAAI,EAAE,cAAc,CAAC;IAErB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IAEpB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;OAEG;IACH,YAAY,CAAC,EAAE,cAAc,CAAC,eAAe,CAAC,CAAC;IAE/C;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACjD;AAED,UAAU,KAAM,SAAQ,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACtF;;OAEG;IACH,OAAO,EAAE,aAAa,EAAE,CAAC;IAEzB;;OAEG;IACH,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAE1B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Toolbar/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,wBAAwB,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIjG;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,IAAI,EAAE,cAAc,CAAC;IAErB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IAEpB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;OAEG;IACH,YAAY,CAAC,EAAE,cAAc,CAAC,eAAe,CAAC,CAAC;IAE/C;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACjD;AAED,UAAU,KAAM,SAAQ,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACtF;;OAEG;IACH,OAAO,EAAE,aAAa,EAAE,CAAC;IAEzB;;OAEG;IACH,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAE1B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoED;;GAEG;AACH,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,OAAO,EACP,SAAqB,EACrB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAqBrB"}
|