@workbench-kit/shell-react 0.0.2-prototype.0.2.6 → 0.0.2-prototype.0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -0
- package/package.json +9 -9
- package/src/{chat-ai-mock-proposals.ts → chat/ai-mock-proposals.ts} +39 -39
- package/src/{chat-command-input.ts → chat/command-input.ts} +52 -52
- package/src/{chat-command-policy.ts → chat/command-policy.ts} +54 -54
- package/src/{chat-command-surface.tsx → chat/command-surface.tsx} +155 -155
- package/src/{use-workbench-chat-command-proposals.ts → chat/use-chat-command-proposals.ts} +194 -194
- package/src/{chat-view-data.ts → chat/view-data.ts} +20 -20
- package/src/{chat-view.tsx → chat/view.tsx} +220 -220
- package/src/{command-inspector-surface.tsx → commands/inspector-surface.tsx} +46 -46
- package/src/{use-workbench-command-descriptors.ts → commands/use-command-descriptors.ts} +41 -41
- package/src/{use-context-key-revision.ts → commands/use-context-key-revision.ts} +18 -18
- package/src/{commands-view-data.ts → commands/view-data.ts} +17 -17
- package/src/{commands-view.tsx → commands/view.tsx} +43 -43
- package/src/devtools/WorkbenchDevtoolsPanel.tsx +124 -124
- package/src/devtools/WorkbenchDevtoolsShell.tsx +17 -17
- package/src/devtools/index.ts +11 -11
- package/src/devtools/use-workbench-devtools-snapshot.ts +84 -84
- package/src/devtools/workbench-devtools-snapshot.ts +140 -140
- package/src/devtools/workbench-devtools.css +82 -82
- package/src/{editor-area-dnd.ts → editor/area-dnd.ts} +69 -69
- package/src/{editor-area-model.ts → editor/area-model.ts} +71 -71
- package/src/{editor-area.css → editor/area.css} +454 -454
- package/src/{editor-area.tsx → editor/area.tsx} +676 -676
- package/src/{editor-host-surface.tsx → editor/host-surface.tsx} +631 -634
- package/src/{editor-pane-visibility.ts → editor/pane-visibility.ts} +130 -130
- package/src/{editor-resource.ts → editor/resource.ts} +36 -36
- package/src/{editor-state-storage.ts → editor/state-storage.ts} +182 -193
- package/src/{editor-tab-context-menu.ts → editor/tab-context-menu.ts} +118 -118
- package/src/{use-editor.ts → editor/use-editor.ts} +114 -107
- package/src/{editor-view-providers.tsx → editor/view-providers.tsx} +552 -552
- package/src/{editor-workspace-file-availability.ts → editor/workspace-file-availability.ts} +15 -15
- package/src/{editor-workspace-reconcile.tsx → editor/workspace-reconcile.tsx} +31 -28
- package/src/{explorer-context-menu.ts → explorer/context-menu.ts} +114 -114
- package/src/{createCommandWorkspaceExplorerPort.ts → explorer/create-command-workspace-explorer-port.ts} +86 -86
- package/src/{explorer-reveal.ts → explorer/reveal.ts} +112 -112
- package/src/{search-view-data.ts → explorer/search-view-data.ts} +15 -15
- package/src/{search-view.tsx → explorer/search-view.tsx} +65 -62
- package/src/{use-active-workspace-path.ts → explorer/use-active-workspace-path.ts} +15 -15
- package/src/{explorer-view-data.ts → explorer/view-data.ts} +58 -58
- package/src/{explorer-view.tsx → explorer/view.tsx} +227 -224
- package/src/{extension-context-menu.ts → extensions/context-menu.ts} +52 -52
- package/src/{extension-management-model.ts → extensions/management-model.ts} +313 -313
- package/src/{use-extension-management.ts → extensions/use-extension-management.ts} +241 -193
- package/src/{extensions-view-data.ts → extensions/view-data.ts} +19 -19
- package/src/{extensions-view.tsx → extensions/view.tsx} +63 -38
- package/src/{field-remap-demo.tsx → field-remap/demo.tsx} +18 -18
- package/src/{field-remap-editor-surface.tsx → field-remap/editor-surface.tsx} +36 -36
- package/src/{field-remap-flow-adapter.ts → field-remap/flow-adapter.ts} +240 -240
- package/src/{field-remap-flow.tsx → field-remap/flow.tsx} +369 -369
- package/src/{field-remap-graph.tsx → field-remap/graph.tsx} +559 -559
- package/src/field-remap/jsonata-transform.ts +166 -0
- package/src/{field-remap-panel.tsx → field-remap/panel.tsx} +193 -175
- package/src/{field-remap-samples.ts → field-remap/samples.ts} +352 -352
- package/src/{table-mapping-adapter.ts → field-remap/table-mapping-adapter.ts} +59 -59
- package/src/{field-remap-tree.tsx → field-remap/tree.tsx} +404 -404
- package/src/{field-remap-view-data.ts → field-remap/view-data.ts} +16 -16
- package/src/{field-remap-view.css → field-remap/view.css} +676 -676
- package/src/{field-remap-view.tsx → field-remap/view.tsx} +86 -86
- package/src/index.ts +212 -199
- package/src/{json-form-source-patch.ts → jdw/json-form-source-patch.ts} +323 -323
- package/src/{jdw-lab-view-data.ts → jdw/lab-view-data.ts} +25 -25
- package/src/{jdw-lab-view.css → jdw/lab-view.css} +21 -21
- package/src/{jdw-lab-view.tsx → jdw/lab-view.tsx} +79 -79
- package/src/{jdw-widget-form-view.tsx → jdw/widget-form-view.tsx} +68 -65
- package/src/{jdw-widget-preview-view.tsx → jdw/widget-preview-view.tsx} +54 -51
- package/src/{keybinding-overrides-storage.ts → management/keybinding-overrides-storage.ts} +49 -57
- package/src/{keybinding-management-settings.tsx → management/keybinding-settings.tsx} +16 -16
- package/src/{management-palette-commands.ts → management/palette-commands.ts} +38 -38
- package/src/{preference-settings-storage.ts → management/preference-settings-storage.ts} +50 -58
- package/src/{management-settings-ids.ts → management/settings-ids.ts} +12 -12
- package/src/{management-settings.tsx → management/settings.tsx} +96 -75
- package/src/{use-command-management.ts → management/use-command-management.ts} +191 -191
- package/src/{use-keybinding-management.ts → management/use-keybinding-management.ts} +130 -130
- package/src/{shell-model.tsx → shell/model.tsx} +149 -149
- package/src/{provider.tsx → shell/provider.tsx} +603 -573
- package/src/{shell-secondary-actions.tsx → shell/secondary-actions.tsx} +59 -59
- package/src/{shell-settings-constants.ts → shell/settings-constants.ts} +9 -9
- package/src/{shell-settings.tsx → shell/settings.tsx} +599 -599
- package/src/{shell.tsx → shell/shell.tsx} +680 -649
- package/src/{shell-titlebar-layout-controls.tsx → shell/titlebar-layout-controls.tsx} +4 -4
- package/src/{shell-view-host.tsx → shell/view-host.tsx} +212 -199
- package/src/{workbench-appearance-storage.ts → workbench/appearance-storage.ts} +107 -115
- package/src/{workbench-command-host.tsx → workbench/command-host.tsx} +243 -243
- package/src/{workbench-command-palette.ts → workbench/command-palette.ts} +208 -208
- package/src/{workbench-keybinding-bridge.ts → workbench/keybinding-bridge.ts} +54 -54
- package/src/{workbench-layout-storage.ts → workbench/layout-storage.ts} +134 -145
- package/src/{workbench-profile-modal.tsx → workbench/profile-modal.tsx} +118 -118
- package/src/{workbench-shell-command-registration.ts → workbench/shell-command-registration.ts} +58 -58
- package/src/{workbench-startup-gate.tsx → workbench/startup-gate.tsx} +136 -136
- package/src/{workbench-status-sections.ts → workbench/status-sections.ts} +43 -43
- package/src/{use-persisted-workbench-appearance.ts → workbench/use-persisted-appearance.ts} +33 -33
- package/src/{workbench-user-commands.ts → workbench/user-commands.ts} +46 -46
- package/src/{workspace-view-state.ts → workbench/workspace-view-state.ts} +35 -35
- package/src/jsonata-transform.ts +0 -36
|
@@ -1,145 +1,134 @@
|
|
|
1
|
-
import {
|
|
2
|
-
parseWorkbenchLayoutConfig,
|
|
3
|
-
type WorkbenchLayoutConfig,
|
|
4
|
-
} from '@workbench-kit/workbench-config';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type
|
|
9
|
-
type
|
|
10
|
-
type
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
visible: config.
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
visible: config.
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
...(state.activityBar.
|
|
53
|
-
? {
|
|
54
|
-
: {}),
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
visible: state.
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
visible: state.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
...(state.sideBar.
|
|
68
|
-
? {
|
|
69
|
-
: {}),
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return createWorkbenchLayoutState(persisted, createWorkbenchLayoutState(baseLayout ?? {}));
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function getBrowserLocalStorage(): (WorkbenchStorageReader & WorkbenchStorageWriter) | undefined {
|
|
140
|
-
if (!isWorkbenchLayoutPersistenceAvailable()) {
|
|
141
|
-
return undefined;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return globalThis.localStorage;
|
|
145
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
parseWorkbenchLayoutConfig,
|
|
3
|
+
type WorkbenchLayoutConfig,
|
|
4
|
+
} from '@workbench-kit/workbench-config';
|
|
5
|
+
import {
|
|
6
|
+
createBrowserWorkbenchStorage,
|
|
7
|
+
createWorkbenchLayoutState,
|
|
8
|
+
type WorkbenchStorageReader,
|
|
9
|
+
type WorkbenchStorageWriter,
|
|
10
|
+
type WorkbenchLayoutState,
|
|
11
|
+
type WorkbenchLayoutStateInput,
|
|
12
|
+
} from '@workbench-kit/workbench-core';
|
|
13
|
+
|
|
14
|
+
export const DEFAULT_WORKBENCH_LAYOUT_STORAGE_KEY = 'workbench-kit/.workbench/layout';
|
|
15
|
+
|
|
16
|
+
export function isWorkbenchLayoutPersistenceAvailable(): boolean {
|
|
17
|
+
return createBrowserWorkbenchStorage({ kind: 'local' }) !== undefined;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function workbenchLayoutConfigToInput(
|
|
21
|
+
config: WorkbenchLayoutConfig,
|
|
22
|
+
): WorkbenchLayoutStateInput {
|
|
23
|
+
return {
|
|
24
|
+
activityBar: {
|
|
25
|
+
hiddenItemIds: config.activityBar.hiddenItemIds,
|
|
26
|
+
itemOrder: config.activityBar.itemOrder,
|
|
27
|
+
visible: config.activityBar.visible,
|
|
28
|
+
},
|
|
29
|
+
auxiliaryBar: {
|
|
30
|
+
visible: config.auxiliaryBar.visible,
|
|
31
|
+
},
|
|
32
|
+
panel: {
|
|
33
|
+
visible: config.panel.visible,
|
|
34
|
+
},
|
|
35
|
+
sideBar: {
|
|
36
|
+
activeViewContainer: config.sideBar.activeViewContainer,
|
|
37
|
+
sizePercent: config.sideBar.sizePercent,
|
|
38
|
+
visible: config.sideBar.visible,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function workbenchLayoutStateToStorageValue(
|
|
44
|
+
state: WorkbenchLayoutState,
|
|
45
|
+
): WorkbenchLayoutConfig {
|
|
46
|
+
return {
|
|
47
|
+
activityBar: {
|
|
48
|
+
visible: state.activityBar.visible,
|
|
49
|
+
...(state.activityBar.hiddenItemIds?.length
|
|
50
|
+
? { hiddenItemIds: [...state.activityBar.hiddenItemIds] }
|
|
51
|
+
: {}),
|
|
52
|
+
...(state.activityBar.itemOrder?.length
|
|
53
|
+
? { itemOrder: [...state.activityBar.itemOrder] }
|
|
54
|
+
: {}),
|
|
55
|
+
},
|
|
56
|
+
auxiliaryBar: {
|
|
57
|
+
visible: state.auxiliaryBar.visible,
|
|
58
|
+
},
|
|
59
|
+
panel: {
|
|
60
|
+
visible: state.panel.visible,
|
|
61
|
+
},
|
|
62
|
+
sideBar: {
|
|
63
|
+
visible: state.sideBar.visible,
|
|
64
|
+
...(state.sideBar.activeViewContainer
|
|
65
|
+
? { activeViewContainer: state.sideBar.activeViewContainer }
|
|
66
|
+
: {}),
|
|
67
|
+
...(state.sideBar.sizePercent !== undefined
|
|
68
|
+
? { sizePercent: state.sideBar.sizePercent }
|
|
69
|
+
: {}),
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function readPersistedWorkbenchLayout(
|
|
75
|
+
storageKey = DEFAULT_WORKBENCH_LAYOUT_STORAGE_KEY,
|
|
76
|
+
storage?: WorkbenchStorageReader,
|
|
77
|
+
): WorkbenchLayoutStateInput | undefined {
|
|
78
|
+
const resolvedStorage = storage ?? createBrowserWorkbenchStorage({ kind: 'local' });
|
|
79
|
+
if (!resolvedStorage) return undefined;
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
const raw = resolvedStorage.getItem(storageKey);
|
|
83
|
+
if (!raw) return undefined;
|
|
84
|
+
|
|
85
|
+
return workbenchLayoutConfigToInput(parseWorkbenchLayoutConfig(JSON.parse(raw) as unknown));
|
|
86
|
+
} catch {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function writePersistedWorkbenchLayout(
|
|
92
|
+
state: WorkbenchLayoutState,
|
|
93
|
+
storageKey = DEFAULT_WORKBENCH_LAYOUT_STORAGE_KEY,
|
|
94
|
+
storage?: WorkbenchStorageWriter,
|
|
95
|
+
): void {
|
|
96
|
+
const resolvedStorage = storage ?? createBrowserWorkbenchStorage({ kind: 'local' });
|
|
97
|
+
if (!resolvedStorage) return;
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
resolvedStorage.setItem(
|
|
101
|
+
storageKey,
|
|
102
|
+
JSON.stringify(workbenchLayoutStateToStorageValue(state), null, 2),
|
|
103
|
+
);
|
|
104
|
+
} catch {
|
|
105
|
+
// Ignore quota and security errors so the shell keeps working offline.
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function resolvePersistedWorkbenchLayout(
|
|
110
|
+
initialLayout: WorkbenchLayoutStateInput | undefined,
|
|
111
|
+
options: {
|
|
112
|
+
persistLayout?: boolean | undefined;
|
|
113
|
+
storage?: WorkbenchStorageReader | undefined;
|
|
114
|
+
storageKey?: string | undefined;
|
|
115
|
+
} = {},
|
|
116
|
+
): WorkbenchLayoutStateInput | undefined {
|
|
117
|
+
const {
|
|
118
|
+
initialLayout: baseLayout,
|
|
119
|
+
persistLayout = options.storage !== undefined || isWorkbenchLayoutPersistenceAvailable(),
|
|
120
|
+
storage,
|
|
121
|
+
storageKey = DEFAULT_WORKBENCH_LAYOUT_STORAGE_KEY,
|
|
122
|
+
} = { initialLayout, ...options };
|
|
123
|
+
|
|
124
|
+
if (!persistLayout) {
|
|
125
|
+
return baseLayout;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const persisted = readPersistedWorkbenchLayout(storageKey, storage);
|
|
129
|
+
if (!persisted) {
|
|
130
|
+
return baseLayout;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return createWorkbenchLayoutState(persisted, createWorkbenchLayoutState(baseLayout ?? {}));
|
|
134
|
+
}
|
|
@@ -1,118 +1,118 @@
|
|
|
1
|
-
import { Modal } from '@workbench-kit/react/modal';
|
|
2
|
-
import { Badge, Button } from '@workbench-kit/react/primitives';
|
|
3
|
-
import type { ReactNode } from 'react';
|
|
4
|
-
|
|
5
|
-
export interface WorkbenchProfileDetail {
|
|
6
|
-
readonly label: string;
|
|
7
|
-
readonly value: ReactNode;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface WorkbenchProfileInput {
|
|
11
|
-
readonly accountId?: string | undefined;
|
|
12
|
-
readonly displayName: string;
|
|
13
|
-
readonly email?: string | undefined;
|
|
14
|
-
readonly providerLabel?: string | undefined;
|
|
15
|
-
readonly roleLabel?: string | undefined;
|
|
16
|
-
readonly sessionLabel?: string | undefined;
|
|
17
|
-
readonly statusLabel?: string | undefined;
|
|
18
|
-
readonly workspaceLabel?: string | undefined;
|
|
19
|
-
readonly details?: readonly WorkbenchProfileDetail[] | undefined;
|
|
20
|
-
readonly onSignOut?: (() => void) | undefined;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface WorkbenchProfileModalProps {
|
|
24
|
-
extraContent?: ReactNode | undefined;
|
|
25
|
-
profile: WorkbenchProfileInput;
|
|
26
|
-
onClose: () => void;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function WorkbenchProfileModal({
|
|
30
|
-
extraContent,
|
|
31
|
-
profile,
|
|
32
|
-
onClose,
|
|
33
|
-
}: WorkbenchProfileModalProps) {
|
|
34
|
-
const initials = getProfileInitials(profile.displayName);
|
|
35
|
-
const details = createProfileDetails(profile);
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<Modal
|
|
39
|
-
bodyLayout="stack"
|
|
40
|
-
bodyPadding="lg"
|
|
41
|
-
bodyScroll="auto"
|
|
42
|
-
className="workbench-profile-modal"
|
|
43
|
-
closeLabel="Close profile"
|
|
44
|
-
footer={
|
|
45
|
-
<>
|
|
46
|
-
{profile.onSignOut ? (
|
|
47
|
-
<Button type="button" variant="danger" onClick={profile.onSignOut}>
|
|
48
|
-
Sign out
|
|
49
|
-
</Button>
|
|
50
|
-
) : null}
|
|
51
|
-
<span className="workbench-profile-modal__footer-spacer" />
|
|
52
|
-
<Button type="button" onClick={onClose}>
|
|
53
|
-
Close
|
|
54
|
-
</Button>
|
|
55
|
-
</>
|
|
56
|
-
}
|
|
57
|
-
title="Profile"
|
|
58
|
-
titleSuffix={
|
|
59
|
-
profile.statusLabel ? <Badge variant="accent">{profile.statusLabel}</Badge> : null
|
|
60
|
-
}
|
|
61
|
-
onClose={onClose}
|
|
62
|
-
>
|
|
63
|
-
<section className="workbench-profile-card" aria-label="Workbench profile">
|
|
64
|
-
<div className="workbench-profile-card__avatar" aria-hidden="true">
|
|
65
|
-
{initials}
|
|
66
|
-
</div>
|
|
67
|
-
<div className="workbench-profile-card__identity">
|
|
68
|
-
<h2>{profile.displayName}</h2>
|
|
69
|
-
{profile.email ? <p>{profile.email}</p> : null}
|
|
70
|
-
</div>
|
|
71
|
-
</section>
|
|
72
|
-
|
|
73
|
-
{profile.sessionLabel ? (
|
|
74
|
-
<p className="workbench-profile-session" role="status">
|
|
75
|
-
{profile.sessionLabel}
|
|
76
|
-
</p>
|
|
77
|
-
) : null}
|
|
78
|
-
|
|
79
|
-
<section className="workbench-profile-section" aria-label="Account details">
|
|
80
|
-
<h3>Account</h3>
|
|
81
|
-
<dl className="workbench-profile-detail-grid">
|
|
82
|
-
{details.map((detail) => (
|
|
83
|
-
<div key={detail.label}>
|
|
84
|
-
<dt>{detail.label}</dt>
|
|
85
|
-
<dd>{detail.value}</dd>
|
|
86
|
-
</div>
|
|
87
|
-
))}
|
|
88
|
-
</dl>
|
|
89
|
-
</section>
|
|
90
|
-
|
|
91
|
-
{extraContent}
|
|
92
|
-
</Modal>
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function createProfileDetails(profile: WorkbenchProfileInput): WorkbenchProfileDetail[] {
|
|
97
|
-
return [
|
|
98
|
-
...(profile.providerLabel ? [{ label: 'Provider', value: profile.providerLabel }] : []),
|
|
99
|
-
...(profile.roleLabel ? [{ label: 'Role', value: profile.roleLabel }] : []),
|
|
100
|
-
...(profile.workspaceLabel ? [{ label: 'Workspace', value: profile.workspaceLabel }] : []),
|
|
101
|
-
...(profile.accountId
|
|
102
|
-
? [{ label: 'Account ID', value: <code>{profile.accountId}</code> }]
|
|
103
|
-
: []),
|
|
104
|
-
...(profile.details ?? []),
|
|
105
|
-
];
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function getProfileInitials(displayName: string): string {
|
|
109
|
-
const initials = displayName
|
|
110
|
-
.split(/\s+/)
|
|
111
|
-
.map((part) => part[0])
|
|
112
|
-
.filter(Boolean)
|
|
113
|
-
.slice(0, 2)
|
|
114
|
-
.join('')
|
|
115
|
-
.toUpperCase();
|
|
116
|
-
|
|
117
|
-
return initials || 'U';
|
|
118
|
-
}
|
|
1
|
+
import { Modal } from '@workbench-kit/react/modal';
|
|
2
|
+
import { Badge, Button } from '@workbench-kit/react/primitives';
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
export interface WorkbenchProfileDetail {
|
|
6
|
+
readonly label: string;
|
|
7
|
+
readonly value: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface WorkbenchProfileInput {
|
|
11
|
+
readonly accountId?: string | undefined;
|
|
12
|
+
readonly displayName: string;
|
|
13
|
+
readonly email?: string | undefined;
|
|
14
|
+
readonly providerLabel?: string | undefined;
|
|
15
|
+
readonly roleLabel?: string | undefined;
|
|
16
|
+
readonly sessionLabel?: string | undefined;
|
|
17
|
+
readonly statusLabel?: string | undefined;
|
|
18
|
+
readonly workspaceLabel?: string | undefined;
|
|
19
|
+
readonly details?: readonly WorkbenchProfileDetail[] | undefined;
|
|
20
|
+
readonly onSignOut?: (() => void) | undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface WorkbenchProfileModalProps {
|
|
24
|
+
extraContent?: ReactNode | undefined;
|
|
25
|
+
profile: WorkbenchProfileInput;
|
|
26
|
+
onClose: () => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function WorkbenchProfileModal({
|
|
30
|
+
extraContent,
|
|
31
|
+
profile,
|
|
32
|
+
onClose,
|
|
33
|
+
}: WorkbenchProfileModalProps) {
|
|
34
|
+
const initials = getProfileInitials(profile.displayName);
|
|
35
|
+
const details = createProfileDetails(profile);
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<Modal
|
|
39
|
+
bodyLayout="stack"
|
|
40
|
+
bodyPadding="lg"
|
|
41
|
+
bodyScroll="auto"
|
|
42
|
+
className="workbench-profile-modal"
|
|
43
|
+
closeLabel="Close profile"
|
|
44
|
+
footer={
|
|
45
|
+
<>
|
|
46
|
+
{profile.onSignOut ? (
|
|
47
|
+
<Button type="button" variant="danger" onClick={profile.onSignOut}>
|
|
48
|
+
Sign out
|
|
49
|
+
</Button>
|
|
50
|
+
) : null}
|
|
51
|
+
<span className="workbench-profile-modal__footer-spacer" />
|
|
52
|
+
<Button type="button" onClick={onClose}>
|
|
53
|
+
Close
|
|
54
|
+
</Button>
|
|
55
|
+
</>
|
|
56
|
+
}
|
|
57
|
+
title="Profile"
|
|
58
|
+
titleSuffix={
|
|
59
|
+
profile.statusLabel ? <Badge variant="accent">{profile.statusLabel}</Badge> : null
|
|
60
|
+
}
|
|
61
|
+
onClose={onClose}
|
|
62
|
+
>
|
|
63
|
+
<section className="workbench-profile-card" aria-label="Workbench profile">
|
|
64
|
+
<div className="workbench-profile-card__avatar" aria-hidden="true">
|
|
65
|
+
{initials}
|
|
66
|
+
</div>
|
|
67
|
+
<div className="workbench-profile-card__identity">
|
|
68
|
+
<h2>{profile.displayName}</h2>
|
|
69
|
+
{profile.email ? <p>{profile.email}</p> : null}
|
|
70
|
+
</div>
|
|
71
|
+
</section>
|
|
72
|
+
|
|
73
|
+
{profile.sessionLabel ? (
|
|
74
|
+
<p className="workbench-profile-session" role="status">
|
|
75
|
+
{profile.sessionLabel}
|
|
76
|
+
</p>
|
|
77
|
+
) : null}
|
|
78
|
+
|
|
79
|
+
<section className="workbench-profile-section" aria-label="Account details">
|
|
80
|
+
<h3>Account</h3>
|
|
81
|
+
<dl className="workbench-profile-detail-grid">
|
|
82
|
+
{details.map((detail) => (
|
|
83
|
+
<div key={detail.label}>
|
|
84
|
+
<dt>{detail.label}</dt>
|
|
85
|
+
<dd>{detail.value}</dd>
|
|
86
|
+
</div>
|
|
87
|
+
))}
|
|
88
|
+
</dl>
|
|
89
|
+
</section>
|
|
90
|
+
|
|
91
|
+
{extraContent}
|
|
92
|
+
</Modal>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function createProfileDetails(profile: WorkbenchProfileInput): WorkbenchProfileDetail[] {
|
|
97
|
+
return [
|
|
98
|
+
...(profile.providerLabel ? [{ label: 'Provider', value: profile.providerLabel }] : []),
|
|
99
|
+
...(profile.roleLabel ? [{ label: 'Role', value: profile.roleLabel }] : []),
|
|
100
|
+
...(profile.workspaceLabel ? [{ label: 'Workspace', value: profile.workspaceLabel }] : []),
|
|
101
|
+
...(profile.accountId
|
|
102
|
+
? [{ label: 'Account ID', value: <code>{profile.accountId}</code> }]
|
|
103
|
+
: []),
|
|
104
|
+
...(profile.details ?? []),
|
|
105
|
+
];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function getProfileInitials(displayName: string): string {
|
|
109
|
+
const initials = displayName
|
|
110
|
+
.split(/\s+/)
|
|
111
|
+
.map((part) => part[0])
|
|
112
|
+
.filter(Boolean)
|
|
113
|
+
.slice(0, 2)
|
|
114
|
+
.join('')
|
|
115
|
+
.toUpperCase();
|
|
116
|
+
|
|
117
|
+
return initials || 'U';
|
|
118
|
+
}
|
package/src/{workbench-shell-command-registration.ts → workbench/shell-command-registration.ts}
RENAMED
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
import type { CommandDefinition, CommandRegistry } from '@workbench-kit/platform';
|
|
2
|
-
import type { WorkbenchShellCommandContext } from '@workbench-kit/react/workbench';
|
|
3
|
-
|
|
4
|
-
export interface WorkbenchShellCommandRegistration {
|
|
5
|
-
dispose(): void;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function registerWorkbenchShellCommandHandlers(
|
|
9
|
-
registry: CommandRegistry,
|
|
10
|
-
commands: readonly CommandDefinition<WorkbenchShellCommandContext>[],
|
|
11
|
-
getContext: () => WorkbenchShellCommandContext,
|
|
12
|
-
): WorkbenchShellCommandRegistration {
|
|
13
|
-
const disposables = commands.map((command) => {
|
|
14
|
-
const handler = () => {
|
|
15
|
-
command.run?.(getContext());
|
|
16
|
-
};
|
|
17
|
-
const existing = registry.getCommand(command.id);
|
|
18
|
-
|
|
19
|
-
if (existing) {
|
|
20
|
-
const previousHandler = existing.handler;
|
|
21
|
-
existing.handler = handler;
|
|
22
|
-
|
|
23
|
-
return {
|
|
24
|
-
dispose() {
|
|
25
|
-
if (existing.handler === handler) {
|
|
26
|
-
existing.handler = previousHandler;
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return registry.registerCommand({
|
|
33
|
-
category: command.category ?? 'Workbench',
|
|
34
|
-
handler,
|
|
35
|
-
icon: resolveStaticCommandIcon(command),
|
|
36
|
-
id: command.id,
|
|
37
|
-
title: resolveStaticCommandTitle(command),
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
return {
|
|
42
|
-
dispose() {
|
|
43
|
-
[...disposables].reverse().forEach((disposable) => disposable.dispose());
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function resolveStaticCommandTitle(command: CommandDefinition<WorkbenchShellCommandContext>) {
|
|
49
|
-
if (command.title) {
|
|
50
|
-
return command.title;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return typeof command.label === 'string' ? command.label : command.id;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function resolveStaticCommandIcon(command: CommandDefinition<WorkbenchShellCommandContext>) {
|
|
57
|
-
return typeof command.icon === 'string' ? command.icon : undefined;
|
|
58
|
-
}
|
|
1
|
+
import type { CommandDefinition, CommandRegistry } from '@workbench-kit/platform';
|
|
2
|
+
import type { WorkbenchShellCommandContext } from '@workbench-kit/react/workbench';
|
|
3
|
+
|
|
4
|
+
export interface WorkbenchShellCommandRegistration {
|
|
5
|
+
dispose(): void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function registerWorkbenchShellCommandHandlers(
|
|
9
|
+
registry: CommandRegistry,
|
|
10
|
+
commands: readonly CommandDefinition<WorkbenchShellCommandContext>[],
|
|
11
|
+
getContext: () => WorkbenchShellCommandContext,
|
|
12
|
+
): WorkbenchShellCommandRegistration {
|
|
13
|
+
const disposables = commands.map((command) => {
|
|
14
|
+
const handler = () => {
|
|
15
|
+
command.run?.(getContext());
|
|
16
|
+
};
|
|
17
|
+
const existing = registry.getCommand(command.id);
|
|
18
|
+
|
|
19
|
+
if (existing) {
|
|
20
|
+
const previousHandler = existing.handler;
|
|
21
|
+
existing.handler = handler;
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
dispose() {
|
|
25
|
+
if (existing.handler === handler) {
|
|
26
|
+
existing.handler = previousHandler;
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return registry.registerCommand({
|
|
33
|
+
category: command.category ?? 'Workbench',
|
|
34
|
+
handler,
|
|
35
|
+
icon: resolveStaticCommandIcon(command),
|
|
36
|
+
id: command.id,
|
|
37
|
+
title: resolveStaticCommandTitle(command),
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
dispose() {
|
|
43
|
+
[...disposables].reverse().forEach((disposable) => disposable.dispose());
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function resolveStaticCommandTitle(command: CommandDefinition<WorkbenchShellCommandContext>) {
|
|
49
|
+
if (command.title) {
|
|
50
|
+
return command.title;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return typeof command.label === 'string' ? command.label : command.id;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function resolveStaticCommandIcon(command: CommandDefinition<WorkbenchShellCommandContext>) {
|
|
57
|
+
return typeof command.icon === 'string' ? command.icon : undefined;
|
|
58
|
+
}
|