@workbench-kit/react 0.0.1-prototype.0 → 0.0.2-prototype.0.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.
Files changed (155) hide show
  1. package/package.json +33 -9
  2. package/src/index.ts +545 -43
  3. package/src/jdw/JdwPreview.tsx +38 -0
  4. package/src/jdw/JsonCodeEditorPane.tsx +274 -0
  5. package/src/jdw/builtins/renderBuiltinWidgetLeaf.tsx +29 -0
  6. package/src/jdw/builtins/renderBuiltinWidgetNode.tsx +126 -0
  7. package/src/jdw/createBuiltinJdwRegistry.ts +111 -0
  8. package/src/jdw/cssRenderBackend.tsx +134 -0
  9. package/src/jdw/document.ts +38 -0
  10. package/src/jdw/fixtures/jdw-fixtures.ts +52 -0
  11. package/src/jdw/fixtures/jdw-sample-screens.ts +522 -0
  12. package/src/jdw/index.ts +45 -0
  13. package/src/jdw/parse.ts +1 -0
  14. package/src/jdw/renderJdw.tsx +32 -0
  15. package/src/json-config/JsonConfigWorkbench.tsx +316 -0
  16. package/src/json-config/index.ts +6 -0
  17. package/src/json-config/json-config-editor-state.ts +42 -0
  18. package/src/layout/Panel.tsx +146 -1
  19. package/src/layout/SideBarViewFrame.tsx +367 -328
  20. package/src/layout/WorkbenchCanvas.tsx +849 -0
  21. package/src/layout/WorkbenchFullscreen.tsx +368 -0
  22. package/src/layout/WorkbenchLayout.tsx +5 -0
  23. package/src/layout/WorkbenchLayoutBase.tsx +294 -0
  24. package/src/layout/WorkbenchPropertyPanel.tsx +497 -0
  25. package/src/layout/WorkbenchSidebarActions.tsx +274 -0
  26. package/src/layout/WorkbenchTree.tsx +351 -0
  27. package/src/layout/layoutHelpers.ts +25 -0
  28. package/src/modal/ConfirmDialog.tsx +61 -53
  29. package/src/modal/Modal.tsx +295 -35
  30. package/src/overlay/ContextMenu.tsx +146 -145
  31. package/src/primitives/AbsoluteBox.tsx +46 -0
  32. package/src/primitives/Badge.tsx +12 -12
  33. package/src/primitives/Button.tsx +44 -14
  34. package/src/primitives/Checkbox.tsx +11 -5
  35. package/src/primitives/EmptyState.tsx +27 -26
  36. package/src/primitives/Field.tsx +38 -38
  37. package/src/primitives/IconButton.tsx +5 -2
  38. package/src/primitives/List.tsx +111 -0
  39. package/src/primitives/NumberInput.tsx +38 -0
  40. package/src/primitives/ScrollArea.tsx +42 -0
  41. package/src/primitives/Select.tsx +1 -12
  42. package/src/primitives/StatusBar.tsx +46 -0
  43. package/src/primitives/TextArea.tsx +36 -0
  44. package/src/primitives/TextInput.tsx +11 -2
  45. package/src/primitives/WorkbenchChrome.tsx +424 -0
  46. package/src/primitives/WorkbenchEditor.tsx +394 -0
  47. package/src/primitives/index.ts +105 -0
  48. package/src/primitives/select/Select.tsx +266 -0
  49. package/src/primitives/select/index.ts +2 -0
  50. package/src/primitives/select/options.ts +38 -0
  51. package/src/primitives/select/overlay.ts +63 -0
  52. package/src/primitives/select/select.app.css +9 -0
  53. package/src/primitives/select/select.css +140 -0
  54. package/src/primitives/select/types.ts +18 -0
  55. package/src/primitives/styles.css +955 -0
  56. package/src/scrollbars.css +69 -0
  57. package/src/styles.css +7738 -1762
  58. package/src/utils/codicon.ts +17 -0
  59. package/src/widget-asset/WidgetAssetEditor.tsx +140 -0
  60. package/src/widget-asset/WidgetAssetMetadataForm.tsx +82 -0
  61. package/src/widget-asset/WidgetAssetModeControls.tsx +42 -0
  62. package/src/widget-asset/WidgetAssetSourceEditor.tsx +50 -0
  63. package/src/widget-asset/WidgetAssetWorkbench.tsx +112 -0
  64. package/src/widget-asset/index.ts +17 -0
  65. package/src/widget-asset/widget-asset-document.ts +37 -0
  66. package/src/widget-asset/widget-asset-mode.ts +3 -0
  67. package/src/widget-studio/builtin-widget-asset-catalog.ts +12 -0
  68. package/src/widget-studio/create-widget-studio-workspace-editor.tsx +79 -0
  69. package/src/widget-studio/index.ts +7 -0
  70. package/src/widget-studio/resolve-widget-studio-asset-catalog.ts +26 -0
  71. package/src/widget-tree/WidgetAssetPalette.tsx +77 -0
  72. package/src/widget-tree/WidgetInspectorPanel.tsx +266 -0
  73. package/src/widget-tree/WidgetSourceEditor.tsx +56 -0
  74. package/src/widget-tree/WidgetTreeLab.tsx +272 -0
  75. package/src/widget-tree/WidgetTreeModeControls.tsx +44 -0
  76. package/src/widget-tree/WidgetTreeSidePanel.tsx +49 -0
  77. package/src/widget-tree/WidgetTreeView.tsx +97 -0
  78. package/src/widget-tree/WidgetTreeWorkbench.tsx +111 -0
  79. package/src/widget-tree/WidgetTreeWorkspaceShell.tsx +154 -0
  80. package/src/widget-tree/demo-registry.ts +32 -0
  81. package/src/widget-tree/demo-widget-assets.ts +4 -0
  82. package/src/widget-tree/index.ts +27 -0
  83. package/src/widget-tree/widget-tree-document.ts +20 -0
  84. package/src/widget-tree/widget-tree-layout.ts +31 -0
  85. package/src/widget-tree/widget-tree-mode.ts +7 -0
  86. package/src/widget-tree/widget-tree-play-helpers.ts +74 -0
  87. package/src/workbench/ActivityBar.tsx +52 -52
  88. package/src/workbench/ArtifactShell.tsx +397 -0
  89. package/src/workbench/CommandPalette.tsx +819 -0
  90. package/src/workbench/ConfirmationFlow.tsx +245 -0
  91. package/src/workbench/MarkdownPreview.tsx +151 -0
  92. package/src/workbench/ShortcutCommandBridge.tsx +368 -0
  93. package/src/workbench/SplitView.tsx +136 -136
  94. package/src/workbench/StatusBar.tsx +178 -123
  95. package/src/workbench/StructuredArtifactEditor.tsx +205 -0
  96. package/src/workbench/Timeline.tsx +302 -0
  97. package/src/workbench/WorkbenchCanvasShell.tsx +941 -0
  98. package/src/workbench/WorkbenchShell.tsx +74 -70
  99. package/src/workbench/WorkbenchStandaloneShell.tsx +318 -291
  100. package/src/workbench/auth/WorkbenchAuthGate.tsx +61 -0
  101. package/src/workbench/auth/WorkbenchLoginView.tsx +635 -0
  102. package/src/workbench/auth/index.ts +19 -0
  103. package/src/workbench/chat/ChatComposer.tsx +165 -148
  104. package/src/workbench/chat/ChatMessageItem.tsx +10 -1
  105. package/src/workbench/chat/index.ts +9 -0
  106. package/src/workbench/chat/slashCommand.ts +28 -0
  107. package/src/workbench/chat/useChatRuntimeState.ts +76 -0
  108. package/src/workbench/chat/useSlashCommandSuggest.ts +101 -0
  109. package/src/workbench/commands.ts +520 -490
  110. package/src/workbench/index.ts +443 -98
  111. package/src/workbench/keyboard.ts +53 -0
  112. package/src/workbench/schema/index.ts +48 -0
  113. package/src/workbench/schema/workbenchDocument.ts +31 -0
  114. package/src/workbench/schema/workbenchDocumentActions.ts +6 -0
  115. package/src/workbench/schema/workbenchDocumentAdapter.ts +9 -0
  116. package/src/workbench/schema/workbenchDocumentPatch.ts +13 -0
  117. package/src/workbench/schema/workbenchDocumentRenderer.tsx +702 -0
  118. package/src/workbench/settings/NavigationPanel.tsx +47 -0
  119. package/src/workbench/settings/SchemaForm.tsx +420 -0
  120. package/src/workbench/settings/SectionedPanel.tsx +415 -0
  121. package/src/workbench/settings/StructuredDataForm.tsx +539 -0
  122. package/src/workbench/settings/StructuredDataSchemaPanel.tsx +559 -0
  123. package/src/workbench/settings/StructuredDataSchemaPanelEmbed.tsx +21 -0
  124. package/src/workbench/settings/StructuredDataSchemaPanelFrame.tsx +76 -0
  125. package/src/workbench/settings/StructuredDataTableView.tsx +127 -0
  126. package/src/workbench/settings/WorkbenchPanelRegion.tsx +46 -0
  127. package/src/workbench/settings/WorkbenchSettingsModal.tsx +21 -12
  128. package/src/workbench/settings/WorkbenchSettingsNav.tsx +38 -22
  129. package/src/workbench/settings/index.ts +135 -0
  130. package/src/workbench/settings/panel-region.css +21 -0
  131. package/src/workbench/settings/sectionedPanelScrollSpy.ts +143 -0
  132. package/src/workbench/settings/structured-data-schema-panel.css +330 -0
  133. package/src/workbench/settings/structured-data-table-view.css +85 -0
  134. package/src/workbench/settings/structuredDataSchema.ts +886 -0
  135. package/src/workbench/shell.ts +15 -0
  136. package/src/workbench/shellState.ts +203 -203
  137. package/src/workbench/standalone.ts +101 -94
  138. package/src/workbench/status.ts +129 -0
  139. package/src/workbench/theme.ts +44 -0
  140. package/src/workbench/workspace/MultiProviderExplorer.tsx +625 -0
  141. package/src/workbench/workspace/WorkspaceDraftsContext.tsx +111 -0
  142. package/src/workbench/workspace/WorkspaceEditor.tsx +47 -12
  143. package/src/workbench/workspace/WorkspaceEditorPanel.tsx +334 -353
  144. package/src/workbench/workspace/WorkspaceExplorer.tsx +532 -524
  145. package/src/workbench/workspace/WorkspaceFileIcon.tsx +32 -2
  146. package/src/workbench/workspace/WorkspaceSearchPanel.tsx +113 -113
  147. package/src/workbench/workspace/WorkspaceSearchResults.tsx +47 -47
  148. package/src/workbench/workspace/index.ts +156 -98
  149. package/src/workbench/workspace/mimeType.ts +45 -0
  150. package/src/workbench/workspace/path.ts +10 -10
  151. package/src/workbench/workspace/search.ts +6 -6
  152. package/src/workbench/workspace/tree.ts +1 -1
  153. package/src/workbench/workspace/types.ts +10 -10
  154. package/src/workbench/workspace/useVirtualWorkspace.ts +111 -98
  155. package/src/workbench/workspace/workspaceJsonDiagnostics.ts +83 -0
@@ -1,490 +1,520 @@
1
- import {
2
- commandMenuEntries,
3
- commandMenuEntry,
4
- commandMenuSeparator,
5
- type CommandDefinition,
6
- type CommandValue,
7
- type CommandMenuEntry,
8
- type CommandMenuItem,
9
- } from '@workbench-kit/core';
10
-
11
- import type { ContextMenuItem } from '../overlay/ContextMenu';
12
-
13
- export const WORKBENCH_OPEN_SETTINGS_COMMAND_ID = 'workbench.openSettings';
14
- export const WORKBENCH_TOGGLE_PRIMARY_SIDEBAR_COMMAND_ID = 'workbench.togglePrimarySidebar';
15
- export const WORKBENCH_EDITOR_SAVE_COMMAND_ID = 'editor.save';
16
- export const WORKBENCH_EDITOR_DISCARD_CHANGES_COMMAND_ID = 'editor.discardChanges';
17
- export const WORKBENCH_EDITOR_COPY_PATH_COMMAND_ID = 'editor.copyPath';
18
- export const WORKBENCH_EDITOR_CLOSE_COMMAND_ID = 'editor.close';
19
- export const WORKBENCH_EDITOR_CLOSE_OTHERS_COMMAND_ID = 'editor.closeOthers';
20
- export const WORKBENCH_EDITOR_CLOSE_ALL_COMMAND_ID = 'editor.closeAll';
21
- export const WORKBENCH_EDITOR_DELETE_COMMAND_ID = 'editor.delete';
22
- export const WORKBENCH_WORKSPACE_NEW_FILE_COMMAND_ID = 'workspace.newFile';
23
- export const WORKBENCH_WORKSPACE_NEW_FOLDER_COMMAND_ID = 'workspace.newFolder';
24
- export const WORKBENCH_WORKSPACE_OPEN_COMMAND_ID = 'workspace.open';
25
- export const WORKBENCH_WORKSPACE_COPY_PATH_COMMAND_ID = 'workspace.copyPath';
26
- export const WORKBENCH_WORKSPACE_RENAME_COMMAND_ID = 'workspace.rename';
27
- export const WORKBENCH_WORKSPACE_DELETE_COMMAND_ID = 'workspace.delete';
28
- export const WORKBENCH_SEARCH_OPEN_RESULT_COMMAND_ID = 'search.openResult';
29
- export const WORKBENCH_SEARCH_COPY_RESULT_PATH_COMMAND_ID = 'search.copyResultPath';
30
- export const WORKBENCH_SEARCH_DELETE_RESULT_COMMAND_ID = 'search.deleteResult';
31
-
32
- export const WORKBENCH_COMMAND_SURFACE_ACTIVITY_BAR = 'activityBar';
33
- export const WORKBENCH_COMMAND_SURFACE_EDITOR = 'editor';
34
- export const WORKBENCH_COMMAND_SURFACE_SEARCH = 'search';
35
- export const WORKBENCH_COMMAND_SURFACE_SETTINGS = 'settings';
36
- export const WORKBENCH_COMMAND_SURFACE_WORKSPACE = 'workspace';
37
-
38
- export type WorkbenchCommandSurface =
39
- | typeof WORKBENCH_COMMAND_SURFACE_ACTIVITY_BAR
40
- | typeof WORKBENCH_COMMAND_SURFACE_EDITOR
41
- | typeof WORKBENCH_COMMAND_SURFACE_SEARCH
42
- | typeof WORKBENCH_COMMAND_SURFACE_SETTINGS
43
- | typeof WORKBENCH_COMMAND_SURFACE_WORKSPACE;
44
-
45
- export interface WorkbenchShellCommandActivity<TActivityId extends string = string> {
46
- icon?: string;
47
- id: TActivityId;
48
- label: string;
49
- }
50
-
51
- export interface WorkbenchShellCommandContext<TActivityId extends string = string> {
52
- isPrimarySidebarVisible: boolean;
53
- openSettings: () => void;
54
- showActivity: (activityId: TActivityId) => void;
55
- togglePrimarySidebar: () => void;
56
- }
57
-
58
- export interface WorkbenchCommandOverride<TContext = void> {
59
- icon?: CommandValue<TContext, string | undefined>;
60
- label?: CommandValue<TContext, string>;
61
- shortcut?: CommandValue<TContext, string | undefined>;
62
- }
63
-
64
- export type WorkbenchCommandOverrides<TContext = void> = Partial<
65
- Record<string, WorkbenchCommandOverride<TContext>>
66
- >;
67
-
68
- interface WorkbenchCommandPresetOptions<TContext = void> {
69
- commandOverrides?: WorkbenchCommandOverrides<TContext>;
70
- }
71
-
72
- function applyWorkbenchCommandOverrides<TContext>(
73
- commands: CommandDefinition<TContext>[],
74
- options: WorkbenchCommandPresetOptions<TContext> = {},
75
- ): CommandDefinition<TContext>[] {
76
- const { commandOverrides } = options;
77
- if (!commandOverrides) return commands;
78
-
79
- return commands.map((command) => {
80
- const override = commandOverrides[command.id];
81
- if (!override) return command;
82
-
83
- return {
84
- ...command,
85
- icon: override.icon ?? command.icon,
86
- label: override.label ?? command.label,
87
- shortcut: override.shortcut ?? command.shortcut,
88
- };
89
- });
90
- }
91
-
92
- export interface WorkbenchShellCommandPresetOptions<TActivityId extends string = string> {
93
- activities: WorkbenchShellCommandActivity<TActivityId>[];
94
- includeSettings?: boolean;
95
- includeSidebarToggle?: boolean;
96
- menuSeparatorId?: string;
97
- settingsIcon?: string;
98
- settingsLabel?: string;
99
- sidebarIcon?: string;
100
- commandOverrides?: WorkbenchCommandOverrides<WorkbenchShellCommandContext<TActivityId>>;
101
- }
102
-
103
- export interface WorkbenchEditorCommandContext {
104
- canCloseAll: boolean;
105
- canCloseOthers: boolean;
106
- canClosePath: boolean;
107
- canCopyPath: boolean;
108
- canDeletePath: boolean;
109
- canDiscardFile: boolean;
110
- canSaveFile: boolean;
111
- closeAll: () => void;
112
- closeOthers: () => void;
113
- closePath: () => void;
114
- copyPath: () => void;
115
- deletePath: () => void;
116
- discardFile: () => void;
117
- filePath?: string;
118
- hasMultipleOpenFiles: boolean;
119
- hasOpenFiles: boolean;
120
- hasUnsavedChanges: boolean;
121
- saveFile: () => void;
122
- }
123
-
124
- export interface WorkbenchWorkspaceCommandContext {
125
- copyWorkspaceTarget: () => void;
126
- createWorkspaceFile: () => void;
127
- createWorkspaceFolder: () => void;
128
- deleteWorkspaceTarget: () => void;
129
- fileActionPaths: string[];
130
- multiFileAction: boolean;
131
- openWorkspaceTarget: () => void;
132
- renameWorkspaceTarget: () => void;
133
- targetPaths: string[];
134
- workspaceTargetKind: 'file' | 'folder';
135
- }
136
-
137
- export interface WorkbenchSearchResultCommandContext {
138
- copyPath: () => void;
139
- deleteResult: () => void;
140
- openResult: () => void;
141
- }
142
-
143
- export function getWorkbenchShowActivityCommandId(activityId: string) {
144
- return `workbench.showActivity.${activityId}`;
145
- }
146
-
147
- export function createWorkbenchShellCommands<TActivityId extends string>({
148
- activities,
149
- includeSettings = true,
150
- includeSidebarToggle = true,
151
- settingsIcon = 'codicon-settings-gear',
152
- settingsLabel = 'Settings',
153
- sidebarIcon = 'codicon-layout-sidebar-left',
154
- commandOverrides,
155
- }: WorkbenchShellCommandPresetOptions<TActivityId>): CommandDefinition<
156
- WorkbenchShellCommandContext<TActivityId>
157
- >[] {
158
- const activityCommands = activities.map<
159
- CommandDefinition<WorkbenchShellCommandContext<TActivityId>>
160
- >((activity) => ({
161
- id: getWorkbenchShowActivityCommandId(activity.id),
162
- icon: activity.icon,
163
- label: activity.label,
164
- run: ({ showActivity }) => showActivity(activity.id),
165
- }));
166
-
167
- const shellCommands: CommandDefinition<WorkbenchShellCommandContext<TActivityId>>[] = [];
168
-
169
- if (includeSidebarToggle) {
170
- shellCommands.push({
171
- id: WORKBENCH_TOGGLE_PRIMARY_SIDEBAR_COMMAND_ID,
172
- icon: sidebarIcon,
173
- label: ({ isPrimarySidebarVisible }) =>
174
- isPrimarySidebarVisible ? 'Hide primary sidebar' : 'Show primary sidebar',
175
- run: ({ togglePrimarySidebar }) => togglePrimarySidebar(),
176
- });
177
- }
178
-
179
- if (includeSettings) {
180
- shellCommands.push({
181
- id: WORKBENCH_OPEN_SETTINGS_COMMAND_ID,
182
- icon: settingsIcon,
183
- label: settingsLabel,
184
- run: ({ openSettings }) => openSettings(),
185
- });
186
- }
187
-
188
- return applyWorkbenchCommandOverrides([...activityCommands, ...shellCommands], {
189
- commandOverrides,
190
- });
191
- }
192
-
193
- export function createWorkbenchShellMenuEntries<TActivityId extends string>({
194
- activities,
195
- includeSettings = true,
196
- includeSidebarToggle = true,
197
- menuSeparatorId = 'workbench-shell-separator',
198
- }: WorkbenchShellCommandPresetOptions<TActivityId>): CommandMenuEntry<
199
- WorkbenchShellCommandContext<TActivityId>
200
- >[] {
201
- const activityEntries = activities.map<
202
- CommandMenuEntry<WorkbenchShellCommandContext<TActivityId>>
203
- >((activity) =>
204
- commandMenuEntry<WorkbenchShellCommandContext<TActivityId>>(
205
- getWorkbenchShowActivityCommandId(activity.id),
206
- { surfaces: [WORKBENCH_COMMAND_SURFACE_ACTIVITY_BAR] },
207
- ),
208
- );
209
- const shellEntries: CommandMenuEntry<WorkbenchShellCommandContext<TActivityId>>[] = [];
210
-
211
- if (includeSidebarToggle) {
212
- shellEntries.push(
213
- commandMenuEntry<WorkbenchShellCommandContext<TActivityId>>(
214
- WORKBENCH_TOGGLE_PRIMARY_SIDEBAR_COMMAND_ID,
215
- { surfaces: [WORKBENCH_COMMAND_SURFACE_ACTIVITY_BAR] },
216
- ),
217
- );
218
- }
219
-
220
- if (includeSettings) {
221
- shellEntries.push(
222
- commandMenuEntry<WorkbenchShellCommandContext<TActivityId>>(
223
- WORKBENCH_OPEN_SETTINGS_COMMAND_ID,
224
- { surfaces: [WORKBENCH_COMMAND_SURFACE_ACTIVITY_BAR] },
225
- ),
226
- );
227
- }
228
-
229
- if (!shellEntries.length) return activityEntries;
230
- return [...activityEntries, commandMenuSeparator(menuSeparatorId), ...shellEntries];
231
- }
232
-
233
- export interface WorkbenchEditorCommandPresetOptions {
234
- commandOverrides?: WorkbenchCommandOverrides<WorkbenchEditorCommandContext>;
235
- }
236
-
237
- export function createWorkbenchEditorCommands({
238
- commandOverrides,
239
- }: WorkbenchEditorCommandPresetOptions = {}): CommandDefinition<WorkbenchEditorCommandContext>[] {
240
- return applyWorkbenchCommandOverrides(
241
- [
242
- {
243
- id: WORKBENCH_EDITOR_SAVE_COMMAND_ID,
244
- icon: 'codicon-save',
245
- isEnabled: ({ canSaveFile, hasUnsavedChanges }) => canSaveFile && hasUnsavedChanges,
246
- label: 'Save',
247
- run: ({ saveFile }) => saveFile(),
248
- },
249
- {
250
- id: WORKBENCH_EDITOR_DISCARD_CHANGES_COMMAND_ID,
251
- icon: 'codicon-discard',
252
- isEnabled: ({ canDiscardFile, hasUnsavedChanges }) => canDiscardFile && hasUnsavedChanges,
253
- label: 'Discard changes',
254
- run: ({ discardFile }) => discardFile(),
255
- },
256
- {
257
- id: WORKBENCH_EDITOR_COPY_PATH_COMMAND_ID,
258
- icon: 'codicon-copy',
259
- isEnabled: ({ canCopyPath, filePath }) => Boolean(filePath && canCopyPath),
260
- label: 'Copy path',
261
- run: ({ copyPath }) => copyPath(),
262
- },
263
- {
264
- id: WORKBENCH_EDITOR_CLOSE_COMMAND_ID,
265
- icon: 'codicon-close',
266
- isEnabled: ({ canClosePath, filePath }) => Boolean(filePath && canClosePath),
267
- label: 'Close',
268
- run: ({ closePath }) => closePath(),
269
- },
270
- {
271
- id: WORKBENCH_EDITOR_CLOSE_OTHERS_COMMAND_ID,
272
- icon: 'codicon-close-all',
273
- isEnabled: ({ canCloseOthers, filePath, hasMultipleOpenFiles }) =>
274
- Boolean(filePath && canCloseOthers && hasMultipleOpenFiles),
275
- label: 'Close others',
276
- run: ({ closeOthers }) => closeOthers(),
277
- },
278
- {
279
- id: WORKBENCH_EDITOR_CLOSE_ALL_COMMAND_ID,
280
- icon: 'codicon-close-all',
281
- isEnabled: ({ canCloseAll, hasOpenFiles }) => canCloseAll && hasOpenFiles,
282
- label: 'Close all',
283
- run: ({ closeAll }) => closeAll(),
284
- },
285
- {
286
- id: WORKBENCH_EDITOR_DELETE_COMMAND_ID,
287
- danger: true,
288
- icon: 'codicon-trash',
289
- isEnabled: ({ canDeletePath, filePath }) => Boolean(filePath && canDeletePath),
290
- label: 'Delete',
291
- run: ({ deletePath }) => deletePath(),
292
- },
293
- ],
294
- { commandOverrides },
295
- );
296
- }
297
-
298
- export function createWorkbenchEditorTabListMenuEntries(): CommandMenuEntry<WorkbenchEditorCommandContext>[] {
299
- return [
300
- commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_CLOSE_ALL_COMMAND_ID, {
301
- surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
302
- }),
303
- ];
304
- }
305
-
306
- export function createWorkbenchEditorTabMenuEntries(): CommandMenuEntry<WorkbenchEditorCommandContext>[] {
307
- return [
308
- commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_COPY_PATH_COMMAND_ID, {
309
- surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
310
- }),
311
- commandMenuSeparator('tab-file-separator'),
312
- commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_CLOSE_COMMAND_ID, {
313
- surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
314
- }),
315
- commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_CLOSE_OTHERS_COMMAND_ID, {
316
- surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
317
- }),
318
- commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_CLOSE_ALL_COMMAND_ID, {
319
- surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
320
- }),
321
- commandMenuSeparator('tab-danger-separator'),
322
- commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_DELETE_COMMAND_ID, {
323
- surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
324
- }),
325
- ];
326
- }
327
-
328
- export function createWorkbenchWorkspaceCommands<
329
- TContext extends WorkbenchWorkspaceCommandContext = WorkbenchWorkspaceCommandContext,
330
- >({
331
- commandOverrides,
332
- }: WorkbenchCommandPresetOptions<TContext> = {}): CommandDefinition<TContext>[] {
333
- const commands: CommandDefinition<TContext>[] = [
334
- {
335
- id: WORKBENCH_WORKSPACE_NEW_FILE_COMMAND_ID,
336
- icon: 'codicon-new-file',
337
- label: 'New file',
338
- run: ({ createWorkspaceFile }) => createWorkspaceFile(),
339
- },
340
- {
341
- id: WORKBENCH_WORKSPACE_NEW_FOLDER_COMMAND_ID,
342
- icon: 'codicon-new-folder',
343
- label: 'New folder',
344
- run: ({ createWorkspaceFolder }) => createWorkspaceFolder(),
345
- },
346
- {
347
- id: WORKBENCH_WORKSPACE_OPEN_COMMAND_ID,
348
- icon: ({ workspaceTargetKind }) =>
349
- workspaceTargetKind === 'folder' ? 'codicon-folder-opened' : 'codicon-go-to-file',
350
- label: ({ multiFileAction, workspaceTargetKind }) =>
351
- workspaceTargetKind === 'folder'
352
- ? 'Reveal folder'
353
- : multiFileAction
354
- ? 'Open selected files'
355
- : 'Open file',
356
- run: ({ openWorkspaceTarget }) => openWorkspaceTarget(),
357
- },
358
- {
359
- id: WORKBENCH_WORKSPACE_COPY_PATH_COMMAND_ID,
360
- icon: 'codicon-copy',
361
- label: ({ targetPaths }) => (targetPaths.length > 1 ? 'Copy paths' : 'Copy path'),
362
- run: ({ copyWorkspaceTarget }) => copyWorkspaceTarget(),
363
- },
364
- {
365
- id: WORKBENCH_WORKSPACE_RENAME_COMMAND_ID,
366
- icon: 'codicon-edit',
367
- isEnabled: ({ targetPaths }) => targetPaths.length === 1,
368
- label: 'Rename',
369
- run: ({ renameWorkspaceTarget }) => renameWorkspaceTarget(),
370
- shortcut: 'F2',
371
- },
372
- {
373
- id: WORKBENCH_WORKSPACE_DELETE_COMMAND_ID,
374
- danger: true,
375
- icon: 'codicon-trash',
376
- isEnabled: ({ fileActionPaths, workspaceTargetKind }) =>
377
- workspaceTargetKind === 'folder' || fileActionPaths.length > 0,
378
- label: ({ fileActionPaths, multiFileAction, workspaceTargetKind }) =>
379
- workspaceTargetKind === 'folder'
380
- ? 'Delete folder'
381
- : multiFileAction
382
- ? `Delete ${fileActionPaths.length} files`
383
- : 'Delete',
384
- run: ({ deleteWorkspaceTarget }) => deleteWorkspaceTarget(),
385
- shortcut: 'Del',
386
- },
387
- ];
388
-
389
- return applyWorkbenchCommandOverrides(commands, { commandOverrides });
390
- }
391
-
392
- export function createWorkbenchWorkspaceCreateMenuEntries<
393
- TContext extends WorkbenchWorkspaceCommandContext = WorkbenchWorkspaceCommandContext,
394
- >(): CommandMenuEntry<TContext>[] {
395
- return commandMenuEntries<TContext>(
396
- WORKBENCH_WORKSPACE_NEW_FILE_COMMAND_ID,
397
- WORKBENCH_WORKSPACE_NEW_FOLDER_COMMAND_ID,
398
- ).map((entry) => ({ ...entry, surfaces: [WORKBENCH_COMMAND_SURFACE_WORKSPACE] }));
399
- }
400
-
401
- export function createWorkbenchWorkspaceTargetMenuEntries<
402
- TContext extends WorkbenchWorkspaceCommandContext = WorkbenchWorkspaceCommandContext,
403
- >(): CommandMenuEntry<TContext>[] {
404
- return [
405
- ...commandMenuEntries<TContext>(
406
- WORKBENCH_WORKSPACE_OPEN_COMMAND_ID,
407
- WORKBENCH_WORKSPACE_COPY_PATH_COMMAND_ID,
408
- ).map((entry) => ({ ...entry, surfaces: [WORKBENCH_COMMAND_SURFACE_WORKSPACE] })),
409
- commandMenuSeparator('workspace-separator'),
410
- ...commandMenuEntries<TContext>(
411
- WORKBENCH_WORKSPACE_RENAME_COMMAND_ID,
412
- WORKBENCH_WORKSPACE_DELETE_COMMAND_ID,
413
- ).map((entry) => ({ ...entry, surfaces: [WORKBENCH_COMMAND_SURFACE_WORKSPACE] })),
414
- ];
415
- }
416
-
417
- export function createWorkbenchWorkspaceFolderMenuEntries<
418
- TContext extends WorkbenchWorkspaceCommandContext = WorkbenchWorkspaceCommandContext,
419
- >(): CommandMenuEntry<TContext>[] {
420
- return [
421
- ...createWorkbenchWorkspaceCreateMenuEntries(),
422
- commandMenuSeparator('workspace-create-separator'),
423
- ...createWorkbenchWorkspaceTargetMenuEntries(),
424
- ];
425
- }
426
-
427
- export function createWorkbenchSearchResultCommands<
428
- TContext extends WorkbenchSearchResultCommandContext = WorkbenchSearchResultCommandContext,
429
- >({
430
- commandOverrides,
431
- }: WorkbenchCommandPresetOptions<TContext> = {}): CommandDefinition<TContext>[] {
432
- const commands: CommandDefinition<TContext>[] = [
433
- {
434
- id: WORKBENCH_SEARCH_OPEN_RESULT_COMMAND_ID,
435
- icon: 'codicon-folder-opened',
436
- label: 'Open',
437
- run: ({ openResult }) => openResult(),
438
- shortcut: 'Enter',
439
- },
440
- {
441
- id: WORKBENCH_SEARCH_COPY_RESULT_PATH_COMMAND_ID,
442
- icon: 'codicon-copy',
443
- label: 'Copy path',
444
- run: ({ copyPath }) => copyPath(),
445
- },
446
- {
447
- id: WORKBENCH_SEARCH_DELETE_RESULT_COMMAND_ID,
448
- danger: true,
449
- icon: 'codicon-trash',
450
- label: 'Delete',
451
- run: ({ deleteResult }) => deleteResult(),
452
- },
453
- ];
454
-
455
- return applyWorkbenchCommandOverrides(commands, { commandOverrides });
456
- }
457
-
458
- export function createWorkbenchSearchResultMenuEntries<
459
- TContext extends WorkbenchSearchResultCommandContext = WorkbenchSearchResultCommandContext,
460
- >(): CommandMenuEntry<TContext>[] {
461
- return [
462
- ...commandMenuEntries<TContext>(
463
- WORKBENCH_SEARCH_OPEN_RESULT_COMMAND_ID,
464
- WORKBENCH_SEARCH_COPY_RESULT_PATH_COMMAND_ID,
465
- ).map((entry) => ({ ...entry, surfaces: [WORKBENCH_COMMAND_SURFACE_SEARCH] })),
466
- commandMenuSeparator('result-menu-separator'),
467
- commandMenuEntry<TContext>(WORKBENCH_SEARCH_DELETE_RESULT_COMMAND_ID, {
468
- surfaces: [WORKBENCH_COMMAND_SURFACE_SEARCH],
469
- }),
470
- ];
471
- }
472
-
473
- export function commandMenuItemsToContextMenuItems(
474
- items: CommandMenuItem[],
475
- onSelectCommand: (commandId: string) => void,
476
- ): ContextMenuItem[] {
477
- return items.map((item) =>
478
- item.type === 'separator'
479
- ? { id: item.id, type: 'separator' }
480
- : {
481
- id: item.id,
482
- label: item.label,
483
- icon: item.icon,
484
- shortcut: item.shortcut,
485
- disabled: item.disabled,
486
- danger: item.danger,
487
- onSelect: () => onSelectCommand(item.commandId),
488
- },
489
- );
490
- }
1
+ import {
2
+ commandMenuEntries,
3
+ commandMenuEntry,
4
+ commandMenuSeparator,
5
+ resolveCommandMenuItems,
6
+ type CommandDefinition,
7
+ type CommandMenuEntry,
8
+ type CommandMenuItem,
9
+ type CommandRegistry,
10
+ type CommandValue,
11
+ } from '@workbench-kit/platform';
12
+
13
+ import type { ContextMenuItem } from '../overlay/ContextMenu';
14
+
15
+ export const WORKBENCH_OPEN_SETTINGS_COMMAND_ID = 'workbench.openSettings';
16
+ export const WORKBENCH_TOGGLE_PRIMARY_SIDEBAR_COMMAND_ID = 'workbench.togglePrimarySidebar';
17
+ export const WORKBENCH_EDITOR_SAVE_COMMAND_ID = 'editor.save';
18
+ export const WORKBENCH_EDITOR_DISCARD_CHANGES_COMMAND_ID = 'editor.discardChanges';
19
+ export const WORKBENCH_EDITOR_COPY_PATH_COMMAND_ID = 'editor.copyPath';
20
+ export const WORKBENCH_EDITOR_CLOSE_COMMAND_ID = 'editor.close';
21
+ export const WORKBENCH_EDITOR_CLOSE_OTHERS_COMMAND_ID = 'editor.closeOthers';
22
+ export const WORKBENCH_EDITOR_CLOSE_ALL_COMMAND_ID = 'editor.closeAll';
23
+ export const WORKBENCH_EDITOR_DELETE_COMMAND_ID = 'editor.delete';
24
+ export const WORKBENCH_WORKSPACE_NEW_FILE_COMMAND_ID = 'workspace.newFile';
25
+ export const WORKBENCH_WORKSPACE_NEW_FOLDER_COMMAND_ID = 'workspace.newFolder';
26
+ export const WORKBENCH_WORKSPACE_OPEN_COMMAND_ID = 'workspace.open';
27
+ export const WORKBENCH_WORKSPACE_COPY_PATH_COMMAND_ID = 'workspace.copyPath';
28
+ export const WORKBENCH_WORKSPACE_RENAME_COMMAND_ID = 'workspace.rename';
29
+ export const WORKBENCH_WORKSPACE_DELETE_COMMAND_ID = 'workspace.delete';
30
+ export const WORKBENCH_SEARCH_OPEN_RESULT_COMMAND_ID = 'search.openResult';
31
+ export const WORKBENCH_SEARCH_COPY_RESULT_PATH_COMMAND_ID = 'search.copyResultPath';
32
+ export const WORKBENCH_SEARCH_DELETE_RESULT_COMMAND_ID = 'search.deleteResult';
33
+
34
+ export const WORKBENCH_COMMAND_SURFACE_ACTIVITY_BAR = 'activityBar';
35
+ export const WORKBENCH_COMMAND_SURFACE_EDITOR = 'editor';
36
+ export const WORKBENCH_COMMAND_SURFACE_SEARCH = 'search';
37
+ export const WORKBENCH_COMMAND_SURFACE_SETTINGS = 'settings';
38
+ export const WORKBENCH_COMMAND_SURFACE_WORKSPACE = 'workspace';
39
+
40
+ export type WorkbenchCommandSurface =
41
+ | typeof WORKBENCH_COMMAND_SURFACE_ACTIVITY_BAR
42
+ | typeof WORKBENCH_COMMAND_SURFACE_EDITOR
43
+ | typeof WORKBENCH_COMMAND_SURFACE_SEARCH
44
+ | typeof WORKBENCH_COMMAND_SURFACE_SETTINGS
45
+ | typeof WORKBENCH_COMMAND_SURFACE_WORKSPACE;
46
+
47
+ export interface WorkbenchShellCommandActivity<TActivityId extends string = string> {
48
+ icon?: string | undefined;
49
+ id: TActivityId;
50
+ label: string;
51
+ }
52
+
53
+ export interface WorkbenchShellCommandContext<TActivityId extends string = string> {
54
+ isPrimarySidebarVisible: boolean;
55
+ openSettings: () => void;
56
+ showActivity: (activityId: TActivityId) => void;
57
+ togglePrimarySidebar: () => void;
58
+ }
59
+
60
+ export interface WorkbenchCommandOverride<TContext = void> {
61
+ icon?: CommandValue<TContext, string | undefined>;
62
+ label?: CommandValue<TContext, string>;
63
+ shortcut?: CommandValue<TContext, string | undefined>;
64
+ }
65
+
66
+ export type WorkbenchCommandOverrides<TContext = void> = Partial<
67
+ Record<string, WorkbenchCommandOverride<TContext>>
68
+ >;
69
+
70
+ interface WorkbenchCommandPresetOptions<TContext = void> {
71
+ commandOverrides?: WorkbenchCommandOverrides<TContext> | undefined;
72
+ }
73
+
74
+ function applyWorkbenchCommandOverrides<TContext>(
75
+ commands: CommandDefinition<TContext>[],
76
+ options: WorkbenchCommandPresetOptions<TContext> = {},
77
+ ): CommandDefinition<TContext>[] {
78
+ const { commandOverrides } = options;
79
+ if (!commandOverrides) return commands;
80
+
81
+ return commands.map((command) => {
82
+ const override = commandOverrides[command.id];
83
+ if (!override) return command;
84
+
85
+ return {
86
+ ...command,
87
+ icon: override.icon ?? command.icon,
88
+ label: override.label ?? command.label,
89
+ shortcut: override.shortcut ?? command.shortcut,
90
+ };
91
+ });
92
+ }
93
+
94
+ export interface WorkbenchShellCommandPresetOptions<TActivityId extends string = string> {
95
+ activities: WorkbenchShellCommandActivity<TActivityId>[];
96
+ includeSettings?: boolean | undefined;
97
+ includeSidebarToggle?: boolean | undefined;
98
+ menuSeparatorId?: string | undefined;
99
+ settingsIcon?: string | undefined;
100
+ settingsLabel?: string | undefined;
101
+ sidebarIcon?: string | undefined;
102
+ commandOverrides?:
103
+ | WorkbenchCommandOverrides<WorkbenchShellCommandContext<TActivityId>>
104
+ | undefined;
105
+ }
106
+
107
+ export interface WorkbenchEditorCommandContext {
108
+ canCloseAll: boolean;
109
+ canCloseOthers: boolean;
110
+ canClosePath: boolean;
111
+ canCopyPath: boolean;
112
+ canDeletePath: boolean;
113
+ canDiscardFile: boolean;
114
+ canSaveFile: boolean;
115
+ closeAll: () => void;
116
+ closeOthers: () => void;
117
+ closePath: () => void;
118
+ copyPath: () => void;
119
+ deletePath: () => void;
120
+ discardFile: () => void;
121
+ filePath?: string | undefined;
122
+ hasMultipleOpenFiles: boolean;
123
+ hasOpenFiles: boolean;
124
+ hasUnsavedChanges: boolean;
125
+ saveFile: () => void;
126
+ }
127
+
128
+ export interface WorkbenchWorkspaceCommandContext {
129
+ copyWorkspaceTarget: () => void;
130
+ createWorkspaceFile: () => void;
131
+ createWorkspaceFolder: () => void;
132
+ deleteWorkspaceTarget: () => void;
133
+ fileActionPaths: string[];
134
+ multiFileAction: boolean;
135
+ openWorkspaceTarget: () => void;
136
+ renameWorkspaceTarget: () => void;
137
+ targetPaths: string[];
138
+ workspaceTargetKind: 'file' | 'folder';
139
+ }
140
+
141
+ export interface WorkbenchSearchResultCommandContext {
142
+ copyPath: () => void;
143
+ deleteResult: () => void;
144
+ openResult: () => void;
145
+ }
146
+
147
+ export function getWorkbenchShowActivityCommandId(activityId: string) {
148
+ return `workbench.showActivity.${activityId}`;
149
+ }
150
+
151
+ export function createWorkbenchShellCommands<TActivityId extends string>({
152
+ activities,
153
+ includeSettings = true,
154
+ includeSidebarToggle = true,
155
+ settingsIcon = 'codicon-settings-gear',
156
+ settingsLabel = 'Settings',
157
+ sidebarIcon = 'codicon-layout-sidebar-left',
158
+ commandOverrides,
159
+ }: WorkbenchShellCommandPresetOptions<TActivityId>): CommandDefinition<
160
+ WorkbenchShellCommandContext<TActivityId>
161
+ >[] {
162
+ const activityCommands = activities.map<
163
+ CommandDefinition<WorkbenchShellCommandContext<TActivityId>>
164
+ >((activity) => ({
165
+ id: getWorkbenchShowActivityCommandId(activity.id),
166
+ icon: activity.icon,
167
+ label: activity.label,
168
+ run: ({ showActivity }) => showActivity(activity.id),
169
+ }));
170
+
171
+ const shellCommands: CommandDefinition<WorkbenchShellCommandContext<TActivityId>>[] = [];
172
+
173
+ if (includeSidebarToggle) {
174
+ shellCommands.push({
175
+ id: WORKBENCH_TOGGLE_PRIMARY_SIDEBAR_COMMAND_ID,
176
+ icon: sidebarIcon,
177
+ label: ({ isPrimarySidebarVisible }) =>
178
+ isPrimarySidebarVisible ? 'Hide primary sidebar' : 'Show primary sidebar',
179
+ run: ({ togglePrimarySidebar }) => togglePrimarySidebar(),
180
+ });
181
+ }
182
+
183
+ if (includeSettings) {
184
+ shellCommands.push({
185
+ id: WORKBENCH_OPEN_SETTINGS_COMMAND_ID,
186
+ icon: settingsIcon,
187
+ label: settingsLabel,
188
+ run: ({ openSettings }) => openSettings(),
189
+ });
190
+ }
191
+
192
+ return applyWorkbenchCommandOverrides([...activityCommands, ...shellCommands], {
193
+ commandOverrides,
194
+ });
195
+ }
196
+
197
+ export function createWorkbenchShellMenuEntries<TActivityId extends string>({
198
+ activities,
199
+ includeSettings = true,
200
+ includeSidebarToggle = true,
201
+ menuSeparatorId = 'workbench-shell-separator',
202
+ }: WorkbenchShellCommandPresetOptions<TActivityId>): CommandMenuEntry<
203
+ WorkbenchShellCommandContext<TActivityId>
204
+ >[] {
205
+ const activityEntries = activities.map<
206
+ CommandMenuEntry<WorkbenchShellCommandContext<TActivityId>>
207
+ >((activity) =>
208
+ commandMenuEntry<WorkbenchShellCommandContext<TActivityId>>(
209
+ getWorkbenchShowActivityCommandId(activity.id),
210
+ { surfaces: [WORKBENCH_COMMAND_SURFACE_ACTIVITY_BAR] },
211
+ ),
212
+ );
213
+ const shellEntries: CommandMenuEntry<WorkbenchShellCommandContext<TActivityId>>[] = [];
214
+
215
+ if (includeSidebarToggle) {
216
+ shellEntries.push(
217
+ commandMenuEntry<WorkbenchShellCommandContext<TActivityId>>(
218
+ WORKBENCH_TOGGLE_PRIMARY_SIDEBAR_COMMAND_ID,
219
+ { surfaces: [WORKBENCH_COMMAND_SURFACE_ACTIVITY_BAR] },
220
+ ),
221
+ );
222
+ }
223
+
224
+ if (includeSettings) {
225
+ shellEntries.push(
226
+ commandMenuEntry<WorkbenchShellCommandContext<TActivityId>>(
227
+ WORKBENCH_OPEN_SETTINGS_COMMAND_ID,
228
+ { surfaces: [WORKBENCH_COMMAND_SURFACE_ACTIVITY_BAR] },
229
+ ),
230
+ );
231
+ }
232
+
233
+ if (!shellEntries.length) return activityEntries;
234
+ return [...activityEntries, commandMenuSeparator(menuSeparatorId), ...shellEntries];
235
+ }
236
+
237
+ export interface WorkbenchEditorCommandPresetOptions {
238
+ commandOverrides?: WorkbenchCommandOverrides<WorkbenchEditorCommandContext> | undefined;
239
+ }
240
+
241
+ export function createWorkbenchEditorCommands({
242
+ commandOverrides,
243
+ }: WorkbenchEditorCommandPresetOptions = {}): CommandDefinition<WorkbenchEditorCommandContext>[] {
244
+ return applyWorkbenchCommandOverrides(
245
+ [
246
+ {
247
+ id: WORKBENCH_EDITOR_SAVE_COMMAND_ID,
248
+ icon: 'codicon-save',
249
+ isEnabled: ({ canSaveFile, hasUnsavedChanges }) => canSaveFile && hasUnsavedChanges,
250
+ label: 'Save',
251
+ run: ({ saveFile }) => saveFile(),
252
+ },
253
+ {
254
+ id: WORKBENCH_EDITOR_DISCARD_CHANGES_COMMAND_ID,
255
+ icon: 'codicon-discard',
256
+ isEnabled: ({ canDiscardFile, hasUnsavedChanges }) => canDiscardFile && hasUnsavedChanges,
257
+ label: 'Discard changes',
258
+ run: ({ discardFile }) => discardFile(),
259
+ },
260
+ {
261
+ id: WORKBENCH_EDITOR_COPY_PATH_COMMAND_ID,
262
+ icon: 'codicon-copy',
263
+ isEnabled: ({ canCopyPath, filePath }) => Boolean(filePath && canCopyPath),
264
+ label: 'Copy path',
265
+ run: ({ copyPath }) => copyPath(),
266
+ },
267
+ {
268
+ id: WORKBENCH_EDITOR_CLOSE_COMMAND_ID,
269
+ icon: 'codicon-close',
270
+ isEnabled: ({ canClosePath, filePath }) => Boolean(filePath && canClosePath),
271
+ label: 'Close',
272
+ run: ({ closePath }) => closePath(),
273
+ },
274
+ {
275
+ id: WORKBENCH_EDITOR_CLOSE_OTHERS_COMMAND_ID,
276
+ icon: 'codicon-close-all',
277
+ isEnabled: ({ canCloseOthers, filePath, hasMultipleOpenFiles }) =>
278
+ Boolean(filePath && canCloseOthers && hasMultipleOpenFiles),
279
+ label: 'Close others',
280
+ run: ({ closeOthers }) => closeOthers(),
281
+ },
282
+ {
283
+ id: WORKBENCH_EDITOR_CLOSE_ALL_COMMAND_ID,
284
+ icon: 'codicon-close-all',
285
+ isEnabled: ({ canCloseAll, hasOpenFiles }) => canCloseAll && hasOpenFiles,
286
+ label: 'Close all',
287
+ run: ({ closeAll }) => closeAll(),
288
+ },
289
+ {
290
+ id: WORKBENCH_EDITOR_DELETE_COMMAND_ID,
291
+ danger: true,
292
+ icon: 'codicon-trash',
293
+ isEnabled: ({ canDeletePath, filePath }) => Boolean(filePath && canDeletePath),
294
+ label: 'Delete',
295
+ run: ({ deletePath }) => deletePath(),
296
+ },
297
+ ],
298
+ { commandOverrides },
299
+ );
300
+ }
301
+
302
+ export function createWorkbenchEditorTabListMenuEntries(): CommandMenuEntry<WorkbenchEditorCommandContext>[] {
303
+ return [
304
+ commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_CLOSE_ALL_COMMAND_ID, {
305
+ surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
306
+ }),
307
+ ];
308
+ }
309
+
310
+ export function createWorkbenchEditorTabMenuEntries(): CommandMenuEntry<WorkbenchEditorCommandContext>[] {
311
+ return [
312
+ commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_COPY_PATH_COMMAND_ID, {
313
+ surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
314
+ }),
315
+ commandMenuSeparator('tab-file-separator'),
316
+ commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_CLOSE_COMMAND_ID, {
317
+ surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
318
+ }),
319
+ commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_CLOSE_OTHERS_COMMAND_ID, {
320
+ surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
321
+ }),
322
+ commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_CLOSE_ALL_COMMAND_ID, {
323
+ surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
324
+ }),
325
+ commandMenuSeparator('tab-danger-separator'),
326
+ commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_DELETE_COMMAND_ID, {
327
+ surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
328
+ }),
329
+ ];
330
+ }
331
+
332
+ export function createWorkbenchWorkspaceCommands<
333
+ TContext extends WorkbenchWorkspaceCommandContext = WorkbenchWorkspaceCommandContext,
334
+ >({
335
+ commandOverrides,
336
+ }: WorkbenchCommandPresetOptions<TContext> = {}): CommandDefinition<TContext>[] {
337
+ const commands: CommandDefinition<TContext>[] = [
338
+ {
339
+ id: WORKBENCH_WORKSPACE_NEW_FILE_COMMAND_ID,
340
+ icon: 'codicon-new-file',
341
+ label: 'New file',
342
+ run: ({ createWorkspaceFile }) => createWorkspaceFile(),
343
+ },
344
+ {
345
+ id: WORKBENCH_WORKSPACE_NEW_FOLDER_COMMAND_ID,
346
+ icon: 'codicon-new-folder',
347
+ label: 'New folder',
348
+ run: ({ createWorkspaceFolder }) => createWorkspaceFolder(),
349
+ },
350
+ {
351
+ id: WORKBENCH_WORKSPACE_OPEN_COMMAND_ID,
352
+ icon: ({ workspaceTargetKind }) =>
353
+ workspaceTargetKind === 'folder' ? 'codicon-folder-opened' : 'codicon-go-to-file',
354
+ label: ({ multiFileAction, workspaceTargetKind }) =>
355
+ workspaceTargetKind === 'folder'
356
+ ? 'Reveal folder'
357
+ : multiFileAction
358
+ ? 'Open selected files'
359
+ : 'Open file',
360
+ run: ({ openWorkspaceTarget }) => openWorkspaceTarget(),
361
+ when: 'workspace.hasSelection',
362
+ },
363
+ {
364
+ id: WORKBENCH_WORKSPACE_COPY_PATH_COMMAND_ID,
365
+ icon: 'codicon-copy',
366
+ label: ({ targetPaths }) => (targetPaths.length > 1 ? 'Copy paths' : 'Copy path'),
367
+ run: ({ copyWorkspaceTarget }) => copyWorkspaceTarget(),
368
+ when: 'workspace.hasSelection',
369
+ },
370
+ {
371
+ id: WORKBENCH_WORKSPACE_RENAME_COMMAND_ID,
372
+ icon: 'codicon-edit',
373
+ isEnabled: ({ targetPaths }) => targetPaths.length === 1,
374
+ label: 'Rename',
375
+ run: ({ renameWorkspaceTarget }) => renameWorkspaceTarget(),
376
+ shortcut: 'F2',
377
+ when: 'workspace.hasSelection && !workspace.multiSelection',
378
+ },
379
+ {
380
+ id: WORKBENCH_WORKSPACE_DELETE_COMMAND_ID,
381
+ danger: true,
382
+ icon: 'codicon-trash',
383
+ isEnabled: ({ fileActionPaths, workspaceTargetKind }) =>
384
+ workspaceTargetKind === 'folder' || fileActionPaths.length > 0,
385
+ label: ({ fileActionPaths, multiFileAction, workspaceTargetKind }) =>
386
+ workspaceTargetKind === 'folder'
387
+ ? 'Delete folder'
388
+ : multiFileAction
389
+ ? `Delete ${fileActionPaths.length} files`
390
+ : 'Delete',
391
+ run: ({ deleteWorkspaceTarget }) => deleteWorkspaceTarget(),
392
+ shortcut: 'Del',
393
+ when: 'workspace.hasSelection',
394
+ },
395
+ ];
396
+
397
+ return applyWorkbenchCommandOverrides(commands, { commandOverrides });
398
+ }
399
+
400
+ export function createWorkbenchWorkspaceCreateMenuEntries<
401
+ TContext extends WorkbenchWorkspaceCommandContext = WorkbenchWorkspaceCommandContext,
402
+ >(): CommandMenuEntry<TContext>[] {
403
+ return commandMenuEntries<TContext>(
404
+ WORKBENCH_WORKSPACE_NEW_FILE_COMMAND_ID,
405
+ WORKBENCH_WORKSPACE_NEW_FOLDER_COMMAND_ID,
406
+ ).map((entry) => ({ ...entry, surfaces: [WORKBENCH_COMMAND_SURFACE_WORKSPACE] }));
407
+ }
408
+
409
+ export function createWorkbenchWorkspaceTargetMenuEntries<
410
+ TContext extends WorkbenchWorkspaceCommandContext = WorkbenchWorkspaceCommandContext,
411
+ >(): CommandMenuEntry<TContext>[] {
412
+ return [
413
+ ...commandMenuEntries<TContext>(
414
+ WORKBENCH_WORKSPACE_OPEN_COMMAND_ID,
415
+ WORKBENCH_WORKSPACE_COPY_PATH_COMMAND_ID,
416
+ ).map((entry) => ({ ...entry, surfaces: [WORKBENCH_COMMAND_SURFACE_WORKSPACE] })),
417
+ commandMenuSeparator('workspace-separator'),
418
+ ...commandMenuEntries<TContext>(
419
+ WORKBENCH_WORKSPACE_RENAME_COMMAND_ID,
420
+ WORKBENCH_WORKSPACE_DELETE_COMMAND_ID,
421
+ ).map((entry) => ({ ...entry, surfaces: [WORKBENCH_COMMAND_SURFACE_WORKSPACE] })),
422
+ ];
423
+ }
424
+
425
+ export function createWorkbenchWorkspaceFolderMenuEntries<
426
+ TContext extends WorkbenchWorkspaceCommandContext = WorkbenchWorkspaceCommandContext,
427
+ >(): CommandMenuEntry<TContext>[] {
428
+ return [
429
+ ...createWorkbenchWorkspaceCreateMenuEntries(),
430
+ commandMenuSeparator('workspace-create-separator'),
431
+ ...createWorkbenchWorkspaceTargetMenuEntries(),
432
+ ];
433
+ }
434
+
435
+ export function createWorkbenchSearchResultCommands<
436
+ TContext extends WorkbenchSearchResultCommandContext = WorkbenchSearchResultCommandContext,
437
+ >({
438
+ commandOverrides,
439
+ }: WorkbenchCommandPresetOptions<TContext> = {}): CommandDefinition<TContext>[] {
440
+ const commands: CommandDefinition<TContext>[] = [
441
+ {
442
+ id: WORKBENCH_SEARCH_OPEN_RESULT_COMMAND_ID,
443
+ icon: 'codicon-folder-opened',
444
+ label: 'Open',
445
+ run: ({ openResult }) => openResult(),
446
+ shortcut: 'Enter',
447
+ },
448
+ {
449
+ id: WORKBENCH_SEARCH_COPY_RESULT_PATH_COMMAND_ID,
450
+ icon: 'codicon-copy',
451
+ label: 'Copy path',
452
+ run: ({ copyPath }) => copyPath(),
453
+ },
454
+ {
455
+ id: WORKBENCH_SEARCH_DELETE_RESULT_COMMAND_ID,
456
+ danger: true,
457
+ icon: 'codicon-trash',
458
+ label: 'Delete',
459
+ run: ({ deleteResult }) => deleteResult(),
460
+ },
461
+ ];
462
+
463
+ return applyWorkbenchCommandOverrides(commands, { commandOverrides });
464
+ }
465
+
466
+ export function createWorkbenchSearchResultMenuEntries<
467
+ TContext extends WorkbenchSearchResultCommandContext = WorkbenchSearchResultCommandContext,
468
+ >(): CommandMenuEntry<TContext>[] {
469
+ return [
470
+ ...commandMenuEntries<TContext>(
471
+ WORKBENCH_SEARCH_OPEN_RESULT_COMMAND_ID,
472
+ WORKBENCH_SEARCH_COPY_RESULT_PATH_COMMAND_ID,
473
+ ).map((entry) => ({ ...entry, surfaces: [WORKBENCH_COMMAND_SURFACE_SEARCH] })),
474
+ commandMenuSeparator('result-menu-separator'),
475
+ commandMenuEntry<TContext>(WORKBENCH_SEARCH_DELETE_RESULT_COMMAND_ID, {
476
+ surfaces: [WORKBENCH_COMMAND_SURFACE_SEARCH],
477
+ }),
478
+ ];
479
+ }
480
+
481
+ export function resolveWorkbenchCommandMenuItems<TContext>({
482
+ registry,
483
+ entries,
484
+ context,
485
+ surface,
486
+ contextKeys,
487
+ }: {
488
+ registry: CommandRegistry<TContext>;
489
+ entries: CommandMenuEntry<TContext>[];
490
+ context: TContext;
491
+ surface?: string;
492
+ contextKeys?: object;
493
+ }): CommandMenuItem[] {
494
+ return resolveCommandMenuItems({
495
+ context,
496
+ contextKeys,
497
+ entries,
498
+ registry,
499
+ surface,
500
+ });
501
+ }
502
+
503
+ export function commandMenuItemsToContextMenuItems(
504
+ items: CommandMenuItem[],
505
+ onSelectCommand: (commandId: string) => void,
506
+ ): ContextMenuItem[] {
507
+ return items.map((item) =>
508
+ item.type === 'separator'
509
+ ? { id: item.id, type: 'separator' }
510
+ : {
511
+ id: item.id,
512
+ label: item.label,
513
+ icon: item.icon,
514
+ shortcut: item.shortcut,
515
+ disabled: item.disabled,
516
+ danger: item.danger,
517
+ onSelect: () => onSelectCommand(item.commandId),
518
+ },
519
+ );
520
+ }