@workbench-kit/shell-react 0.0.2-prototype.0.2.41 → 0.0.2-prototype.0.2.44
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/README.md +81 -2
- package/package.json +14 -10
- package/src/editor/workspace-reconcile.tsx +12 -7
- package/src/extensions/extension-enablement-controller.ts +40 -9
- package/src/extensions/theme-selection-protection.ts +80 -55
- package/src/field-remap/chrome-labels.ts +117 -0
- package/src/field-remap/convert-note-editor.tsx +119 -104
- package/src/field-remap/convert-palette.tsx +6 -0
- package/src/field-remap/demo.tsx +8 -2
- package/src/field-remap/detail-panel.tsx +535 -434
- package/src/field-remap/document-io.tsx +299 -0
- package/src/field-remap/drag-payload.ts +48 -0
- package/src/field-remap/flow-adapter.ts +216 -88
- package/src/field-remap/flow-ops.ts +150 -0
- package/src/field-remap/flow.tsx +1227 -272
- package/src/field-remap/index.ts +2 -0
- package/src/field-remap/io-class-browse.tsx +34 -22
- package/src/field-remap/keyboard.ts +16 -0
- package/src/field-remap/modal-detail.tsx +34 -0
- package/src/field-remap/panel.tsx +110 -14
- package/src/field-remap/transform-options-editor.tsx +68 -48
- package/src/field-remap/view.css +107 -189
- package/src/index.ts +7 -0
- package/src/keybinding-management-settings.ts +4 -0
- package/src/management/keybinding-overrides-storage.ts +48 -23
- package/src/management/keybinding-settings-view.tsx +31 -0
- package/src/management/keybinding-settings.tsx +4 -12
- package/src/management/use-keybinding-management.ts +72 -22
- package/src/shell/appearance-catalog.ts +453 -0
- package/src/shell/appearance-controller.ts +331 -0
- package/src/shell/appearance-presentation.ts +269 -0
- package/src/shell/provider.tsx +157 -19
- package/src/shell/settings.tsx +282 -153
- package/src/shell/shell.tsx +88 -18
- package/src/workbench/appearance-storage.ts +2 -2
- package/src/workbench/command-host-controller.tsx +223 -0
- package/src/workbench/command-host.tsx +100 -150
- package/src/workbench/keybinding-bridge.ts +84 -38
- package/src/workbench/shell-command-registration.ts +27 -2
package/src/shell/shell.tsx
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
useCallback,
|
|
3
|
+
useEffect,
|
|
4
|
+
useMemo,
|
|
5
|
+
useReducer,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
type CSSProperties,
|
|
9
|
+
type ReactNode,
|
|
10
|
+
} from 'react';
|
|
2
11
|
import { Modal } from '@workbench-kit/react/modal';
|
|
3
12
|
import { Badge, Button, IconButton } from '@workbench-kit/react/primitives';
|
|
4
13
|
import {
|
|
@@ -18,7 +27,6 @@ import type {
|
|
|
18
27
|
import { WORKBENCH_PERMISSION_CONTEXT_KEY_CAN_OPEN_SETTINGS } from '@workbench-kit/platform';
|
|
19
28
|
import { isPreferenceScope, type PreferenceScope } from '@workbench-kit/workbench-config';
|
|
20
29
|
import {
|
|
21
|
-
resolveActiveThemePreset,
|
|
22
30
|
DEFAULT_SHELL_PRESET,
|
|
23
31
|
useResolvedWorkbenchTheme,
|
|
24
32
|
type WorkbenchCommandDescriptor,
|
|
@@ -62,7 +70,17 @@ import {
|
|
|
62
70
|
getWorkbenchSecondaryActivityRoute,
|
|
63
71
|
} from './secondary-actions.js';
|
|
64
72
|
import { SETTINGS_EXTENSION_ID, WORKBENCH_PREFERENCE_SCOPES } from './settings-constants.js';
|
|
65
|
-
import {
|
|
73
|
+
import {
|
|
74
|
+
createSettingsCategories,
|
|
75
|
+
createWorkbenchThemeOptionSnapshot,
|
|
76
|
+
type WorkbenchThemeOption,
|
|
77
|
+
} from './settings.js';
|
|
78
|
+
import { createWorkbenchAppearanceCatalogSnapshot } from './appearance-catalog.js';
|
|
79
|
+
import {
|
|
80
|
+
createWorkbenchDocumentAppearanceDiagnosticController,
|
|
81
|
+
createWorkbenchDocumentAppearanceOverrideController,
|
|
82
|
+
} from './appearance-controller.js';
|
|
83
|
+
import { resolveWorkbenchAppearancePresentation } from './appearance-presentation.js';
|
|
66
84
|
import {
|
|
67
85
|
createContributedWorkbenchStatusSections,
|
|
68
86
|
createDefaultWorkbenchStatusSections,
|
|
@@ -200,10 +218,6 @@ export function WorkbenchShell({
|
|
|
200
218
|
}: WorkbenchShellProps) {
|
|
201
219
|
const resolvedEditorArea = editorArea ?? null;
|
|
202
220
|
const resolvedWorkbenchTheme = useResolvedWorkbenchTheme(theme ?? 'system');
|
|
203
|
-
const activeThemePreset =
|
|
204
|
-
lightPreset !== undefined && darkPreset !== undefined
|
|
205
|
-
? resolveActiveThemePreset(resolvedWorkbenchTheme, { darkPreset, lightPreset })
|
|
206
|
-
: undefined;
|
|
207
221
|
const {
|
|
208
222
|
activities,
|
|
209
223
|
commands,
|
|
@@ -222,6 +236,26 @@ export function WorkbenchShell({
|
|
|
222
236
|
viewHostFactories,
|
|
223
237
|
views,
|
|
224
238
|
} = useWorkbench();
|
|
239
|
+
const appearanceThemeOptions = createWorkbenchThemeOptionSnapshot(themeOptions);
|
|
240
|
+
const appearanceCatalog = createWorkbenchAppearanceCatalogSnapshot({
|
|
241
|
+
hostOptions: appearanceThemeOptions,
|
|
242
|
+
themes,
|
|
243
|
+
});
|
|
244
|
+
const appearancePresentation = resolveWorkbenchAppearancePresentation({
|
|
245
|
+
catalog: appearanceCatalog,
|
|
246
|
+
darkPreset,
|
|
247
|
+
lightPreset,
|
|
248
|
+
resolvedSystemTheme: resolvedWorkbenchTheme,
|
|
249
|
+
theme,
|
|
250
|
+
});
|
|
251
|
+
const rootAppearanceStyle = appearancePresentation.legacyTokenOverrides as
|
|
252
|
+
CSSProperties | undefined;
|
|
253
|
+
const documentAppearanceControllerRef = useRef<
|
|
254
|
+
ReturnType<typeof createWorkbenchDocumentAppearanceOverrideController> | undefined
|
|
255
|
+
>(undefined);
|
|
256
|
+
const documentAppearanceDiagnosticControllerRef = useRef<
|
|
257
|
+
ReturnType<typeof createWorkbenchDocumentAppearanceDiagnosticController> | undefined
|
|
258
|
+
>(undefined);
|
|
225
259
|
const extensionEnablement = useExtensionEnablementController();
|
|
226
260
|
const contextKeyRevision = useContextKeyRevision(contextKeyService);
|
|
227
261
|
const contextKeySnapshot = useMemo(
|
|
@@ -233,13 +267,14 @@ export function WorkbenchShell({
|
|
|
233
267
|
const themeSelectionProtection = useMemo(
|
|
234
268
|
() =>
|
|
235
269
|
createThemeSelectionProtectionSnapshot({
|
|
270
|
+
catalog: appearanceCatalog,
|
|
236
271
|
darkPreset,
|
|
237
272
|
lightPreset,
|
|
238
273
|
theme,
|
|
239
274
|
themeOptions,
|
|
240
275
|
themes,
|
|
241
276
|
}),
|
|
242
|
-
[darkPreset, lightPreset, theme, themeOptions, themeRevision, themes],
|
|
277
|
+
[appearanceCatalog, darkPreset, lightPreset, theme, themeOptions, themeRevision, themes],
|
|
243
278
|
);
|
|
244
279
|
const [preferenceRevision, bumpPreferenceRevision] = useReducer((count: number) => count + 1, 0);
|
|
245
280
|
const [isHelpOpen, setHelpOpen] = useState(false);
|
|
@@ -254,6 +289,9 @@ export function WorkbenchShell({
|
|
|
254
289
|
setSettingsCategoryId(categoryId);
|
|
255
290
|
setSettingsOpen(true);
|
|
256
291
|
}, []);
|
|
292
|
+
const closeSettingsModal = useCallback(() => {
|
|
293
|
+
setSettingsOpen(false);
|
|
294
|
+
}, []);
|
|
257
295
|
const settingsCapability = useMemo<WorkbenchSettingsCapability>(
|
|
258
296
|
() => ({
|
|
259
297
|
openSettings: showSettingsModal,
|
|
@@ -313,11 +351,40 @@ export function WorkbenchShell({
|
|
|
313
351
|
});
|
|
314
352
|
|
|
315
353
|
useEffect(() => {
|
|
316
|
-
extensionEnablement.setThemeSelectionProtection(themeSelectionProtection);
|
|
354
|
+
return extensionEnablement.setThemeSelectionProtection(themeSelectionProtection);
|
|
355
|
+
}, [extensionEnablement, themeSelectionProtection]);
|
|
356
|
+
|
|
357
|
+
useEffect(() => {
|
|
358
|
+
if (typeof document === 'undefined') {
|
|
359
|
+
return undefined;
|
|
360
|
+
}
|
|
361
|
+
const controller = createWorkbenchDocumentAppearanceOverrideController(
|
|
362
|
+
document.documentElement,
|
|
363
|
+
);
|
|
364
|
+
const diagnosticController = createWorkbenchDocumentAppearanceDiagnosticController(
|
|
365
|
+
document.documentElement,
|
|
366
|
+
);
|
|
367
|
+
documentAppearanceControllerRef.current = controller;
|
|
368
|
+
documentAppearanceDiagnosticControllerRef.current = diagnosticController;
|
|
317
369
|
return () => {
|
|
318
|
-
|
|
370
|
+
documentAppearanceControllerRef.current = undefined;
|
|
371
|
+
documentAppearanceDiagnosticControllerRef.current = undefined;
|
|
372
|
+
diagnosticController.dispose();
|
|
373
|
+
controller.dispose();
|
|
319
374
|
};
|
|
320
|
-
}, [
|
|
375
|
+
}, []);
|
|
376
|
+
|
|
377
|
+
useEffect(() => {
|
|
378
|
+
documentAppearanceControllerRef.current?.update(appearancePresentation.legacyTokenOverrides);
|
|
379
|
+
documentAppearanceDiagnosticControllerRef.current?.update({
|
|
380
|
+
unresolvedTheme: appearancePresentation.unresolvedTheme,
|
|
381
|
+
unresolvedThemePreset: appearancePresentation.unresolvedThemePreset,
|
|
382
|
+
});
|
|
383
|
+
}, [
|
|
384
|
+
appearancePresentation.legacyTokenOverrides,
|
|
385
|
+
appearancePresentation.unresolvedTheme,
|
|
386
|
+
appearancePresentation.unresolvedThemePreset,
|
|
387
|
+
]);
|
|
321
388
|
|
|
322
389
|
useEffect(() => {
|
|
323
390
|
if (visibleActivityItems.length === 0) {
|
|
@@ -374,7 +441,7 @@ export function WorkbenchShell({
|
|
|
374
441
|
...managementCategories,
|
|
375
442
|
...(additionalSettingsCategories ?? []),
|
|
376
443
|
...createSettingsCategories(
|
|
377
|
-
{ configurations, extensionCatalog, localizations
|
|
444
|
+
{ appearanceCatalog, configurations, extensionCatalog, localizations },
|
|
378
445
|
{
|
|
379
446
|
activeScope: settingsScopeId,
|
|
380
447
|
darkPreset,
|
|
@@ -388,13 +455,14 @@ export function WorkbenchShell({
|
|
|
388
455
|
preferenceService,
|
|
389
456
|
shellPreset,
|
|
390
457
|
theme,
|
|
391
|
-
themeOptions,
|
|
458
|
+
themeOptions: appearanceThemeOptions,
|
|
392
459
|
},
|
|
393
460
|
),
|
|
394
461
|
];
|
|
395
462
|
}, [
|
|
396
463
|
accountManagement,
|
|
397
464
|
additionalSettingsCategories,
|
|
465
|
+
appearanceCatalog,
|
|
398
466
|
commandHost,
|
|
399
467
|
darkPreset,
|
|
400
468
|
configurations,
|
|
@@ -414,7 +482,7 @@ export function WorkbenchShell({
|
|
|
414
482
|
theme,
|
|
415
483
|
themeRevision,
|
|
416
484
|
themes,
|
|
417
|
-
|
|
485
|
+
appearanceThemeOptions,
|
|
418
486
|
]);
|
|
419
487
|
const defaultSettingsCategoryId =
|
|
420
488
|
settingsCategories.find((category) => category.id === SETTINGS_EXTENSION_ID)?.id ??
|
|
@@ -699,11 +767,13 @@ export function WorkbenchShell({
|
|
|
699
767
|
sizePercent: layout.panel.sizePercent,
|
|
700
768
|
}}
|
|
701
769
|
rootClassName={rootClassName}
|
|
770
|
+
rootStyle={rootAppearanceStyle}
|
|
702
771
|
secondaryArea={resolvedEditorArea}
|
|
703
772
|
statusSections={resolvedStatusSections}
|
|
704
773
|
titleBar={resolvedTitleBar}
|
|
705
|
-
theme={
|
|
706
|
-
|
|
774
|
+
theme={appearancePresentation.theme}
|
|
775
|
+
themePreference={appearancePresentation.themePreference}
|
|
776
|
+
themePreset={appearancePresentation.themePreset}
|
|
707
777
|
shellPreset={shellPreset}
|
|
708
778
|
overlays={
|
|
709
779
|
<>
|
|
@@ -721,7 +791,7 @@ export function WorkbenchShell({
|
|
|
721
791
|
categories={settingsCategories}
|
|
722
792
|
defaultActiveCategoryId={defaultSettingsCategoryId}
|
|
723
793
|
defaultActiveScopeId="workspace"
|
|
724
|
-
footer={<Button onClick={
|
|
794
|
+
footer={<Button onClick={closeSettingsModal}>Close</Button>}
|
|
725
795
|
scopes={[...WORKBENCH_PREFERENCE_SCOPES]}
|
|
726
796
|
searchValue={settingsSearchValue}
|
|
727
797
|
title={chromeLabels.settingsLabel}
|
|
@@ -733,7 +803,7 @@ export function WorkbenchShell({
|
|
|
733
803
|
</Badge>
|
|
734
804
|
}
|
|
735
805
|
onActiveCategoryIdChange={setSettingsCategoryId}
|
|
736
|
-
onClose={
|
|
806
|
+
onClose={closeSettingsModal}
|
|
737
807
|
onScopeChange={(scopeId) => {
|
|
738
808
|
if (isPreferenceScope(scopeId)) {
|
|
739
809
|
setSettingsScopeId(scopeId);
|
|
@@ -88,8 +88,8 @@ function normalizeWorkbenchAppearance(value: unknown): WorkbenchAppearanceSettin
|
|
|
88
88
|
const record = value as Record<string, unknown>;
|
|
89
89
|
const themePreference = normalizeThemePreference(record.themePreference);
|
|
90
90
|
// Preset ids may belong to a contributed theme, which isn't known until extensions
|
|
91
|
-
// register, so we can only validate shape here
|
|
92
|
-
//
|
|
91
|
+
// register, so we can only validate shape here. The appearance UI keeps an unresolved
|
|
92
|
+
// string visible until the user explicitly chooses a current option.
|
|
93
93
|
const lightPreset = normalizePresetId(
|
|
94
94
|
record.lightPreset,
|
|
95
95
|
DEFAULT_WORKBENCH_APPEARANCE.lightPreset,
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import {
|
|
2
|
+
WorkbenchCommandPalette,
|
|
3
|
+
WorkbenchQuickOpen,
|
|
4
|
+
WorkbenchShortcutCommandBridge,
|
|
5
|
+
matchesWorkbenchCommandPaletteShortcut,
|
|
6
|
+
matchesWorkbenchQuickAccessShortcut,
|
|
7
|
+
resolveQuickOpenItemPath,
|
|
8
|
+
type QuickOpenItem,
|
|
9
|
+
type QuickOpenProvider,
|
|
10
|
+
type QuickOpenSelectContext,
|
|
11
|
+
type WorkbenchCommandDescriptor,
|
|
12
|
+
type WorkbenchCommandRunContext,
|
|
13
|
+
type WorkbenchShortcutCommandBridgeProps,
|
|
14
|
+
} from '@workbench-kit/react/workbench/command-ui';
|
|
15
|
+
import { useCallback, useEffect, useState, type JSX } from 'react';
|
|
16
|
+
|
|
17
|
+
const WORKSPACE_OPEN_COMMAND_ID = 'workspace.open' as const;
|
|
18
|
+
const EMPTY_QUICK_OPEN_PROVIDERS: readonly QuickOpenProvider[] = Object.freeze([]);
|
|
19
|
+
|
|
20
|
+
export type WorkbenchCommandHostExecutor = (
|
|
21
|
+
commandId: string,
|
|
22
|
+
...args: unknown[]
|
|
23
|
+
) => unknown | Promise<unknown>;
|
|
24
|
+
|
|
25
|
+
export interface WorkbenchCommandHostControllerProps<TContext = unknown> {
|
|
26
|
+
commands: readonly WorkbenchCommandDescriptor[];
|
|
27
|
+
executeCommand: WorkbenchCommandHostExecutor;
|
|
28
|
+
|
|
29
|
+
commandPaletteCloseLabel?: string;
|
|
30
|
+
commandPaletteEmptyLabel?: string;
|
|
31
|
+
commandPalettePlaceholder?: string;
|
|
32
|
+
commandPaletteTitle?: string;
|
|
33
|
+
enableCommandPalette?: boolean;
|
|
34
|
+
enableQuickOpen?: boolean;
|
|
35
|
+
quickOpenCloseLabel?: string;
|
|
36
|
+
quickOpenEmptyLabel?: string;
|
|
37
|
+
quickOpenPlaceholder?: string;
|
|
38
|
+
quickOpenProviders?: readonly QuickOpenProvider[];
|
|
39
|
+
quickOpenTitle?: string;
|
|
40
|
+
|
|
41
|
+
onOpenQuickOpenItem?: (item: QuickOpenItem, context: QuickOpenSelectContext) => boolean | void;
|
|
42
|
+
onRunCommand?: (
|
|
43
|
+
command: WorkbenchCommandDescriptor,
|
|
44
|
+
context: WorkbenchCommandRunContext,
|
|
45
|
+
) => boolean | void;
|
|
46
|
+
|
|
47
|
+
shortcutBridge?: false | WorkbenchShortcutCommandBridgeProps<TContext>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function WorkbenchCommandHostController<TContext = unknown>({
|
|
51
|
+
commands,
|
|
52
|
+
executeCommand,
|
|
53
|
+
commandPaletteCloseLabel = 'Close command palette',
|
|
54
|
+
commandPaletteEmptyLabel = 'No commands match your search',
|
|
55
|
+
commandPalettePlaceholder = 'Search commands',
|
|
56
|
+
commandPaletteTitle = 'Command Palette',
|
|
57
|
+
enableCommandPalette = true,
|
|
58
|
+
enableQuickOpen = true,
|
|
59
|
+
quickOpenCloseLabel = 'Close Quick Open',
|
|
60
|
+
quickOpenEmptyLabel = 'No matching files',
|
|
61
|
+
quickOpenPlaceholder = 'Search files by name',
|
|
62
|
+
quickOpenProviders = EMPTY_QUICK_OPEN_PROVIDERS,
|
|
63
|
+
quickOpenTitle = 'Quick Open',
|
|
64
|
+
onOpenQuickOpenItem,
|
|
65
|
+
onRunCommand,
|
|
66
|
+
shortcutBridge,
|
|
67
|
+
}: WorkbenchCommandHostControllerProps<TContext>): JSX.Element {
|
|
68
|
+
const [paletteOpen, setPaletteOpen] = useState(false);
|
|
69
|
+
const [paletteQuery, setPaletteQuery] = useState('');
|
|
70
|
+
const [quickOpenOpen, setQuickOpenOpen] = useState(false);
|
|
71
|
+
const [quickOpenQuery, setQuickOpenQuery] = useState('');
|
|
72
|
+
|
|
73
|
+
const closePalette = useCallback(() => {
|
|
74
|
+
setPaletteOpen(false);
|
|
75
|
+
}, []);
|
|
76
|
+
|
|
77
|
+
const openPalette = useCallback((query = '') => {
|
|
78
|
+
setQuickOpenOpen(false);
|
|
79
|
+
setPaletteQuery(query);
|
|
80
|
+
setPaletteOpen(true);
|
|
81
|
+
}, []);
|
|
82
|
+
|
|
83
|
+
const closeQuickOpen = useCallback(() => {
|
|
84
|
+
setQuickOpenOpen(false);
|
|
85
|
+
}, []);
|
|
86
|
+
|
|
87
|
+
const openQuickOpen = useCallback((query = '') => {
|
|
88
|
+
setPaletteOpen(false);
|
|
89
|
+
setQuickOpenQuery(query);
|
|
90
|
+
setQuickOpenOpen(true);
|
|
91
|
+
}, []);
|
|
92
|
+
|
|
93
|
+
const runPaletteCommand = useCallback(
|
|
94
|
+
(command: WorkbenchCommandDescriptor, context: WorkbenchCommandRunContext) => {
|
|
95
|
+
if (onRunCommand?.(command, context)) {
|
|
96
|
+
closePalette();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
runCommandHostExecution(() => executeCommand(command.id), closePalette);
|
|
101
|
+
},
|
|
102
|
+
[closePalette, executeCommand, onRunCommand],
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const runQuickOpenItem = useCallback(
|
|
106
|
+
(item: QuickOpenItem, context: QuickOpenSelectContext) => {
|
|
107
|
+
if (onOpenQuickOpenItem?.(item, context)) {
|
|
108
|
+
closeQuickOpen();
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const path = resolveQuickOpenItemPath(item);
|
|
113
|
+
if (!path) {
|
|
114
|
+
closeQuickOpen();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
runCommandHostExecution(
|
|
119
|
+
() => executeCommand(WORKSPACE_OPEN_COMMAND_ID, { path }),
|
|
120
|
+
closeQuickOpen,
|
|
121
|
+
);
|
|
122
|
+
},
|
|
123
|
+
[closeQuickOpen, executeCommand, onOpenQuickOpenItem],
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
if (!enableCommandPalette && !enableQuickOpen) {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const onKeyDown = (event: KeyboardEvent) => {
|
|
132
|
+
if (enableCommandPalette && matchesWorkbenchCommandPaletteShortcut(event)) {
|
|
133
|
+
event.preventDefault();
|
|
134
|
+
openPalette('>');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (matchesWorkbenchQuickAccessShortcut(event)) {
|
|
139
|
+
event.preventDefault();
|
|
140
|
+
if (enableQuickOpen) {
|
|
141
|
+
openQuickOpen();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (enableCommandPalette) {
|
|
146
|
+
openPalette();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
window.addEventListener('keydown', onKeyDown);
|
|
152
|
+
return () => {
|
|
153
|
+
window.removeEventListener('keydown', onKeyDown);
|
|
154
|
+
};
|
|
155
|
+
}, [enableCommandPalette, enableQuickOpen, openPalette, openQuickOpen]);
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<>
|
|
159
|
+
{shortcutBridge ? <WorkbenchShortcutCommandBridge {...shortcutBridge} /> : null}
|
|
160
|
+
{enableCommandPalette ? (
|
|
161
|
+
<WorkbenchCommandPalette
|
|
162
|
+
closeLabel={commandPaletteCloseLabel}
|
|
163
|
+
commands={commands}
|
|
164
|
+
emptyLabel={commandPaletteEmptyLabel}
|
|
165
|
+
open={paletteOpen}
|
|
166
|
+
placeholder={commandPalettePlaceholder}
|
|
167
|
+
query={paletteQuery}
|
|
168
|
+
title={commandPaletteTitle}
|
|
169
|
+
onClose={closePalette}
|
|
170
|
+
onQueryChange={setPaletteQuery}
|
|
171
|
+
onRunCommand={runPaletteCommand}
|
|
172
|
+
/>
|
|
173
|
+
) : null}
|
|
174
|
+
{enableQuickOpen ? (
|
|
175
|
+
<WorkbenchQuickOpen
|
|
176
|
+
closeLabel={quickOpenCloseLabel}
|
|
177
|
+
emptyLabel={quickOpenEmptyLabel}
|
|
178
|
+
open={quickOpenOpen}
|
|
179
|
+
placeholder={quickOpenPlaceholder}
|
|
180
|
+
providers={quickOpenProviders}
|
|
181
|
+
query={quickOpenQuery}
|
|
182
|
+
title={quickOpenTitle}
|
|
183
|
+
onClose={closeQuickOpen}
|
|
184
|
+
onQueryChange={setQuickOpenQuery}
|
|
185
|
+
onSelectItem={runQuickOpenItem}
|
|
186
|
+
/>
|
|
187
|
+
) : null}
|
|
188
|
+
</>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function runCommandHostExecution(execute: () => unknown, close: () => void): void {
|
|
193
|
+
let result: unknown;
|
|
194
|
+
try {
|
|
195
|
+
result = execute();
|
|
196
|
+
} catch (error) {
|
|
197
|
+
close();
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
let pending: boolean;
|
|
202
|
+
try {
|
|
203
|
+
pending = isPromiseLike(result);
|
|
204
|
+
} catch (error) {
|
|
205
|
+
close();
|
|
206
|
+
throw error;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (!pending) {
|
|
210
|
+
close();
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
void Promise.resolve(result).finally(close);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function isPromiseLike(value: unknown): value is PromiseLike<unknown> {
|
|
218
|
+
return (
|
|
219
|
+
((typeof value === 'object' && value !== null) || typeof value === 'function') &&
|
|
220
|
+
'then' in value &&
|
|
221
|
+
typeof value.then === 'function'
|
|
222
|
+
);
|
|
223
|
+
}
|