@finos/legend-application 10.0.15 → 10.1.1
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/lib/application/LegendApplication.d.ts.map +1 -1
- package/lib/application/LegendApplication.js +7 -4
- package/lib/application/LegendApplication.js.map +1 -1
- package/lib/components/LegendApplicationComponentFrameworkProvider.d.ts.map +1 -1
- package/lib/components/LegendApplicationComponentFrameworkProvider.js +18 -7
- package/lib/components/LegendApplicationComponentFrameworkProvider.js.map +1 -1
- package/lib/components/shared/TabManager.d.ts +24 -0
- package/lib/components/shared/TabManager.d.ts.map +1 -0
- package/lib/components/shared/TabManager.js +115 -0
- package/lib/components/shared/TabManager.js.map +1 -0
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -3
- package/lib/index.js.map +1 -1
- package/lib/stores/CommandCenter.d.ts +10 -2
- package/lib/stores/CommandCenter.d.ts.map +1 -1
- package/lib/stores/CommandCenter.js +2 -2
- package/lib/stores/CommandCenter.js.map +1 -1
- package/lib/stores/DocumentationService.d.ts +5 -0
- package/lib/stores/DocumentationService.d.ts.map +1 -1
- package/lib/stores/DocumentationService.js.map +1 -1
- package/lib/stores/KeyboardShortcutsService.d.ts +5 -0
- package/lib/stores/KeyboardShortcutsService.d.ts.map +1 -1
- package/lib/stores/KeyboardShortcutsService.js +5 -0
- package/lib/stores/KeyboardShortcutsService.js.map +1 -1
- package/lib/stores/PureLanguageSupport.d.ts.map +1 -1
- package/lib/stores/PureLanguageSupport.js +5 -0
- package/lib/stores/PureLanguageSupport.js.map +1 -1
- package/lib/stores/shared/TabManagerState.d.ts +37 -0
- package/lib/stores/shared/TabManagerState.d.ts.map +1 -0
- package/lib/stores/shared/TabManagerState.js +55 -0
- package/lib/stores/shared/TabManagerState.js.map +1 -0
- package/package.json +5 -5
- package/src/application/LegendApplication.tsx +10 -3
- package/src/components/LegendApplicationComponentFrameworkProvider.tsx +18 -6
- package/src/components/shared/TabManager.tsx +285 -0
- package/src/index.ts +2 -3
- package/src/stores/CommandCenter.ts +11 -3
- package/src/stores/DocumentationService.ts +5 -0
- package/src/stores/KeyboardShortcutsService.ts +5 -0
- package/src/stores/PureLanguageSupport.ts +5 -0
- package/src/stores/shared/TabManagerState.ts +77 -0
- package/tsconfig.json +2 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2020-present, Goldman Sachs
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
ChevronDownIcon,
|
|
19
|
+
clsx,
|
|
20
|
+
ContextMenu,
|
|
21
|
+
DragPreviewLayer,
|
|
22
|
+
DropdownMenu,
|
|
23
|
+
MenuContent,
|
|
24
|
+
MenuContentItem,
|
|
25
|
+
PanelEntryDropZonePlaceholder,
|
|
26
|
+
TimesIcon,
|
|
27
|
+
useDragPreviewLayer,
|
|
28
|
+
} from '@finos/legend-art';
|
|
29
|
+
import { observer } from 'mobx-react-lite';
|
|
30
|
+
import { useRef, useCallback } from 'react';
|
|
31
|
+
import { type DropTargetMonitor, useDrop, useDrag } from 'react-dnd';
|
|
32
|
+
import type {
|
|
33
|
+
TabManagerState,
|
|
34
|
+
TabState,
|
|
35
|
+
} from '../../stores/shared/TabManagerState.js';
|
|
36
|
+
|
|
37
|
+
type TabDragSource = {
|
|
38
|
+
tab: TabState;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const horizontalToVerticalScroll: React.WheelEventHandler = (event) => {
|
|
42
|
+
// if scrolling is more horizontal than vertical, there's nothing much to do, the OS should handle it just fine
|
|
43
|
+
// else, intercept
|
|
44
|
+
if (Math.abs(event.deltaY) <= Math.abs(event.deltaX)) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
event.stopPropagation();
|
|
48
|
+
let deltaX = event.deltaX;
|
|
49
|
+
// NOTE: only convert horizontal to vertical scroll when the scroll causes more horizontal than vertical displacement
|
|
50
|
+
// let the direction of `deltaY` be the direction of the scroll, i.e.
|
|
51
|
+
// - if we scroll upward, that translate to a left scroll
|
|
52
|
+
// - if we scroll downward, that translates to a right scroll
|
|
53
|
+
if (event.deltaY === 0) {
|
|
54
|
+
deltaX = event.deltaY;
|
|
55
|
+
} else if (event.deltaY < 0) {
|
|
56
|
+
deltaX = -Math.abs(event.deltaY);
|
|
57
|
+
} else {
|
|
58
|
+
deltaX = Math.abs(event.deltaY);
|
|
59
|
+
}
|
|
60
|
+
event.currentTarget.scrollBy(deltaX, 0);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const TabContextMenu = observer(
|
|
64
|
+
(props: { tabState: TabState; managerTabState: TabManagerState }) => {
|
|
65
|
+
const { tabState, managerTabState } = props;
|
|
66
|
+
const close = (): void => managerTabState.closeTab(tabState);
|
|
67
|
+
const closeOthers = (): void => managerTabState.closeAllOtherTabs(tabState);
|
|
68
|
+
const closeAll = (): void => managerTabState.closeAllTabs();
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<MenuContent>
|
|
72
|
+
<MenuContentItem onClick={close}>Close</MenuContentItem>
|
|
73
|
+
<MenuContentItem
|
|
74
|
+
disabled={managerTabState.tabs.length < 2}
|
|
75
|
+
onClick={closeOthers}
|
|
76
|
+
>
|
|
77
|
+
Close Others
|
|
78
|
+
</MenuContentItem>
|
|
79
|
+
<MenuContentItem onClick={closeAll}>Close All</MenuContentItem>
|
|
80
|
+
</MenuContent>
|
|
81
|
+
);
|
|
82
|
+
},
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const Tab = observer(
|
|
86
|
+
(props: {
|
|
87
|
+
tabState: TabState;
|
|
88
|
+
tabManagerState: TabManagerState;
|
|
89
|
+
tabRenderer?: ((editorState: TabState) => React.ReactNode) | undefined;
|
|
90
|
+
}) => {
|
|
91
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
92
|
+
const { tabManagerState, tabState, tabRenderer } = props;
|
|
93
|
+
|
|
94
|
+
// Drag and Drop
|
|
95
|
+
const handleHover = useCallback(
|
|
96
|
+
(item: TabDragSource, monitor: DropTargetMonitor): void => {
|
|
97
|
+
const draggingTab = item.tab;
|
|
98
|
+
const hoveredTab = tabState;
|
|
99
|
+
|
|
100
|
+
const dragIndex = tabManagerState.tabs.findIndex(
|
|
101
|
+
(e) => e === draggingTab,
|
|
102
|
+
);
|
|
103
|
+
const hoverIndex = tabManagerState.tabs.findIndex(
|
|
104
|
+
(e) => e === hoveredTab,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
const hoverBoundingReact = ref.current?.getBoundingClientRect();
|
|
108
|
+
const distanceThreshold =
|
|
109
|
+
((hoverBoundingReact?.left ?? 0) - (hoverBoundingReact?.right ?? 0)) /
|
|
110
|
+
2;
|
|
111
|
+
const dragDistance =
|
|
112
|
+
(monitor.getClientOffset()?.x ?? 0) -
|
|
113
|
+
(hoverBoundingReact?.right ?? 0);
|
|
114
|
+
if (dragIndex < hoverIndex && dragDistance < distanceThreshold) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (dragIndex > hoverIndex && dragDistance > distanceThreshold) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
tabManagerState.swapTabs(draggingTab, hoveredTab);
|
|
122
|
+
},
|
|
123
|
+
[tabManagerState, tabState],
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const closeTabOnMiddleClick =
|
|
127
|
+
(currTab: TabState): React.MouseEventHandler =>
|
|
128
|
+
(event): void => {
|
|
129
|
+
if (event.nativeEvent.button === 1) {
|
|
130
|
+
tabManagerState.closeTab(currTab);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const [{ isBeingDraggedEditorPanel }, dropConnector] = useDrop<
|
|
135
|
+
TabDragSource,
|
|
136
|
+
void,
|
|
137
|
+
{ isBeingDraggedEditorPanel: TabState | undefined }
|
|
138
|
+
>(
|
|
139
|
+
() => ({
|
|
140
|
+
accept: [tabManagerState.dndType],
|
|
141
|
+
hover: (item, monitor) => handleHover(item, monitor),
|
|
142
|
+
collect: (
|
|
143
|
+
monitor,
|
|
144
|
+
): {
|
|
145
|
+
isBeingDraggedEditorPanel: TabState | undefined;
|
|
146
|
+
} => ({
|
|
147
|
+
isBeingDraggedEditorPanel: monitor.getItem<TabDragSource | null>()
|
|
148
|
+
?.tab,
|
|
149
|
+
}),
|
|
150
|
+
}),
|
|
151
|
+
[handleHover],
|
|
152
|
+
);
|
|
153
|
+
const isBeingDragged = tabState === isBeingDraggedEditorPanel;
|
|
154
|
+
|
|
155
|
+
const [, dragConnector, dragPreviewConnector] = useDrag<TabDragSource>(
|
|
156
|
+
() => ({
|
|
157
|
+
type: tabManagerState.dndType,
|
|
158
|
+
item: () => ({
|
|
159
|
+
tab: tabState,
|
|
160
|
+
}),
|
|
161
|
+
}),
|
|
162
|
+
[tabState, tabManagerState],
|
|
163
|
+
);
|
|
164
|
+
dragConnector(dropConnector(ref));
|
|
165
|
+
useDragPreviewLayer(dragPreviewConnector);
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<div
|
|
169
|
+
ref={ref}
|
|
170
|
+
className={clsx('tab-manager__tab', {
|
|
171
|
+
'tab-manager__tab--active': tabState === tabManagerState.currentTab,
|
|
172
|
+
'tab-manager__tab--dragged': isBeingDragged,
|
|
173
|
+
})}
|
|
174
|
+
onMouseUp={closeTabOnMiddleClick(tabState)}
|
|
175
|
+
>
|
|
176
|
+
<PanelEntryDropZonePlaceholder
|
|
177
|
+
showPlaceholder={false}
|
|
178
|
+
className="tab-manager__tab__dnd__placeholder"
|
|
179
|
+
>
|
|
180
|
+
<ContextMenu
|
|
181
|
+
content={
|
|
182
|
+
<TabContextMenu
|
|
183
|
+
tabState={tabState}
|
|
184
|
+
managerTabState={tabManagerState}
|
|
185
|
+
/>
|
|
186
|
+
}
|
|
187
|
+
className="tab-manager__tab__content"
|
|
188
|
+
>
|
|
189
|
+
<button
|
|
190
|
+
className="tab-manager__tab__label"
|
|
191
|
+
tabIndex={-1}
|
|
192
|
+
onClick={() => tabManagerState.openTab(tabState)}
|
|
193
|
+
title={tabState.description}
|
|
194
|
+
>
|
|
195
|
+
{tabRenderer?.(tabState) ?? tabState.label}
|
|
196
|
+
</button>
|
|
197
|
+
<button
|
|
198
|
+
className="tab-manager__tab__close-btn"
|
|
199
|
+
onClick={() => tabManagerState.closeTab(tabState)}
|
|
200
|
+
tabIndex={-1}
|
|
201
|
+
title="Close"
|
|
202
|
+
>
|
|
203
|
+
<TimesIcon />
|
|
204
|
+
</button>
|
|
205
|
+
</ContextMenu>
|
|
206
|
+
</PanelEntryDropZonePlaceholder>
|
|
207
|
+
</div>
|
|
208
|
+
);
|
|
209
|
+
},
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
const TabMenu = observer((props: { managerTabState: TabManagerState }) => {
|
|
213
|
+
const { managerTabState } = props;
|
|
214
|
+
return (
|
|
215
|
+
<DropdownMenu
|
|
216
|
+
className="tab-manager__menu__toggler"
|
|
217
|
+
title="Show All Tabs"
|
|
218
|
+
content={
|
|
219
|
+
<MenuContent className="tab-manager__menu">
|
|
220
|
+
{managerTabState.tabs.map((tabState) => (
|
|
221
|
+
<MenuContentItem
|
|
222
|
+
key={tabState.uuid}
|
|
223
|
+
className="tab-manager__menu__item"
|
|
224
|
+
onClick={() => managerTabState.openTab(tabState)}
|
|
225
|
+
>
|
|
226
|
+
<div className="tab-manager__menu__item__label">
|
|
227
|
+
{tabState.label}
|
|
228
|
+
</div>
|
|
229
|
+
<div
|
|
230
|
+
className="tab-manager__menu__item__close-btn"
|
|
231
|
+
onClick={(event) => {
|
|
232
|
+
// NOTE: prevent default action of dropdown menu
|
|
233
|
+
event.stopPropagation();
|
|
234
|
+
managerTabState.closeTab(tabState);
|
|
235
|
+
}}
|
|
236
|
+
tabIndex={-1}
|
|
237
|
+
title="Close"
|
|
238
|
+
>
|
|
239
|
+
<TimesIcon />
|
|
240
|
+
</div>
|
|
241
|
+
</MenuContentItem>
|
|
242
|
+
))}
|
|
243
|
+
</MenuContent>
|
|
244
|
+
}
|
|
245
|
+
menuProps={{
|
|
246
|
+
anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
|
|
247
|
+
transformOrigin: { vertical: 'top', horizontal: 'right' },
|
|
248
|
+
}}
|
|
249
|
+
>
|
|
250
|
+
<ChevronDownIcon />
|
|
251
|
+
</DropdownMenu>
|
|
252
|
+
);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
export const TabManager = observer(
|
|
256
|
+
(props: {
|
|
257
|
+
tabManagerState: TabManagerState;
|
|
258
|
+
tabRenderer?: ((editorState: TabState) => React.ReactNode) | undefined;
|
|
259
|
+
}) => {
|
|
260
|
+
const { tabManagerState, tabRenderer } = props;
|
|
261
|
+
|
|
262
|
+
return (
|
|
263
|
+
<div className="tab-manager">
|
|
264
|
+
<div
|
|
265
|
+
className="tab-manager__content"
|
|
266
|
+
onWheel={horizontalToVerticalScroll}
|
|
267
|
+
>
|
|
268
|
+
{tabManagerState.tabs.map((tab) => (
|
|
269
|
+
<Tab
|
|
270
|
+
key={tab.uuid}
|
|
271
|
+
tabState={tab}
|
|
272
|
+
tabManagerState={tabManagerState}
|
|
273
|
+
tabRenderer={tabRenderer}
|
|
274
|
+
/>
|
|
275
|
+
))}
|
|
276
|
+
<DragPreviewLayer
|
|
277
|
+
labelGetter={(item: TabDragSource): string => item.tab.label}
|
|
278
|
+
types={[tabManagerState.dndType]}
|
|
279
|
+
/>
|
|
280
|
+
</div>
|
|
281
|
+
<TabMenu managerTabState={tabManagerState} />
|
|
282
|
+
</div>
|
|
283
|
+
);
|
|
284
|
+
},
|
|
285
|
+
);
|
package/src/index.ts
CHANGED
|
@@ -25,9 +25,6 @@ export * from './components/useApplicationNavigationContext.js';
|
|
|
25
25
|
export * from './components/useCommands.js';
|
|
26
26
|
export * from './components/ApplicationStoreProviderTestUtils.js';
|
|
27
27
|
export * from './components/WebApplicationNavigatorProviderTestUtils.js';
|
|
28
|
-
// TODO: consider moving this to `LegendApplicationComponentFrameworkProvider`
|
|
29
|
-
// once we think we can add virtual assistant support for all apps
|
|
30
|
-
export * from './components/VirtualAssistant.js';
|
|
31
28
|
|
|
32
29
|
export * from './stores/ApplicationStore.js';
|
|
33
30
|
export * from './stores/ApplicationTelemetry.js';
|
|
@@ -53,8 +50,10 @@ export * from './stores/WebApplicationRouter.js';
|
|
|
53
50
|
export * from './components/shared/DocumentationLink.js';
|
|
54
51
|
export * from './components/shared/TextInputEditor.js';
|
|
55
52
|
export * from './components/shared/PackageableElementOptionLabel.js';
|
|
53
|
+
export * from './components/shared/TabManager.js';
|
|
56
54
|
|
|
57
55
|
export * from './stores/shared/PackageableElementOption.js';
|
|
56
|
+
export * from './stores/shared/TabManagerState.js';
|
|
58
57
|
|
|
59
58
|
/**
|
|
60
59
|
* @modularize
|
|
@@ -25,6 +25,11 @@ export interface CommandRegistrar {
|
|
|
25
25
|
}
|
|
26
26
|
export type CommandConfigEntry = {
|
|
27
27
|
title?: string;
|
|
28
|
+
/**
|
|
29
|
+
* NOTE: only support keyboard code instead of key
|
|
30
|
+
* See https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
|
|
31
|
+
* See https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code
|
|
32
|
+
*/
|
|
28
33
|
defaultKeyboardShortcut?: string;
|
|
29
34
|
when?: string;
|
|
30
35
|
};
|
|
@@ -40,10 +45,13 @@ export const collectKeyedCommandConfigEntriesFromConfig = (
|
|
|
40
45
|
key: entry[0],
|
|
41
46
|
content: entry[1],
|
|
42
47
|
}));
|
|
48
|
+
export type CommandArguments = {
|
|
49
|
+
event?: Event;
|
|
50
|
+
};
|
|
43
51
|
export type Command = {
|
|
44
52
|
key: string;
|
|
45
53
|
trigger?: () => boolean;
|
|
46
|
-
action?: () => void;
|
|
54
|
+
action?: (args?: CommandArguments) => void;
|
|
47
55
|
};
|
|
48
56
|
|
|
49
57
|
export class CommandCenter {
|
|
@@ -78,10 +86,10 @@ export class CommandCenter {
|
|
|
78
86
|
this.commandRegistry.delete(commandKey);
|
|
79
87
|
}
|
|
80
88
|
|
|
81
|
-
runCommand(commandKey: string): boolean {
|
|
89
|
+
runCommand(commandKey: string, args?: CommandArguments): boolean {
|
|
82
90
|
const command = this.commandRegistry.get(commandKey);
|
|
83
91
|
if (command && (!command.trigger || command.trigger())) {
|
|
84
|
-
command.action?.();
|
|
92
|
+
command.action?.(args);
|
|
85
93
|
return true;
|
|
86
94
|
}
|
|
87
95
|
return false;
|
|
@@ -48,6 +48,11 @@ export type DocumentationRegistryEntry = {
|
|
|
48
48
|
* See https://cors-anywhere.herokuapp.com/
|
|
49
49
|
*/
|
|
50
50
|
simple?: boolean | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Optional list of wildcard patterns to be matched against documentation entries' keys to
|
|
53
|
+
* narrow the scope of inclusion
|
|
54
|
+
*/
|
|
55
|
+
includes?: string[];
|
|
51
56
|
};
|
|
52
57
|
|
|
53
58
|
export type DocumentationRegistryData = {
|
|
@@ -21,6 +21,11 @@ import type { GenericLegendApplicationStore } from './ApplicationStore.js';
|
|
|
21
21
|
|
|
22
22
|
export class KeyboardShortcutsService {
|
|
23
23
|
readonly applicationStore: GenericLegendApplicationStore;
|
|
24
|
+
/**
|
|
25
|
+
* NOTE: with this design, the relationship between command and key is many-to-one
|
|
26
|
+
* We can have multiple commands being mapped to the same key combination, not the other
|
|
27
|
+
* way around
|
|
28
|
+
*/
|
|
24
29
|
readonly keyMap = new Map<string, string[]>();
|
|
25
30
|
/**
|
|
26
31
|
* NOTE: we want to leave the value of the map as optional because we want
|
|
@@ -362,6 +362,11 @@ export const setupPureLanguageService = (
|
|
|
362
362
|
// Override `monaco-editor` native hotkeys
|
|
363
363
|
// See https://github.com/microsoft/monaco-editor/issues/102#issuecomment-1282897640
|
|
364
364
|
monacoEditorAPI.addKeybindingRules([
|
|
365
|
+
{
|
|
366
|
+
// disable cursor move (core command)
|
|
367
|
+
keybinding: KeyMod.WinCtrl | KeyCode.KeyB,
|
|
368
|
+
command: null,
|
|
369
|
+
},
|
|
365
370
|
{
|
|
366
371
|
// disable cursor move (core command)
|
|
367
372
|
keybinding: KeyMod.WinCtrl | KeyCode.KeyO,
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2020-present, Goldman Sachs
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { assertNonNullable, swapEntry, uuid } from '@finos/legend-shared';
|
|
18
|
+
import { action, makeObservable, observable } from 'mobx';
|
|
19
|
+
|
|
20
|
+
export abstract class TabState {
|
|
21
|
+
readonly uuid = uuid();
|
|
22
|
+
|
|
23
|
+
abstract get label(): string;
|
|
24
|
+
|
|
25
|
+
get description(): string | undefined {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export abstract class TabManagerState {
|
|
31
|
+
currentTab?: TabState | undefined;
|
|
32
|
+
tabs: TabState[] = [];
|
|
33
|
+
|
|
34
|
+
constructor() {
|
|
35
|
+
makeObservable(this, {
|
|
36
|
+
currentTab: observable,
|
|
37
|
+
tabs: observable,
|
|
38
|
+
setCurrentTab: action,
|
|
39
|
+
closeTab: action,
|
|
40
|
+
closeAllTabs: action,
|
|
41
|
+
closeAllOtherTabs: action,
|
|
42
|
+
openTab: action,
|
|
43
|
+
swapTabs: action,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
setCurrentTab(val: TabState | undefined): void {
|
|
48
|
+
this.currentTab = val;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
closeAllOtherTabs(tab: TabState): void {
|
|
52
|
+
assertNonNullable(
|
|
53
|
+
this.tabs.find((e) => e === tab),
|
|
54
|
+
'Specified tab should be currently opened',
|
|
55
|
+
);
|
|
56
|
+
this.setCurrentTab(tab);
|
|
57
|
+
this.tabs = [tab];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
closeAllTabs(): void {
|
|
61
|
+
this.setCurrentTab(undefined);
|
|
62
|
+
this.tabs = [];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
swapTabs(tab1: TabState, tab2: TabState): void {
|
|
66
|
+
swapEntry(this.tabs, tab1, tab2);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The unique drag and drop type
|
|
71
|
+
* See https://react-dnd.github.io/react-dnd/docs/overview#items-and-types
|
|
72
|
+
*/
|
|
73
|
+
abstract get dndType(): string;
|
|
74
|
+
|
|
75
|
+
abstract openTab(tab: TabState): void;
|
|
76
|
+
abstract closeTab(tab: TabState): void;
|
|
77
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"./src/stores/WebApplicationNavigator.ts",
|
|
49
49
|
"./src/stores/WebApplicationRouter.ts",
|
|
50
50
|
"./src/stores/shared/PackageableElementOption.ts",
|
|
51
|
+
"./src/stores/shared/TabManagerState.ts",
|
|
51
52
|
"./src/stores/shared/TextSearchAdvancedConfigState.ts",
|
|
52
53
|
"./src/application/LegendApplication.tsx",
|
|
53
54
|
"./src/application/LegendApplicationPluginManager.tsx",
|
|
@@ -66,6 +67,7 @@
|
|
|
66
67
|
"./src/components/execution-plan-viewer/SQLExecutionNodeViewer.tsx",
|
|
67
68
|
"./src/components/shared/DocumentationLink.tsx",
|
|
68
69
|
"./src/components/shared/PackageableElementOptionLabel.tsx",
|
|
70
|
+
"./src/components/shared/TabManager.tsx",
|
|
69
71
|
"./src/components/shared/TextInputEditor.tsx",
|
|
70
72
|
"./src/components/shared/TextSearchAdvancedConfigMenu.tsx"
|
|
71
73
|
],
|