@workbench-kit/react 0.0.2-prototype.0.2.2 → 0.0.2-prototype.0.2.20
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 +125 -0
- package/package.json +27 -20
- package/src/index.ts +60 -29
- package/src/jdw/JsonCodeEditorPane.tsx +7 -6
- package/src/jdw/builtins/renderBuiltinWidgetLeaf.tsx +1 -3
- package/src/jdw/createBuiltinJdwRegistry.ts +1 -4
- package/src/jdw/cssRenderBackend.tsx +1 -4
- package/src/json-config/JsonConfigWorkbench.tsx +1 -1
- package/src/layout/index.ts +11 -0
- package/src/layout/sidebar/SideBarTree.tsx +301 -0
- package/src/layout/sidebar/SidebarActionIconBar.tsx +3 -3
- package/src/layout/sidebar/WorkbenchSidebarActions.tsx +1 -1
- package/src/layout/sidebar/index.ts +13 -0
- package/src/modal/Modal.tsx +55 -25
- package/src/modal/ModalTitlebar.tsx +8 -8
- package/src/modal/modalPosition.ts +3 -6
- package/src/modal/useModalFocusTrap.ts +142 -0
- package/src/modal/useModalWindowFrame.ts +2 -2
- package/src/overlay/ContextMenu.tsx +112 -5
- package/src/overlay/context-menu.css +4 -2
- package/src/overlay/measureAnchoredOverlayPanel.ts +4 -6
- package/src/overlay/usePointerPassthroughRegion.ts +2 -0
- package/src/primitives/absolute-box/AbsoluteBox.tsx +4 -4
- package/src/primitives/button/Button.tsx +4 -4
- package/src/primitives/catalog-browse-card/CatalogBrowseCard.tsx +6 -6
- package/src/primitives/catalog-browse-pane/CatalogBrowsePane.tsx +15 -15
- package/src/primitives/catalog-filter-overlay/CatalogFilterOverlay.tsx +2 -2
- package/src/primitives/checkbox/Checkbox.tsx +1 -1
- package/src/primitives/chip/Chip.tsx +2 -2
- package/src/primitives/codicon/Codicon.tsx +1 -1
- package/src/primitives/file-icon/FileIcon.tsx +1 -1
- package/src/primitives/icon-button/IconButton.tsx +1 -1
- package/src/primitives/index.ts +5 -0
- package/src/primitives/library-detail-layout/LibraryDetailLayout.tsx +123 -9
- package/src/primitives/library-detail-layout/index.ts +5 -0
- package/src/primitives/library-detail-layout/library-detail-layout.css +57 -0
- package/src/primitives/library-detail-layout/resolve-hero-cover-media.ts +80 -0
- package/src/primitives/library-facet-filter-panel/LibraryFacetFilterPanel.tsx +12 -12
- package/src/primitives/library-facet-filter-strip/LibraryFacetFilterStrip.tsx +4 -4
- package/src/primitives/number-input/NumberInput.tsx +5 -5
- package/src/primitives/record-media-hero/RecordMediaHero.tsx +10 -6
- package/src/primitives/scroll-area/ScrollArea.tsx +5 -5
- package/src/primitives/scroll-area-infinite-load/useScrollAreaInfiniteLoad.ts +5 -5
- package/src/primitives/searchable-multi-select/SearchableMultiSelect.tsx +7 -7
- package/src/primitives/select/Select.tsx +1 -13
- package/src/primitives/text-area/TextArea.tsx +1 -1
- package/src/primitives/text-input/TextInput.tsx +1 -1
- package/src/primitives/workbench-media-slot/WorkbenchMediaPlaceholder.tsx +2 -2
- package/src/primitives/workbench-media-slot/WorkbenchMediaSlot.tsx +16 -10
- package/src/primitives/workbench-thumbnail/WorkbenchThumbnail.tsx +4 -4
- package/src/styles.css +1 -2
- package/src/test-utils/workbenchMonacoMock.tsx +20 -0
- package/src/utils/clamp.ts +4 -0
- package/src/utils/normalizeKeyToken.ts +13 -0
- package/src/utils/readNumber.ts +4 -0
- package/src/widget-tree/WidgetTreeCanvasPreview.tsx +1 -4
- package/src/widget-tree/WidgetTreeWorkspaceShell.tsx +2 -2
- package/src/workbench/chat/ChatCommandProposalCard.tsx +4 -4
- package/src/workbench/chat/ChatConversationBar.tsx +3 -3
- package/src/workbench/chat/ChatHistoryMenu.tsx +1 -1
- package/src/workbench/chat/ChatMessageCollapsible.tsx +4 -0
- package/src/workbench/chat/ChatMessageItem.tsx +68 -10
- package/src/workbench/chat/ChatMessageList.tsx +1 -1
- package/src/workbench/chat/ChatPanel.tsx +32 -23
- package/src/workbench/chat/ChatPhasedRunProgress.tsx +86 -13
- package/src/workbench/chat/ChatRenameDialog.tsx +1 -1
- package/src/workbench/chat/chat-conversation.css +2 -2
- package/src/workbench/chat/chat-ui.css +8 -0
- package/src/workbench/chat/chatConversation.ts +2 -2
- package/src/workbench/chat/chatMessageMeta.tsx +4 -4
- package/src/workbench/chat/index.ts +1 -0
- package/src/workbench/chat/types.ts +7 -7
- package/src/workbench/chat/useCancelRuntimeOnUnmount.ts +4 -4
- package/src/workbench/chat/useChatPrependPagination.ts +10 -10
- package/src/workbench/chat/useSlashCommandSuggest.ts +1 -1
- package/src/workbench/{WorkbenchModalPortal.tsx → chrome/WorkbenchModalPortal.tsx} +1 -1
- package/src/workbench/chrome/workbench-chrome.css +4 -0
- package/src/workbench/{CommandGroupShell.tsx → commands/CommandGroupShell.tsx} +2 -2
- package/src/workbench/{CommandList.tsx → commands/CommandList.tsx} +5 -5
- package/src/workbench/{CommandPalette.tsx → commands/CommandPalette.tsx} +16 -42
- package/src/workbench/{ConfirmationFlow.tsx → commands/ConfirmationFlow.tsx} +5 -5
- package/src/workbench/{ShortcutCommandBridge.tsx → commands/ShortcutCommandBridge.tsx} +1 -13
- package/src/workbench/commands/WorkbenchQuickOpen.tsx +462 -0
- package/src/workbench/{command-model.ts → commands/command-model.ts} +5 -1
- package/src/workbench/commands/command-ui.ts +3 -0
- package/src/workbench/{commands.ts → commands/commands.ts} +1 -1
- package/src/workbench/commands/createWorkspaceFilesQuickOpenProvider.ts +86 -0
- package/src/workbench/commands/quick-open-model.ts +66 -0
- package/src/workbench/{WorkbenchEditorTabs.tsx → editor/WorkbenchEditorTabs.tsx} +1 -1
- package/src/workbench/{editor-tabs-dnd.ts → editor/editor-tabs-dnd.ts} +1 -1
- package/src/workbench/{editorTabContextMenu.ts → editor/editorTabContextMenu.ts} +2 -2
- package/src/workbench/{useEditorTabsStripDnd.ts → editor/useEditorTabsStripDnd.ts} +1 -1
- package/src/workbench/{useWorkbenchEditorTabContextMenu.tsx → editor/useWorkbenchEditorTabContextMenu.tsx} +1 -1
- package/src/workbench/editor-tabs/index.ts +9 -9
- package/src/workbench/index.ts +110 -74
- package/src/workbench/management/ExtensionManagementPanel.tsx +32 -36
- package/src/workbench/management/ExtensionManagementSidebar.tsx +19 -35
- package/src/workbench/management/IntegrationSettingsSurface.tsx +2 -5
- package/src/workbench/management/IntegrationsShell.tsx +1 -1
- package/src/workbench/management/KeybindingCaptureField.tsx +1 -9
- package/src/workbench/management/WorkbenchDialogFrame.tsx +2 -2
- package/src/workbench/management/WorkbenchNotice.tsx +2 -5
- package/src/workbench/management/createWorkbenchNotify.tsx +88 -0
- package/src/workbench/management/extension-install-approval.ts +72 -0
- package/src/workbench/management/extension-management-filters.ts +38 -0
- package/src/workbench/management/index.ts +14 -0
- package/src/workbench/management/management.css +28 -0
- package/src/workbench/management/types.ts +14 -1
- package/src/workbench/management/useWorkbenchNotify.ts +10 -0
- package/src/workbench/{MarkdownPreview.tsx → markdown/MarkdownPreview.tsx} +22 -7
- package/src/workbench/markdown/markdownRemarkPlugins.ts +12 -0
- package/src/workbench/markdown/sanitizeMarkdownHref.ts +29 -0
- package/src/workbench/settings/StructuredDataForm.tsx +1 -4
- package/src/workbench/settings/structuredDataFormModel.ts +2 -1
- package/src/workbench/{ActivityBar.tsx → shell/ActivityBar.tsx} +8 -8
- package/src/workbench/{ArtifactShell.tsx → shell/ArtifactShell.tsx} +25 -25
- package/src/workbench/{SplitView.tsx → shell/SplitView.tsx} +3 -3
- package/src/workbench/{StatusBar.tsx → shell/StatusBar.tsx} +8 -8
- package/src/workbench/{StructuredArtifactEditor.tsx → shell/StructuredArtifactEditor.tsx} +9 -9
- package/src/workbench/{Timeline.tsx → shell/Timeline.tsx} +77 -20
- package/src/workbench/{WorkbenchCanvasShell.defaults.ts → shell/WorkbenchCanvasShell.defaults.ts} +1 -1
- package/src/workbench/{WorkbenchCanvasShell.model.ts → shell/WorkbenchCanvasShell.model.ts} +5 -5
- package/src/workbench/{WorkbenchCanvasShell.tsx → shell/WorkbenchCanvasShell.tsx} +6 -6
- package/src/workbench/{WorkbenchDesktopTitleBar.tsx → shell/WorkbenchDesktopTitleBar.tsx} +15 -15
- package/src/workbench/{WorkbenchShell.tsx → shell/WorkbenchShell.tsx} +45 -6
- package/src/workbench/{WorkbenchShellTitleBarLayoutControls.tsx → shell/WorkbenchShellTitleBarLayoutControls.tsx} +16 -19
- package/src/workbench/{WorkbenchStandaloneShell.tsx → shell/WorkbenchStandaloneShell.tsx} +4 -4
- package/src/workbench/{WorkbenchViewEditor.tsx → shell/WorkbenchViewEditor.tsx} +7 -7
- package/src/workbench/{WorkbenchViewSidebar.tsx → shell/WorkbenchViewSidebar.tsx} +7 -7
- package/src/workbench/{WorkbenchWindowChromeControls.tsx → shell/WorkbenchWindowChromeControls.tsx} +18 -15
- package/src/workbench/shell/activity-bar.css +47 -0
- package/src/workbench/{shell.ts → shell/shell.ts} +18 -12
- package/src/workbench/{shellViewModel.ts → shell/shellViewModel.ts} +3 -3
- package/src/workbench/{standalone.ts → shell/standalone.ts} +14 -2
- package/src/workbench/{useDeferredWorkbenchMount.ts → shell/useDeferredWorkbenchMount.ts} +3 -3
- package/src/workbench/{useWorkbenchAppearanceDocumentSync.tsx → shell/useWorkbenchAppearanceDocumentSync.tsx} +1 -1
- package/src/workbench/{useWorkbenchSidebarActionBarDnd.ts → shell/useWorkbenchSidebarActionBarDnd.ts} +1 -1
- package/src/workbench/{useWorkbenchSidebarViewPlacementDropZone.ts → shell/useWorkbenchSidebarViewPlacementDropZone.ts} +2 -2
- package/src/workbench/{workbenchViewRouteState.ts → shell/workbenchViewRouteState.ts} +4 -4
- package/src/workbench/{WorkbenchThemeProvider.tsx → theme/WorkbenchThemeProvider.tsx} +4 -4
- package/src/workbench/{theme.ts → theme/theme.ts} +1 -1
- package/src/workbench/{themePresets.ts → theme/themePresets.ts} +3 -2
- package/src/workbench/views/view-hosts.css +3 -3
- package/src/workbench/workspace/WorkspaceEditorPanel.tsx +1 -1
- package/src/workbench/workspace/WorkspaceExplorer.tsx +104 -3
- package/src/workbench/workspace/workspaceExplorerKeyboard.ts +109 -0
- package/src/workbench/workspace/workspaceJsonDiagnostics.ts +6 -5
- package/src/workbench/jdw/jdw-editors.css +0 -4
- package/src/workbench/jdw/jdw.css +0 -2
- package/src/workbench/markdownRemarkPlugins.ts +0 -4
- package/src/workbench/workbench-chrome.css +0 -4
- /package/src/workbench/{WorkbenchPlatformContext.tsx → chrome/WorkbenchPlatformContext.tsx} +0 -0
- /package/src/workbench/{workbenchModalViewState.ts → chrome/workbenchModalViewState.ts} +0 -0
- /package/src/workbench/{workbenchOverlaysContext.tsx → chrome/workbenchOverlaysContext.tsx} +0 -0
- /package/src/workbench/{workbenchPlatformChrome.ts → chrome/workbenchPlatformChrome.ts} +0 -0
- /package/src/workbench/{command-execution-policy.ts → commands/command-execution-policy.ts} +0 -0
- /package/src/workbench/{keyboard.ts → commands/keyboard.ts} +0 -0
- /package/src/workbench/{workbenchContextMenu.ts → commands/workbenchContextMenu.ts} +0 -0
- /package/src/workbench/{activityBarOrder.ts → shell/activityBarOrder.ts} +0 -0
- /package/src/workbench/{appearanceLabels.ts → shell/appearanceLabels.ts} +0 -0
- /package/src/workbench/{hardReset.ts → shell/hardReset.ts} +0 -0
- /package/src/workbench/{shellPresets.ts → shell/shellPresets.ts} +0 -0
- /package/src/workbench/{shellState.ts → shell/shellState.ts} +0 -0
- /package/src/workbench/{sidebarViewPlacementDnd.ts → shell/sidebarViewPlacementDnd.ts} +0 -0
- /package/src/workbench/{status.ts → shell/status.ts} +0 -0
- /package/src/workbench/{useWorkbenchSidebarLayout.tsx → shell/useWorkbenchSidebarLayout.tsx} +0 -0
- /package/src/workbench/{useWorkbenchStandaloneShellStateSync.tsx → shell/useWorkbenchStandaloneShellStateSync.tsx} +0 -0
- /package/src/workbench/{workbenchSidebarLayoutContext.ts → shell/workbenchSidebarLayoutContext.ts} +0 -0
- /package/src/workbench/{workbenchStandaloneShellReactContext.tsx → shell/workbenchStandaloneShellReactContext.tsx} +0 -0
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useCallback,
|
|
3
|
+
useEffect,
|
|
4
|
+
useId,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
type ComponentPropsWithRef,
|
|
9
|
+
type KeyboardEvent,
|
|
10
|
+
type ReactNode,
|
|
11
|
+
} from 'react';
|
|
12
|
+
import { useModalFocusTrap } from '../../modal/useModalFocusTrap';
|
|
13
|
+
import { Button } from '../../primitives/button';
|
|
14
|
+
import { EmptyState } from '../../primitives/empty-state';
|
|
15
|
+
import { IconButton } from '../../primitives/icon-button';
|
|
16
|
+
import { TextInput } from '../../primitives/text-input';
|
|
17
|
+
import { cxCodicon } from '../../utils/codicon';
|
|
18
|
+
import { cx } from '../../utils/cx';
|
|
19
|
+
import {
|
|
20
|
+
DEFAULT_QUICK_OPEN_SEARCH_DEBOUNCE_MS,
|
|
21
|
+
getNextQuickOpenItemIndex,
|
|
22
|
+
isQuickOpenItemSelectable,
|
|
23
|
+
type QuickOpenItem,
|
|
24
|
+
type QuickOpenProvider,
|
|
25
|
+
type QuickOpenSelectContext,
|
|
26
|
+
} from './quick-open-model';
|
|
27
|
+
|
|
28
|
+
interface WorkbenchQuickOpenKeyEvent {
|
|
29
|
+
key: string;
|
|
30
|
+
preventDefault: () => void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface QuickOpenResult {
|
|
34
|
+
item: QuickOpenItem;
|
|
35
|
+
key: string;
|
|
36
|
+
provider: QuickOpenProvider;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function useControllableQuery({
|
|
40
|
+
defaultQuery = '',
|
|
41
|
+
query,
|
|
42
|
+
onQueryChange,
|
|
43
|
+
}: {
|
|
44
|
+
defaultQuery?: string | undefined;
|
|
45
|
+
query?: string | undefined;
|
|
46
|
+
onQueryChange?: ((query: string) => void) | undefined;
|
|
47
|
+
}) {
|
|
48
|
+
const [uncontrolledQuery, setUncontrolledQuery] = useState(defaultQuery);
|
|
49
|
+
const resolvedQuery = query ?? uncontrolledQuery;
|
|
50
|
+
|
|
51
|
+
const setQuery = (nextQuery: string) => {
|
|
52
|
+
if (query === undefined) {
|
|
53
|
+
setUncontrolledQuery(nextQuery);
|
|
54
|
+
}
|
|
55
|
+
onQueryChange?.(nextQuery);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
return [resolvedQuery, setQuery] as const;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface WorkbenchQuickOpenProps extends Omit<
|
|
62
|
+
ComponentPropsWithRef<'div'>,
|
|
63
|
+
'children' | 'onSelect' | 'title'
|
|
64
|
+
> {
|
|
65
|
+
activeItemId?: string | undefined;
|
|
66
|
+
closeLabel?: string | undefined;
|
|
67
|
+
debounceMs?: number | undefined;
|
|
68
|
+
defaultQuery?: string | undefined;
|
|
69
|
+
emptyLabel?: ReactNode | undefined;
|
|
70
|
+
onActiveItemChange?: ((itemId: string) => void) | undefined;
|
|
71
|
+
onClose: () => void;
|
|
72
|
+
onProviderError?: ((error: unknown, provider: QuickOpenProvider) => void) | undefined;
|
|
73
|
+
onQueryChange?: ((query: string) => void) | undefined;
|
|
74
|
+
onSelectItem?: ((item: QuickOpenItem, context: QuickOpenSelectContext) => void) | undefined;
|
|
75
|
+
open?: boolean | undefined;
|
|
76
|
+
placeholder?: string | undefined;
|
|
77
|
+
/** Restrict search to one provider. When omitted, all providers contribute. */
|
|
78
|
+
providerId?: string | undefined;
|
|
79
|
+
providers: readonly QuickOpenProvider[];
|
|
80
|
+
query?: string | undefined;
|
|
81
|
+
restoreFocusOnClose?: boolean | undefined;
|
|
82
|
+
title?: ReactNode | undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function WorkbenchQuickOpen({
|
|
86
|
+
activeItemId,
|
|
87
|
+
className,
|
|
88
|
+
closeLabel = 'Close Quick Open',
|
|
89
|
+
debounceMs = DEFAULT_QUICK_OPEN_SEARCH_DEBOUNCE_MS,
|
|
90
|
+
defaultQuery,
|
|
91
|
+
emptyLabel = 'No matching files',
|
|
92
|
+
onActiveItemChange,
|
|
93
|
+
onClose,
|
|
94
|
+
onProviderError,
|
|
95
|
+
onQueryChange,
|
|
96
|
+
onSelectItem,
|
|
97
|
+
open = true,
|
|
98
|
+
placeholder = 'Search files by name',
|
|
99
|
+
providerId,
|
|
100
|
+
providers,
|
|
101
|
+
query,
|
|
102
|
+
restoreFocusOnClose = true,
|
|
103
|
+
title = 'Quick Open',
|
|
104
|
+
...props
|
|
105
|
+
}: WorkbenchQuickOpenProps) {
|
|
106
|
+
const titleId = useId();
|
|
107
|
+
const listId = useId();
|
|
108
|
+
const dialogRef = useRef<HTMLDivElement>(null);
|
|
109
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
110
|
+
const [uncontrolledActiveResultKey, setUncontrolledActiveResultKey] = useState<string>();
|
|
111
|
+
const [results, setResults] = useState<QuickOpenResult[]>([]);
|
|
112
|
+
const [searching, setSearching] = useState(false);
|
|
113
|
+
const onProviderErrorRef = useRef(onProviderError);
|
|
114
|
+
const [resolvedQuery, setResolvedQuery] = useControllableQuery({
|
|
115
|
+
defaultQuery,
|
|
116
|
+
onQueryChange,
|
|
117
|
+
query,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
onProviderErrorRef.current = onProviderError;
|
|
122
|
+
}, [onProviderError]);
|
|
123
|
+
|
|
124
|
+
const activeProviders = useMemo(() => {
|
|
125
|
+
if (providerId) {
|
|
126
|
+
const provider = providers.find((candidate) => candidate.id === providerId);
|
|
127
|
+
return provider ? [provider] : [];
|
|
128
|
+
}
|
|
129
|
+
return providers;
|
|
130
|
+
}, [providerId, providers]);
|
|
131
|
+
|
|
132
|
+
const items = useMemo(() => results.map(({ item }) => item), [results]);
|
|
133
|
+
const controlledActiveResult = activeItemId
|
|
134
|
+
? results.find(({ item }) => item.id === activeItemId && isQuickOpenItemSelectable(item))
|
|
135
|
+
: undefined;
|
|
136
|
+
const uncontrolledActiveResult = results.find(
|
|
137
|
+
({ item, key }) => key === uncontrolledActiveResultKey && isQuickOpenItemSelectable(item),
|
|
138
|
+
);
|
|
139
|
+
const activeResult =
|
|
140
|
+
controlledActiveResult ??
|
|
141
|
+
uncontrolledActiveResult ??
|
|
142
|
+
results.find(({ item }) => isQuickOpenItemSelectable(item));
|
|
143
|
+
const resolvedActiveResultKey = activeResult?.key;
|
|
144
|
+
const activeIndex = activeResult ? results.indexOf(activeResult) : -1;
|
|
145
|
+
|
|
146
|
+
const updateActiveItem = useCallback(
|
|
147
|
+
(result: QuickOpenResult | undefined) => {
|
|
148
|
+
if (!result) return;
|
|
149
|
+
if (activeItemId === undefined) {
|
|
150
|
+
setUncontrolledActiveResultKey(result.key);
|
|
151
|
+
}
|
|
152
|
+
onActiveItemChange?.(result.item.id);
|
|
153
|
+
},
|
|
154
|
+
[activeItemId, onActiveItemChange],
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
useModalFocusTrap({
|
|
158
|
+
enabled: open,
|
|
159
|
+
containerRef: dialogRef,
|
|
160
|
+
initialFocusRef: inputRef,
|
|
161
|
+
onClose,
|
|
162
|
+
restoreFocusOnClose,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
useEffect(() => {
|
|
166
|
+
if (!open || activeProviders.length === 0) {
|
|
167
|
+
setResults([]);
|
|
168
|
+
setSearching(false);
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const controller = new AbortController();
|
|
173
|
+
let cancelled = false;
|
|
174
|
+
const runSearch = async () => {
|
|
175
|
+
setResults([]);
|
|
176
|
+
setSearching(true);
|
|
177
|
+
const providerResults = activeProviders.map<QuickOpenResult[] | undefined>(() => undefined);
|
|
178
|
+
const publishAvailableResults = () => {
|
|
179
|
+
setResults(providerResults.flatMap((providerItems) => providerItems ?? []));
|
|
180
|
+
};
|
|
181
|
+
const searches = activeProviders.map(async (provider, providerIndex) => {
|
|
182
|
+
try {
|
|
183
|
+
const providerItems = await Promise.resolve(
|
|
184
|
+
provider.search(resolvedQuery, { signal: controller.signal }),
|
|
185
|
+
);
|
|
186
|
+
if (cancelled) return;
|
|
187
|
+
|
|
188
|
+
providerResults[providerIndex] = providerItems.map((item, itemIndex) => ({
|
|
189
|
+
item,
|
|
190
|
+
key: `${providerIndex}:${itemIndex}:${provider.id}:${item.id}`,
|
|
191
|
+
provider,
|
|
192
|
+
}));
|
|
193
|
+
publishAvailableResults();
|
|
194
|
+
} catch (error) {
|
|
195
|
+
if (cancelled) return;
|
|
196
|
+
providerResults[providerIndex] = [];
|
|
197
|
+
publishAvailableResults();
|
|
198
|
+
onProviderErrorRef.current?.(error, provider);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
await Promise.allSettled(searches);
|
|
203
|
+
if (!cancelled) setSearching(false);
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// Empty query (recent / top-level) should paint immediately; debounce typed queries.
|
|
207
|
+
const delay = resolvedQuery.trim() ? Math.max(0, debounceMs) : 0;
|
|
208
|
+
if (delay === 0) {
|
|
209
|
+
void runSearch();
|
|
210
|
+
return () => {
|
|
211
|
+
cancelled = true;
|
|
212
|
+
controller.abort();
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const timer = window.setTimeout(() => {
|
|
217
|
+
void runSearch();
|
|
218
|
+
}, delay);
|
|
219
|
+
|
|
220
|
+
return () => {
|
|
221
|
+
cancelled = true;
|
|
222
|
+
controller.abort();
|
|
223
|
+
window.clearTimeout(timer);
|
|
224
|
+
};
|
|
225
|
+
}, [activeProviders, debounceMs, open, resolvedQuery]);
|
|
226
|
+
|
|
227
|
+
useEffect(() => {
|
|
228
|
+
if (!open) return;
|
|
229
|
+
if (activeItemId !== undefined) return;
|
|
230
|
+
|
|
231
|
+
setUncontrolledActiveResultKey((currentResultKey) => {
|
|
232
|
+
const currentResult = results.find(({ key }) => key === currentResultKey);
|
|
233
|
+
if (currentResult && isQuickOpenItemSelectable(currentResult.item)) {
|
|
234
|
+
return currentResultKey;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return results.find(({ item }) => isQuickOpenItemSelectable(item))?.key;
|
|
238
|
+
});
|
|
239
|
+
}, [activeItemId, open, results]);
|
|
240
|
+
|
|
241
|
+
const selectItem = useCallback(
|
|
242
|
+
(result: QuickOpenResult, index: number) => {
|
|
243
|
+
if (!isQuickOpenItemSelectable(result.item)) return;
|
|
244
|
+
onSelectItem?.(result.item, {
|
|
245
|
+
index,
|
|
246
|
+
providerId: result.provider.id,
|
|
247
|
+
query: resolvedQuery,
|
|
248
|
+
});
|
|
249
|
+
},
|
|
250
|
+
[onSelectItem, resolvedQuery],
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
const handleQuickOpenKeyDown = useCallback(
|
|
254
|
+
(event: WorkbenchQuickOpenKeyEvent) => {
|
|
255
|
+
if (
|
|
256
|
+
event.key !== 'ArrowDown' &&
|
|
257
|
+
event.key !== 'ArrowUp' &&
|
|
258
|
+
event.key !== 'Home' &&
|
|
259
|
+
event.key !== 'End' &&
|
|
260
|
+
event.key !== 'PageDown' &&
|
|
261
|
+
event.key !== 'PageUp' &&
|
|
262
|
+
event.key !== 'Enter'
|
|
263
|
+
) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (event.key === 'Enter') {
|
|
268
|
+
if (!activeResult) return;
|
|
269
|
+
event.preventDefault();
|
|
270
|
+
selectItem(activeResult, Math.max(activeIndex, 0));
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
event.preventDefault();
|
|
275
|
+
|
|
276
|
+
const direction =
|
|
277
|
+
event.key === 'ArrowUp' || event.key === 'End' || event.key === 'PageUp'
|
|
278
|
+
? 'previous'
|
|
279
|
+
: 'next';
|
|
280
|
+
const stepCount = event.key === 'PageDown' || event.key === 'PageUp' ? 5 : 1;
|
|
281
|
+
let nextIndex =
|
|
282
|
+
event.key === 'Home'
|
|
283
|
+
? getNextQuickOpenItemIndex({
|
|
284
|
+
currentIndex: -1,
|
|
285
|
+
direction: 'next',
|
|
286
|
+
items,
|
|
287
|
+
})
|
|
288
|
+
: event.key === 'End'
|
|
289
|
+
? getNextQuickOpenItemIndex({
|
|
290
|
+
currentIndex: 0,
|
|
291
|
+
direction: 'previous',
|
|
292
|
+
items,
|
|
293
|
+
})
|
|
294
|
+
: activeIndex;
|
|
295
|
+
|
|
296
|
+
if (event.key !== 'Home' && event.key !== 'End') {
|
|
297
|
+
for (let step = 0; step < stepCount; step += 1) {
|
|
298
|
+
const steppedIndex = getNextQuickOpenItemIndex({
|
|
299
|
+
currentIndex: nextIndex,
|
|
300
|
+
direction,
|
|
301
|
+
items,
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
if (steppedIndex < 0 || steppedIndex === nextIndex) break;
|
|
305
|
+
nextIndex = steppedIndex;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (nextIndex >= 0) {
|
|
310
|
+
updateActiveItem(results[nextIndex]);
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
[activeIndex, activeResult, items, results, selectItem, updateActiveItem],
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
useEffect(() => {
|
|
317
|
+
if (!open) return undefined;
|
|
318
|
+
|
|
319
|
+
const onKeyDown = (event: globalThis.KeyboardEvent) => {
|
|
320
|
+
if (event.defaultPrevented) return;
|
|
321
|
+
handleQuickOpenKeyDown(event);
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
window.addEventListener('keydown', onKeyDown);
|
|
325
|
+
return () => {
|
|
326
|
+
window.removeEventListener('keydown', onKeyDown);
|
|
327
|
+
};
|
|
328
|
+
}, [handleQuickOpenKeyDown, open]);
|
|
329
|
+
|
|
330
|
+
const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
|
|
331
|
+
handleQuickOpenKeyDown(event);
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
useEffect(() => {
|
|
335
|
+
if (!resolvedActiveResultKey) return;
|
|
336
|
+
|
|
337
|
+
const activeElement = Array.from(
|
|
338
|
+
dialogRef.current?.querySelectorAll<HTMLElement>('[data-quick-open-id]') ?? [],
|
|
339
|
+
).find((element) => element.dataset.quickOpenId === resolvedActiveResultKey);
|
|
340
|
+
|
|
341
|
+
activeElement?.scrollIntoView?.({ block: 'nearest' });
|
|
342
|
+
}, [resolvedActiveResultKey, results]);
|
|
343
|
+
|
|
344
|
+
if (!open) return null;
|
|
345
|
+
|
|
346
|
+
return (
|
|
347
|
+
<div className="ui-workbench-command-palette-overlay" onClick={onClose}>
|
|
348
|
+
<div
|
|
349
|
+
aria-labelledby={titleId}
|
|
350
|
+
aria-modal="true"
|
|
351
|
+
className={cx('ui-workbench-command-palette', className)}
|
|
352
|
+
data-testid="workbench-quick-open"
|
|
353
|
+
role="dialog"
|
|
354
|
+
{...props}
|
|
355
|
+
ref={dialogRef}
|
|
356
|
+
onClick={(event) => event.stopPropagation()}
|
|
357
|
+
>
|
|
358
|
+
<div className="ui-workbench-command-palette__header">
|
|
359
|
+
<span id={titleId} className="ui-workbench-command-palette__title">
|
|
360
|
+
{title}
|
|
361
|
+
</span>
|
|
362
|
+
<IconButton
|
|
363
|
+
className="ui-workbench-command-palette__close"
|
|
364
|
+
icon="codicon-close"
|
|
365
|
+
label={closeLabel}
|
|
366
|
+
onClick={onClose}
|
|
367
|
+
/>
|
|
368
|
+
</div>
|
|
369
|
+
<div className="ui-workbench-command-palette__search">
|
|
370
|
+
<i aria-hidden="true" className="codicon codicon-search" />
|
|
371
|
+
<TextInput
|
|
372
|
+
ref={inputRef}
|
|
373
|
+
aria-activedescendant={
|
|
374
|
+
activeResult ? `${listId}-${activeResult.key.replace(/[^\w-]/g, '_')}` : undefined
|
|
375
|
+
}
|
|
376
|
+
aria-controls={listId}
|
|
377
|
+
aria-label={placeholder}
|
|
378
|
+
className="ui-workbench-command-palette__input"
|
|
379
|
+
controlWidth="full"
|
|
380
|
+
placeholder={placeholder}
|
|
381
|
+
type="search"
|
|
382
|
+
value={resolvedQuery}
|
|
383
|
+
onValueChange={setResolvedQuery}
|
|
384
|
+
onKeyDown={handleKeyDown}
|
|
385
|
+
/>
|
|
386
|
+
</div>
|
|
387
|
+
<div
|
|
388
|
+
id={listId}
|
|
389
|
+
aria-busy={searching || undefined}
|
|
390
|
+
aria-label="Quick Open results"
|
|
391
|
+
className={cx('ui-workbench-command-list', 'ui-workbench-scrollbar')}
|
|
392
|
+
role="listbox"
|
|
393
|
+
>
|
|
394
|
+
{results.length === 0 ? (
|
|
395
|
+
<EmptyState compact icon="codicon-search">
|
|
396
|
+
{emptyLabel}
|
|
397
|
+
</EmptyState>
|
|
398
|
+
) : (
|
|
399
|
+
results.map((result, index) => {
|
|
400
|
+
const { item, key, provider } = result;
|
|
401
|
+
const active = key === resolvedActiveResultKey;
|
|
402
|
+
const itemDomId = `${listId}-${key.replace(/[^\w-]/g, '_')}`;
|
|
403
|
+
const descriptionId = item.description ? `${itemDomId}-description` : undefined;
|
|
404
|
+
|
|
405
|
+
return (
|
|
406
|
+
<Button
|
|
407
|
+
key={key}
|
|
408
|
+
id={itemDomId}
|
|
409
|
+
aria-describedby={descriptionId}
|
|
410
|
+
aria-selected={active}
|
|
411
|
+
className="ui-workbench-command-item"
|
|
412
|
+
data-active={active ? 'true' : undefined}
|
|
413
|
+
data-quick-open-id={key}
|
|
414
|
+
disabled={item.disabled}
|
|
415
|
+
role="option"
|
|
416
|
+
onClick={() => selectItem(result, index)}
|
|
417
|
+
onMouseEnter={() => updateActiveItem(result)}
|
|
418
|
+
>
|
|
419
|
+
<span className="ui-workbench-command-item__icon">
|
|
420
|
+
{item.icon ? <i aria-hidden="true" className={cxCodicon(item.icon)} /> : null}
|
|
421
|
+
</span>
|
|
422
|
+
<span className="ui-workbench-command-item__content">
|
|
423
|
+
<span className="ui-workbench-command-item__label">{item.label}</span>
|
|
424
|
+
{item.description ? (
|
|
425
|
+
<span id={descriptionId} className="ui-workbench-command-item__description">
|
|
426
|
+
{item.description}
|
|
427
|
+
</span>
|
|
428
|
+
) : null}
|
|
429
|
+
</span>
|
|
430
|
+
<span className="ui-workbench-command-item__meta">
|
|
431
|
+
{item.detail ? (
|
|
432
|
+
<span className="ui-workbench-command-item__category">{item.detail}</span>
|
|
433
|
+
) : null}
|
|
434
|
+
<span className="ui-workbench-command-item__category">{provider.label}</span>
|
|
435
|
+
</span>
|
|
436
|
+
</Button>
|
|
437
|
+
);
|
|
438
|
+
})
|
|
439
|
+
)}
|
|
440
|
+
</div>
|
|
441
|
+
</div>
|
|
442
|
+
</div>
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
export type {
|
|
447
|
+
QuickOpenItem,
|
|
448
|
+
QuickOpenProvider,
|
|
449
|
+
QuickOpenSearchContext,
|
|
450
|
+
QuickOpenSelectContext,
|
|
451
|
+
} from './quick-open-model';
|
|
452
|
+
export {
|
|
453
|
+
DEFAULT_QUICK_OPEN_SEARCH_DEBOUNCE_MS,
|
|
454
|
+
getNextQuickOpenItemIndex,
|
|
455
|
+
isQuickOpenItemSelectable,
|
|
456
|
+
} from './quick-open-model';
|
|
457
|
+
export {
|
|
458
|
+
WORKSPACE_FILES_QUICK_OPEN_PROVIDER_ID,
|
|
459
|
+
createWorkspaceFilesQuickOpenProvider,
|
|
460
|
+
resolveQuickOpenItemPath,
|
|
461
|
+
} from './createWorkspaceFilesQuickOpenProvider';
|
|
462
|
+
export type { CreateWorkspaceFilesQuickOpenProviderOptions } from './createWorkspaceFilesQuickOpenProvider';
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { CommandMenuItem, ResolvedCommandMenuCommandItem } from '@workbench-kit/platform';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
getWorkbenchStatusLabel,
|
|
5
|
+
isWorkbenchStatusDisabled,
|
|
6
|
+
type WorkbenchStatus,
|
|
7
|
+
} from '../shell/status';
|
|
4
8
|
|
|
5
9
|
export type WorkbenchCommandStatus = WorkbenchStatus;
|
|
6
10
|
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
type CommandValue,
|
|
11
11
|
} from '@workbench-kit/platform';
|
|
12
12
|
|
|
13
|
-
import type { ContextMenuItem } from '
|
|
13
|
+
import type { ContextMenuItem } from '../../overlay/ContextMenu';
|
|
14
14
|
|
|
15
15
|
export const WORKBENCH_OPEN_SETTINGS_COMMAND_ID = 'workbench.openSettings';
|
|
16
16
|
export const WORKBENCH_TOGGLE_PRIMARY_SIDEBAR_COMMAND_ID = 'workbench.togglePrimarySidebar';
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { searchWorkspaceFiles, type WorkspaceFile } from '@workbench-kit/workspace';
|
|
2
|
+
|
|
3
|
+
import type { QuickOpenItem, QuickOpenProvider } from './quick-open-model';
|
|
4
|
+
|
|
5
|
+
export const WORKSPACE_FILES_QUICK_OPEN_PROVIDER_ID = 'workspace.files' as const;
|
|
6
|
+
|
|
7
|
+
export interface CreateWorkspaceFilesQuickOpenProviderOptions {
|
|
8
|
+
/** Current workspace files, or a getter read on each search. */
|
|
9
|
+
files: readonly WorkspaceFile[] | (() => readonly WorkspaceFile[]);
|
|
10
|
+
id?: string | undefined;
|
|
11
|
+
label?: string | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* When the query is empty, these paths appear first (still present in `files`).
|
|
14
|
+
* Remaining files follow in `searchWorkspaceFiles` order.
|
|
15
|
+
*/
|
|
16
|
+
recentPaths?: readonly string[] | undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function resolveFiles(
|
|
20
|
+
files: CreateWorkspaceFilesQuickOpenProviderOptions['files'],
|
|
21
|
+
): readonly WorkspaceFile[] {
|
|
22
|
+
return typeof files === 'function' ? files() : files;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function toQuickOpenItem(path: string, matchedBy?: string, preview?: string): QuickOpenItem {
|
|
26
|
+
const segments = path.split('/');
|
|
27
|
+
const label = segments[segments.length - 1] || path;
|
|
28
|
+
const parent = segments.length > 1 ? segments.slice(0, -1).join('/') : undefined;
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
data: { path },
|
|
32
|
+
description: parent,
|
|
33
|
+
detail: matchedBy ?? preview,
|
|
34
|
+
icon: 'codicon-file',
|
|
35
|
+
id: path,
|
|
36
|
+
label,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function createWorkspaceFilesQuickOpenProvider(
|
|
41
|
+
options: CreateWorkspaceFilesQuickOpenProviderOptions,
|
|
42
|
+
): QuickOpenProvider {
|
|
43
|
+
const providerId = options.id ?? WORKSPACE_FILES_QUICK_OPEN_PROVIDER_ID;
|
|
44
|
+
const providerLabel = options.label ?? 'Files';
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
id: providerId,
|
|
48
|
+
label: providerLabel,
|
|
49
|
+
search(query: string) {
|
|
50
|
+
const files = [...resolveFiles(options.files)];
|
|
51
|
+
const results = searchWorkspaceFiles(files, query);
|
|
52
|
+
const items = results.map((result) =>
|
|
53
|
+
toQuickOpenItem(result.path, result.matchedBy, result.preview),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
if (query.trim() || !options.recentPaths?.length) {
|
|
57
|
+
return items;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const recentSet = new Set(options.recentPaths);
|
|
61
|
+
const byPath = new Map(items.map((item) => [item.id, item]));
|
|
62
|
+
const recentItems: QuickOpenItem[] = [];
|
|
63
|
+
|
|
64
|
+
for (const path of options.recentPaths) {
|
|
65
|
+
const item = byPath.get(path);
|
|
66
|
+
if (item) {
|
|
67
|
+
recentItems.push({ ...item, detail: 'Recent' });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const rest = items.filter((item) => !recentSet.has(item.id));
|
|
72
|
+
return [...recentItems, ...rest];
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function resolveQuickOpenItemPath(item: QuickOpenItem): string | undefined {
|
|
78
|
+
if (typeof item.data === 'object' && item.data !== null && 'path' in item.data) {
|
|
79
|
+
const path = (item.data as { path?: unknown }).path;
|
|
80
|
+
if (typeof path === 'string' && path.length > 0) {
|
|
81
|
+
return path;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return item.id || undefined;
|
|
86
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export interface QuickOpenItem {
|
|
2
|
+
/** Stable within its provider (often a workspace path). */
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
description?: string | undefined;
|
|
6
|
+
detail?: string | undefined;
|
|
7
|
+
icon?: string | undefined;
|
|
8
|
+
disabled?: boolean | undefined;
|
|
9
|
+
/** Provider-specific payload (e.g. `{ path }`). */
|
|
10
|
+
data?: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface QuickOpenSearchContext {
|
|
14
|
+
/** Aborted when the query, provider set, or open state changes. */
|
|
15
|
+
signal: AbortSignal;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface QuickOpenProvider {
|
|
19
|
+
/** Unique within the provider set passed to Quick Open. */
|
|
20
|
+
id: string;
|
|
21
|
+
label: string;
|
|
22
|
+
search: (
|
|
23
|
+
query: string,
|
|
24
|
+
context?: QuickOpenSearchContext,
|
|
25
|
+
) => Promise<QuickOpenItem[]> | QuickOpenItem[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface QuickOpenSelectContext {
|
|
29
|
+
index: number;
|
|
30
|
+
providerId: string;
|
|
31
|
+
query: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function isQuickOpenItemSelectable(item: QuickOpenItem) {
|
|
35
|
+
return !item.disabled;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function getNextQuickOpenItemIndex({
|
|
39
|
+
currentIndex,
|
|
40
|
+
direction,
|
|
41
|
+
items,
|
|
42
|
+
}: {
|
|
43
|
+
currentIndex: number;
|
|
44
|
+
direction: 'next' | 'previous';
|
|
45
|
+
items: readonly QuickOpenItem[];
|
|
46
|
+
}) {
|
|
47
|
+
if (items.length === 0) {
|
|
48
|
+
return -1;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const step = direction === 'next' ? 1 : -1;
|
|
52
|
+
let nextIndex = currentIndex;
|
|
53
|
+
|
|
54
|
+
for (let attempt = 0; attempt < items.length; attempt += 1) {
|
|
55
|
+
nextIndex = (nextIndex + step + items.length) % items.length;
|
|
56
|
+
const item = items[nextIndex];
|
|
57
|
+
if (item && isQuickOpenItemSelectable(item)) {
|
|
58
|
+
return nextIndex;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return -1;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Default debounce for provider search while typing. */
|
|
66
|
+
export const DEFAULT_QUICK_OPEN_SEARCH_DEBOUNCE_MS = 200;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EditorTabs, type EditorTabsProps } from '
|
|
1
|
+
import { EditorTabs, type EditorTabsProps } from '../../primitives/workbench-editor';
|
|
2
2
|
import { useWorkbenchEditorTabContextMenu } from './useWorkbenchEditorTabContextMenu';
|
|
3
3
|
|
|
4
4
|
export interface WorkbenchEditorTabsProps extends EditorTabsProps {
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
resolveCommandMenuItems,
|
|
5
5
|
} from '@workbench-kit/platform';
|
|
6
6
|
|
|
7
|
-
import type { ContextMenuItem } from '
|
|
7
|
+
import type { ContextMenuItem } from '../../overlay/ContextMenu';
|
|
8
8
|
import {
|
|
9
9
|
WORKBENCH_COMMAND_SURFACE_EDITOR,
|
|
10
10
|
commandMenuItemsToContextMenuItems,
|
|
11
11
|
createWorkbenchEditorCommands,
|
|
12
12
|
createWorkbenchStandaloneEditorTabMenuEntries,
|
|
13
13
|
type WorkbenchEditorCommandContext,
|
|
14
|
-
} from '
|
|
14
|
+
} from '../commands/commands';
|
|
15
15
|
|
|
16
16
|
const editorCommandRegistry = createCommandRegistry(createWorkbenchEditorCommands());
|
|
17
17
|
const standaloneEditorTabMenuEntries = createWorkbenchStandaloneEditorTabMenuEntries();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import type { DragEvent as ReactDragEvent } from 'react';
|
|
3
3
|
|
|
4
|
-
import type { EditorTabDropPosition, EditorTabsProps } from '
|
|
4
|
+
import type { EditorTabDropPosition, EditorTabsProps } from '../../primitives/workbench-editor';
|
|
5
5
|
import {
|
|
6
6
|
EDITOR_TAB_DRAG_DATA_TYPE,
|
|
7
7
|
isEditorTabsScrollerEventTarget,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useCallback, useState, type MouseEvent as ReactMouseEvent, type ReactNode } from 'react';
|
|
2
2
|
|
|
3
|
-
import { ContextMenu } from '
|
|
3
|
+
import { ContextMenu } from '../../overlay/ContextMenu';
|
|
4
4
|
import {
|
|
5
5
|
createWorkbenchStandaloneEditorTabContextMenuItems,
|
|
6
6
|
type WorkbenchStandaloneEditorTabLike,
|