@eclipse-docks/core 0.7.125 → 0.7.127
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/dist/api/index.js +4 -4
- package/dist/api/services.d.ts +3 -0
- package/dist/api/services.d.ts.map +1 -1
- package/dist/{api-CTU-FxEv.js → api-Da9zQcfd.js} +187 -38
- package/dist/api-Da9zQcfd.js.map +1 -0
- package/dist/components/command.d.ts +4 -4
- package/dist/components/command.d.ts.map +1 -1
- package/dist/components/filebrowser.d.ts.map +1 -1
- package/dist/components/release-history.d.ts.map +1 -1
- package/dist/core/contribution-names.d.ts +0 -2
- package/dist/core/contribution-names.d.ts.map +1 -1
- package/dist/core/contributionregistry.d.ts +3 -0
- package/dist/core/contributionregistry.d.ts.map +1 -1
- package/dist/core/dropdown-item.d.ts +35 -0
- package/dist/core/dropdown-item.d.ts.map +1 -0
- package/dist/core/dropdown-menu-utils.d.ts +5 -0
- package/dist/core/dropdown-menu-utils.d.ts.map +1 -1
- package/dist/core/markdown-html.d.ts +4 -0
- package/dist/core/markdown-html.d.ts.map +1 -0
- package/dist/index.js +4 -4
- package/dist/parts/contextmenu.d.ts +5 -2
- package/dist/parts/contextmenu.d.ts.map +1 -1
- package/dist/parts/index.d.ts.map +1 -1
- package/dist/parts/index.js +1 -1
- package/dist/parts/part.d.ts +2 -0
- package/dist/parts/part.d.ts.map +1 -1
- package/dist/{parts-BRaXx8PD.js → parts-CRVxaDd-.js} +197 -263
- package/dist/parts-CRVxaDd-.js.map +1 -0
- package/dist/{widget-DbLusgAH.js → widget-BqQtioK1.js} +11 -5
- package/dist/widget-BqQtioK1.js.map +1 -0
- package/dist/widgets/index.js +1 -1
- package/dist/{widgets-DnnSZhsi.js → widgets-C9V42Mqq.js} +2 -2
- package/dist/{widgets-DnnSZhsi.js.map → widgets-C9V42Mqq.js.map} +1 -1
- package/package.json +2 -1
- package/src/api/services.ts +9 -0
- package/src/commands/filebrowser-contributions.ts +0 -16
- package/src/components/command.ts +45 -113
- package/src/components/filebrowser.ts +15 -12
- package/src/components/release-history.ts +2 -4
- package/src/core/contribution-names.ts +0 -3
- package/src/core/contributionregistry.ts +19 -3
- package/src/core/dropdown-item.ts +152 -0
- package/src/core/dropdown-menu-utils.ts +59 -0
- package/src/core/markdown-html.ts +11 -0
- package/src/parts/contextmenu.ts +38 -44
- package/src/parts/dialog-content.ts +2 -2
- package/src/parts/index.ts +4 -1
- package/src/parts/part.ts +2 -0
- package/dist/api-CTU-FxEv.js.map +0 -1
- package/dist/parts-BRaXx8PD.js.map +0 -1
- package/dist/widget-DbLusgAH.js.map +0 -1
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared render helpers for {@link https://webawesome.com/docs/components/dropdown-item | wa-dropdown-item}
|
|
3
|
+
* rows inside any Docks popup list.
|
|
4
|
+
*
|
|
5
|
+
* **Docks surfaces** (distinct UX and contribution targets):
|
|
6
|
+
* - **Toolbar dropdown** — anchored to a toolbar control (`docks-command`, `docks-toolbar`).
|
|
7
|
+
* Part-level registry targets use the `toolbar:` prefix (e.g. `toolbar:view.filebrowser`).
|
|
8
|
+
* - **Context menu** — opened at the pointer (`docks-contextmenu`).
|
|
9
|
+
* Part-level registry targets use the `contextmenu:` prefix (e.g. `contextmenu:view.filebrowser`).
|
|
10
|
+
*
|
|
11
|
+
* A part can expose both surfaces with the same part id but different prefixes, registering
|
|
12
|
+
* different contributions on each. Feature-scoped targets (e.g. `filebrowser.create`) may also
|
|
13
|
+
* be referenced explicitly from either surface when several controls share the same item set.
|
|
14
|
+
*/
|
|
15
|
+
import { html, nothing, type TemplateResult } from 'lit';
|
|
16
|
+
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
|
17
|
+
import { commandRegistry } from './commandregistry';
|
|
18
|
+
import { icon } from './icon-utils';
|
|
19
|
+
import { keyBindingManager } from './keybindings';
|
|
20
|
+
import {
|
|
21
|
+
type Contribution,
|
|
22
|
+
type CommandContribution,
|
|
23
|
+
type HTMLContribution,
|
|
24
|
+
type ReactiveBoolean,
|
|
25
|
+
contributionRegistry,
|
|
26
|
+
getContributionVisible,
|
|
27
|
+
readReactiveBoolean,
|
|
28
|
+
} from './contributionregistry';
|
|
29
|
+
|
|
30
|
+
export type { ReactiveBoolean };
|
|
31
|
+
|
|
32
|
+
export interface DropdownItemOptions {
|
|
33
|
+
cmd?: string;
|
|
34
|
+
icon?: string;
|
|
35
|
+
label: string;
|
|
36
|
+
title?: string;
|
|
37
|
+
params?: Record<string, unknown>;
|
|
38
|
+
disabled?: ReactiveBoolean;
|
|
39
|
+
variant?: 'default' | 'danger';
|
|
40
|
+
slot?: string;
|
|
41
|
+
action?: (event: Event) => void;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function closeParentDropdown(event: Event): void {
|
|
45
|
+
const dropdown = (event.target as Element | null)?.closest('wa-dropdown') as { open?: boolean } | null;
|
|
46
|
+
if (dropdown && dropdown.open !== undefined) {
|
|
47
|
+
dropdown.open = false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function onDropdownItemClick(options: DropdownItemOptions) {
|
|
52
|
+
return (event: Event) => {
|
|
53
|
+
if (readReactiveBoolean(options.disabled, false)) return;
|
|
54
|
+
event.stopPropagation();
|
|
55
|
+
closeParentDropdown(event);
|
|
56
|
+
if (options.action) {
|
|
57
|
+
options.action(event);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (options.cmd) {
|
|
61
|
+
void commandRegistry.execute(
|
|
62
|
+
options.cmd,
|
|
63
|
+
commandRegistry.createExecutionContext(options.params ?? {})
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function keybindingDetails(cmd?: string): TemplateResult | typeof nothing {
|
|
70
|
+
if (!cmd) return nothing;
|
|
71
|
+
const bindings = keyBindingManager.getKeyBindingsForCommand(cmd);
|
|
72
|
+
if (bindings.length === 0) return nothing;
|
|
73
|
+
return html`<span slot="details">${bindings[0]}</span>`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Renders a native {@link https://webawesome.com/docs/components/dropdown-item | wa-dropdown-item}. */
|
|
77
|
+
export function renderDropdownItem(options: DropdownItemOptions): TemplateResult {
|
|
78
|
+
const iconSpec = options.icon ?? '';
|
|
79
|
+
return html`
|
|
80
|
+
<wa-dropdown-item
|
|
81
|
+
slot=${options.slot ?? nothing}
|
|
82
|
+
variant=${options.variant ?? 'default'}
|
|
83
|
+
?disabled=${readReactiveBoolean(options.disabled, false)}
|
|
84
|
+
@click=${onDropdownItemClick(options)}>
|
|
85
|
+
${iconSpec ? icon(iconSpec, { label: options.title ?? options.label, slot: 'icon' }) : nothing}
|
|
86
|
+
${options.label}
|
|
87
|
+
${keybindingDetails(options.cmd)}
|
|
88
|
+
</wa-dropdown-item>
|
|
89
|
+
`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function renderCommandContribution(
|
|
93
|
+
contribution: CommandContribution,
|
|
94
|
+
options?: { slot?: string }
|
|
95
|
+
): TemplateResult | typeof nothing {
|
|
96
|
+
if (!getContributionVisible(contribution)) return nothing;
|
|
97
|
+
return renderDropdownItem({
|
|
98
|
+
cmd: contribution.command,
|
|
99
|
+
icon: contribution.icon,
|
|
100
|
+
label: contribution.label,
|
|
101
|
+
params: contribution.params,
|
|
102
|
+
disabled: contribution.disabled,
|
|
103
|
+
slot: options?.slot,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function renderDropdownContribution(
|
|
108
|
+
contribution: Contribution,
|
|
109
|
+
options?: { slot?: string }
|
|
110
|
+
): TemplateResult | typeof nothing {
|
|
111
|
+
if ('command' in contribution) {
|
|
112
|
+
return renderCommandContribution(contribution as CommandContribution, options);
|
|
113
|
+
}
|
|
114
|
+
if ('component' in contribution) {
|
|
115
|
+
if (!getContributionVisible(contribution)) return nothing;
|
|
116
|
+
const contents = (contribution as HTMLContribution).component;
|
|
117
|
+
if (contents instanceof Function) {
|
|
118
|
+
return contents();
|
|
119
|
+
}
|
|
120
|
+
return html`${unsafeHTML(contents)}` as TemplateResult;
|
|
121
|
+
}
|
|
122
|
+
return nothing;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Renders all visible contributions registered for a contribution target. */
|
|
126
|
+
export function renderDropdownContributions(
|
|
127
|
+
target: string,
|
|
128
|
+
options?: { slot?: string }
|
|
129
|
+
): TemplateResult {
|
|
130
|
+
const items = contributionRegistry
|
|
131
|
+
.getContributions(target)
|
|
132
|
+
.map((c) => renderDropdownContribution(c, options))
|
|
133
|
+
.filter((item) => item !== nothing);
|
|
134
|
+
return html`${items}`;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Renders a {@link wa-dropdown-item} with nested items from a contribution target in {@code slot="submenu"}. */
|
|
138
|
+
export function renderDropdownSubmenu(options: {
|
|
139
|
+
icon?: string;
|
|
140
|
+
label: string;
|
|
141
|
+
title?: string;
|
|
142
|
+
contributionTarget: string;
|
|
143
|
+
disabled?: ReactiveBoolean;
|
|
144
|
+
}): TemplateResult {
|
|
145
|
+
return html`
|
|
146
|
+
<wa-dropdown-item ?disabled=${readReactiveBoolean(options.disabled, false)}>
|
|
147
|
+
${options.icon ? icon(options.icon, { label: options.title ?? options.label, slot: 'icon' }) : nothing}
|
|
148
|
+
${options.label}
|
|
149
|
+
${renderDropdownContributions(options.contributionTarget, { slot: 'submenu' })}
|
|
150
|
+
</wa-dropdown-item>
|
|
151
|
+
`;
|
|
152
|
+
}
|
|
@@ -1,4 +1,63 @@
|
|
|
1
1
|
type DropdownItemElement = HTMLElement & { submenuOpen?: boolean };
|
|
2
|
+
type OpenDropdownElement = HTMLElement & { open?: boolean };
|
|
3
|
+
|
|
4
|
+
function isOpenDropdown(element: Element): element is OpenDropdownElement {
|
|
5
|
+
if (element.localName !== "wa-dropdown") return false;
|
|
6
|
+
const dropdown = element as OpenDropdownElement;
|
|
7
|
+
return dropdown.open === true || dropdown.hasAttribute("open");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function elementsFromEventPath(event: Event): Element[] {
|
|
11
|
+
const fromComposedPath = event
|
|
12
|
+
.composedPath()
|
|
13
|
+
.filter((node): node is Element => node instanceof Element);
|
|
14
|
+
if (fromComposedPath.length > 0) return fromComposedPath;
|
|
15
|
+
|
|
16
|
+
if (!(event.target instanceof Element)) return [];
|
|
17
|
+
|
|
18
|
+
const path: Element[] = [];
|
|
19
|
+
let current: Element | null = event.target;
|
|
20
|
+
while (current) {
|
|
21
|
+
path.push(current);
|
|
22
|
+
const root = current.getRootNode();
|
|
23
|
+
if (root instanceof ShadowRoot) {
|
|
24
|
+
current = root.host;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
current = current.parentElement;
|
|
28
|
+
}
|
|
29
|
+
return path;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function elementTargetsOpenDropdown(element: Element): boolean {
|
|
33
|
+
if (isOpenDropdown(element)) return true;
|
|
34
|
+
if (element.localName !== "wa-dropdown-item") return false;
|
|
35
|
+
const dropdown = element.closest("wa-dropdown");
|
|
36
|
+
if (dropdown && isOpenDropdown(dropdown)) return true;
|
|
37
|
+
const root = element.getRootNode();
|
|
38
|
+
return root instanceof ShadowRoot
|
|
39
|
+
&& root.host instanceof Element
|
|
40
|
+
&& isOpenDropdown(root.host);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** True when the event occurred inside a wa-dropdown that is currently open. */
|
|
44
|
+
export function eventTargetsOpenDropdown(event: Event): boolean {
|
|
45
|
+
return elementsFromEventPath(event).some(elementTargetsOpenDropdown);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Prevents the browser context menu on open Docks popup lists (context menus, toolbar dropdowns). */
|
|
49
|
+
export function suppressNativeContextMenuInOpenDropdowns(event: Event): void {
|
|
50
|
+
if (!event.cancelable || !eventTargetsOpenDropdown(event)) return;
|
|
51
|
+
event.preventDefault();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let openDropdownContextMenuGuardInstalled = false;
|
|
55
|
+
|
|
56
|
+
export function installOpenDropdownNativeContextMenuGuard(): void {
|
|
57
|
+
if (openDropdownContextMenuGuardInstalled || typeof document === "undefined") return;
|
|
58
|
+
openDropdownContextMenuGuardInstalled = true;
|
|
59
|
+
document.addEventListener("contextmenu", suppressNativeContextMenuInOpenDropdowns, { capture: true });
|
|
60
|
+
}
|
|
2
61
|
|
|
3
62
|
function visitElementTree(root: Node, visit: (element: Element) => void): void {
|
|
4
63
|
if (root instanceof Element) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import DOMPurify from 'dompurify';
|
|
2
|
+
import { marked, type MarkedOptions } from 'marked';
|
|
3
|
+
|
|
4
|
+
export function sanitizeHtml(html: string): string {
|
|
5
|
+
return DOMPurify.sanitize(html);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function parseMarkdownHtml(markdown: string, options?: MarkedOptions): string {
|
|
9
|
+
const html = marked.parse(markdown, { async: false, ...options }) as string;
|
|
10
|
+
return sanitizeHtml(html);
|
|
11
|
+
}
|
package/src/parts/contextmenu.ts
CHANGED
|
@@ -2,20 +2,24 @@ import {css, html, nothing} from 'lit'
|
|
|
2
2
|
import {customElement, property, state} from 'lit/decorators.js'
|
|
3
3
|
import {DocksElement} from "./element";
|
|
4
4
|
import {
|
|
5
|
-
CommandContribution,
|
|
6
5
|
Contribution,
|
|
7
6
|
ContributionChangeEvent,
|
|
8
7
|
contributionRegistry,
|
|
9
|
-
getContributionDisabled,
|
|
10
|
-
HTMLContribution,
|
|
11
|
-
getContributionVisible,
|
|
12
8
|
TOPIC_CONTRIBUTEIONS_CHANGED
|
|
13
9
|
} from "../core/contributionregistry";
|
|
14
|
-
import {unsafeHTML} from "lit/directives/unsafe-html.js";
|
|
15
10
|
import {subscribe} from "../core/events";
|
|
16
11
|
import {closeSiblingSubmenus} from "../core/dropdown-menu-utils";
|
|
17
12
|
import {createRef, ref} from "lit/directives/ref.js";
|
|
18
|
-
import
|
|
13
|
+
import {renderDropdownContribution} from "../core/dropdown-item";
|
|
14
|
+
|
|
15
|
+
interface VirtualPopupAnchor {
|
|
16
|
+
getBoundingClientRect(): DOMRect;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface WaPopupElement extends HTMLElement {
|
|
20
|
+
anchor?: Element | string | VirtualPopupAnchor;
|
|
21
|
+
reposition(): void;
|
|
22
|
+
}
|
|
19
23
|
|
|
20
24
|
@customElement('docks-contextmenu')
|
|
21
25
|
export class DocksContextMenu extends DocksElement {
|
|
@@ -31,10 +35,15 @@ export class DocksContextMenu extends DocksElement {
|
|
|
31
35
|
@state()
|
|
32
36
|
private isOpen: boolean = false;
|
|
33
37
|
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
private menuPosition: { x: number; y: number } = { x: 0, y: 0 };
|
|
39
|
+
|
|
40
|
+
private readonly virtualAnchor: VirtualPopupAnchor = {
|
|
41
|
+
getBoundingClientRect: () => {
|
|
42
|
+
const { x, y } = this.menuPosition;
|
|
43
|
+
return new DOMRect(x, y, 0, 0);
|
|
44
|
+
},
|
|
45
|
+
};
|
|
36
46
|
|
|
37
|
-
private anchorRef = createRef<HTMLElement>();
|
|
38
47
|
private dropdownRef = createRef<HTMLElement>();
|
|
39
48
|
|
|
40
49
|
private boundHandleDocumentPointerDown = this.handleDocumentPointerDown.bind(this);
|
|
@@ -225,43 +234,38 @@ export class DocksContextMenu extends DocksElement {
|
|
|
225
234
|
await this.updateComplete;
|
|
226
235
|
}
|
|
227
236
|
|
|
228
|
-
this.
|
|
237
|
+
this.menuPosition = position;
|
|
229
238
|
this.isOpen = true;
|
|
230
239
|
await this.updateComplete;
|
|
240
|
+
this.syncVirtualPopupAnchor();
|
|
231
241
|
document.addEventListener('pointerdown', this.boundHandleDocumentPointerDown, { capture: true });
|
|
232
242
|
return true;
|
|
233
243
|
}
|
|
234
244
|
|
|
245
|
+
/** Points wa-dropdown's internal wa-popup at the pointer via a VirtualElement anchor. */
|
|
246
|
+
private syncVirtualPopupAnchor(): void {
|
|
247
|
+
const dropdown = this.dropdownRef.value;
|
|
248
|
+
const popup = dropdown?.shadowRoot?.querySelector('wa-popup') as WaPopupElement | null;
|
|
249
|
+
if (!popup) return;
|
|
250
|
+
popup.anchor = this.virtualAnchor;
|
|
251
|
+
popup.reposition();
|
|
252
|
+
}
|
|
253
|
+
|
|
235
254
|
private onClose() {
|
|
236
255
|
if (!this.isOpen) return;
|
|
237
256
|
this.isOpen = false;
|
|
238
257
|
document.removeEventListener('pointerdown', this.boundHandleDocumentPointerDown, { capture: true });
|
|
239
258
|
}
|
|
240
259
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
return nothing;
|
|
246
|
-
}
|
|
247
|
-
const disabled = getContributionDisabled(commandContribution);
|
|
248
|
-
return html`
|
|
249
|
-
<docks-command
|
|
250
|
-
cmd="${commandContribution.command}"
|
|
251
|
-
icon="${commandContribution.icon ?? ''}"
|
|
252
|
-
.params=${commandContribution.params ?? {}}
|
|
253
|
-
?disabled="${disabled}">
|
|
254
|
-
${commandContribution.label}
|
|
255
|
-
</docks-command>
|
|
256
|
-
`;
|
|
257
|
-
} else if ("component" in contribution) {
|
|
258
|
-
const contents = (contribution as HTMLContribution).component;
|
|
259
|
-
if (contents instanceof Function) {
|
|
260
|
-
return contents();
|
|
261
|
-
}
|
|
262
|
-
return unsafeHTML(contents);
|
|
260
|
+
protected updated(changedProperties: Map<string, unknown>): void {
|
|
261
|
+
super.updated(changedProperties);
|
|
262
|
+
if (changedProperties.has('isOpen') && this.isOpen) {
|
|
263
|
+
this.syncVirtualPopupAnchor();
|
|
263
264
|
}
|
|
264
|
-
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
private renderContribution(contribution: Contribution) {
|
|
268
|
+
return renderDropdownContribution(contribution);
|
|
265
269
|
}
|
|
266
270
|
|
|
267
271
|
render() {
|
|
@@ -273,17 +277,7 @@ export class DocksContextMenu extends DocksElement {
|
|
|
273
277
|
?open=${this.isOpen}
|
|
274
278
|
@submenu-opening=${this.handleSubmenuOpening}
|
|
275
279
|
@wa-after-hide=${this.onClose}>
|
|
276
|
-
|
|
277
|
-
<div
|
|
278
|
-
slot="trigger"
|
|
279
|
-
${ref(this.anchorRef)}
|
|
280
|
-
style="position: fixed;
|
|
281
|
-
left: ${this.position.x}px;
|
|
282
|
-
top: ${this.position.y}px;
|
|
283
|
-
width: 1px;
|
|
284
|
-
height: 1px;
|
|
285
|
-
pointer-events: none;">
|
|
286
|
-
</div>
|
|
280
|
+
<span slot="trigger" hidden aria-hidden="true"></span>
|
|
287
281
|
|
|
288
282
|
${partContent}
|
|
289
283
|
${this.contributions.map(c => this.renderContribution(c))}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { html, TemplateResult, css } from "lit";
|
|
2
2
|
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
|
3
|
-
import {
|
|
3
|
+
import { parseMarkdownHtml } from "../core/markdown-html";
|
|
4
4
|
import { DocksElement } from "./element";
|
|
5
5
|
|
|
6
6
|
export abstract class DocksDialogContent extends DocksElement {
|
|
@@ -22,7 +22,7 @@ export abstract class DocksDialogContent extends DocksElement {
|
|
|
22
22
|
|
|
23
23
|
protected renderMessage(message: string, markdown: boolean = false): TemplateResult {
|
|
24
24
|
if (markdown) {
|
|
25
|
-
const htmlContent =
|
|
25
|
+
const htmlContent = parseMarkdownHtml(message);
|
|
26
26
|
return html`<div class="dialog-message" style="white-space: normal;">${unsafeHTML(htmlContent)}</div>`;
|
|
27
27
|
}
|
|
28
28
|
return html`<div class="dialog-message" style="white-space: pre-line;">${message}</div>`;
|
package/src/parts/index.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import "../externals/webawesome"
|
|
2
|
+
import { installOpenDropdownNativeContextMenuGuard } from "../core/dropdown-menu-utils";
|
|
2
3
|
import "./toolbar"
|
|
3
4
|
import "./contextmenu"
|
|
4
5
|
import "./tabs"
|
|
5
|
-
import "./resizable-grid"
|
|
6
|
+
import "./resizable-grid"
|
|
7
|
+
|
|
8
|
+
installOpenDropdownNativeContextMenuGuard();
|
package/src/parts/part.ts
CHANGED
|
@@ -135,11 +135,13 @@ export abstract class DocksPart extends DocksContainer {
|
|
|
135
135
|
return nothing;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
/** Part-level toolbar contributions (`toolbar:${partId}`). */
|
|
138
139
|
private getToolbarTarget(): string | undefined {
|
|
139
140
|
const contributionKey = this.tabContribution?.editorId ?? this.id ?? this.tabContribution?.name;
|
|
140
141
|
return contributionKey ? `toolbar:${contributionKey}` : undefined;
|
|
141
142
|
}
|
|
142
143
|
|
|
144
|
+
/** Part-level context-menu contributions (`contextmenu:${partId}`). */
|
|
143
145
|
private getContextMenuTarget(): string | undefined {
|
|
144
146
|
const contributionKey = this.tabContribution?.editorId ?? this.id ?? this.tabContribution?.name;
|
|
145
147
|
return contributionKey ? `contextmenu:${contributionKey}` : undefined;
|