@workbench-kit/shell-react 0.0.2-prototype.0.2.15 → 0.0.2-prototype.0.2.17

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workbench-kit/shell-react",
3
- "version": "0.0.2-prototype.0.2.15",
3
+ "version": "0.0.2-prototype.0.2.17",
4
4
  "private": false,
5
5
  "sideEffects": [
6
6
  "**/*.css"
@@ -24,13 +24,13 @@
24
24
  "@xyflow/react": "^12.11.2",
25
25
  "jsonata": "^2.2.0",
26
26
  "react-table-mapping": "^1.0.3",
27
- "@workbench-kit/platform": "0.0.2-prototype.0.2.15",
28
- "@workbench-kit/field-remap": "0.0.2-prototype.0.2.15",
29
- "@workbench-kit/tokens": "0.0.2-prototype.0.2.15",
30
- "@workbench-kit/react": "0.0.2-prototype.0.2.15",
31
- "@workbench-kit/workbench-config": "0.0.2-prototype.0.2.15",
32
- "@workbench-kit/workbench-core": "0.0.2-prototype.0.2.15",
33
- "@workbench-kit/workspace": "0.0.2-prototype.0.2.15"
27
+ "@workbench-kit/react": "0.0.2-prototype.0.2.17",
28
+ "@workbench-kit/tokens": "0.0.2-prototype.0.2.17",
29
+ "@workbench-kit/workbench-config": "0.0.2-prototype.0.2.17",
30
+ "@workbench-kit/field-remap": "0.0.2-prototype.0.2.17",
31
+ "@workbench-kit/workbench-core": "0.0.2-prototype.0.2.17",
32
+ "@workbench-kit/platform": "0.0.2-prototype.0.2.17",
33
+ "@workbench-kit/workspace": "0.0.2-prototype.0.2.17"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "react": "^19.0.0",
@@ -1,5 +1,6 @@
1
1
  export const SAMPLE_FIELD_REMAP_VIEW_RENDER_KIND =
2
2
  'workbench-kit.samples.field-remap.view' as const;
3
+ export const SAMPLE_FIELD_REMAP_VIEW_ID = 'workbench-kit.samples.field-remap.panel' as const;
3
4
 
4
5
  export interface SampleFieldRemapViewRenderData {
5
6
  readonly kind: typeof SAMPLE_FIELD_REMAP_VIEW_RENDER_KIND;
@@ -1,5 +1,6 @@
1
1
  import type { JSX } from 'react';
2
2
  import { WorkbenchActionSidebar } from '@workbench-kit/react/layout';
3
+ import type { ViewHostFactory } from '@workbench-kit/workbench-core';
3
4
 
4
5
  import './view.css';
5
6
 
@@ -10,6 +11,7 @@ import {
10
11
  } from './samples.js';
11
12
  import {
12
13
  isSampleFieldRemapViewRenderData,
14
+ SAMPLE_FIELD_REMAP_VIEW_ID,
13
15
  SAMPLE_FIELD_REMAP_VIEW_RENDER_KIND,
14
16
  type SampleFieldRemapViewRenderData,
15
17
  } from './view-data.js';
@@ -43,6 +45,23 @@ export interface SampleFieldRemapViewProps {
43
45
  readonly className?: string | undefined;
44
46
  }
45
47
 
48
+ export const SAMPLE_FIELD_REMAP_VIEW_HOST_FACTORY: ViewHostFactory = {
49
+ id: 'workbench-kit.samples.field-remap.react-view-host',
50
+ priority: 100,
51
+ canCreate: ({ viewId }) => viewId === SAMPLE_FIELD_REMAP_VIEW_ID,
52
+ create: ({ provider }) => {
53
+ const host = provider.resolveViewHost();
54
+ const render = host.render.bind(host);
55
+
56
+ host.render = () => {
57
+ const renderData = render();
58
+ return isSampleFieldRemapViewRenderData(renderData) ? <SampleFieldRemapView /> : renderData;
59
+ };
60
+
61
+ return host;
62
+ },
63
+ };
64
+
46
65
  /** Sidebar: catalog of field-remap / table-mapping samples. */
47
66
  export function SampleFieldRemapView({ className }: SampleFieldRemapViewProps = {}): JSX.Element {
48
67
  const editorService = useEditorService();
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@ export {
4
4
  WorkbenchProvider,
5
5
  useWorkbench,
6
6
  type WorkbenchContextValue,
7
+ type WorkbenchProviderProps,
7
8
  type WorkbenchStorageAdapter,
8
9
  type WorkbenchWorkspaceHostPort,
9
10
  } from './shell/provider.js';
@@ -80,7 +81,11 @@ export {
80
81
  isBuiltinEditorMarkdownPreviewRenderData,
81
82
  type BuiltinEditorMarkdownPreviewRenderData,
82
83
  } from './editor/markdown-document-view-data.js';
83
- export { SampleJdwLabView, type SampleJdwLabViewProps } from './jdw/lab-view.js';
84
+ export {
85
+ SAMPLE_JDW_LAB_VIEW_HOST_FACTORY,
86
+ SampleJdwLabView,
87
+ type SampleJdwLabViewProps,
88
+ } from './jdw/lab-view.js';
84
89
  export { JdwWidgetFormView, type JdwWidgetFormViewProps } from './jdw/widget-form-view.js';
85
90
  export { JdwWidgetPreviewView, type JdwWidgetPreviewViewProps } from './jdw/widget-preview-view.js';
86
91
  export {
@@ -186,6 +191,7 @@ export {
186
191
  type FieldRemapSampleId,
187
192
  } from './field-remap/samples.js';
188
193
  export {
194
+ SAMPLE_FIELD_REMAP_VIEW_HOST_FACTORY,
189
195
  SampleFieldRemapView,
190
196
  buildFieldRemapEditorUri,
191
197
  parseFieldRemapEditorSampleId,
@@ -1,4 +1,5 @@
1
1
  export const SAMPLE_JDW_LAB_VIEW_RENDER_KIND = 'workbench-kit.samples.jdw.view' as const;
2
+ export const SAMPLE_JDW_LAB_VIEW_ID = 'workbench-kit.samples.jdw.panel' as const;
2
3
 
3
4
  export interface SampleJdwLabViewRenderData {
4
5
  readonly kind: typeof SAMPLE_JDW_LAB_VIEW_RENDER_KIND;
@@ -1,4 +1,5 @@
1
1
  import { WorkbenchActionSidebar } from '@workbench-kit/react/layout';
2
+ import type { ViewHostFactory } from '@workbench-kit/workbench-core';
2
3
 
3
4
  import './lab-view.css';
4
5
 
@@ -7,6 +8,7 @@ import { useActiveEditorTab } from '../editor/use-editor.js';
7
8
  import { useActiveWorkspacePath } from '../explorer/use-active-workspace-path.js';
8
9
  import {
9
10
  isSampleJdwLabViewRenderData,
11
+ SAMPLE_JDW_LAB_VIEW_ID,
10
12
  SAMPLE_JDW_LAB_VIEW_RENDER_KIND,
11
13
  type SampleJdwLabViewRenderData,
12
14
  } from './lab-view-data.js';
@@ -24,6 +26,31 @@ export interface SampleJdwLabViewProps {
24
26
  readonly widgetTreePath?: string | undefined;
25
27
  }
26
28
 
29
+ export const SAMPLE_JDW_LAB_VIEW_HOST_FACTORY: ViewHostFactory = {
30
+ id: 'workbench-kit.samples.jdw.react-view-host',
31
+ priority: 100,
32
+ canCreate: ({ viewId }) => viewId === SAMPLE_JDW_LAB_VIEW_ID,
33
+ create: ({ provider }) => {
34
+ const host = provider.resolveViewHost();
35
+ const render = host.render.bind(host);
36
+
37
+ host.render = () => {
38
+ const renderData = render();
39
+
40
+ return isSampleJdwLabViewRenderData(renderData) ? (
41
+ <SampleJdwLabView
42
+ templateJdwPath={renderData.templateJdwPath}
43
+ widgetTreePath={renderData.widgetTreePath}
44
+ />
45
+ ) : (
46
+ renderData
47
+ );
48
+ };
49
+
50
+ return host;
51
+ },
52
+ };
53
+
27
54
  function pathMatches(activePath: string | undefined, candidate: string): boolean {
28
55
  if (!activePath) {
29
56
  return false;
@@ -34,6 +34,7 @@ import {
34
34
  type WorkbenchEditorSavePort,
35
35
  type WorkbenchExtensionDescription,
36
36
  type WorkbenchLayoutStateInput,
37
+ type ViewHostFactory,
37
38
  } from '@workbench-kit/workbench-core';
38
39
  import {
39
40
  ContextKeyService,
@@ -101,6 +102,9 @@ const DEFAULT_AVAILABLE_EXTENSIONS = [
101
102
  ...SAMPLE_WORKBENCH_EXTENSIONS,
102
103
  ] as const;
103
104
 
105
+ const EMPTY_HOST_THEMES: readonly WorkbenchHostThemeRegistration[] = Object.freeze([]);
106
+ const EMPTY_USER_COMMANDS: readonly WorkbenchUserCommandDefinition[] = Object.freeze([]);
107
+
104
108
  export interface WorkbenchProviderProps {
105
109
  availableExtensions?: readonly WorkbenchExtensionDescription[];
106
110
  children: ReactNode;
@@ -140,6 +144,8 @@ export interface WorkbenchProviderProps {
140
144
  persistLayout?: boolean;
141
145
  persistLocalPreferences?: boolean;
142
146
  userCommands?: readonly WorkbenchUserCommandDefinition[];
147
+ /** Host-owned framework adapters registered before extension activation. */
148
+ viewHostFactories?: readonly ViewHostFactory[] | undefined;
143
149
  workspaceHostPort?: WorkbenchWorkspaceHostPort | undefined;
144
150
  }
145
151
 
@@ -192,7 +198,7 @@ export function WorkbenchProvider({
192
198
  extensionIntegrityMode = 'off',
193
199
  extensionsConfig,
194
200
  extensionsLock,
195
- hostThemes = [],
201
+ hostThemes = EMPTY_HOST_THEMES,
196
202
  initialEditorState,
197
203
  initialKeybindingOverrides,
198
204
  initialLayout,
@@ -211,7 +217,8 @@ export function WorkbenchProvider({
211
217
  persistKeybindingOverrides,
212
218
  persistLayout,
213
219
  persistLocalPreferences,
214
- userCommands = [],
220
+ userCommands = EMPTY_USER_COMMANDS,
221
+ viewHostFactories,
215
222
  workspaceHostPort,
216
223
  }: WorkbenchProviderProps) {
217
224
  const hostAvailableExtensions = availableExtensions ?? DEFAULT_AVAILABLE_EXTENSIONS;
@@ -335,6 +342,9 @@ export function WorkbenchProvider({
335
342
 
336
343
  const services = useMemo<WorkbenchProviderServices>(() => {
337
344
  const extensionRegistry = new ExtensionRegistry();
345
+ const viewHostFactoryDisposables = (viewHostFactories ?? []).map((factory) =>
346
+ extensionRegistry.viewHostFactories.register(factory),
347
+ );
338
348
  const editorDocumentViewProviders = extensionRegistry.editorDocumentViews;
339
349
  const editorDocumentViewProviderDisposables = [
340
350
  ...(includeDefaultDocumentViewProviders === false
@@ -433,6 +443,9 @@ export function WorkbenchProvider({
433
443
  for (const disposable of editorDocumentViewProviderDisposables) {
434
444
  disposable.dispose();
435
445
  }
446
+ for (const disposable of viewHostFactoryDisposables) {
447
+ disposable.dispose();
448
+ }
436
449
  extensionRegistry.dispose();
437
450
  layoutService.dispose();
438
451
  preferenceService.dispose();
@@ -465,6 +478,7 @@ export function WorkbenchProvider({
465
478
  resolvedInitialLayout,
466
479
  resolvedInitialLocalPreferences,
467
480
  userCommands,
481
+ viewHostFactories,
468
482
  workspaceHostPort,
469
483
  ]);
470
484
 
@@ -473,7 +487,11 @@ export function WorkbenchProvider({
473
487
  return undefined;
474
488
  }
475
489
 
476
- const disposable = services.layoutService.onDidChangeLayout(({ state }) => {
490
+ const disposable = services.layoutService.onDidChangeLayout(({ state, transient }) => {
491
+ if (transient) {
492
+ return;
493
+ }
494
+
477
495
  writePersistedWorkbenchLayout(state, layoutStorageKey, layoutStorage);
478
496
  });
479
497
 
@@ -70,7 +70,12 @@ import {
70
70
  createWorkbenchShellActivityItems,
71
71
  } from './model.js';
72
72
  import { mergeWorkbenchStatusSections } from '../workbench/status-sections.js';
73
- import { renderDefaultBottomPanel, renderDefaultPrimarySidebar } from './view-host.js';
73
+ import {
74
+ getVisibleWorkbenchViews,
75
+ renderDefaultAuxiliarySidebar,
76
+ renderDefaultBottomPanel,
77
+ renderDefaultPrimarySidebar,
78
+ } from './view-host.js';
74
79
  import { WorkbenchShellTitleBarLayoutControls } from './titlebar-layout-controls.js';
75
80
  import { WorkbenchProfileModal, type WorkbenchProfileInput } from '../workbench/profile-modal.js';
76
81
  import { useContextKeyRevision } from '../commands/use-context-key-revision.js';
@@ -122,6 +127,8 @@ export interface WorkbenchShellProps {
122
127
  onLocaleChange?: ((locale: string) => void) | undefined;
123
128
  locale?: string | undefined;
124
129
  onStatusItemActivate?: (item: StatusBarItemModel) => void;
130
+ /** Host-owned dialogs and command surfaces rendered inside the shell overlay container. */
131
+ overlays?: ReactNode;
125
132
  primarySidebar?: ReactNode;
126
133
  profile?: WorkbenchProfileInput | undefined;
127
134
  profileExtraContent?: ReactNode;
@@ -174,6 +181,7 @@ export function WorkbenchShell({
174
181
  onShellPresetChange,
175
182
  onThemeChange,
176
183
  onStatusItemActivate,
184
+ overlays,
177
185
  primarySidebar,
178
186
  profile,
179
187
  profileExtraContent,
@@ -205,6 +213,10 @@ export function WorkbenchShell({
205
213
  preferenceService,
206
214
  } = useWorkbench();
207
215
  const contextKeyRevision = useContextKeyRevision(contextKeyService);
216
+ const contextKeySnapshot = useMemo(
217
+ () => contextKeyService.createSnapshot(),
218
+ [contextKeyRevision, contextKeyService],
219
+ );
208
220
  const forceRender = useForceRender();
209
221
  const [preferenceRevision, bumpPreferenceRevision] = useReducer((count: number) => count + 1, 0);
210
222
  const [isHelpOpen, setHelpOpen] = useState(false);
@@ -247,9 +259,9 @@ export function WorkbenchShell({
247
259
  () =>
248
260
  filterActivitiesByWhenClause(
249
261
  extensionRegistry.activities.getActivities(),
250
- contextKeyService.createSnapshot(),
262
+ contextKeySnapshot,
251
263
  ),
252
- [contextKeyRevision, contextKeyService, extensionRegistry],
264
+ [contextKeySnapshot, extensionRegistry],
253
265
  );
254
266
  const activityItems = sortActivityBarItems(
255
267
  createWorkbenchShellActivityItems({
@@ -429,20 +441,44 @@ export function WorkbenchShell({
429
441
  return;
430
442
  }
431
443
 
432
- for (const view of extensionRegistry.views.getViews(activeViewContainerId)) {
444
+ for (const view of getVisibleWorkbenchViews(
445
+ extensionRegistry,
446
+ activeViewContainerId,
447
+ contextKeySnapshot,
448
+ )) {
433
449
  void extensionRegistry.activateView(view.id).then(forceRender);
434
450
  }
435
- }, [activeViewContainerId, extensionRegistry, forceRender]);
451
+ }, [activeViewContainerId, contextKeySnapshot, extensionRegistry, forceRender]);
436
452
 
437
453
  useEffect(() => {
438
454
  if (!activePanelViewContainerId) {
439
455
  return;
440
456
  }
441
457
 
442
- for (const view of extensionRegistry.views.getViews(activePanelViewContainerId)) {
458
+ for (const view of getVisibleWorkbenchViews(
459
+ extensionRegistry,
460
+ activePanelViewContainerId,
461
+ contextKeySnapshot,
462
+ )) {
443
463
  void extensionRegistry.activateView(view.id).then(forceRender);
444
464
  }
445
- }, [activePanelViewContainerId, extensionRegistry, forceRender]);
465
+ }, [activePanelViewContainerId, contextKeySnapshot, extensionRegistry, forceRender]);
466
+
467
+ useEffect(() => {
468
+ if (!layout.auxiliaryBar.visible) {
469
+ return;
470
+ }
471
+
472
+ for (const container of extensionRegistry.views.getViewContainers('auxiliarybar')) {
473
+ for (const view of getVisibleWorkbenchViews(
474
+ extensionRegistry,
475
+ container.id,
476
+ contextKeySnapshot,
477
+ )) {
478
+ void extensionRegistry.activateView(view.id).then(forceRender);
479
+ }
480
+ }
481
+ }, [contextKeySnapshot, extensionRegistry, forceRender, layout.auxiliaryBar.visible]);
446
482
 
447
483
  useEffect(() => {
448
484
  if (extensionRegistry.capabilityRegistry.has(WORKBENCH_SETTINGS_CAPABILITY_ID)) {
@@ -601,6 +637,7 @@ export function WorkbenchShell({
601
637
  activeViewContainerId,
602
638
  catalogUrl,
603
639
  catalogTrustPolicy,
640
+ contextKeySnapshot,
604
641
  ),
605
642
  onSizePxChange: (sizePx) => {
606
643
  layoutService.setSideBarSizePercent(
@@ -613,13 +650,19 @@ export function WorkbenchShell({
613
650
  }}
614
651
  auxiliarySidebar={{
615
652
  isVisible: layout.auxiliaryBar.visible,
616
- node: <aside aria-label="Secondary Side Bar" className="workbench-auxiliary-side-bar" />,
653
+ node: renderDefaultAuxiliarySidebar(
654
+ extensionRegistry,
655
+ contextKeySnapshot,
656
+ catalogUrl,
657
+ catalogTrustPolicy,
658
+ ),
617
659
  }}
618
660
  bottomPanel={{
619
661
  isVisible: layout.panel.visible,
620
662
  node: renderDefaultBottomPanel(extensionRegistry, activePanelViewContainerId, {
621
663
  catalogTrustPolicy,
622
664
  catalogUrl,
665
+ contextKeys: contextKeySnapshot,
623
666
  onActiveViewContainerChange: (viewContainerId) => {
624
667
  layoutService.setActivePanelViewContainer(viewContainerId);
625
668
  if (!layout.panel.visible) {
@@ -641,6 +684,7 @@ export function WorkbenchShell({
641
684
  shellPreset={shellPreset}
642
685
  overlays={
643
686
  <>
687
+ {overlays}
644
688
  {commandHost !== false ? (
645
689
  <WorkbenchCommandHost
646
690
  {...(resolvedCommandHost === false ? {} : resolvedCommandHost)}
@@ -5,7 +5,12 @@ import type {
5
5
  ViewHost,
6
6
  ViewHostFactoryRegistry,
7
7
  ViewProvider,
8
+ WorkbenchViewContribution,
8
9
  } from '@workbench-kit/workbench-core';
10
+ import {
11
+ filterWorkbenchContributionsByWhenClause,
12
+ type WorkbenchContextKeySnapshot,
13
+ } from '@workbench-kit/platform';
9
14
 
10
15
  import { BuiltinChatView } from '../chat/view.js';
11
16
  import { isBuiltinChatViewRenderData } from '../chat/view-data.js';
@@ -15,10 +20,6 @@ import { BuiltinExplorerView } from '../explorer/view.js';
15
20
  import { isBuiltinExplorerViewRenderData } from '../explorer/view-data.js';
16
21
  import { BuiltinExtensionsView } from '../extensions/view.js';
17
22
  import { isBuiltinExtensionsViewRenderData } from '../extensions/view-data.js';
18
- import { SampleJdwLabView } from '../jdw/lab-view.js';
19
- import { isSampleJdwLabViewRenderData } from '../jdw/lab-view-data.js';
20
- import { SampleFieldRemapView } from '../field-remap/view.js';
21
- import { isSampleFieldRemapViewRenderData } from '../field-remap/view-data.js';
22
23
  import { BuiltinSearchView } from '../explorer/search-view.js';
23
24
  import { isBuiltinSearchViewRenderData } from '../explorer/search-view-data.js';
24
25
 
@@ -27,10 +28,11 @@ export function renderDefaultPrimarySidebar(
27
28
  activeViewContainerId: string | undefined,
28
29
  catalogUrl?: string | undefined,
29
30
  catalogTrustPolicy?: ExtensionCatalogTrustPolicy | undefined,
31
+ contextKeys: WorkbenchContextKeySnapshot = {},
30
32
  ) {
31
33
  const views = activeViewContainerId
32
- ? extensionRegistry.views.getViews(activeViewContainerId)
33
- : extensionRegistry.views.getViews();
34
+ ? getVisibleWorkbenchViews(extensionRegistry, activeViewContainerId, contextKeys)
35
+ : filterWorkbenchContributionsByWhenClause(extensionRegistry.views.getViews(), contextKeys);
34
36
  if (views.length === 0) {
35
37
  return <aside aria-label="Primary sidebar" />;
36
38
  }
@@ -38,20 +40,29 @@ export function renderDefaultPrimarySidebar(
38
40
  return (
39
41
  <aside
40
42
  aria-label="Primary sidebar"
41
- className="workbench-primary-side-bar shell-react-primary-sidebar"
43
+ className="workbench-primary-side-bar shell-react-sidebar-host"
42
44
  >
43
- {views.map((view) => (
44
- <section key={view.id} data-view-id={view.id}>
45
- <WorkbenchViewHost
46
- catalogTrustPolicy={catalogTrustPolicy}
47
- catalogUrl={catalogUrl}
48
- fallback={view.name}
49
- provider={extensionRegistry.views.getViewProvider(view.id)}
50
- viewHostFactories={extensionRegistry.viewHostFactories}
51
- viewId={view.id}
52
- />
53
- </section>
54
- ))}
45
+ {renderWorkbenchViews(extensionRegistry, views, { catalogTrustPolicy, catalogUrl })}
46
+ </aside>
47
+ );
48
+ }
49
+
50
+ export function renderDefaultAuxiliarySidebar(
51
+ extensionRegistry: Pick<ExtensionRegistry, 'viewHostFactories' | 'views'>,
52
+ contextKeys: WorkbenchContextKeySnapshot,
53
+ catalogUrl?: string | undefined,
54
+ catalogTrustPolicy?: ExtensionCatalogTrustPolicy | undefined,
55
+ ) {
56
+ const views = extensionRegistry.views
57
+ .getViewContainers('auxiliarybar')
58
+ .flatMap((container) => getVisibleWorkbenchViews(extensionRegistry, container.id, contextKeys));
59
+
60
+ return (
61
+ <aside
62
+ aria-label="Secondary Side Bar"
63
+ className="workbench-auxiliary-side-bar shell-react-sidebar-host"
64
+ >
65
+ {renderWorkbenchViews(extensionRegistry, views, { catalogTrustPolicy, catalogUrl })}
55
66
  </aside>
56
67
  );
57
68
  }
@@ -62,6 +73,7 @@ export function renderDefaultBottomPanel(
62
73
  options: {
63
74
  catalogTrustPolicy?: ExtensionCatalogTrustPolicy | undefined;
64
75
  catalogUrl?: string | undefined;
76
+ contextKeys?: WorkbenchContextKeySnapshot | undefined;
65
77
  onActiveViewContainerChange?: ((viewContainerId: string) => void) | undefined;
66
78
  } = {},
67
79
  ) {
@@ -80,7 +92,11 @@ export function renderDefaultBottomPanel(
80
92
  ? activeViewContainerId
81
93
  : containers[0]?.id;
82
94
  const views = resolvedActiveViewContainerId
83
- ? extensionRegistry.views.getViews(resolvedActiveViewContainerId)
95
+ ? getVisibleWorkbenchViews(
96
+ extensionRegistry,
97
+ resolvedActiveViewContainerId,
98
+ options.contextKeys ?? {},
99
+ )
84
100
  : [];
85
101
 
86
102
  return (
@@ -111,24 +127,56 @@ export function renderDefaultBottomPanel(
111
127
  {views.length === 0 ? (
112
128
  <div className="workbench-bottom-panel__empty">No views in this panel container.</div>
113
129
  ) : (
114
- views.map((view) => (
115
- <section key={view.id} data-view-id={view.id} className="workbench-bottom-panel__view">
116
- <WorkbenchViewHost
117
- catalogTrustPolicy={options.catalogTrustPolicy}
118
- catalogUrl={options.catalogUrl}
119
- fallback={view.name}
120
- provider={extensionRegistry.views.getViewProvider(view.id)}
121
- viewHostFactories={extensionRegistry.viewHostFactories}
122
- viewId={view.id}
123
- />
124
- </section>
125
- ))
130
+ renderWorkbenchViews(extensionRegistry, views, {
131
+ catalogTrustPolicy: options.catalogTrustPolicy,
132
+ catalogUrl: options.catalogUrl,
133
+ sectionClassName: 'workbench-bottom-panel__view',
134
+ })
126
135
  )}
127
136
  </div>
128
137
  </section>
129
138
  );
130
139
  }
131
140
 
141
+ export function getVisibleWorkbenchViews(
142
+ extensionRegistry: Pick<ExtensionRegistry, 'views'>,
143
+ viewContainerId: string,
144
+ contextKeys: WorkbenchContextKeySnapshot,
145
+ ): WorkbenchViewContribution[] {
146
+ return filterWorkbenchContributionsByWhenClause(
147
+ extensionRegistry.views.getViews(viewContainerId),
148
+ contextKeys,
149
+ );
150
+ }
151
+
152
+ function renderWorkbenchViews(
153
+ extensionRegistry: Pick<ExtensionRegistry, 'viewHostFactories' | 'views'>,
154
+ views: readonly WorkbenchViewContribution[],
155
+ options: {
156
+ catalogTrustPolicy?: ExtensionCatalogTrustPolicy | undefined;
157
+ catalogUrl?: string | undefined;
158
+ sectionClassName?: string | undefined;
159
+ },
160
+ ): ReactNode {
161
+ return views.map((view) => (
162
+ <section
163
+ key={view.id}
164
+ className={options.sectionClassName}
165
+ data-view-container-id={view.containerId}
166
+ data-view-id={view.id}
167
+ >
168
+ <WorkbenchViewHost
169
+ catalogTrustPolicy={options.catalogTrustPolicy}
170
+ catalogUrl={options.catalogUrl}
171
+ fallback={view.name}
172
+ provider={extensionRegistry.views.getViewProvider(view.id)}
173
+ viewHostFactories={extensionRegistry.viewHostFactories}
174
+ viewId={view.id}
175
+ />
176
+ </section>
177
+ ));
178
+ }
179
+
132
180
  export function WorkbenchViewHost({
133
181
  catalogTrustPolicy,
134
182
  catalogUrl,
@@ -268,18 +316,5 @@ export function toWorkbenchViewHostReactNode(
268
316
  );
269
317
  }
270
318
 
271
- if (isSampleJdwLabViewRenderData(value)) {
272
- return (
273
- <SampleJdwLabView
274
- templateJdwPath={value.templateJdwPath}
275
- widgetTreePath={value.widgetTreePath}
276
- />
277
- );
278
- }
279
-
280
- if (isSampleFieldRemapViewRenderData(value)) {
281
- return <SampleFieldRemapView />;
282
- }
283
-
284
319
  return toReactNode(value, fallback);
285
320
  }