@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,136 @@
1
+ import { useEffect, useMemo, useRef, type ReactNode } from 'react';
2
+ import {
3
+ WorkbenchBootstrapGate,
4
+ useWorkbenchBootstrap,
5
+ type WorkbenchBootstrapTaskDefinition,
6
+ } from '@workbench-kit/react/workbench/bootstrap';
7
+ import type { VirtualWorkspaceInitialState } from '@workbench-kit/workspace';
8
+ import { useWorkbench } from './provider.js';
9
+
10
+ export interface WorkbenchStartupGateProps {
11
+ children: ReactNode;
12
+ className?: string | undefined;
13
+ footer?: ReactNode;
14
+ heading?: string | undefined;
15
+ onFailed?: ((error: Error) => void) | undefined;
16
+ onReady?: (() => void) | undefined;
17
+ renderBootstrap?:
18
+ ((bootstrap: ReturnType<typeof useWorkbenchBootstrap>) => ReactNode) | undefined;
19
+ subtitle?: string | undefined;
20
+ tasks?: readonly WorkbenchBootstrapTaskDefinition[] | undefined;
21
+ workspaceInit?: VirtualWorkspaceInitialState | undefined;
22
+ }
23
+
24
+ function countWorkspaceEntries(
25
+ workspaceInit: VirtualWorkspaceInitialState | undefined,
26
+ ): string | undefined {
27
+ if (!workspaceInit) {
28
+ return undefined;
29
+ }
30
+
31
+ const fileCount = workspaceInit.files?.length ?? 0;
32
+ const folderCount = workspaceInit.folders?.length ?? 0;
33
+ const parts: string[] = [];
34
+
35
+ if (fileCount > 0) {
36
+ parts.push(`${fileCount} file${fileCount === 1 ? '' : 's'}`);
37
+ }
38
+
39
+ if (folderCount > 0) {
40
+ parts.push(`${folderCount} folder${folderCount === 1 ? '' : 's'}`);
41
+ }
42
+
43
+ return parts.length > 0 ? parts.join(', ') : undefined;
44
+ }
45
+
46
+ export function WorkbenchStartupGate({
47
+ children,
48
+ className,
49
+ footer,
50
+ heading = 'Preparing workbench',
51
+ onFailed,
52
+ onReady,
53
+ renderBootstrap,
54
+ subtitle = 'Loading extensions and preparing your workspace.',
55
+ tasks,
56
+ workspaceInit,
57
+ }: WorkbenchStartupGateProps) {
58
+ const { executeCommand, missingExtensionIds, waitForExtensionStartup } = useWorkbench();
59
+ const bootstrap = useWorkbenchBootstrap();
60
+ const startedRef = useRef(false);
61
+ const workspaceDetail = countWorkspaceEntries(workspaceInit);
62
+
63
+ const startupTasks = useMemo<readonly WorkbenchBootstrapTaskDefinition[]>(() => {
64
+ if (tasks) {
65
+ return tasks;
66
+ }
67
+
68
+ const resolvedTasks: WorkbenchBootstrapTaskDefinition[] = [
69
+ {
70
+ detail:
71
+ missingExtensionIds.length > 0 ? `${missingExtensionIds.length} missing` : undefined,
72
+ id: 'extensions',
73
+ label: 'Loading extensions',
74
+ run: async () => {
75
+ await waitForExtensionStartup();
76
+ },
77
+ },
78
+ ];
79
+
80
+ if (workspaceInit) {
81
+ resolvedTasks.push({
82
+ detail: workspaceDetail,
83
+ id: 'workspace',
84
+ label: 'Preparing workspace',
85
+ run: async () => {
86
+ await executeCommand('workspace.init', workspaceInit);
87
+ },
88
+ });
89
+ }
90
+
91
+ return resolvedTasks;
92
+ }, [
93
+ executeCommand,
94
+ missingExtensionIds.length,
95
+ tasks,
96
+ waitForExtensionStartup,
97
+ workspaceDetail,
98
+ workspaceInit,
99
+ ]);
100
+
101
+ useEffect(() => {
102
+ if (startedRef.current) {
103
+ return;
104
+ }
105
+
106
+ startedRef.current = true;
107
+ void bootstrap.run(startupTasks).catch((error: unknown) => {
108
+ onFailed?.(error instanceof Error ? error : new Error('Startup failed.'));
109
+ });
110
+ }, [bootstrap, onFailed, startupTasks]);
111
+
112
+ useEffect(() => {
113
+ if (bootstrap.isReady) {
114
+ onReady?.();
115
+ }
116
+ }, [bootstrap.isReady, onReady]);
117
+
118
+ useEffect(() => {
119
+ if (bootstrap.status === 'failed' && bootstrap.error) {
120
+ onFailed?.(new Error(bootstrap.error));
121
+ }
122
+ }, [bootstrap.error, bootstrap.status, onFailed]);
123
+
124
+ return (
125
+ <WorkbenchBootstrapGate
126
+ bootstrap={bootstrap}
127
+ className={className}
128
+ footer={footer}
129
+ heading={heading}
130
+ renderBootstrap={renderBootstrap}
131
+ subtitle={subtitle}
132
+ >
133
+ {children}
134
+ </WorkbenchBootstrapGate>
135
+ );
136
+ }
@@ -0,0 +1,43 @@
1
+ import type {
2
+ StatusBarItemModel,
3
+ StatusBarSectionModel,
4
+ } from '@workbench-kit/react/workbench/shell';
5
+
6
+ export interface WorkspaceResourceStatusItemsInput {
7
+ fileCount: number;
8
+ fileItemId?: string | undefined;
9
+ fileTitle?: string | undefined;
10
+ folderCount: number;
11
+ folderItemId?: string | undefined;
12
+ folderTitle?: string | undefined;
13
+ }
14
+
15
+ export function createWorkspaceResourceStatusItems({
16
+ fileCount,
17
+ fileItemId = 'workbench.workspace.files',
18
+ fileTitle = 'Workspace files',
19
+ folderCount,
20
+ folderItemId = 'workbench.workspace.folders',
21
+ folderTitle = 'Workspace folders',
22
+ }: WorkspaceResourceStatusItemsInput): StatusBarItemModel[] {
23
+ return [
24
+ {
25
+ icon: 'files',
26
+ id: fileItemId,
27
+ label: `${fileCount} files`,
28
+ title: fileTitle,
29
+ },
30
+ {
31
+ icon: 'folder',
32
+ id: folderItemId,
33
+ label: `${folderCount} folders`,
34
+ title: folderTitle,
35
+ },
36
+ ];
37
+ }
38
+
39
+ export function mergeWorkbenchStatusSections(
40
+ ...sectionGroups: ReadonlyArray<readonly StatusBarSectionModel[]>
41
+ ): StatusBarSectionModel[] {
42
+ return sectionGroups.flat().filter((section) => section.items.length > 0);
43
+ }
@@ -0,0 +1,46 @@
1
+ import type {
2
+ WorkbenchUserCommandAction,
3
+ WorkbenchUserCommandDefinition,
4
+ } from '@workbench-kit/workbench-config';
5
+ import type { ExtensionRegistry } from '@workbench-kit/workbench-core';
6
+
7
+ export async function executeWorkbenchUserCommandAction(
8
+ action: WorkbenchUserCommandAction,
9
+ executeCommand: (commandId: string, ...args: unknown[]) => Promise<unknown>,
10
+ ): Promise<unknown> {
11
+ if (action.type === 'executeCommand') {
12
+ return executeCommand(action.command, ...(action.args !== undefined ? [action.args] : []));
13
+ }
14
+
15
+ let lastResult: unknown;
16
+ for (const step of action.steps) {
17
+ lastResult = await executeWorkbenchUserCommandAction(step, executeCommand);
18
+ }
19
+
20
+ return lastResult;
21
+ }
22
+
23
+ export function registerWorkbenchUserCommands(
24
+ extensionRegistry: ExtensionRegistry,
25
+ userCommands: readonly WorkbenchUserCommandDefinition[],
26
+ ): { dispose(): void } {
27
+ const disposables = userCommands.map((userCommand) =>
28
+ extensionRegistry.commands.registerCommand({
29
+ category: userCommand.category,
30
+ handler: () =>
31
+ executeWorkbenchUserCommandAction(userCommand.action, (commandId, ...args) =>
32
+ extensionRegistry.executeCommand(commandId, ...args),
33
+ ),
34
+ id: userCommand.command,
35
+ title: userCommand.title,
36
+ }),
37
+ );
38
+
39
+ return {
40
+ dispose() {
41
+ for (const disposable of disposables) {
42
+ disposable.dispose();
43
+ }
44
+ },
45
+ };
46
+ }
@@ -0,0 +1,35 @@
1
+ import { useEffect, useState } from 'react';
2
+ import type {
3
+ VirtualWorkspaceState,
4
+ WorkspaceChangeEvent,
5
+ WorkspaceResourceService,
6
+ } from '@workbench-kit/workspace';
7
+
8
+ export function isWorkspaceResourceService(value: unknown): value is WorkspaceResourceService {
9
+ return (
10
+ typeof value === 'object' &&
11
+ value !== null &&
12
+ typeof (value as WorkspaceResourceService).getState === 'function' &&
13
+ typeof (value as WorkspaceResourceService).onDidChangeWorkspace === 'function'
14
+ );
15
+ }
16
+
17
+ export function useWorkspaceResourceState(
18
+ workspaceService: WorkspaceResourceService | undefined,
19
+ ): VirtualWorkspaceState | undefined {
20
+ const [state, setState] = useState(() => workspaceService?.getState());
21
+
22
+ useEffect(() => {
23
+ if (!workspaceService) {
24
+ setState(undefined);
25
+ return undefined;
26
+ }
27
+
28
+ setState(workspaceService.getState());
29
+ return workspaceService.onDidChangeWorkspace((event: WorkspaceChangeEvent) => {
30
+ setState(event.state);
31
+ });
32
+ }, [workspaceService]);
33
+
34
+ return state;
35
+ }