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

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 (93) hide show
  1. package/package.json +49 -0
  2. package/src/chat-ai-mock-proposals.ts +39 -0
  3. package/src/chat-command-input.ts +52 -0
  4. package/src/chat-command-policy.ts +54 -0
  5. package/src/chat-command-surface.tsx +155 -0
  6. package/src/chat-view-data.ts +20 -0
  7. package/src/chat-view.tsx +220 -0
  8. package/src/command-inspector-surface.tsx +46 -0
  9. package/src/commands-view-data.ts +17 -0
  10. package/src/commands-view.tsx +43 -0
  11. package/src/createCommandWorkspaceExplorerPort.ts +86 -0
  12. package/src/devtools/WorkbenchDevtoolsPanel.tsx +124 -0
  13. package/src/devtools/WorkbenchDevtoolsShell.tsx +17 -0
  14. package/src/devtools/index.ts +11 -0
  15. package/src/devtools/use-workbench-devtools-snapshot.ts +84 -0
  16. package/src/devtools/workbench-devtools-snapshot.ts +140 -0
  17. package/src/devtools/workbench-devtools.css +82 -0
  18. package/src/editor-area-dnd.ts +69 -0
  19. package/src/editor-area-model.ts +71 -0
  20. package/src/editor-area.css +454 -0
  21. package/src/editor-area.tsx +676 -0
  22. package/src/editor-host-surface.tsx +634 -0
  23. package/src/editor-pane-visibility.ts +130 -0
  24. package/src/editor-resource.ts +36 -0
  25. package/src/editor-state-storage.ts +193 -0
  26. package/src/editor-tab-context-menu.ts +118 -0
  27. package/src/editor-view-providers.tsx +552 -0
  28. package/src/editor-workspace-file-availability.ts +15 -0
  29. package/src/editor-workspace-reconcile.tsx +28 -0
  30. package/src/explorer-context-menu.ts +114 -0
  31. package/src/explorer-reveal.ts +112 -0
  32. package/src/explorer-view-data.ts +58 -0
  33. package/src/explorer-view.tsx +224 -0
  34. package/src/extension-context-menu.ts +52 -0
  35. package/src/extension-management-model.ts +313 -0
  36. package/src/extensions-view-data.ts +19 -0
  37. package/src/extensions-view.tsx +38 -0
  38. package/src/field-remap-demo.tsx +18 -0
  39. package/src/field-remap-editor-surface.tsx +36 -0
  40. package/src/field-remap-flow-adapter.ts +240 -0
  41. package/src/field-remap-flow.tsx +369 -0
  42. package/src/field-remap-graph.tsx +559 -0
  43. package/src/field-remap-panel.tsx +175 -0
  44. package/src/field-remap-samples.ts +352 -0
  45. package/src/field-remap-tree.tsx +404 -0
  46. package/src/field-remap-view-data.ts +16 -0
  47. package/src/field-remap-view.css +676 -0
  48. package/src/field-remap-view.tsx +86 -0
  49. package/src/index.ts +199 -0
  50. package/src/jdw-lab-view-data.ts +25 -0
  51. package/src/jdw-lab-view.css +21 -0
  52. package/src/jdw-lab-view.tsx +79 -0
  53. package/src/jdw-widget-form-view.tsx +65 -0
  54. package/src/jdw-widget-preview-view.tsx +51 -0
  55. package/src/json-form-source-patch.ts +323 -0
  56. package/src/jsonata-transform.ts +36 -0
  57. package/src/keybinding-management-settings.tsx +16 -0
  58. package/src/keybinding-overrides-storage.ts +57 -0
  59. package/src/management-palette-commands.ts +38 -0
  60. package/src/management-settings-ids.ts +12 -0
  61. package/src/management-settings.tsx +75 -0
  62. package/src/preference-settings-storage.ts +58 -0
  63. package/src/provider.tsx +573 -0
  64. package/src/search-view-data.ts +15 -0
  65. package/src/search-view.tsx +62 -0
  66. package/src/shell-model.tsx +149 -0
  67. package/src/shell-secondary-actions.tsx +59 -0
  68. package/src/shell-settings-constants.ts +9 -0
  69. package/src/shell-settings.tsx +599 -0
  70. package/src/shell-titlebar-layout-controls.tsx +4 -0
  71. package/src/shell-view-host.tsx +199 -0
  72. package/src/shell.tsx +649 -0
  73. package/src/table-mapping-adapter.ts +59 -0
  74. package/src/use-active-workspace-path.ts +15 -0
  75. package/src/use-command-management.ts +191 -0
  76. package/src/use-context-key-revision.ts +18 -0
  77. package/src/use-editor.ts +107 -0
  78. package/src/use-extension-management.ts +193 -0
  79. package/src/use-keybinding-management.ts +130 -0
  80. package/src/use-persisted-workbench-appearance.ts +33 -0
  81. package/src/use-workbench-chat-command-proposals.ts +194 -0
  82. package/src/use-workbench-command-descriptors.ts +41 -0
  83. package/src/workbench-appearance-storage.ts +115 -0
  84. package/src/workbench-command-host.tsx +243 -0
  85. package/src/workbench-command-palette.ts +208 -0
  86. package/src/workbench-keybinding-bridge.ts +54 -0
  87. package/src/workbench-layout-storage.ts +145 -0
  88. package/src/workbench-profile-modal.tsx +118 -0
  89. package/src/workbench-shell-command-registration.ts +58 -0
  90. package/src/workbench-startup-gate.tsx +136 -0
  91. package/src/workbench-status-sections.ts +43 -0
  92. package/src/workbench-user-commands.ts +46 -0
  93. package/src/workspace-view-state.ts +35 -0
@@ -0,0 +1,43 @@
1
+ import {
2
+ CommandManagementSidebar,
3
+ buildCommandInspectorUri,
4
+ findCommandManagementEntry,
5
+ } from '@workbench-kit/react/workbench/management';
6
+
7
+ import {
8
+ BUILTIN_COMMANDS_VIEW_RENDER_KIND,
9
+ isBuiltinCommandsViewRenderData,
10
+ type BuiltinCommandsViewRenderData,
11
+ } from './commands-view-data.js';
12
+ import { useCommandManagementModel } from './use-command-management.js';
13
+ import { useEditorService } from './use-editor.js';
14
+
15
+ export type { BuiltinCommandsViewRenderData };
16
+ export { BUILTIN_COMMANDS_VIEW_RENDER_KIND, isBuiltinCommandsViewRenderData };
17
+
18
+ export function BuiltinCommandsView() {
19
+ const editorService = useEditorService();
20
+ const { groups, lastRun, refreshRegistry, runCommand } = useCommandManagementModel();
21
+
22
+ const inspectCommand = (commandId: string) => {
23
+ const entry = findCommandManagementEntry(groups, commandId);
24
+ editorService.openEditor({
25
+ icon: 'codicon-terminal',
26
+ pinned: true,
27
+ preview: false,
28
+ resourceUri: buildCommandInspectorUri(commandId),
29
+ title: entry?.label ?? commandId,
30
+ });
31
+ };
32
+
33
+ return (
34
+ <CommandManagementSidebar
35
+ className="workbench-commands-view"
36
+ groups={groups}
37
+ lastRun={lastRun}
38
+ onInspectCommand={inspectCommand}
39
+ onRefresh={refreshRegistry}
40
+ onRunCommand={runCommand}
41
+ />
42
+ );
43
+ }
@@ -0,0 +1,86 @@
1
+ import type {
2
+ WorkspaceExplorerControllerPort,
3
+ WorkspaceExplorerMutationResult,
4
+ WorkspaceExplorerWorkspaceSnapshot,
5
+ } from '@workbench-kit/react/workbench/workspace';
6
+ import type { VirtualWorkspaceState } from '@workbench-kit/workspace';
7
+
8
+ import { BUILTIN_EXPLORER_MOVE_COMMAND_ID } from './explorer-view-data.js';
9
+
10
+ const WORKBENCH_WORKSPACE_DELETE_COMMAND_ID = 'workspace.delete' as const;
11
+ const WORKBENCH_WORKSPACE_NEW_FILE_COMMAND_ID = 'workspace.newFile' as const;
12
+ const WORKBENCH_WORKSPACE_NEW_FOLDER_COMMAND_ID = 'workspace.newFolder' as const;
13
+ const WORKBENCH_WORKSPACE_OPEN_COMMAND_ID = 'workspace.open' as const;
14
+ const WORKBENCH_WORKSPACE_RENAME_COMMAND_ID = 'workspace.rename' as const;
15
+
16
+ interface WorkspaceCommandResult {
17
+ readonly path?: string | undefined;
18
+ readonly paths?: readonly string[] | undefined;
19
+ }
20
+
21
+ export function createCommandWorkspaceExplorerPort({
22
+ executeCommand,
23
+ workspaceState,
24
+ }: {
25
+ executeCommand(commandId: string, payload?: unknown): Promise<unknown>;
26
+ workspaceState: VirtualWorkspaceState | undefined;
27
+ }): WorkspaceExplorerControllerPort {
28
+ const snapshot: WorkspaceExplorerWorkspaceSnapshot = {
29
+ files: workspaceState?.files ?? [],
30
+ folders: workspaceState?.folders ?? [],
31
+ };
32
+
33
+ return {
34
+ snapshot,
35
+ createFile(input) {
36
+ return runWorkspaceCommand(executeCommand, WORKBENCH_WORKSPACE_NEW_FILE_COMMAND_ID, input);
37
+ },
38
+ createFolder(input) {
39
+ return runWorkspaceCommand(executeCommand, WORKBENCH_WORKSPACE_NEW_FOLDER_COMMAND_ID, input);
40
+ },
41
+ deleteEntries({ kind, paths }) {
42
+ void executeCommand(WORKBENCH_WORKSPACE_DELETE_COMMAND_ID, {
43
+ kind,
44
+ paths,
45
+ });
46
+ },
47
+ moveEntries(input) {
48
+ return runWorkspaceCommand(executeCommand, BUILTIN_EXPLORER_MOVE_COMMAND_ID, {
49
+ sourcePaths: input.sourcePaths,
50
+ targetFolderPath: input.targetFolderPath,
51
+ });
52
+ },
53
+ openFile(path) {
54
+ void executeCommand(WORKBENCH_WORKSPACE_OPEN_COMMAND_ID, {
55
+ kind: 'file',
56
+ path,
57
+ paths: [path],
58
+ });
59
+ },
60
+ renameEntry(input) {
61
+ return runWorkspaceCommand(executeCommand, WORKBENCH_WORKSPACE_RENAME_COMMAND_ID, input);
62
+ },
63
+ };
64
+ }
65
+
66
+ async function runWorkspaceCommand(
67
+ executeCommand: (commandId: string, payload?: unknown) => Promise<unknown>,
68
+ commandId: string,
69
+ payload: unknown,
70
+ ): Promise<WorkspaceExplorerMutationResult | undefined> {
71
+ const result = await executeCommand(commandId, payload);
72
+ return isWorkspaceCommandResult(result) ? result : undefined;
73
+ }
74
+
75
+ function isWorkspaceCommandResult(value: unknown): value is WorkspaceCommandResult {
76
+ if (typeof value !== 'object' || value === null) {
77
+ return false;
78
+ }
79
+
80
+ const result = value as WorkspaceCommandResult;
81
+ return (
82
+ (result.path === undefined || typeof result.path === 'string') &&
83
+ (result.paths === undefined ||
84
+ (Array.isArray(result.paths) && result.paths.every((path) => typeof path === 'string')))
85
+ );
86
+ }
@@ -0,0 +1,124 @@
1
+ import { useMemo, useState } from 'react';
2
+
3
+ import { Button, ScrollArea } from '@workbench-kit/react/primitives';
4
+
5
+ import { useWorkbenchDevtoolsSnapshot } from './use-workbench-devtools-snapshot.js';
6
+
7
+ type DevtoolsSectionId =
8
+ | 'commands'
9
+ | 'menus'
10
+ | 'keybindings'
11
+ | 'contextKeys'
12
+ | 'capabilities'
13
+ | 'layout'
14
+ | 'editor'
15
+ | 'views'
16
+ | 'transactions'
17
+ | 'diagnostics';
18
+
19
+ const DEVTOOLS_SECTIONS: readonly {
20
+ readonly id: DevtoolsSectionId;
21
+ readonly label: string;
22
+ }[] = [
23
+ { id: 'commands', label: 'Commands' },
24
+ { id: 'menus', label: 'Menus' },
25
+ { id: 'keybindings', label: 'Keybindings' },
26
+ { id: 'contextKeys', label: 'Context keys' },
27
+ { id: 'capabilities', label: 'Capabilities' },
28
+ { id: 'layout', label: 'Layout' },
29
+ { id: 'editor', label: 'Editor' },
30
+ { id: 'views', label: 'Views' },
31
+ { id: 'transactions', label: 'Transactions' },
32
+ { id: 'diagnostics', label: 'Diagnostics' },
33
+ ];
34
+
35
+ function formatSectionValue(
36
+ sectionId: DevtoolsSectionId,
37
+ snapshot: ReturnType<typeof useWorkbenchDevtoolsSnapshot>,
38
+ ): string {
39
+ switch (sectionId) {
40
+ case 'commands':
41
+ return JSON.stringify(snapshot.commands, null, 2);
42
+ case 'menus':
43
+ return JSON.stringify(snapshot.menus, null, 2);
44
+ case 'keybindings':
45
+ return JSON.stringify(snapshot.keybindings, null, 2);
46
+ case 'contextKeys':
47
+ return JSON.stringify(snapshot.contextKeys, null, 2);
48
+ case 'capabilities':
49
+ return JSON.stringify(
50
+ {
51
+ activeExtensions: snapshot.activeExtensions,
52
+ capabilities: snapshot.capabilities,
53
+ },
54
+ null,
55
+ 2,
56
+ );
57
+ case 'layout':
58
+ return JSON.stringify(snapshot.layout, null, 2);
59
+ case 'editor':
60
+ return JSON.stringify(snapshot.editor, null, 2);
61
+ case 'views':
62
+ return JSON.stringify(
63
+ {
64
+ activities: snapshot.activities,
65
+ viewContainers: snapshot.viewContainers,
66
+ views: snapshot.views,
67
+ },
68
+ null,
69
+ 2,
70
+ );
71
+ case 'transactions':
72
+ return JSON.stringify(snapshot.transactions, null, 2);
73
+ case 'diagnostics':
74
+ return JSON.stringify(snapshot.dependencyDiagnostics, null, 2);
75
+ default:
76
+ return '';
77
+ }
78
+ }
79
+
80
+ export function WorkbenchDevtoolsPanel() {
81
+ const snapshot = useWorkbenchDevtoolsSnapshot();
82
+ const [activeSection, setActiveSection] = useState<DevtoolsSectionId>('commands');
83
+ const sectionValue = useMemo(
84
+ () => formatSectionValue(activeSection, snapshot),
85
+ [activeSection, snapshot],
86
+ );
87
+
88
+ return (
89
+ <aside
90
+ aria-label="Workbench devtools"
91
+ className="workbench-devtools-panel"
92
+ data-testid="workbench-devtools-panel"
93
+ >
94
+ <header className="workbench-devtools-panel__header">
95
+ <strong>Workbench Devtools</strong>
96
+ <span className="workbench-devtools-panel__meta">Read-only</span>
97
+ </header>
98
+ <p className="workbench-devtools-panel__timestamp">Updated {snapshot.capturedAt}</p>
99
+ <nav aria-label="Devtools sections" className="workbench-devtools-panel__tabs">
100
+ {DEVTOOLS_SECTIONS.map((section) => (
101
+ <Button
102
+ key={section.id}
103
+ aria-pressed={activeSection === section.id}
104
+ compact
105
+ className="workbench-devtools-panel__tab"
106
+ onClick={() => {
107
+ setActiveSection(section.id);
108
+ }}
109
+ >
110
+ {section.label}
111
+ </Button>
112
+ ))}
113
+ </nav>
114
+ <ScrollArea
115
+ as="pre"
116
+ className="workbench-devtools-panel__output"
117
+ gutter="stable"
118
+ orientation="vertical"
119
+ >
120
+ {sectionValue}
121
+ </ScrollArea>
122
+ </aside>
123
+ );
124
+ }
@@ -0,0 +1,17 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ import { WorkbenchDevtoolsPanel } from './WorkbenchDevtoolsPanel.js';
4
+ import './workbench-devtools.css';
5
+
6
+ export interface WorkbenchDevtoolsShellProps {
7
+ readonly children: ReactNode;
8
+ }
9
+
10
+ export function WorkbenchDevtoolsShell({ children }: WorkbenchDevtoolsShellProps) {
11
+ return (
12
+ <div className="workbench-devtools-shell" data-testid="workbench-devtools-shell">
13
+ <div className="workbench-devtools-shell__main">{children}</div>
14
+ <WorkbenchDevtoolsPanel />
15
+ </div>
16
+ );
17
+ }
@@ -0,0 +1,11 @@
1
+ export { WorkbenchDevtoolsPanel } from './WorkbenchDevtoolsPanel.js';
2
+ export {
3
+ WorkbenchDevtoolsShell,
4
+ type WorkbenchDevtoolsShellProps,
5
+ } from './WorkbenchDevtoolsShell.js';
6
+ export {
7
+ collectWorkbenchDevtoolsSnapshot,
8
+ type CollectWorkbenchDevtoolsSnapshotInput,
9
+ type WorkbenchDevtoolsSnapshot,
10
+ } from './workbench-devtools-snapshot.js';
11
+ export { useWorkbenchDevtoolsSnapshot } from './use-workbench-devtools-snapshot.js';
@@ -0,0 +1,84 @@
1
+ import { useMemo, useSyncExternalStore } from 'react';
2
+
3
+ import {
4
+ collectWorkbenchDevtoolsSnapshot,
5
+ type WorkbenchDevtoolsSnapshot,
6
+ } from './workbench-devtools-snapshot.js';
7
+ import { useWorkbench } from '../provider.js';
8
+ import type { WorkbenchWorkspaceHostPort as WorkspaceHostPort } from '@workbench-kit/workspace';
9
+
10
+ export function useWorkbenchDevtoolsSnapshot(): WorkbenchDevtoolsSnapshot {
11
+ const { editorService, extensionRegistry, layoutService, workspaceHostPort } = useWorkbench();
12
+
13
+ const store = useMemo(() => {
14
+ const collectSnapshot = () =>
15
+ collectWorkbenchDevtoolsSnapshot({
16
+ editorService,
17
+ extensionRegistry,
18
+ layoutService,
19
+ workspaceHostPort,
20
+ });
21
+ let snapshot = collectSnapshot();
22
+
23
+ const notifyChange = (onStoreChange: () => void) => {
24
+ snapshot = collectSnapshot();
25
+ onStoreChange();
26
+ };
27
+
28
+ return {
29
+ getSnapshot: () => snapshot,
30
+ subscribe: (onStoreChange: () => void) => {
31
+ const disposables = [
32
+ layoutService.onDidChangeLayout(() => {
33
+ notifyChange(onStoreChange);
34
+ }),
35
+ editorService.onDidChangeEditors(() => {
36
+ notifyChange(onStoreChange);
37
+ }),
38
+ extensionRegistry.commands.onDidRegisterCommand(() => {
39
+ notifyChange(onStoreChange);
40
+ }),
41
+ extensionRegistry.menus.onDidRegisterMenuItem(() => {
42
+ notifyChange(onStoreChange);
43
+ }),
44
+ extensionRegistry.keybindings.onDidRegisterKeybinding(() => {
45
+ notifyChange(onStoreChange);
46
+ }),
47
+ extensionRegistry.views.onDidRegisterView(() => {
48
+ notifyChange(onStoreChange);
49
+ }),
50
+ extensionRegistry.views.onDidRegisterViewContainer(() => {
51
+ notifyChange(onStoreChange);
52
+ }),
53
+ extensionRegistry.views.onDidRegisterViewProvider(() => {
54
+ notifyChange(onStoreChange);
55
+ }),
56
+ extensionRegistry.activities.onDidRegisterActivity(() => {
57
+ notifyChange(onStoreChange);
58
+ }),
59
+ extensionRegistry.onDidActivateExtension(() => {
60
+ notifyChange(onStoreChange);
61
+ }),
62
+ extensionRegistry.onDidDeactivateExtension(() => {
63
+ notifyChange(onStoreChange);
64
+ }),
65
+ ];
66
+
67
+ const workspacePort = workspaceHostPort as WorkspaceHostPort | undefined;
68
+ const unsubscribeWorkspace = workspacePort?.service.onDidChangeWorkspace(() => {
69
+ notifyChange(onStoreChange);
70
+ });
71
+
72
+ return () => {
73
+ for (const disposable of disposables) {
74
+ disposable.dispose();
75
+ }
76
+
77
+ unsubscribeWorkspace?.();
78
+ };
79
+ },
80
+ };
81
+ }, [editorService, extensionRegistry, layoutService, workspaceHostPort]);
82
+
83
+ return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
84
+ }
@@ -0,0 +1,140 @@
1
+ import type {
2
+ EditorService,
3
+ EditorState,
4
+ ExtensionDependencyDiagnostic,
5
+ ExtensionRegistry,
6
+ LayoutService,
7
+ WorkbenchLayoutState,
8
+ } from '@workbench-kit/workbench-core';
9
+ import type {
10
+ WorkbenchWorkspaceHostPort as WorkspaceHostPort,
11
+ WorkspaceResourceTransaction,
12
+ } from '@workbench-kit/workspace';
13
+
14
+ import type { WorkbenchWorkspaceHostPort } from '../provider.js';
15
+
16
+ export interface WorkbenchDevtoolsSnapshot {
17
+ readonly activeExtensions: readonly { readonly extensionId: string }[];
18
+ readonly activities: readonly {
19
+ readonly icon?: string;
20
+ readonly id: string;
21
+ readonly title?: string;
22
+ }[];
23
+ readonly capabilities: readonly string[];
24
+ readonly capturedAt: string;
25
+ readonly commands: readonly {
26
+ readonly category?: string;
27
+ readonly id: string;
28
+ readonly title?: string;
29
+ }[];
30
+ readonly contextKeys: Readonly<Record<string, boolean | number | string>>;
31
+ readonly dependencyDiagnostics: readonly ExtensionDependencyDiagnostic[];
32
+ readonly editor: EditorState;
33
+ readonly keybindings: readonly {
34
+ readonly command: string;
35
+ readonly key: string;
36
+ readonly when?: string | undefined;
37
+ }[];
38
+ readonly layout: WorkbenchLayoutState;
39
+ readonly menus: readonly {
40
+ readonly command: string;
41
+ readonly group?: string | undefined;
42
+ readonly menu: string;
43
+ readonly order?: number | undefined;
44
+ readonly when?: string | undefined;
45
+ }[];
46
+ readonly transactions: readonly WorkspaceResourceTransaction[];
47
+ readonly viewContainers: readonly {
48
+ readonly icon?: string;
49
+ readonly id: string;
50
+ readonly location: string;
51
+ readonly title?: string;
52
+ }[];
53
+ readonly views: readonly {
54
+ readonly containerId: string;
55
+ readonly id: string;
56
+ readonly name?: string;
57
+ }[];
58
+ }
59
+
60
+ export interface CollectWorkbenchDevtoolsSnapshotInput {
61
+ readonly capturedAt?: string | undefined;
62
+ readonly editorService: EditorService;
63
+ readonly extensionRegistry: ExtensionRegistry;
64
+ readonly layoutService: LayoutService;
65
+ readonly workspaceHostPort?: WorkbenchWorkspaceHostPort | undefined;
66
+ }
67
+
68
+ export function collectWorkbenchDevtoolsSnapshot({
69
+ capturedAt = new Date().toISOString(),
70
+ editorService,
71
+ extensionRegistry,
72
+ layoutService,
73
+ workspaceHostPort,
74
+ }: CollectWorkbenchDevtoolsSnapshotInput): WorkbenchDevtoolsSnapshot {
75
+ const layout = layoutService.getState();
76
+ const editor = editorService.getState();
77
+ const activeTabCount = editor.groups.reduce((count, group) => count + group.tabs.length, 0);
78
+
79
+ return {
80
+ activeExtensions: extensionRegistry.getActiveExtensions().map(({ extensionId }) => ({
81
+ extensionId,
82
+ })),
83
+ activities: extensionRegistry.activities.getActivities().map((activity) => ({
84
+ icon: activity.icon,
85
+ id: activity.id,
86
+ title: activity.title,
87
+ })),
88
+ capabilities: extensionRegistry.capabilityRegistry.listProviderIds(),
89
+ capturedAt,
90
+ commands: extensionRegistry.commands.getCommands().map((command) => ({
91
+ category: command.category,
92
+ id: command.id,
93
+ title: command.title,
94
+ })),
95
+ contextKeys: {
96
+ 'editor.activeGroupId': editor.activeGroupId ?? '',
97
+ 'editor.openTabCount': activeTabCount,
98
+ 'layout.activityBar.visible': layout.activityBar.visible,
99
+ 'layout.auxiliaryBar.visible': layout.auxiliaryBar.visible,
100
+ 'layout.panel.visible': layout.panel.visible,
101
+ 'layout.sideBar.activeViewContainer': layout.sideBar.activeViewContainer ?? '',
102
+ 'layout.sideBar.visible': layout.sideBar.visible,
103
+ 'workspace.hasHostPort': workspaceHostPort !== undefined,
104
+ },
105
+ dependencyDiagnostics: extensionRegistry.getDependencyDiagnostics(),
106
+ editor,
107
+ keybindings: extensionRegistry.keybindings.getKeybindings().map((binding) => ({
108
+ command: binding.command,
109
+ key: binding.key,
110
+ when: binding.when,
111
+ })),
112
+ layout,
113
+ menus: extensionRegistry.menus.getMenuItems().map((menu) => ({
114
+ command: menu.command,
115
+ group: menu.group,
116
+ menu: menu.menu,
117
+ order: menu.order,
118
+ when: menu.when,
119
+ })),
120
+ transactions: readWorkspaceTransactionJournal(workspaceHostPort),
121
+ viewContainers: extensionRegistry.views.getViewContainers().map((container) => ({
122
+ icon: container.icon,
123
+ id: container.id,
124
+ location: container.location,
125
+ title: container.title,
126
+ })),
127
+ views: extensionRegistry.views.getViews().map((view) => ({
128
+ containerId: view.containerId,
129
+ id: view.id,
130
+ name: view.name,
131
+ })),
132
+ };
133
+ }
134
+
135
+ function readWorkspaceTransactionJournal(
136
+ workspaceHostPort: WorkbenchWorkspaceHostPort | undefined,
137
+ ): readonly WorkspaceResourceTransaction[] {
138
+ const port = workspaceHostPort as WorkspaceHostPort | undefined;
139
+ return port?.service.getTransactionJournal() ?? [];
140
+ }
@@ -0,0 +1,82 @@
1
+ .workbench-devtools-shell {
2
+ display: grid;
3
+ grid-template-columns: minmax(0, 1fr) min(360px, 34vw);
4
+ height: 100%;
5
+ min-height: 0;
6
+ width: 100%;
7
+ }
8
+
9
+ .workbench-devtools-shell__main {
10
+ min-height: 0;
11
+ min-width: 0;
12
+ overflow: hidden;
13
+ }
14
+
15
+ .workbench-devtools-panel {
16
+ background: var(--color-bg);
17
+ border-left: 1px solid var(--color-border);
18
+ color: var(--color-text);
19
+ display: flex;
20
+ flex-direction: column;
21
+ font-family: var(--vscode-font-family, system-ui, sans-serif);
22
+ font-size: var(--font-size-sm);
23
+ min-height: 0;
24
+ min-width: 0;
25
+ }
26
+
27
+ .workbench-devtools-panel__header {
28
+ align-items: center;
29
+ display: flex;
30
+ gap: 8px;
31
+ justify-content: space-between;
32
+ padding: 12px 12px 4px;
33
+ }
34
+
35
+ .workbench-devtools-panel__meta {
36
+ color: var(--color-text-muted);
37
+ font-size: 11px;
38
+ }
39
+
40
+ .workbench-devtools-panel__timestamp {
41
+ color: var(--color-text-muted);
42
+ font-size: 11px;
43
+ margin: 0;
44
+ padding: 0 12px 8px;
45
+ }
46
+
47
+ .workbench-devtools-panel__tabs {
48
+ display: flex;
49
+ flex-wrap: wrap;
50
+ gap: 4px;
51
+ padding: 0 8px 8px;
52
+ }
53
+
54
+ .workbench-devtools-panel__tab.ui-button {
55
+ height: auto;
56
+ min-height: 26px;
57
+ padding: 4px 8px;
58
+ border: 1px solid var(--color-border);
59
+ border-radius: var(--radius-sm);
60
+ background: transparent;
61
+ color: inherit;
62
+ font: inherit;
63
+ font-weight: 400;
64
+ }
65
+
66
+ .workbench-devtools-panel__tab.ui-button[aria-pressed='true'] {
67
+ background: var(--color-surface-hover);
68
+ border-color: var(--color-accent);
69
+ }
70
+
71
+ .workbench-devtools-panel__output {
72
+ border-top: 1px solid var(--color-border);
73
+ flex: 1;
74
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
75
+ font-size: 11px;
76
+ line-height: 1.45;
77
+ margin: 0;
78
+ min-height: 0;
79
+ padding: 12px;
80
+ white-space: pre-wrap;
81
+ word-break: break-word;
82
+ }
@@ -0,0 +1,69 @@
1
+ import { WORKSPACE_EXPLORER_DRAG_DATA_TYPE } from '@workbench-kit/react/workbench/workspace/explorer';
2
+ import {
3
+ resolveEditorGroupDropSide,
4
+ type EditorDropRect,
5
+ type EditorGroupDropSide,
6
+ } from '@workbench-kit/workbench-core';
7
+
8
+ export {
9
+ EDITOR_TAB_DRAG_DATA_TYPE,
10
+ getEditorTabDropPosition,
11
+ isEditorTabMoveNoop,
12
+ isEditorTabsScrollerEventTarget,
13
+ readEditorTabDragPayload,
14
+ resolveEditorTabDropTarget,
15
+ resolveEditorTabStripDropTarget,
16
+ } from '@workbench-kit/react';
17
+
18
+ export type { EditorTabDragPayload, EditorTabDropTarget } from '@workbench-kit/react';
19
+
20
+ const INTERNAL_EDITOR_AREA_DRAG_DATA_TYPES = [
21
+ 'application/x-workbench-kit-editor-tab',
22
+ WORKSPACE_EXPLORER_DRAG_DATA_TYPE,
23
+ ] as const;
24
+
25
+ interface EditorDropTargetElement {
26
+ getBoundingClientRect(): EditorDropRect;
27
+ }
28
+
29
+ export function isInternalEditorAreaDrag(
30
+ dataTransfer: Pick<DataTransfer, 'types'>,
31
+ draggedTab: { readonly groupId: string; readonly tabId: string } | null,
32
+ ): boolean {
33
+ return (
34
+ draggedTab !== null ||
35
+ INTERNAL_EDITOR_AREA_DRAG_DATA_TYPES.some((dataType) =>
36
+ dataTransferHasType(dataTransfer, dataType),
37
+ )
38
+ );
39
+ }
40
+
41
+ export function dataTransferHasType(
42
+ dataTransfer: Pick<DataTransfer, 'types'>,
43
+ dataType: string,
44
+ ): boolean {
45
+ return Array.from(dataTransfer.types).includes(dataType);
46
+ }
47
+
48
+ export function getEditorGroupDropSide(
49
+ target: EditorDropTargetElement,
50
+ clientX: number,
51
+ clientY: number,
52
+ ): EditorGroupDropSide {
53
+ return resolveEditorGroupDropSide({
54
+ point: { x: clientX, y: clientY },
55
+ rect: getEditorDropRect(target),
56
+ });
57
+ }
58
+
59
+ export function getEditorDropRect(target: EditorDropTargetElement): EditorDropRect {
60
+ const rect = target.getBoundingClientRect();
61
+ return {
62
+ bottom: rect.bottom,
63
+ height: rect.height,
64
+ left: rect.left,
65
+ right: rect.right,
66
+ top: rect.top,
67
+ width: rect.width,
68
+ };
69
+ }