@pstdio/workbench 0.1.0
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 +343 -0
- package/dist/context-key-service-C--cHa0B.js +447 -0
- package/dist/context-key-service-C--cHa0B.js.map +1 -0
- package/dist/core.d.ts +1885 -0
- package/dist/core.js +64 -0
- package/dist/core.js.map +1 -0
- package/dist/extensions.d.ts +1934 -0
- package/dist/extensions.js +1728 -0
- package/dist/extensions.js.map +1 -0
- package/dist/file-renderer-view-DrrhYnb_.js +171 -0
- package/dist/file-renderer-view-DrrhYnb_.js.map +1 -0
- package/dist/icon-B9XolQG8.js +35 -0
- package/dist/icon-B9XolQG8.js.map +1 -0
- package/dist/index.d.ts +1885 -0
- package/dist/index.js +64 -0
- package/dist/index.js.map +1 -0
- package/dist/react.d.ts +2020 -0
- package/dist/react.js +3905 -0
- package/dist/react.js.map +1 -0
- package/dist/storage.d.ts +128 -0
- package/dist/storage.js +87 -0
- package/dist/storage.js.map +1 -0
- package/dist/surface-reconcile-DkRf01ro.js +260 -0
- package/dist/surface-reconcile-DkRf01ro.js.map +1 -0
- package/dist/testing.d.ts +1620 -0
- package/dist/testing.js +46 -0
- package/dist/testing.js.map +1 -0
- package/dist/webview-runtime.d.ts +10 -0
- package/dist/webview-runtime.js +31 -0
- package/dist/webview-runtime.js.map +1 -0
- package/dist/workbench-core-DFpwi8Lo.js +2264 -0
- package/dist/workbench-core-DFpwi8Lo.js.map +1 -0
- package/dist/workbench-menu-paths-CQVH6z4_.js +11 -0
- package/dist/workbench-menu-paths-CQVH6z4_.js.map +1 -0
- package/package.json +95 -0
package/README.md
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
# pstdio-workbench
|
|
2
|
+
|
|
3
|
+
`pstdio-workbench` is the workbench composition layer for Prompt Studio. It provides a typed core for registering contributions and a React workbench for rendering those contributions.
|
|
4
|
+
|
|
5
|
+
## Key Concepts
|
|
6
|
+
|
|
7
|
+
- **Core**: the headless workbench model created by `createWorkbenchCore()`. It owns registries, controllers, and shared state.
|
|
8
|
+
- **Workbench**: the React shell rendered by `Workbench`. It reads the core and turns registered contributions into visible UI.
|
|
9
|
+
- **Module**: an owner for related contributions. Modules register against the core and their contributions are disposed together. See [Contribution Ownership](../../.pstdio/docs/references/workbench/contribution-ownership.md).
|
|
10
|
+
- **Registry**: a typed collection of contributions, such as widgets, tree views, commands, menus, resources, and renderers.
|
|
11
|
+
- **Contribution**: a declarative unit registered by a module. Contributions describe what exists; the workbench decides how to render or route them.
|
|
12
|
+
- **Controller**: a stateful workbench service, such as breadcrumbs, panels, focus, history, command palette, or the session panel.
|
|
13
|
+
- **Area**: a named layout target where widgets can be placed. The workbench owns the chrome around each area.
|
|
14
|
+
- **Resource**: a typed reference to something the workbench can open or navigate to.
|
|
15
|
+
|
|
16
|
+
## Contributions
|
|
17
|
+
|
|
18
|
+
Contributions are the workbench extension points. A module contributes capabilities into the core; the React workbench renders the current state from those contributions. Contributions are grouped by role: layout, views, resources, navigation, and supporting plumbing. Ownership metadata is documented in [Contribution Ownership](../../.pstdio/docs/references/workbench/contribution-ownership.md).
|
|
19
|
+
|
|
20
|
+
## Public Entry Points
|
|
21
|
+
|
|
22
|
+
- `pstdio-workbench/core` exports the headless workbench core, registries, controllers, and contribution types.
|
|
23
|
+
- `pstdio-workbench/react` exports the React shell, view hosts, shared hooks, and `WorkbenchModuleHost` for syncing a dynamic module list into a core.
|
|
24
|
+
- `pstdio-workbench/storage` exports local-storage-backed layout and panel persistence adapters for hosts that want browser persistence with a namespace and scope.
|
|
25
|
+
|
|
26
|
+
## 🏁 Layout Contributions
|
|
27
|
+
|
|
28
|
+
Layout contributions are the glue between an area and a view. They declare where a renderer appears in the shell, what config it receives, and how its placements behave — without owning any UI themselves.
|
|
29
|
+
|
|
30
|
+
### Widgets
|
|
31
|
+
|
|
32
|
+
Pin a renderer to an area as a panel, editor, dashboard, inspector, status item, or overlay. Widgets declare an `area`, `title`, `rendererId`, optional `resourceKinds`, optional sizing and collapsibility, and renderer-owned `config`. They do not contain render code — the shell looks the `rendererId` up in the renderer registry.
|
|
33
|
+
|
|
34
|
+
- Register with `layout.registerWidget()`
|
|
35
|
+
- Set `singleton: true` for one placement total, such as a tree, sidebar, or status view.
|
|
36
|
+
- Non-singleton widgets default to `reuse: "resource"`: one placement per resource URI, with no-resource opens reusing the widget placement.
|
|
37
|
+
- Set `reuse: "none"` for scratch, untitled, or transient views where every open should create a new placement.
|
|
38
|
+
|
|
39
|
+
#### Examples
|
|
40
|
+
|
|
41
|
+
- [`hello-world`](src/examples/hello-world/module.tsx) — minimal widget pinned to `main`.
|
|
42
|
+
- [`foundation`](src/examples/foundation/module.tsx) — widgets in five different areas all backed by one shared renderer.
|
|
43
|
+
|
|
44
|
+
### Placeholders
|
|
45
|
+
|
|
46
|
+
Empty state for areas after every widget in that area closes. Placeholders render through a `rendererId`, can provide area sizing hints, and do not create tabs, placements, or persisted layout entries.
|
|
47
|
+
|
|
48
|
+
- Register with `layout.registerPlaceholder()`
|
|
49
|
+
|
|
50
|
+
#### Examples
|
|
51
|
+
|
|
52
|
+
- [`hello-world`](src/examples/hello-world/module.tsx) — placeholder shown in `main` when the welcome widget is closed.
|
|
53
|
+
|
|
54
|
+
### Menu items
|
|
55
|
+
|
|
56
|
+
Surface commands in the command palette, area headers, tree context menus, or custom menu paths. Menu items reference existing commands, can be ordered and grouped, and can be gated by context expressions through command/menu metadata.
|
|
57
|
+
|
|
58
|
+
- Register with `layout.registerMenuItem(path, item)`
|
|
59
|
+
|
|
60
|
+
#### Examples
|
|
61
|
+
|
|
62
|
+
- [`hello-world`](src/examples/hello-world/module.tsx) — main-header trailing menu item.
|
|
63
|
+
- [`foundation`](src/examples/foundation/module.tsx) — menu items wired into header paths.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 👁️ View Contributions
|
|
68
|
+
|
|
69
|
+
View contributions are the UI itself — code that turns a placement, a tree node, or a collection into something a user sees and interacts with.
|
|
70
|
+
|
|
71
|
+
### Renderers
|
|
72
|
+
|
|
73
|
+
The React or bridge implementation for a widget or placeholder. Renderers turn a placement, resource, config, and workbench context into UI. A widget contributes only a `rendererId`, so the same renderer can back many widgets and a renderer can be supplied by a different layer than its widget.
|
|
74
|
+
|
|
75
|
+
- Register with `renderers.registerRenderer()`
|
|
76
|
+
- Set `keepAlive: true` on the registration to share one persistent subtree across every widget that points at the same `rendererId`. The subtree is mounted once into a stable host that is reparented between widget slots via DOM moves; React state, focus, scroll, and in-flight effects survive area transitions. Kept-alive renderers receive no per-widget input from `render()`; read the active claim with `useWorkbenchClaim()` from `pstdio-workbench/react`.
|
|
77
|
+
|
|
78
|
+
#### Examples
|
|
79
|
+
|
|
80
|
+
- [`hello-world`](src/examples/hello-world/module.tsx) — one renderer per widget, plus a placeholder renderer.
|
|
81
|
+
- [`foundation`](src/examples/foundation/module.tsx) — one renderer reused across five widgets in different areas via `config`.
|
|
82
|
+
- [`renderer-types`](src/examples/renderer-types/module.tsx) — React and bridge renderers registered side by side.
|
|
83
|
+
- [`keep-alive`](src/examples/keep-alive/module.tsx) — keep-alive renderer shared by an attached panel and a floating bubble widget.
|
|
84
|
+
|
|
85
|
+
### Tree Renderers
|
|
86
|
+
|
|
87
|
+
A tree-shaped renderer for side-panel navigation, outlines, resource lists, and contextual hierarchies. Tree renderers expose body sections (`getBody`), optional footer nodes (`getFooter`), and lazy children (`getChildren`); nodes can carry resources, descriptions, inline actions, context menus, and `contextValue`. Placement is left to widgets — a tree renderer auto-registers a widget renderer with the same id, so `layout.registerWidget({ rendererId: <tree id> })` plus `layout.openWidget(<tree id>)` puts the tree in any tree-hosting area.
|
|
88
|
+
|
|
89
|
+
- Register with `renderers.registerTreeRenderer()`
|
|
90
|
+
|
|
91
|
+
#### Examples
|
|
92
|
+
|
|
93
|
+
- [`dashboard`](src/examples/dashboard/modules/shell/project-nav.ts) — primary tree with resource-backed nodes, footer entries, and context menus.
|
|
94
|
+
- [`dynamic-modules`](src/examples/dynamic-modules/modules/explorer-module.tsx) — tree contributed by a module that can be added and removed at runtime.
|
|
95
|
+
|
|
96
|
+
### Data Renderers
|
|
97
|
+
|
|
98
|
+
A Notion/Linear-style data workspace registered as a renderer. Data renderers contribute the schema (tag definitions, grouping/ordering/display options, filter categories), the rows via `executeQuery(state)` (which receives current settings + filters so backends can push filter/sort/pagination down), and row-mutation callbacks. Like tree renderers, a data renderer auto-registers a widget renderer with the same id, so the workspace is placed via `layout.registerWidget({ rendererId: <data renderer id> })` and opened with `layout.openWidget(...)`.
|
|
99
|
+
|
|
100
|
+
- Register with `renderers.registerDataRenderer()`
|
|
101
|
+
|
|
102
|
+
#### Examples
|
|
103
|
+
|
|
104
|
+
- [`data-renderer`](src/examples/data-renderer/module.tsx) — focused showcase: schema, mock rows, and renderer-owned controls.
|
|
105
|
+
- [`dashboard`](src/examples/dashboard/modules/tickets/collections/ticket-data.ts) — ticket workspace integrated into the dashboard shell.
|
|
106
|
+
|
|
107
|
+
### Breadcrumb (TODO: make it a renderer as well)
|
|
108
|
+
|
|
109
|
+
`<WorkbenchBreadcrumbView workbench={workbench} />` is the React view that turns the breadcrumb controller state into a rendered trail. It subscribes to `workbench.breadcrumbs.store`, builds `BreadcrumbItem`s from the controller items, and returns `null` when the trail is empty. The default `Workbench` top header renders it automatically; embed it directly when a host renders custom chrome (a main-area header, a tab strip, an embedded panel). Modules drive the trail through `ctx.breadcrumbs.setItems(...)` from resource openers — each call replaces the trail, so the opener fully controls what is shown.
|
|
110
|
+
|
|
111
|
+
- Render with `<WorkbenchBreadcrumbView workbench={workbench} />` from `pstdio-workbench/react`
|
|
112
|
+
- Drive items with `workbench.breadcrumbs.setItems([...])` (typically from a resource opener)
|
|
113
|
+
|
|
114
|
+
#### Examples
|
|
115
|
+
|
|
116
|
+
- [`dashboard`](src/examples/dashboard/modules/shell/components/dashboard-main-header.tsx) — custom main-area header that places the view alongside workspace controls.
|
|
117
|
+
- [`onboarding`](src/examples/onboarding/breadcrumb-module.tsx) — three-level trail set from a page opener.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
A typical surface combines both layers: a **renderer** supplies the UI, a **widget** places it in an area with optional `config`, and `layout.openWidget()` creates the placement the user actually sees. Pick the narrowest contribution that matches what you are adding:
|
|
122
|
+
|
|
123
|
+
- Add a **widget** to claim a spot in an area for a renderer.
|
|
124
|
+
- Add a **renderer** to supply the React or bridge UI for a widget or placeholder.
|
|
125
|
+
- Add a **tree renderer** for navigable hierarchy and resource discovery, and place it with a widget.
|
|
126
|
+
- Add a **placeholder** for area-level empty state, not for normal content.
|
|
127
|
+
|
|
128
|
+
## 🗂️ Resource Contributions
|
|
129
|
+
|
|
130
|
+
Resource contributions define typed objects the workbench can open, route, or resolve from product data. They keep trees, navigation, and history speaking the same resource language.
|
|
131
|
+
|
|
132
|
+
### Resource kinds
|
|
133
|
+
|
|
134
|
+
Declare typed things the workbench can open. Resource refs carry `kind`, `uri`, optional `id`, labels, icons, and metadata. Resource kinds make navigation, openers, and history speak the same language.
|
|
135
|
+
|
|
136
|
+
- Register with `resources.registerKind()`
|
|
137
|
+
- Use the standard icon names for common resources: project `folder-root`, workspace `computer`, worktree `git-pull-request-draft`, ticket `component`, data renderer `square-kanban`, settings `settings`.
|
|
138
|
+
|
|
139
|
+
#### Examples
|
|
140
|
+
|
|
141
|
+
- [`renderer-types`](src/examples/renderer-types/module.tsx) — single-kind module.
|
|
142
|
+
- [`navigation`](src/examples/navigation/module.tsx) — multiple kinds participating in routing.
|
|
143
|
+
|
|
144
|
+
### Resource openers
|
|
145
|
+
|
|
146
|
+
Route a resource to a widget placement. Openers declare `canOpen(resource)` and `open(resource, input)`. `openResource()` uses the highest-priority opener, so keep default openers broad and alternate views narrow.
|
|
147
|
+
|
|
148
|
+
- Register with `resources.registerOpener()`
|
|
149
|
+
|
|
150
|
+
#### Examples
|
|
151
|
+
|
|
152
|
+
- [`renderer-types`](src/examples/renderer-types/module.tsx) — opener routing one resource kind to one of two widgets.
|
|
153
|
+
- [`navigation`](src/examples/navigation/module.tsx) — openers used by parsed navigation targets.
|
|
154
|
+
|
|
155
|
+
### Resource providers
|
|
156
|
+
|
|
157
|
+
Look up resources by kind, uri, or search input. Providers let features resolve resources without knowing where they are stored, which keeps trees and navigation decoupled from product data access.
|
|
158
|
+
|
|
159
|
+
- Register with `resources.registerProvider()`
|
|
160
|
+
|
|
161
|
+
#### Examples
|
|
162
|
+
|
|
163
|
+
- [`dashboard`](src/examples/dashboard/modules/dashboard.tsx) — provider behind the ticket DataView.
|
|
164
|
+
|
|
165
|
+
## 🧭 Navigation Contributions
|
|
166
|
+
|
|
167
|
+
Navigation contributions turn incoming locations and resolved workbench targets into concrete workbench actions. They keep URL parsing, command dispatch, view opening, and resource routing centralized.
|
|
168
|
+
|
|
169
|
+
### Navigation parsers
|
|
170
|
+
|
|
171
|
+
Turn ingress locations into workbench targets. Parsers convert URLs or location strings into resource, view, command, or compound targets. Compound targets are dispatched transactionally through a checkpoint.
|
|
172
|
+
|
|
173
|
+
- Register with `navigation.registerParser()`
|
|
174
|
+
|
|
175
|
+
#### Examples
|
|
176
|
+
|
|
177
|
+
- [`navigation`](src/examples/navigation/module.tsx) — parses URL-like locations into typed targets.
|
|
178
|
+
|
|
179
|
+
### Navigation navigators
|
|
180
|
+
|
|
181
|
+
Custom dispatch behavior for navigation targets. Navigators let modules extend how resolved targets are opened while still using the shared navigation service.
|
|
182
|
+
|
|
183
|
+
- Register with `navigation.registerNavigator()`
|
|
184
|
+
|
|
185
|
+
## Other Contributions
|
|
186
|
+
|
|
187
|
+
Supporting contributions make view, layout, resource, and navigation contributions useful. They define actions, persistence, scoping, and preferences without directly owning a workbench area.
|
|
188
|
+
|
|
189
|
+
### Commands
|
|
190
|
+
|
|
191
|
+
Any executable workbench action. Commands are the primitive behind menus, keybindings, tree actions, notification actions, and command palette entries. Handlers can expose `isEnabled()` and execution failures emit `commands.onDidExecuteError`.
|
|
192
|
+
|
|
193
|
+
- Register with `commands.registerCommand()`
|
|
194
|
+
|
|
195
|
+
#### Examples
|
|
196
|
+
|
|
197
|
+
- [`hello-world`](src/examples/hello-world/module.tsx) — command that opens a widget.
|
|
198
|
+
- [`renderer-types`](src/examples/renderer-types/module.tsx) — commands opening different placements.
|
|
199
|
+
|
|
200
|
+
### Keybindings
|
|
201
|
+
|
|
202
|
+
Keyboard access to commands. Keybindings reference command ids and can include a `when` expression such as `project.active && !dialog.open`.
|
|
203
|
+
|
|
204
|
+
- Register with `keybindings.registerKeybinding()`
|
|
205
|
+
|
|
206
|
+
#### Examples
|
|
207
|
+
|
|
208
|
+
- [`foundation`](src/examples/foundation/module.tsx) — keybinding gated by a context key.
|
|
209
|
+
- [`random`](src/examples/random/modules/random-workbench.tsx) — keybindings paired with mode-scoped commands.
|
|
210
|
+
|
|
211
|
+
### Context keys
|
|
212
|
+
|
|
213
|
+
Conditional command, menu, and keybinding behavior. Module contexts create scoped context keys that are cleaned up with the module. Use context keys for current mode, focused surface, selection state, and other workbench-level conditions.
|
|
214
|
+
|
|
215
|
+
- Set through the module context with `context.set()`
|
|
216
|
+
|
|
217
|
+
#### Examples
|
|
218
|
+
|
|
219
|
+
- [`foundation`](src/examples/foundation/module.tsx) — sets `foundation.host` for menu and keybinding gating.
|
|
220
|
+
- [`keep-alive`](src/examples/keep-alive/module.tsx) — context key driving kept-alive subtree visibility.
|
|
221
|
+
|
|
222
|
+
### Modes
|
|
223
|
+
|
|
224
|
+
Temporary bundles of contributions for workspace modes such as project, settings, review, or dashboard. Activating a mode runs its contribution function; switching modes disposes the previous mode's mode-scoped contributions.
|
|
225
|
+
|
|
226
|
+
- Register with `modes.registerMode()`
|
|
227
|
+
|
|
228
|
+
#### Examples
|
|
229
|
+
|
|
230
|
+
- [`workbench-modes`](src/examples/workbench-modes/modules/project-mode.tsx) — switching between mode-scoped bundles.
|
|
231
|
+
- [`dashboard`](src/examples/dashboard/modules/project-mode.tsx) — project and settings modes side by side.
|
|
232
|
+
|
|
233
|
+
### Preference schemas
|
|
234
|
+
|
|
235
|
+
Typed settings contributed by a module or runtime extension. Schemas define the shape and default behavior of workbench preferences, while the host can provide scoped persistence.
|
|
236
|
+
|
|
237
|
+
- Register with `preferences.registerSchema()`
|
|
238
|
+
|
|
239
|
+
#### Examples
|
|
240
|
+
|
|
241
|
+
- [`preferences`](src/examples/preferences/module.tsx) — schema registration with user and workspace-scoped preference values.
|
|
242
|
+
|
|
243
|
+
### Notifications
|
|
244
|
+
|
|
245
|
+
Toast-style messages from modules or extensions. Notifications can include command-backed actions and are rendered by workbench chrome rather than by individual views.
|
|
246
|
+
|
|
247
|
+
- Show with `notifications.show()`
|
|
248
|
+
|
|
249
|
+
#### Examples
|
|
250
|
+
|
|
251
|
+
- [`dynamic-modules`](src/examples/dynamic-modules/modules/diagnostics-module.tsx) — diagnostics module emitting toasts.
|
|
252
|
+
- [`navigation`](src/examples/navigation/module.tsx) — notification surfaced from a navigation flow.
|
|
253
|
+
|
|
254
|
+
### Themes
|
|
255
|
+
|
|
256
|
+
The React workbench owns the shared `@pstdio/ui` theme preference system through `WorkbenchThemeProvider`. The available theme set lives on the workbench: `workbench.themes` holds contributed themes, and `useWorkbenchThemePreferences(workbench)` reads the built-in themes plus those. `<Workbench />` feeds that set into its own provider, so a contributed theme appears in the picker only while its contributor stays registered. The workbench also renders the shared `Toaster` viewport for workbench notifications and toast calls from workbench modules. Hosts that render their own chrome (sizing boxes or app-level loading screens) wrap it in `WorkbenchThemeProvider` with the same set so that chrome is themed too. Workbench chrome reads VS Code-compatible color theme tokens such as `editor.background`, `sideBar.background`, `panel.background`, and `editorWidget.background` when extension themes provide them.
|
|
257
|
+
|
|
258
|
+
#### Examples
|
|
259
|
+
|
|
260
|
+
- [`extension-themes`](src/examples/extension-themes/module.tsx) — extensions registered as workbench modules, enabled and disabled at runtime, contributing VS Code-compatible color themes that restyle the workbench chrome.
|
|
261
|
+
|
|
262
|
+
### Terminal
|
|
263
|
+
|
|
264
|
+
Terminals are a host-owned workbench surface, not extension-composed chrome. `workbench.terminal` (a core controller) owns the session registry; hosts inject how sessions actually open with `workbench.terminal.setSessionOpener(...)` — a real PTY transport in production, `createScriptedTerminalBridge` from `@pstdio/ui/terminal` in stories and the extension testbench. `createWorkbenchTerminalModule()` registers the terminal panel in the `secondary` area plus the `workbench.terminal.open` command; the panel renders the shared `Terminal` component from `@pstdio/ui/terminal`. Closing the panel kills its session; disposing the controller kills every live session.
|
|
265
|
+
|
|
266
|
+
Extension webviews never receive PTY handles. A webview that declares the `terminal.session` capability talks to the same session registry through serializable operations (`open`/`write`/`resize`/`kill`/`subscribe`), with output and exit events pushed over the bridge's host-event channel — `createTerminalSessionBridge(host)` from `@pstdio/sdk/extensions` wraps that protocol into a bridge the `Terminal` component accepts.
|
|
267
|
+
|
|
268
|
+
#### Examples
|
|
269
|
+
|
|
270
|
+
- [`workbench-modes`](src/examples/workbench-modes/module.tsx) — workspace mode opening the host-owned terminal panel against a scripted backend.
|
|
271
|
+
- [`workbench.stories`](src/examples/workbench.stories.tsx) — `HostTerminal` story with the panel driven by `createScriptedTerminalBridge`.
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
Register related contributions inside one **workbench module** so they share ownership and disposal. For example, a ticket collection module usually contributes a resource kind, resource opener, widget, renderer, tree renderer, commands, and menu items together.
|
|
276
|
+
|
|
277
|
+
## Core
|
|
278
|
+
|
|
279
|
+
The core is UI-independent. It is the source of truth that modules write to and the React workbench reads from.
|
|
280
|
+
A host normally creates one core, registers modules into it, and renders `<Workbench workbench={workbench} />`.
|
|
281
|
+
|
|
282
|
+
## Nomenclature
|
|
283
|
+
|
|
284
|
+
- **Workbench core**: the headless object created by `createWorkbenchCore()`. It owns the registries, controllers, and shared workbench state.
|
|
285
|
+
- **Registry**: a typed collection of contributions. The workbench has registries for commands, keybindings, resources, layout (widgets, placeholders, menu items), renderers (widget renderers and tree renderers), modes, navigation, notifications, and preferences.
|
|
286
|
+
- **Controller**: a stateful slice of workbench UX exposed alongside the registries — breadcrumbs, command palette open/close state, focus, history, side-panel open/close state, and session-panel mode.
|
|
287
|
+
- **Contribution**: a declarative unit added to a registry, such as a command, menu item, resource kind, widget, renderer, tree renderer, mode, or DataView.
|
|
288
|
+
- **Workbench module**: contribution owner registered with `workbench.registerModule(module)` and removed with `workbench.unregisterModule(moduleId)`. Module disposables are tracked and disposed together. See [Contribution Ownership](../../.pstdio/docs/references/workbench/contribution-ownership.md).
|
|
289
|
+
- **Runtime extension**: extension metadata from `pstdio-extensions` that a host maps into workbench modules at the trust boundary.
|
|
290
|
+
- **Workbench**: the React frame rendered by `Workbench`. It arranges the workbench areas, command palette, side panels, and session panel from the workbench core only.
|
|
291
|
+
- **Area**: a named layout target. See the Areas Overview table below.
|
|
292
|
+
- **Widget contribution**: a registered view definition in the layout registry. Widgets declare an area, a `rendererId`, and optional renderer-owned `config`.
|
|
293
|
+
- **Widget placement**: an opened instance of a widget contribution in an area. Placements track active widget, resource URI, title, pinned/closable flags, and placement ownership.
|
|
294
|
+
- **Tree renderer contribution**: a tree-shaped renderer registered under `renderers`. Provides `getBody` (sectioned body), optional `getFooter` (flat footer node list), and `getChildren` (lazy children). Auto-registers a widget renderer with the same id so widgets place trees through `layout.registerWidget`.
|
|
295
|
+
- **Data renderer contribution**: a data-workspace renderer registered under `renderers`. Provides a schema, `executeQuery(state)` rows, and row-mutation callbacks. Auto-registers a widget renderer with the same id so widgets place the workspace through `layout.registerWidget`. The presentational layer is `<DataRenderer>` from `@pstdio/ui`.
|
|
296
|
+
- **Placeholder**: an empty-state contribution rendered only when an area has no widget placements. Placeholders do not appear in tabs.
|
|
297
|
+
- **Renderer**: code that turns a widget placement into UI. The widget host looks up `rendererId` in `workbench.renderers` and inserts the returned React node.
|
|
298
|
+
- **Resource**: a typed object reference with `kind`, `id`, `uri`, and label metadata.
|
|
299
|
+
- **Resource opener**: routing logic that maps a resource to a widget placement.
|
|
300
|
+
- **Command**: an executable action registered in the command registry. Errors raised during execution emit `workbench.commands.onDidExecuteError`.
|
|
301
|
+
- **Menu path**: a stable location where commands are surfaced, such as the command palette, an area header, or a tree node context menu.
|
|
302
|
+
- **Keybinding**: a keyboard shortcut bound to a command, optionally gated by a context expression.
|
|
303
|
+
- **Context key**: boolean or scalar workbench state used by commands, menus, and keybindings to decide when they are active.
|
|
304
|
+
- **Preference schema**: typed settings contributed by workbench modules or runtime extensions.
|
|
305
|
+
- **Mode**: a named bundle of temporary contributions activated through `workbench.modes`. Switching modes disposes the previous mode's activation result.
|
|
306
|
+
- **Tree view section**: a group of nodes inside a tree renderer's `getBody`, with an optional label, optional collapsible flag, and inline actions.
|
|
307
|
+
- **Notification**: a transient workbench message emitted by workbench modules or extensions. Notifications can include command-backed actions and are rendered as workbench toast chrome.
|
|
308
|
+
- **Session panel**: the assistant surface controlled by `workbench.sessionPanel`. It can be `attached`, `bubble`, or `closed`, and is rendered from the `floating` area.
|
|
309
|
+
|
|
310
|
+
## Areas Overview
|
|
311
|
+
|
|
312
|
+
Workbench areas are named layout targets used by widget contributions. They describe where a widget belongs in the workbench; the workbench decides the exact chrome, tabs, resize handles, and visibility behavior.
|
|
313
|
+
|
|
314
|
+
Use `layout.registerPlaceholder()` for an area empty state that should render only after all widgets in that area close. Placeholders are not widget placements, so they do not affect tab lists.
|
|
315
|
+
|
|
316
|
+
Most panels are paired with a `<panel>-header` area that the workbench renders directly above the panel. Widgets placed in a header area use a bottom border by default. Set `headerBorderBottom: false` on a widget contribution to let that widget own the header separation.
|
|
317
|
+
|
|
318
|
+
| Area | Workbench location | Typical use |
|
|
319
|
+
| -------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
320
|
+
| `top` | Top of the workbench, right of `activityBar` and `left` | Breadcrumbs, active context, compact global controls, left-panel reopen action |
|
|
321
|
+
| `activityBar` | Narrow rail on the far left | Top-level mode or workspace switching |
|
|
322
|
+
| `left-header` | Header above `left` | Project brand, primary navigation header actions |
|
|
323
|
+
| `left` | Primary left side panel | Navigation trees, registries, project outlines, resource lists |
|
|
324
|
+
| `main-header` | Header above `main`, `main-left`, `main-right` | Active editor context, compact main controls, panel reopen actions |
|
|
325
|
+
| `main-left-header` | Header above `main-left` | Secondary navigation header |
|
|
326
|
+
| `main-left` | Resizable panel to the left of `main` | Per-mode navigation trees (settings, document outlines) |
|
|
327
|
+
| `main` | Central content region | Editors, detail pages, dashboards, primary resource views |
|
|
328
|
+
| `main-right-header` | Header above `main-right` | Inspector controls, contextual filters |
|
|
329
|
+
| `main-right` | Resizable panel to the right of `main` | Inspectors, properties, contextual details |
|
|
330
|
+
| `main-bottom-header` | Header above `main-bottom` | Tab strips, log filters |
|
|
331
|
+
| `main-bottom` | Resizable panel below `main`, `main-left`, `main-right` | Diagnostics, activity, logs, terminals, background task output |
|
|
332
|
+
| `status` | Bottom status strip | Compact state, counters, sync status, environment indicators |
|
|
333
|
+
| `overlay` | Layer above the workbench | Modal flows, blocking prompts, transient overlays |
|
|
334
|
+
| `floating-header` | Header of the session panel | Session-panel title, mode toggle |
|
|
335
|
+
| `floating` | Session panel surface | Assistant or session UI, either attached or floating |
|
|
336
|
+
|
|
337
|
+
The command palette, toast notifications, and resize handles are workbench chrome, not workbench areas. Use the `AreaMap` Storybook story to see the current area placement rendered through the real `Workbench`.
|
|
338
|
+
|
|
339
|
+
## Header Actions
|
|
340
|
+
|
|
341
|
+
Each area header renders command-backed actions from two menu paths derived from `headerLeadingMenuPath(area)` and `headerTrailingMenuPath(area)`. The top header reuses these paths under `workbenchTopHeaderLeadingMenuPath` and `workbenchTopHeaderTrailingMenuPath`. Workbench modules can register commands and add menu actions to those paths to expose compact header controls while keeping breadcrumbs and the `top` area as workbench-owned chrome.
|
|
342
|
+
|
|
343
|
+
Runtime extensions should only target documented public slots through descriptors; hosts map those descriptors into workbench modules instead of giving extension packages direct workbench access.
|