@workbench-kit/shell-react 0.0.2-prototype.0.2.10

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 (105) hide show
  1. package/README.md +98 -0
  2. package/package.json +51 -0
  3. package/src/chat/ai-mock-proposals.ts +39 -0
  4. package/src/chat/command-input.ts +52 -0
  5. package/src/chat/command-policy.ts +54 -0
  6. package/src/chat/command-surface.tsx +155 -0
  7. package/src/chat/use-chat-command-proposals.ts +194 -0
  8. package/src/chat/view-data.ts +20 -0
  9. package/src/chat/view.tsx +220 -0
  10. package/src/commands/inspector-surface.tsx +46 -0
  11. package/src/commands/use-command-descriptors.ts +41 -0
  12. package/src/commands/use-context-key-revision.ts +18 -0
  13. package/src/commands/view-data.ts +17 -0
  14. package/src/commands/view.tsx +43 -0
  15. package/src/devtools/WorkbenchDevtoolsPanel.tsx +124 -0
  16. package/src/devtools/WorkbenchDevtoolsShell.tsx +17 -0
  17. package/src/devtools/index.ts +11 -0
  18. package/src/devtools/use-workbench-devtools-snapshot.ts +84 -0
  19. package/src/devtools/workbench-devtools-snapshot.ts +140 -0
  20. package/src/devtools/workbench-devtools.css +82 -0
  21. package/src/editor/area-dnd.ts +69 -0
  22. package/src/editor/area-model.ts +71 -0
  23. package/src/editor/area.css +454 -0
  24. package/src/editor/area.tsx +676 -0
  25. package/src/editor/host-surface.tsx +691 -0
  26. package/src/editor/markdown-document-view-data.ts +16 -0
  27. package/src/editor/pane-visibility.ts +130 -0
  28. package/src/editor/resource.ts +36 -0
  29. package/src/editor/state-storage.ts +182 -0
  30. package/src/editor/tab-context-menu.ts +118 -0
  31. package/src/editor/use-editor.ts +138 -0
  32. package/src/editor/view-providers.tsx +504 -0
  33. package/src/editor/workspace-file-availability.ts +15 -0
  34. package/src/editor/workspace-reconcile.tsx +31 -0
  35. package/src/explorer/context-menu.ts +114 -0
  36. package/src/explorer/create-command-workspace-explorer-port.ts +86 -0
  37. package/src/explorer/reveal.ts +112 -0
  38. package/src/explorer/search-view-data.ts +15 -0
  39. package/src/explorer/search-view.tsx +65 -0
  40. package/src/explorer/use-active-workspace-path.ts +15 -0
  41. package/src/explorer/view-data.ts +58 -0
  42. package/src/explorer/view.tsx +227 -0
  43. package/src/extensions/context-menu.ts +52 -0
  44. package/src/extensions/management-model.ts +313 -0
  45. package/src/extensions/use-extension-management.ts +241 -0
  46. package/src/extensions/view-data.ts +19 -0
  47. package/src/extensions/view.tsx +63 -0
  48. package/src/field-remap/chrome-labels.ts +74 -0
  49. package/src/field-remap/convert-note-editor.tsx +206 -0
  50. package/src/field-remap/convert-palette.tsx +126 -0
  51. package/src/field-remap/demo.tsx +105 -0
  52. package/src/field-remap/detail-panel.tsx +659 -0
  53. package/src/field-remap/editor-surface.tsx +36 -0
  54. package/src/field-remap/flow-adapter.ts +838 -0
  55. package/src/field-remap/flow-ops.ts +442 -0
  56. package/src/field-remap/flow.tsx +948 -0
  57. package/src/field-remap/graph.tsx +559 -0
  58. package/src/field-remap/index.ts +88 -0
  59. package/src/field-remap/io-class-browse.tsx +145 -0
  60. package/src/field-remap/jsonata-transform.ts +166 -0
  61. package/src/field-remap/panel.tsx +466 -0
  62. package/src/field-remap/samples.ts +507 -0
  63. package/src/field-remap/shape-io-editor.tsx +170 -0
  64. package/src/field-remap/table-mapping-adapter.ts +59 -0
  65. package/src/field-remap/transform-options-editor.tsx +312 -0
  66. package/src/field-remap/tree.tsx +404 -0
  67. package/src/field-remap/view-data.ts +16 -0
  68. package/src/field-remap/view.css +1367 -0
  69. package/src/field-remap/view.tsx +86 -0
  70. package/src/index.ts +294 -0
  71. package/src/jdw/document-view-data.ts +31 -0
  72. package/src/jdw/json-form-source-patch.ts +323 -0
  73. package/src/jdw/lab-view-data.ts +25 -0
  74. package/src/jdw/lab-view.css +21 -0
  75. package/src/jdw/lab-view.tsx +79 -0
  76. package/src/jdw/widget-form-view.tsx +68 -0
  77. package/src/jdw/widget-preview-view.tsx +54 -0
  78. package/src/management/keybinding-overrides-storage.ts +49 -0
  79. package/src/management/keybinding-settings.tsx +16 -0
  80. package/src/management/palette-commands.ts +38 -0
  81. package/src/management/preference-settings-storage.ts +50 -0
  82. package/src/management/settings-ids.ts +12 -0
  83. package/src/management/settings.tsx +96 -0
  84. package/src/management/use-command-management.ts +191 -0
  85. package/src/management/use-keybinding-management.ts +130 -0
  86. package/src/shell/model.tsx +149 -0
  87. package/src/shell/provider.tsx +606 -0
  88. package/src/shell/secondary-actions.tsx +59 -0
  89. package/src/shell/settings-constants.ts +9 -0
  90. package/src/shell/settings.tsx +599 -0
  91. package/src/shell/shell.tsx +680 -0
  92. package/src/shell/titlebar-layout-controls.tsx +4 -0
  93. package/src/shell/view-host.tsx +212 -0
  94. package/src/workbench/appearance-storage.ts +107 -0
  95. package/src/workbench/command-host.tsx +243 -0
  96. package/src/workbench/command-palette.ts +208 -0
  97. package/src/workbench/keybinding-bridge.ts +54 -0
  98. package/src/workbench/layout-storage.ts +134 -0
  99. package/src/workbench/profile-modal.tsx +118 -0
  100. package/src/workbench/shell-command-registration.ts +58 -0
  101. package/src/workbench/startup-gate.tsx +136 -0
  102. package/src/workbench/status-sections.ts +43 -0
  103. package/src/workbench/use-persisted-appearance.ts +33 -0
  104. package/src/workbench/user-commands.ts +46 -0
  105. package/src/workbench/workspace-view-state.ts +35 -0
@@ -0,0 +1,606 @@
1
+ import {
2
+ createContext,
3
+ useCallback,
4
+ useContext,
5
+ useEffect,
6
+ useMemo,
7
+ useRef,
8
+ useState,
9
+ type ReactNode,
10
+ } from 'react';
11
+ import {
12
+ BUILTIN_WORKBENCH_EXTENSIONS,
13
+ collectConfigurationDefaults,
14
+ createEditorService,
15
+ ExtensionRegistry,
16
+ LayoutService,
17
+ loadInstalledExtensions,
18
+ mergeExtensionsConfigWithInstallState,
19
+ PreferenceService,
20
+ registerEditorSaveCommand,
21
+ registerHostWorkbenchThemes,
22
+ resolveInstalledAvailableExtensions,
23
+ resolveWorkbenchExtensions,
24
+ SAMPLE_WORKBENCH_EXTENSIONS,
25
+ DEFAULT_INSTALLED_EXTENSIONS_STORAGE_KEY,
26
+ WORKBENCH_EDITOR_SERVICE_CAPABILITY_ID,
27
+ verifyWorkbenchExtensionsAgainstLock,
28
+ type EditorState,
29
+ type EditorService,
30
+ type ExtensionIntegrityMode,
31
+ type PreferenceService as PreferenceServiceType,
32
+ type WorkbenchHostThemeRegistration,
33
+ type WorkbenchStorageAdapter,
34
+ type WorkbenchEditorSavePort,
35
+ type WorkbenchExtensionDescription,
36
+ type WorkbenchLayoutStateInput,
37
+ } from '@workbench-kit/workbench-core';
38
+ import {
39
+ ContextKeyService,
40
+ createWorkbenchPermissionContextKeys,
41
+ type ContextKeyValue,
42
+ } from '@workbench-kit/platform';
43
+ import type {
44
+ WorkbenchExtensionsConfig,
45
+ WorkbenchExtensionsLock,
46
+ WorkbenchKeybindingDefinition,
47
+ WorkbenchSettingsConfig,
48
+ WorkbenchUserCommandDefinition,
49
+ } from '@workbench-kit/workbench-config';
50
+ import {
51
+ DEFAULT_WORKBENCH_LAYOUT_STORAGE_KEY,
52
+ isWorkbenchLayoutPersistenceAvailable,
53
+ resolvePersistedWorkbenchLayout,
54
+ writePersistedWorkbenchLayout,
55
+ } from '../workbench/layout-storage.js';
56
+ import {
57
+ DEFAULT_WORKBENCH_EDITOR_STATE_STORAGE_KEY,
58
+ isWorkbenchEditorStatePersistenceAvailable,
59
+ readPersistedEditorState,
60
+ writePersistedEditorState,
61
+ } from '../editor/state-storage.js';
62
+ import {
63
+ DEFAULT_WORKBENCH_KEYBINDING_STORAGE_KEY,
64
+ isWorkbenchKeybindingPersistenceAvailable,
65
+ readPersistedKeybindingOverrides,
66
+ writePersistedKeybindingOverrides,
67
+ } from '../management/keybinding-overrides-storage.js';
68
+ import {
69
+ BUILTIN_EXPLORER_VIEW_CONTAINER_ID,
70
+ publishExplorerRevealRequest,
71
+ runExplorerHostCommandSideEffects,
72
+ } from '../explorer/reveal.js';
73
+ import {
74
+ BUILTIN_EXTENSIONS_FOCUS_COMMAND_ID,
75
+ BUILTIN_EXTENSIONS_VIEW_CONTAINER_ID,
76
+ } from '../extensions/view-data.js';
77
+ import {
78
+ DEFAULT_WORKBENCH_LOCAL_PREFERENCE_STORAGE_KEY,
79
+ isWorkbenchLocalPreferencePersistenceAvailable,
80
+ readPersistedLocalPreferences,
81
+ writePersistedLocalPreferences,
82
+ } from '../management/preference-settings-storage.js';
83
+ import { registerWorkbenchUserCommands } from '../workbench/user-commands.js';
84
+ import { EditorWorkspaceReconciler } from '../editor/workspace-reconcile.js';
85
+ import {
86
+ DEFAULT_EDITOR_DOCUMENT_VIEW_PROVIDERS,
87
+ type EditorDocumentViewProvider,
88
+ } from '../editor/view-providers.js';
89
+ import type { EditorDocumentViewProviderRegistry } from '@workbench-kit/workbench-core';
90
+
91
+ export interface WorkbenchWorkspaceHostPort extends WorkbenchEditorSavePort {
92
+ readonly capabilityId?: string | undefined;
93
+ readonly service?: unknown;
94
+ dispose?(): void;
95
+ }
96
+
97
+ export type { WorkbenchStorageAdapter };
98
+
99
+ const DEFAULT_AVAILABLE_EXTENSIONS = [
100
+ ...BUILTIN_WORKBENCH_EXTENSIONS,
101
+ ...SAMPLE_WORKBENCH_EXTENSIONS,
102
+ ] as const;
103
+
104
+ export interface WorkbenchProviderProps {
105
+ availableExtensions?: readonly WorkbenchExtensionDescription[];
106
+ children: ReactNode;
107
+ contextKeyValues?: Readonly<Record<string, ContextKeyValue>> | undefined;
108
+ documentViewProviders?: readonly EditorDocumentViewProvider[] | undefined;
109
+ /**
110
+ * When set with `extensionIntegrityMode` other than `off`, enabled extensions
111
+ * are checked against the lock before registration.
112
+ */
113
+ extensionsLock?: WorkbenchExtensionsLock | undefined;
114
+ /**
115
+ * Lock verification mode. Default `off` preserves existing hosts.
116
+ * Sample hosts may opt into `fail-closed`.
117
+ */
118
+ extensionIntegrityMode?: ExtensionIntegrityMode | undefined;
119
+ extensionsConfig?: WorkbenchExtensionsConfig;
120
+ editorStateStorage?: WorkbenchStorageAdapter;
121
+ editorStateStorageKey?: string;
122
+ hostThemes?: readonly WorkbenchHostThemeRegistration[];
123
+ initialKeybindingOverrides?: readonly WorkbenchKeybindingDefinition[];
124
+ initialEditorState?: EditorState;
125
+ initialLayout?: WorkbenchLayoutStateInput;
126
+ initialWorkspaceSettings?: WorkbenchSettingsConfig;
127
+ includeDefaultDocumentViewProviders?: boolean | undefined;
128
+ installedExtensionsStorage?: WorkbenchStorageAdapter;
129
+ installedExtensionsStorageKey?: string;
130
+ keybindingOverridesStorage?: WorkbenchStorageAdapter;
131
+ keybindingOverridesStorageKey?: string;
132
+ layoutStorage?: WorkbenchStorageAdapter;
133
+ layoutStorageKey?: string;
134
+ localPreferenceStorage?: WorkbenchStorageAdapter;
135
+ localPreferenceStorageKey?: string;
136
+ onKeybindingOverridesChange?:
137
+ ((overrides: readonly WorkbenchKeybindingDefinition[]) => void) | undefined;
138
+ persistEditorState?: boolean;
139
+ persistKeybindingOverrides?: boolean;
140
+ persistLayout?: boolean;
141
+ persistLocalPreferences?: boolean;
142
+ userCommands?: readonly WorkbenchUserCommandDefinition[];
143
+ workspaceHostPort?: WorkbenchWorkspaceHostPort | undefined;
144
+ }
145
+
146
+ export interface WorkbenchContextValue {
147
+ activateCommand(commandId: string): Promise<readonly { readonly extensionId: string }[]>;
148
+ contextKeyService: ContextKeyService;
149
+ editorDocumentViewProviders: EditorDocumentViewProviderRegistry;
150
+ editorService: EditorService;
151
+ executeCommand(commandId: string, ...args: unknown[]): Promise<unknown>;
152
+ extensionRegistry: ExtensionRegistry;
153
+ installedExtensionsStorage?: WorkbenchStorageAdapter;
154
+ installedExtensionsStorageKey: string;
155
+ keybindingOverrides: readonly WorkbenchKeybindingDefinition[];
156
+ layoutService: LayoutService;
157
+ missingExtensionIds: readonly string[];
158
+ preferenceService: PreferenceServiceType;
159
+ resetCommandKeybindingOverride(commandId: string): void;
160
+ setCommandKeybindingOverride(commandId: string, key: string): void;
161
+ waitForExtensionStartup(): Promise<void>;
162
+ workspaceHostPort?: WorkbenchWorkspaceHostPort | undefined;
163
+ }
164
+
165
+ interface WorkbenchProviderServices {
166
+ activateStartup(): void;
167
+ dispose(): void;
168
+ editorDocumentViewProviders: EditorDocumentViewProviderRegistry;
169
+ editorService: EditorService;
170
+ extensionRegistry: ExtensionRegistry;
171
+ layoutService: LayoutService;
172
+ missingExtensionIds: readonly string[];
173
+ preferenceService: PreferenceServiceType;
174
+ waitForExtensionStartup(): Promise<void>;
175
+ workspaceHostPort?: WorkbenchWorkspaceHostPort | undefined;
176
+ }
177
+
178
+ interface DeferredProviderDispose {
179
+ readonly services: WorkbenchProviderServices;
180
+ readonly timeout: ReturnType<typeof setTimeout>;
181
+ }
182
+
183
+ const WorkbenchContext = createContext<WorkbenchContextValue | undefined>(undefined);
184
+
185
+ export function WorkbenchProvider({
186
+ availableExtensions,
187
+ children,
188
+ contextKeyValues,
189
+ documentViewProviders,
190
+ editorStateStorage,
191
+ editorStateStorageKey = DEFAULT_WORKBENCH_EDITOR_STATE_STORAGE_KEY,
192
+ extensionIntegrityMode = 'off',
193
+ extensionsConfig,
194
+ extensionsLock,
195
+ hostThemes = [],
196
+ initialEditorState,
197
+ initialKeybindingOverrides,
198
+ initialLayout,
199
+ initialWorkspaceSettings,
200
+ includeDefaultDocumentViewProviders,
201
+ installedExtensionsStorage,
202
+ installedExtensionsStorageKey = DEFAULT_INSTALLED_EXTENSIONS_STORAGE_KEY,
203
+ keybindingOverridesStorage,
204
+ keybindingOverridesStorageKey = DEFAULT_WORKBENCH_KEYBINDING_STORAGE_KEY,
205
+ layoutStorage,
206
+ layoutStorageKey = DEFAULT_WORKBENCH_LAYOUT_STORAGE_KEY,
207
+ localPreferenceStorage,
208
+ localPreferenceStorageKey = DEFAULT_WORKBENCH_LOCAL_PREFERENCE_STORAGE_KEY,
209
+ onKeybindingOverridesChange,
210
+ persistEditorState,
211
+ persistKeybindingOverrides,
212
+ persistLayout,
213
+ persistLocalPreferences,
214
+ userCommands = [],
215
+ workspaceHostPort,
216
+ }: WorkbenchProviderProps) {
217
+ const hostAvailableExtensions = availableExtensions ?? DEFAULT_AVAILABLE_EXTENSIONS;
218
+ const deferredDisposeRef = useRef<DeferredProviderDispose | undefined>(undefined);
219
+ const shouldPersistEditorState =
220
+ persistEditorState ??
221
+ (editorStateStorage !== undefined || isWorkbenchEditorStatePersistenceAvailable());
222
+ const shouldPersistKeybindingOverrides =
223
+ persistKeybindingOverrides ??
224
+ (keybindingOverridesStorage !== undefined || isWorkbenchKeybindingPersistenceAvailable());
225
+ const shouldPersistLayout =
226
+ persistLayout ?? (layoutStorage !== undefined || isWorkbenchLayoutPersistenceAvailable());
227
+ const shouldPersistLocalPreferences =
228
+ persistLocalPreferences ??
229
+ (localPreferenceStorage !== undefined || isWorkbenchLocalPreferencePersistenceAvailable());
230
+ const resolvedInitialLayout = useMemo(
231
+ () =>
232
+ resolvePersistedWorkbenchLayout(initialLayout, {
233
+ persistLayout: shouldPersistLayout,
234
+ storage: layoutStorage,
235
+ storageKey: layoutStorageKey,
236
+ }),
237
+ [initialLayout, layoutStorage, layoutStorageKey, shouldPersistLayout],
238
+ );
239
+ const resolvedInitialEditorState = useMemo(
240
+ () =>
241
+ initialEditorState ??
242
+ (shouldPersistEditorState
243
+ ? readPersistedEditorState(editorStateStorageKey, editorStateStorage)
244
+ : undefined),
245
+ [editorStateStorage, editorStateStorageKey, initialEditorState, shouldPersistEditorState],
246
+ );
247
+ const resolvedInitialKeybindingOverrides = useMemo(
248
+ () =>
249
+ initialKeybindingOverrides ??
250
+ (shouldPersistKeybindingOverrides
251
+ ? readPersistedKeybindingOverrides(
252
+ keybindingOverridesStorageKey,
253
+ keybindingOverridesStorage,
254
+ )
255
+ : []),
256
+ [
257
+ initialKeybindingOverrides,
258
+ keybindingOverridesStorage,
259
+ keybindingOverridesStorageKey,
260
+ shouldPersistKeybindingOverrides,
261
+ ],
262
+ );
263
+ const [keybindingOverrides, setKeybindingOverridesState] = useState(
264
+ resolvedInitialKeybindingOverrides,
265
+ );
266
+ const contextKeyService = useMemo(() => {
267
+ const service = new ContextKeyService();
268
+ for (const [key, value] of Object.entries(
269
+ createWorkbenchPermissionContextKeys({ role: 'owner' }),
270
+ )) {
271
+ service.set(key, value);
272
+ }
273
+ return service;
274
+ }, []);
275
+
276
+ useEffect(() => {
277
+ return () => {
278
+ contextKeyService.dispose();
279
+ };
280
+ }, [contextKeyService]);
281
+
282
+ useEffect(() => {
283
+ if (contextKeyValues === undefined) {
284
+ return;
285
+ }
286
+
287
+ for (const [key, value] of Object.entries(contextKeyValues)) {
288
+ contextKeyService.set(key, value);
289
+ }
290
+ }, [contextKeyService, contextKeyValues]);
291
+
292
+ useEffect(() => {
293
+ setKeybindingOverridesState(resolvedInitialKeybindingOverrides);
294
+ }, [resolvedInitialKeybindingOverrides]);
295
+
296
+ const setCommandKeybindingOverride = useCallback((commandId: string, key: string) => {
297
+ setKeybindingOverridesState((current) => {
298
+ const without = current.filter((binding) => binding.command !== commandId);
299
+ return [...without, { command: commandId, key }];
300
+ });
301
+ }, []);
302
+
303
+ const resetCommandKeybindingOverride = useCallback((commandId: string) => {
304
+ setKeybindingOverridesState((current) =>
305
+ current.filter((binding) => binding.command !== commandId),
306
+ );
307
+ }, []);
308
+
309
+ useEffect(() => {
310
+ onKeybindingOverridesChange?.(keybindingOverrides);
311
+ if (!shouldPersistKeybindingOverrides) {
312
+ return;
313
+ }
314
+
315
+ writePersistedKeybindingOverrides(
316
+ keybindingOverrides,
317
+ keybindingOverridesStorageKey,
318
+ keybindingOverridesStorage,
319
+ );
320
+ }, [
321
+ keybindingOverrides,
322
+ keybindingOverridesStorage,
323
+ keybindingOverridesStorageKey,
324
+ onKeybindingOverridesChange,
325
+ shouldPersistKeybindingOverrides,
326
+ ]);
327
+
328
+ const resolvedInitialLocalPreferences = useMemo(
329
+ () =>
330
+ shouldPersistLocalPreferences
331
+ ? readPersistedLocalPreferences(localPreferenceStorageKey, localPreferenceStorage)
332
+ : {},
333
+ [localPreferenceStorage, localPreferenceStorageKey, shouldPersistLocalPreferences],
334
+ );
335
+
336
+ const services = useMemo<WorkbenchProviderServices>(() => {
337
+ const extensionRegistry = new ExtensionRegistry();
338
+ const editorDocumentViewProviders = extensionRegistry.editorDocumentViews;
339
+ const editorDocumentViewProviderDisposables = [
340
+ ...(includeDefaultDocumentViewProviders === false
341
+ ? []
342
+ : DEFAULT_EDITOR_DOCUMENT_VIEW_PROVIDERS),
343
+ ...(documentViewProviders ?? []),
344
+ ].map((provider) => editorDocumentViewProviders.registerProvider(provider));
345
+ const layoutService = new LayoutService(resolvedInitialLayout);
346
+ const editorService = createEditorService({
347
+ editorHostFactories: extensionRegistry.editorHostFactories,
348
+ editorResolvers: extensionRegistry.editorResolvers,
349
+ initialState: resolvedInitialEditorState,
350
+ resolveEditorResource: workspaceHostPort?.resolveResource?.bind(workspaceHostPort),
351
+ });
352
+ const installedRecords = loadInstalledExtensions(
353
+ installedExtensionsStorageKey,
354
+ installedExtensionsStorage,
355
+ );
356
+ const baseExtensionsConfig =
357
+ extensionsConfig ??
358
+ ({
359
+ enabled: hostAvailableExtensions.map(({ manifest }) => manifest.id),
360
+ recommendations: [],
361
+ } satisfies WorkbenchExtensionsConfig);
362
+ const resolvedAvailableExtensions =
363
+ availableExtensions === undefined
364
+ ? resolveInstalledAvailableExtensions(
365
+ hostAvailableExtensions,
366
+ installedRecords,
367
+ baseExtensionsConfig.enabled,
368
+ )
369
+ : hostAvailableExtensions;
370
+ const config = mergeExtensionsConfigWithInstallState(baseExtensionsConfig, installedRecords);
371
+ const resolution = resolveWorkbenchExtensions(config, resolvedAvailableExtensions);
372
+ const integrity = verifyWorkbenchExtensionsAgainstLock(
373
+ resolution.enabledExtensions,
374
+ extensionsLock,
375
+ extensionIntegrityMode,
376
+ );
377
+ if (integrity.diagnostics.length > 0 && typeof console !== 'undefined') {
378
+ for (const diagnostic of integrity.diagnostics) {
379
+ console.warn(`[workbench-kit] ${diagnostic.message}`);
380
+ }
381
+ }
382
+ const extensionDisposables = extensionRegistry.registerExtensions(integrity.accepted);
383
+ const hostThemeDisposables = registerHostWorkbenchThemes(extensionRegistry.themes, hostThemes);
384
+ const editorServiceCapabilityDisposable = extensionRegistry.capabilityRegistry.register({
385
+ id: WORKBENCH_EDITOR_SERVICE_CAPABILITY_ID,
386
+ get: () => editorService,
387
+ });
388
+ const workspaceHostCapabilityDisposable =
389
+ workspaceHostPort?.capabilityId && workspaceHostPort.service !== undefined
390
+ ? extensionRegistry.capabilityRegistry.register({
391
+ id: workspaceHostPort.capabilityId,
392
+ get: () => workspaceHostPort.service,
393
+ dispose: workspaceHostPort.dispose,
394
+ })
395
+ : undefined;
396
+ const saveCommandDisposable = workspaceHostPort
397
+ ? registerEditorSaveCommand(extensionRegistry.commands, {
398
+ editorSavePort: workspaceHostPort,
399
+ editorService,
400
+ })
401
+ : undefined;
402
+ const userCommandDisposables = registerWorkbenchUserCommands(extensionRegistry, userCommands);
403
+ const preferenceService = new PreferenceService({
404
+ contributionDefaults: collectConfigurationDefaults(
405
+ extensionRegistry.configurations.getConfigurations(),
406
+ ),
407
+ initialValuesByScope: {
408
+ local: resolvedInitialLocalPreferences,
409
+ workspace: initialWorkspaceSettings ?? {},
410
+ },
411
+ });
412
+ let startupActivation: Promise<readonly { readonly extensionId: string }[]> | undefined;
413
+ const ensureStartupActivation = () => {
414
+ startupActivation ??= extensionRegistry.activateStartup();
415
+ return startupActivation;
416
+ };
417
+
418
+ return {
419
+ activateStartup: () => {
420
+ void ensureStartupActivation();
421
+ },
422
+ dispose: () => {
423
+ saveCommandDisposable?.dispose();
424
+ userCommandDisposables.dispose();
425
+ editorServiceCapabilityDisposable.dispose();
426
+ workspaceHostCapabilityDisposable?.dispose();
427
+ hostThemeDisposables.dispose();
428
+ extensionDisposables.dispose();
429
+ if (!workspaceHostCapabilityDisposable) {
430
+ workspaceHostPort?.dispose?.();
431
+ }
432
+ editorService.dispose();
433
+ for (const disposable of editorDocumentViewProviderDisposables) {
434
+ disposable.dispose();
435
+ }
436
+ extensionRegistry.dispose();
437
+ layoutService.dispose();
438
+ preferenceService.dispose();
439
+ },
440
+ editorDocumentViewProviders,
441
+ editorService,
442
+ extensionRegistry,
443
+ layoutService,
444
+ missingExtensionIds: [
445
+ ...resolution.missingExtensionIds,
446
+ ...integrity.rejected.map((extension) => extension.manifest.id),
447
+ ],
448
+ preferenceService,
449
+ waitForExtensionStartup: () => ensureStartupActivation().then(() => undefined),
450
+ workspaceHostPort,
451
+ };
452
+ }, [
453
+ availableExtensions,
454
+ documentViewProviders,
455
+ extensionIntegrityMode,
456
+ extensionsLock,
457
+ hostAvailableExtensions,
458
+ extensionsConfig,
459
+ hostThemes,
460
+ includeDefaultDocumentViewProviders,
461
+ initialWorkspaceSettings,
462
+ installedExtensionsStorage,
463
+ installedExtensionsStorageKey,
464
+ resolvedInitialEditorState,
465
+ resolvedInitialLayout,
466
+ resolvedInitialLocalPreferences,
467
+ userCommands,
468
+ workspaceHostPort,
469
+ ]);
470
+
471
+ useEffect(() => {
472
+ if (!shouldPersistLayout) {
473
+ return undefined;
474
+ }
475
+
476
+ const disposable = services.layoutService.onDidChangeLayout(({ state }) => {
477
+ writePersistedWorkbenchLayout(state, layoutStorageKey, layoutStorage);
478
+ });
479
+
480
+ return () => {
481
+ disposable.dispose();
482
+ };
483
+ }, [layoutStorage, layoutStorageKey, services.layoutService, shouldPersistLayout]);
484
+
485
+ useEffect(() => {
486
+ if (!shouldPersistEditorState) {
487
+ return undefined;
488
+ }
489
+
490
+ const disposable = services.editorService.onDidChangeEditors(({ state }) => {
491
+ writePersistedEditorState(state, editorStateStorageKey, editorStateStorage);
492
+ });
493
+
494
+ return () => {
495
+ disposable.dispose();
496
+ };
497
+ }, [editorStateStorage, editorStateStorageKey, services.editorService, shouldPersistEditorState]);
498
+
499
+ useEffect(() => {
500
+ if (!shouldPersistLocalPreferences) {
501
+ return undefined;
502
+ }
503
+
504
+ const disposable = services.preferenceService.onDidChangePreference((event) => {
505
+ if (event.scope !== 'local') {
506
+ return;
507
+ }
508
+
509
+ writePersistedLocalPreferences(
510
+ services.preferenceService.getScopedValues('local'),
511
+ localPreferenceStorageKey,
512
+ localPreferenceStorage,
513
+ );
514
+ });
515
+
516
+ return () => {
517
+ disposable.dispose();
518
+ };
519
+ }, [
520
+ localPreferenceStorage,
521
+ localPreferenceStorageKey,
522
+ services.preferenceService,
523
+ shouldPersistLocalPreferences,
524
+ ]);
525
+
526
+ useEffect(() => {
527
+ const deferredDispose = deferredDisposeRef.current;
528
+ if (deferredDispose?.services === services) {
529
+ clearTimeout(deferredDispose.timeout);
530
+ deferredDisposeRef.current = undefined;
531
+ }
532
+
533
+ services.activateStartup();
534
+
535
+ return () => {
536
+ const timeout = setTimeout(() => {
537
+ if (deferredDisposeRef.current?.services === services) {
538
+ deferredDisposeRef.current = undefined;
539
+ }
540
+ services.dispose();
541
+ }, 0);
542
+
543
+ deferredDisposeRef.current = { services, timeout };
544
+ };
545
+ }, [services]);
546
+
547
+ const value = useMemo<WorkbenchContextValue>(
548
+ () => ({
549
+ activateCommand: (commandId) => services.extensionRegistry.activateCommand(commandId),
550
+ contextKeyService,
551
+ editorDocumentViewProviders: services.editorDocumentViewProviders,
552
+ editorService: services.editorService,
553
+ executeCommand: async (commandId, ...args) => {
554
+ const result = await services.extensionRegistry.executeCommand(commandId, ...args);
555
+ await runExplorerHostCommandSideEffects(commandId, args, result, {
556
+ focusExplorerView: () => {
557
+ services.layoutService.setActiveViewContainer(BUILTIN_EXPLORER_VIEW_CONTAINER_ID);
558
+ services.layoutService.setSideBarVisible(true);
559
+ },
560
+ revealPath: publishExplorerRevealRequest,
561
+ });
562
+ if (commandId === BUILTIN_EXTENSIONS_FOCUS_COMMAND_ID) {
563
+ services.layoutService.setActiveViewContainer(BUILTIN_EXTENSIONS_VIEW_CONTAINER_ID);
564
+ services.layoutService.setSideBarVisible(true);
565
+ }
566
+ return result;
567
+ },
568
+ extensionRegistry: services.extensionRegistry,
569
+ installedExtensionsStorage,
570
+ installedExtensionsStorageKey,
571
+ keybindingOverrides,
572
+ layoutService: services.layoutService,
573
+ missingExtensionIds: services.missingExtensionIds,
574
+ preferenceService: services.preferenceService,
575
+ resetCommandKeybindingOverride,
576
+ setCommandKeybindingOverride,
577
+ waitForExtensionStartup: services.waitForExtensionStartup,
578
+ workspaceHostPort: services.workspaceHostPort,
579
+ }),
580
+ [
581
+ contextKeyService,
582
+ installedExtensionsStorage,
583
+ installedExtensionsStorageKey,
584
+ keybindingOverrides,
585
+ resetCommandKeybindingOverride,
586
+ services,
587
+ setCommandKeybindingOverride,
588
+ ],
589
+ );
590
+
591
+ return (
592
+ <WorkbenchContext.Provider value={value}>
593
+ <EditorWorkspaceReconciler />
594
+ {children}
595
+ </WorkbenchContext.Provider>
596
+ );
597
+ }
598
+
599
+ export function useWorkbench(): WorkbenchContextValue {
600
+ const value = useContext(WorkbenchContext);
601
+ if (!value) {
602
+ throw new Error('useWorkbench must be used inside WorkbenchProvider.');
603
+ }
604
+
605
+ return value;
606
+ }
@@ -0,0 +1,59 @@
1
+ import type { ActivityBarItem } from '@workbench-kit/react/workbench/shell';
2
+
3
+ export const WORKBENCH_PROFILE_ACTIVITY_ITEM_ID = 'workbench-kit.shell.profile' as const;
4
+ export const WORKBENCH_ACCOUNT_ACTIVITY_ITEM_ID = WORKBENCH_PROFILE_ACTIVITY_ITEM_ID;
5
+ export const WORKBENCH_SETTINGS_ACTIVITY_ITEM_ID = 'workbench-kit.shell.settings' as const;
6
+
7
+ export type WorkbenchSecondaryActivityRoute = 'profile' | 'settings';
8
+
9
+ export interface WorkbenchSecondaryActivityItemsInput {
10
+ hasProfile: boolean;
11
+ isProfileOpen: boolean;
12
+ isSettingsOpen: boolean;
13
+ showSettings?: boolean | undefined;
14
+ }
15
+
16
+ export function createWorkbenchSecondaryActivityItems({
17
+ hasProfile,
18
+ isProfileOpen,
19
+ isSettingsOpen,
20
+ showSettings = true,
21
+ }: WorkbenchSecondaryActivityItemsInput): ActivityBarItem[] {
22
+ return [
23
+ ...(hasProfile
24
+ ? [
25
+ {
26
+ active: isProfileOpen,
27
+ icon: <i aria-hidden="true" className="codicon codicon-account" />,
28
+ id: WORKBENCH_PROFILE_ACTIVITY_ITEM_ID,
29
+ label: 'Profile',
30
+ title: 'Open profile',
31
+ },
32
+ ]
33
+ : []),
34
+ ...(showSettings
35
+ ? [
36
+ {
37
+ active: isSettingsOpen,
38
+ icon: <i aria-hidden="true" className="codicon codicon-settings-gear" />,
39
+ id: WORKBENCH_SETTINGS_ACTIVITY_ITEM_ID,
40
+ label: 'Settings',
41
+ },
42
+ ]
43
+ : []),
44
+ ];
45
+ }
46
+
47
+ export function getWorkbenchSecondaryActivityRoute(
48
+ itemId: string,
49
+ ): WorkbenchSecondaryActivityRoute | undefined {
50
+ if (itemId === WORKBENCH_PROFILE_ACTIVITY_ITEM_ID) {
51
+ return 'profile';
52
+ }
53
+
54
+ if (itemId === WORKBENCH_SETTINGS_ACTIVITY_ITEM_ID) {
55
+ return 'settings';
56
+ }
57
+
58
+ return undefined;
59
+ }
@@ -0,0 +1,9 @@
1
+ import type { PreferenceScope } from '@workbench-kit/workbench-config';
2
+
3
+ export const SETTINGS_EXTENSION_ID = 'workbench-kit.builtin.settings';
4
+
5
+ export const WORKBENCH_PREFERENCE_SCOPES = [
6
+ { id: 'default', label: 'Default' },
7
+ { id: 'workspace', label: 'Workspace' },
8
+ { id: 'local', label: 'Local' },
9
+ ] as const satisfies ReadonlyArray<{ id: PreferenceScope; label: string }>;