@theia/core 1.76.0-next.28 → 1.76.0-next.34

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 (48) hide show
  1. package/lib/browser/catalog.json +92 -80
  2. package/lib/browser/frontend-application-module.d.ts.map +1 -1
  3. package/lib/browser/frontend-application-module.js +2 -0
  4. package/lib/browser/frontend-application-module.js.map +1 -1
  5. package/lib/browser/index.d.ts +1 -0
  6. package/lib/browser/index.d.ts.map +1 -1
  7. package/lib/browser/index.js +1 -0
  8. package/lib/browser/index.js.map +1 -1
  9. package/lib/browser/resource-context-key.d.ts +25 -0
  10. package/lib/browser/resource-context-key.d.ts.map +1 -1
  11. package/lib/browser/resource-context-key.js +41 -16
  12. package/lib/browser/resource-context-key.js.map +1 -1
  13. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.d.ts +7 -5
  14. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.d.ts.map +1 -1
  15. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js +13 -12
  16. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js.map +1 -1
  17. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.d.ts +11 -1
  18. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.d.ts.map +1 -1
  19. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js +38 -3
  20. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js.map +1 -1
  21. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts +2 -1
  22. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts.map +1 -1
  23. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js +4 -2
  24. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js.map +1 -1
  25. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js +123 -2
  26. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js.map +1 -1
  27. package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.d.ts +12 -4
  28. package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.d.ts.map +1 -1
  29. package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.js +2 -2
  30. package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.js.map +1 -1
  31. package/lib/browser/view-container.d.ts.map +1 -1
  32. package/lib/browser/view-container.js +2 -2
  33. package/lib/browser/view-container.js.map +1 -1
  34. package/lib/browser/widget-context-key-contribution.d.ts +17 -0
  35. package/lib/browser/widget-context-key-contribution.d.ts.map +1 -0
  36. package/lib/browser/widget-context-key-contribution.js +20 -0
  37. package/lib/browser/widget-context-key-contribution.js.map +1 -0
  38. package/package.json +4 -4
  39. package/src/browser/frontend-application-module.ts +2 -0
  40. package/src/browser/index.ts +1 -0
  41. package/src/browser/resource-context-key.ts +61 -16
  42. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.tsx +13 -12
  43. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts +36 -4
  44. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.ts +150 -3
  45. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.tsx +6 -3
  46. package/src/browser/shell/tab-bar-toolbar/tab-toolbar-item.tsx +13 -5
  47. package/src/browser/view-container.ts +3 -3
  48. package/src/browser/widget-context-key-contribution.ts +34 -0
@@ -18,13 +18,18 @@ import { enableJSDOM } from '../../test/jsdom';
18
18
 
19
19
  let disableJSDOM = enableJSDOM();
20
20
  import { expect } from 'chai';
21
+ import { renderToStaticMarkup } from 'react-dom/server';
21
22
  import {
22
23
  CommandMenu, CommandRegistry, CompoundMenuNode, Group, GroupImpl, MenuAction, MenuModelRegistry, MenuNode, MenuNodeFactory, MutableCompoundMenuNode,
23
24
  Submenu, SubmenuImpl, SubMenuLink
24
25
  } from '../../../common';
25
- import { ContextKeyServiceDummyImpl } from '../../context-key-service';
26
+ import { ContextKeyServiceDummyImpl, ContextMatcher } from '../../context-key-service';
26
27
  import { ContextMenuRenderer } from '../../context-menu-renderer';
27
28
  import { Widget } from '../../widgets';
29
+ import URI from '../../../common/uri';
30
+ import { ResourceContextKey } from '../../resource-context-key';
31
+ import { WidgetContextKeyContribution } from '../../widget-context-key-contribution';
32
+ import { TabBarToolbar } from './tab-bar-toolbar';
28
33
  import { TOOLBAR_WRAPPER_ID_SUFFIX } from './tab-bar-toolbar-menu-adapters';
29
34
  import { TabBarToolbarRegistry } from './tab-bar-toolbar-registry';
30
35
  import { TAB_BAR_TOOLBAR_CONTEXT_MENU, TabBarToolbarAction } from './tab-bar-toolbar-types';
@@ -135,6 +140,106 @@ describe('tab-bar-toolbar', () => {
135
140
  testWidget.dispose();
136
141
  });
137
142
 
143
+ it('evaluates delegated items against the resource of the widget that owns the toolbar', () => {
144
+ const testWidget = new TestToolbarWidget(new URI('probe:/a.probe'));
145
+ const commands = createCommandRegistry();
146
+ commands.registerCommand({ id: TEST_COMMAND, label: 'Test Command' }, { execute: () => { } });
147
+ const menuRegistry = createMenuRegistry(commands);
148
+ menuRegistry.registerMenuAction([...TEST_MENU_PATH, 'other'], { commandId: TEST_COMMAND, when: 'resourceScheme == probe' });
149
+ const registry = createToolbarRegistry(commands, menuRegistry, new TestContextKeyService());
150
+ registry.registerMenuDelegate(TEST_MENU_PATH, TestToolbarWidget.is);
151
+
152
+ const commandItem = registry.visibleItems(testWidget).find(item => item.id === `${TEST_COMMAND}${TOOLBAR_WRAPPER_ID_SUFFIX}`);
153
+
154
+ const otherWidget = new TestToolbarWidget(new URI('file:/a.txt'));
155
+
156
+ expect(commandItem).to.exist;
157
+ expect(registry.visibleItems(otherWidget)).to.be.empty;
158
+ testWidget.dispose();
159
+ otherWidget.dispose();
160
+ });
161
+
162
+ it('evaluates registered items against the keys contributed for the widget that owns the toolbar', () => {
163
+ const testWidget = new TestToolbarWidget(new URI('probe:/a.probe'));
164
+ const otherWidget = new TestToolbarWidget(new URI('probe:/b.probe'));
165
+ const commands = createCommandRegistry();
166
+ commands.registerCommand({ id: TEST_COMMAND, label: 'Test Command' }, { execute: () => { } });
167
+ const menuRegistry = createMenuRegistry(commands);
168
+ const contribution: WidgetContextKeyContribution = {
169
+ getContextKeyValues: widget => [['activeCustomEditorId', widget === testWidget ? 'test.probeEditor' : '']]
170
+ };
171
+ const registry = createToolbarRegistry(commands, menuRegistry, new TestContextKeyService(), [contribution]);
172
+ registry.registerItem({ id: 'test-item', command: TEST_COMMAND, when: 'activeCustomEditorId == test.probeEditor' });
173
+
174
+ expect(registry.visibleItems(testWidget).map(item => item.id)).to.deep.equal(['test-item']);
175
+ expect(registry.visibleItems(otherWidget)).to.be.empty;
176
+ testWidget.dispose();
177
+ otherWidget.dispose();
178
+ });
179
+
180
+ it('renders the submenu chevron against the widget that owns the toolbar', () => {
181
+ const testWidget = new TestToolbarWidget();
182
+ const otherWidget = new TestToolbarWidget();
183
+ const commands = createCommandRegistry();
184
+ commands.registerCommand({ id: TEST_SUBMENU_COMMAND, label: 'Test Submenu Command' }, { execute: () => { } });
185
+ const menuRegistry = createMenuRegistry(commands);
186
+ menuRegistry.registerSubmenu([...TEST_MENU_PATH, 'other', 'test-submenu'], 'Test Submenu');
187
+ menuRegistry.registerMenuAction([...TEST_MENU_PATH, 'other', 'test-submenu'],
188
+ { commandId: TEST_SUBMENU_COMMAND, when: 'activeCustomEditorId == test.probeEditor' });
189
+ const contribution: WidgetContextKeyContribution = {
190
+ getContextKeyValues: widget => [['activeCustomEditorId', widget === testWidget ? 'test.probeEditor' : '']]
191
+ };
192
+ const registry = createToolbarRegistry(commands, menuRegistry, new TestContextKeyService(), [contribution]);
193
+ registry.registerMenuDelegate(TEST_MENU_PATH, TestToolbarWidget.is);
194
+ const submenuItem = registry.visibleItems(testWidget).find(item => item.id === `test-submenu${TOOLBAR_WRAPPER_ID_SUFFIX}`);
195
+
196
+ expect(submenuItem).to.exist;
197
+ expect(renderToStaticMarkup(submenuItem!.render(testWidget, registry.contextMatcherFor(testWidget)))).to.contain('chevron');
198
+ expect(renderToStaticMarkup(submenuItem!.render(testWidget, registry.contextMatcherFor(otherWidget)))).to.not.contain('chevron');
199
+ testWidget.dispose();
200
+ otherWidget.dispose();
201
+ });
202
+
203
+ it('opens the More Actions menu against the widget that owns the toolbar', () => {
204
+ const testWidget = new TestToolbarWidget();
205
+ const otherWidget = new TestToolbarWidget();
206
+ const commands = createCommandRegistry();
207
+ commands.registerCommand({ id: TEST_SUBMENU_COMMAND, label: 'Test Submenu Command' }, { execute: () => { } });
208
+ const menuRegistry = createMenuRegistry(commands);
209
+ menuRegistry.registerSubmenu([...TEST_MENU_PATH, 'other', 'test-submenu'], 'Test Submenu');
210
+ menuRegistry.registerMenuAction([...TEST_MENU_PATH, 'other', 'test-submenu'],
211
+ { commandId: TEST_SUBMENU_COMMAND, when: 'activeCustomEditorId == test.probeEditor' });
212
+ const contribution: WidgetContextKeyContribution = {
213
+ getContextKeyValues: widget => [['activeCustomEditorId', widget === testWidget ? 'test.probeEditor' : '']]
214
+ };
215
+ const ambient = new TestContextKeyService();
216
+ const registry = createToolbarRegistry(commands, menuRegistry, ambient, [contribution]);
217
+ registry.registerMenuDelegate(TEST_MENU_PATH, TestToolbarWidget.is);
218
+
219
+ let rendered: { contextKeyService?: ContextMatcher } | undefined;
220
+ const toolbar = new TabBarToolbar();
221
+ Reflect.set(toolbar, 'contextKeyService', ambient);
222
+ Reflect.set(toolbar, 'toolbarRegistry', registry);
223
+ Reflect.set(toolbar, 'contextMenuRenderer', {
224
+ render: (options: { contextKeyService?: ContextMatcher }) => {
225
+ rendered = options;
226
+ return { dispose: () => { } };
227
+ }
228
+ });
229
+ const setCurrent = Reflect.get(toolbar, 'setCurrent') as (widget: Widget) => void;
230
+
231
+ setCurrent.call(toolbar, testWidget);
232
+ toolbar.renderMoreContextMenu({ x: 0, y: 0 });
233
+ expect(rendered?.contextKeyService?.match('activeCustomEditorId == test.probeEditor')).to.be.true;
234
+
235
+ setCurrent.call(toolbar, otherWidget);
236
+ toolbar.renderMoreContextMenu({ x: 0, y: 0 });
237
+ expect(rendered?.contextKeyService?.match('activeCustomEditorId == test.probeEditor')).to.be.false;
238
+
239
+ testWidget.dispose();
240
+ otherWidget.dispose();
241
+ });
242
+
138
243
  it('preserves the widget for wrapped submenu emptiness checks', () => {
139
244
  const testWidget = new TestToolbarWidget();
140
245
  const commands = createCommandRegistry();
@@ -166,6 +271,38 @@ class TestToolbarWidget extends Widget {
166
271
  static is(candidate?: Widget): candidate is TestToolbarWidget {
167
272
  return candidate instanceof TestToolbarWidget;
168
273
  }
274
+
275
+ constructor(protected readonly resourceUri?: URI) {
276
+ super();
277
+ }
278
+
279
+ getResourceUri(): URI | undefined {
280
+ return this.resourceUri;
281
+ }
282
+
283
+ createMoveToUri(resourceUri: URI): URI | undefined {
284
+ return resourceUri;
285
+ }
286
+ }
287
+
288
+ /**
289
+ * Evaluates `key == value` clauses against the overlay alone, so that a visible item can only come from the
290
+ * values the registry attributed to the widget.
291
+ */
292
+ class TestContextKeyService extends ContextKeyServiceDummyImpl {
293
+ override match(expression: string): boolean {
294
+ return false;
295
+ }
296
+
297
+ override createOverlay(overlay: Iterable<[string, unknown]>): ContextMatcher {
298
+ const values = new Map(overlay);
299
+ return {
300
+ match: (expression: string) => {
301
+ const [key, value] = expression.split(' == ');
302
+ return values.get(key) === value;
303
+ }
304
+ };
305
+ }
169
306
  }
170
307
 
171
308
  class TestMenuNodeFactory implements MenuNodeFactory {
@@ -187,7 +324,8 @@ class TestMenuNodeFactory implements MenuNodeFactory {
187
324
 
188
325
  createCommandMenu(item: MenuAction): CommandMenu {
189
326
  return {
190
- isVisible: (_path, _contextMatcher, _context, ...args) => this.commands.isVisible(item.commandId, ...args),
327
+ isVisible: (_path, contextMatcher, context, ...args) =>
328
+ (!item.when || contextMatcher.match(item.when, context)) && this.commands.isVisible(item.commandId, ...args),
191
329
  isEnabled: (_path, ...args) => this.commands.isEnabled(item.commandId, ...args),
192
330
  isToggled: (_path, ...args) => this.commands.isToggled(item.commandId, ...args),
193
331
  id: item.commandId,
@@ -208,7 +346,12 @@ function createMenuRegistry(commands: CommandRegistry): MenuModelRegistry {
208
346
  return new MenuModelRegistry({ getContributions: () => [] }, commands, new TestMenuNodeFactory(commands));
209
347
  }
210
348
 
211
- function createToolbarRegistry(commands: CommandRegistry, menuRegistry: MenuModelRegistry, contextKeyService: ContextKeyServiceDummyImpl): TabBarToolbarRegistry {
349
+ function createToolbarRegistry(
350
+ commands: CommandRegistry,
351
+ menuRegistry: MenuModelRegistry,
352
+ contextKeyService: ContextKeyServiceDummyImpl,
353
+ contextKeyContributions: WidgetContextKeyContribution[] = []
354
+ ): TabBarToolbarRegistry {
212
355
  const registry = new TabBarToolbarRegistry();
213
356
  Reflect.set(registry, 'commandRegistry', commands);
214
357
  Reflect.set(registry, 'contextKeyService', contextKeyService);
@@ -216,5 +359,9 @@ function createToolbarRegistry(commands: CommandRegistry, menuRegistry: MenuMode
216
359
  Reflect.set(registry, 'keybindingRegistry', {});
217
360
  Reflect.set(registry, 'labelParser', {});
218
361
  Reflect.set(registry, 'contextMenuRenderer', { render: () => undefined } as unknown as ContextMenuRenderer);
362
+ const resourceContextKey = new ResourceContextKey();
363
+ Reflect.set(resourceContextKey, 'languages', { languages: [] });
364
+ Reflect.set(registry, 'resourceContextKey', resourceContextKey);
365
+ Reflect.set(registry, 'contextKeyContributionProvider', { getContributions: () => contextKeyContributions });
219
366
  return registry;
220
367
  }
@@ -17,7 +17,7 @@
17
17
  import { inject, injectable, postConstruct } from 'inversify';
18
18
  import * as React from 'react';
19
19
  import { buttonKeyboardProps, isActivationKey } from '../../keyboard/keyboard-utils';
20
- import { ContextKeyService } from '../../context-key-service';
20
+ import { ContextKeyService, ContextMatcher } from '../../context-key-service';
21
21
  import { CommandRegistry, Disposable, DisposableCollection, nls } from '../../../common';
22
22
  import { Anchor, ContextMenuAccess, ContextMenuRenderer } from '../../context-menu-renderer';
23
23
  import { LabelParser } from '../../label-parser';
@@ -48,6 +48,7 @@ export function toAnchor(event: React.MouseEvent): Anchor {
48
48
  export class TabBarToolbar extends ReactWidget {
49
49
 
50
50
  protected current: Widget | undefined;
51
+ protected contextMatcher: ContextMatcher;
51
52
  protected inline = new Map<string, TabBarToolbarItem>();
52
53
  protected more = new Map<string, TabBarToolbarItem>();
53
54
 
@@ -73,6 +74,7 @@ export class TabBarToolbar extends ReactWidget {
73
74
 
74
75
  @postConstruct()
75
76
  protected init(): void {
77
+ this.contextMatcher = this.contextKeyService;
76
78
  this.toDispose.pushAll([
77
79
  this.keybindings.onKeybindingsChanged(() => this.maybeUpdate()),
78
80
  this.contextKeyService.onDidChange(e => {
@@ -129,6 +131,7 @@ export class TabBarToolbar extends ReactWidget {
129
131
  this.toDisposeOnSetCurrent.dispose();
130
132
  this.toDispose.push(this.toDisposeOnSetCurrent);
131
133
  this.current = current;
134
+ this.contextMatcher = current ? this.toolbarRegistry.contextMatcherFor(current) : this.contextKeyService;
132
135
  if (current) {
133
136
  const resetCurrent = () => {
134
137
  this.setCurrent(undefined);
@@ -145,7 +148,7 @@ export class TabBarToolbar extends ReactWidget {
145
148
  this.keybindingContextKeys.clear();
146
149
  return <React.Fragment>
147
150
  {this.renderMore()}
148
- {[...this.inline.values()].map(item => item.render(this.current))}
151
+ {[...this.inline.values()].map(item => item.render(this.current, this.contextMatcher))}
149
152
  </React.Fragment>;
150
153
  }
151
154
 
@@ -199,7 +202,7 @@ export class TabBarToolbar extends ReactWidget {
199
202
  args: [this.current],
200
203
  anchor,
201
204
  context: this.current?.node || this.node,
202
- contextKeyService: this.contextKeyService,
205
+ contextKeyService: this.contextMatcher,
203
206
  includeAnchorArg: false,
204
207
  onHide: () => toDisposeOnHide.dispose()
205
208
  });
@@ -14,7 +14,7 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { ContextKeyService } from '../../context-key-service';
17
+ import { ContextKeyService, ContextMatcher } from '../../context-key-service';
18
18
  import { ReactTabBarToolbarAction, RenderedToolbarAction, TabBarToolbarActionBase } from './tab-bar-toolbar-types';
19
19
  import { Widget } from '@lumino/widgets';
20
20
  import { LabelIcon, LabelParser } from '../../label-parser';
@@ -29,10 +29,18 @@ import { ActionMenuNode, GroupImpl, MenuNode } from '../../../common/menu';
29
29
  export interface TabBarToolbarItem {
30
30
  id: string;
31
31
  when?: string;
32
- isVisible(widget: Widget): boolean;
32
+ /**
33
+ * @param contextMatcher evaluates `when` clauses with the values that describe the given widget. Keys
34
+ * scoped to a DOM node keep resolving against the focused element, as no context node is passed here.
35
+ */
36
+ isVisible(widget: Widget, contextMatcher: ContextMatcher): boolean;
33
37
  isEnabled(widget: Widget): boolean;
34
38
  isToggled(widget: Widget): boolean;
35
- render(widget?: Widget): React.ReactNode;
39
+ /**
40
+ * @param contextMatcher evaluates `when` clauses with the values that describe the given widget. Defaults
41
+ * to the ambient context, for toolbars that render items with no owning widget.
42
+ */
43
+ render(widget?: Widget, contextMatcher?: ContextMatcher): React.ReactNode;
36
44
  onDidChange?: Event<void>;
37
45
  group?: string;
38
46
  priority?: number;
@@ -68,12 +76,12 @@ class AbstractToolbarItemImpl<T extends TabBarToolbarActionBase> {
68
76
  return this.action.onDidChange;
69
77
  }
70
78
 
71
- isVisible(widget: Widget): boolean {
79
+ isVisible(widget: Widget, contextMatcher: ContextMatcher): boolean {
72
80
  if (this.action.isVisible) {
73
81
  return this.action.isVisible(widget);
74
82
  }
75
83
  const actionVisible = !this.action.command || this.commandRegistry.isVisible(this.action.command, widget);
76
- const contextMatches = !this.action.when || this.contextKeyService.match(this.action.when);
84
+ const contextMatches = !this.action.when || contextMatcher.match(this.action.when);
77
85
 
78
86
  return actionVisible && contextMatches;
79
87
  }
@@ -38,7 +38,7 @@ import { Drag } from '@lumino/dragdrop';
38
38
  import { MimeData } from '@lumino/coreutils';
39
39
  import { ElementExt } from '@lumino/domutils';
40
40
  import { TabBarDecoratorService } from './shell/tab-bar-decorator';
41
- import { ContextKeyService } from './context-key-service';
41
+ import { ContextKeyService, ContextMatcher } from './context-key-service';
42
42
  import { KeybindingRegistry } from './keybinding';
43
43
  import { SubmenuAsToolbarItemWrapper } from './shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters';
44
44
  import { TheiaSplitPanel } from './shell/theia-split-panel';
@@ -109,8 +109,8 @@ class PartsMenuToolbarItem extends SubmenuAsToolbarItemWrapper {
109
109
  super(effectiveMenuPath, commandRegistry, menuRegistry, contextKeyService, contextMenuRenderer, menuNode, group);
110
110
  }
111
111
 
112
- override isVisible(widget: Widget): boolean {
113
- return widget === this.target() && super.isVisible(widget);
112
+ override isVisible(widget: Widget, contextMatcher: ContextMatcher): boolean {
113
+ return widget === this.target() && super.isVisible(widget, contextMatcher);
114
114
  }
115
115
  }
116
116
 
@@ -0,0 +1,34 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2026 JuliaHub, Inc. and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { Widget } from '@lumino/widgets';
18
+
19
+ export const WidgetContextKeyContribution = Symbol('WidgetContextKeyContribution');
20
+
21
+ /**
22
+ * Contributes the context key values that describe a particular widget, so that `when` clauses about
23
+ * that widget - such as the ones of its tab bar toolbar items - can be evaluated without consulting the
24
+ * ambient context, which describes whichever widget currently has focus.
25
+ */
26
+ export interface WidgetContextKeyContribution {
27
+ /**
28
+ * @param widget the widget to describe.
29
+ * @returns the values to overlay over the ambient context, or `undefined` if this contribution does not
30
+ * describe the given widget. A contribution owning a key should return an explicit "unset" value for the
31
+ * widgets the key does not apply to, so that the ambient value of another widget cannot leak in.
32
+ */
33
+ getContextKeyValues(widget: Widget): Iterable<[string, unknown]> | undefined;
34
+ }