@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.
Files changed (51) hide show
  1. package/dist/api/index.js +4 -4
  2. package/dist/api/services.d.ts +3 -0
  3. package/dist/api/services.d.ts.map +1 -1
  4. package/dist/{api-CTU-FxEv.js → api-Da9zQcfd.js} +187 -38
  5. package/dist/api-Da9zQcfd.js.map +1 -0
  6. package/dist/components/command.d.ts +4 -4
  7. package/dist/components/command.d.ts.map +1 -1
  8. package/dist/components/filebrowser.d.ts.map +1 -1
  9. package/dist/components/release-history.d.ts.map +1 -1
  10. package/dist/core/contribution-names.d.ts +0 -2
  11. package/dist/core/contribution-names.d.ts.map +1 -1
  12. package/dist/core/contributionregistry.d.ts +3 -0
  13. package/dist/core/contributionregistry.d.ts.map +1 -1
  14. package/dist/core/dropdown-item.d.ts +35 -0
  15. package/dist/core/dropdown-item.d.ts.map +1 -0
  16. package/dist/core/dropdown-menu-utils.d.ts +5 -0
  17. package/dist/core/dropdown-menu-utils.d.ts.map +1 -1
  18. package/dist/core/markdown-html.d.ts +4 -0
  19. package/dist/core/markdown-html.d.ts.map +1 -0
  20. package/dist/index.js +4 -4
  21. package/dist/parts/contextmenu.d.ts +5 -2
  22. package/dist/parts/contextmenu.d.ts.map +1 -1
  23. package/dist/parts/index.d.ts.map +1 -1
  24. package/dist/parts/index.js +1 -1
  25. package/dist/parts/part.d.ts +2 -0
  26. package/dist/parts/part.d.ts.map +1 -1
  27. package/dist/{parts-BRaXx8PD.js → parts-CRVxaDd-.js} +197 -263
  28. package/dist/parts-CRVxaDd-.js.map +1 -0
  29. package/dist/{widget-DbLusgAH.js → widget-BqQtioK1.js} +11 -5
  30. package/dist/widget-BqQtioK1.js.map +1 -0
  31. package/dist/widgets/index.js +1 -1
  32. package/dist/{widgets-DnnSZhsi.js → widgets-C9V42Mqq.js} +2 -2
  33. package/dist/{widgets-DnnSZhsi.js.map → widgets-C9V42Mqq.js.map} +1 -1
  34. package/package.json +2 -1
  35. package/src/api/services.ts +9 -0
  36. package/src/commands/filebrowser-contributions.ts +0 -16
  37. package/src/components/command.ts +45 -113
  38. package/src/components/filebrowser.ts +15 -12
  39. package/src/components/release-history.ts +2 -4
  40. package/src/core/contribution-names.ts +0 -3
  41. package/src/core/contributionregistry.ts +19 -3
  42. package/src/core/dropdown-item.ts +152 -0
  43. package/src/core/dropdown-menu-utils.ts +59 -0
  44. package/src/core/markdown-html.ts +11 -0
  45. package/src/parts/contextmenu.ts +38 -44
  46. package/src/parts/dialog-content.ts +2 -2
  47. package/src/parts/index.ts +4 -1
  48. package/src/parts/part.ts +2 -0
  49. package/dist/api-CTU-FxEv.js.map +0 -1
  50. package/dist/parts-BRaXx8PD.js.map +0 -1
  51. package/dist/widget-DbLusgAH.js.map +0 -1
@@ -1,10 +1,11 @@
1
1
  import { n as defaultLogger, o as rootContext, s as uiContext, t as createLogger } from "./logger-DT0_NW3S.js";
2
- import { C as toastError, _ as getContributionDisabled, a as TOPIC_COMMAND_REGISTERED, b as contributionTargetMappingRegistry, f as activeTasksSignal, g as contributionRegistry, h as TOPIC_CONTRIBUTEIONS_CHANGED, l as activeEditorSignal, n as watchSignal, o as commandRegistry, p as partDirtySignal, t as DocksWidget, u as activePartSignal, v as getContributionVisible, w as toastInfo } from "./widget-DbLusgAH.js";
2
+ import { T as toastInfo, _ as getContributionDisabled, a as TOPIC_COMMAND_REGISTERED, f as activeTasksSignal, g as contributionRegistry, h as TOPIC_CONTRIBUTEIONS_CHANGED, l as activeEditorSignal, n as watchSignal, o as commandRegistry, p as partDirtySignal, t as DocksWidget, u as activePartSignal, v as getContributionVisible, w as toastError, x as contributionTargetMappingRegistry, y as readReactiveBoolean } from "./widget-BqQtioK1.js";
3
3
  import { n as subscribe, t as publish } from "./events-B_ZxkU_G.js";
4
4
  import { a as File, i as Directory, l as TOPIC_WORKSPACE_CHANGED, m as persistenceService, o as FileContentType, p as workspaceService } from "./fs-access-DTXPsV1W.js";
5
5
  import "./webawesome-Y1_HnKa_.js";
6
6
  import { css, html, nothing, render } from "lit";
7
7
  import { unsafeHTML } from "lit/directives/unsafe-html.js";
8
+ import DOMPurify from "dompurify";
8
9
  import { marked } from "marked";
9
10
  import { customElement, property, state } from "lit/decorators.js";
10
11
  import _decorate from "@oxc-project/runtime/helpers/decorate";
@@ -977,6 +978,17 @@ var KeyBindingManager = class {
977
978
  var keyBindingManager = new KeyBindingManager();
978
979
  rootContext.put("keyBindingManager", keyBindingManager);
979
980
  //#endregion
981
+ //#region src/core/markdown-html.ts
982
+ function sanitizeHtml(html) {
983
+ return DOMPurify.sanitize(html);
984
+ }
985
+ function parseMarkdownHtml(markdown, options) {
986
+ return sanitizeHtml(marked.parse(markdown, {
987
+ async: false,
988
+ ...options
989
+ }));
990
+ }
991
+ //#endregion
980
992
  //#region src/parts/element.ts
981
993
  var DocksElement = class extends DocksWidget {
982
994
  constructor(..._args) {
@@ -1062,7 +1074,7 @@ var DocksDialogContent = class extends DocksElement {
1062
1074
  dispose() {}
1063
1075
  getResult() {}
1064
1076
  renderMessage(message, markdown = false) {
1065
- if (markdown) return html`<div class="dialog-message" style="white-space: normal;">${unsafeHTML(marked.parse(message, { async: false }))}</div>`;
1077
+ if (markdown) return html`<div class="dialog-message" style="white-space: normal;">${unsafeHTML(parseMarkdownHtml(message))}</div>`;
1066
1078
  return html`<div class="dialog-message" style="white-space: pre-line;">${message}</div>`;
1067
1079
  }
1068
1080
  };
@@ -3028,6 +3040,74 @@ function versionInfoDialog() {
3028
3040
  return dialogService.open("version-info", { label: `About ${app?.name ?? ""} - ${app?.version ?? "0.0.0"}` });
3029
3041
  }
3030
3042
  //#endregion
3043
+ //#region src/core/dropdown-menu-utils.ts
3044
+ function isOpenDropdown(element) {
3045
+ if (element.localName !== "wa-dropdown") return false;
3046
+ const dropdown = element;
3047
+ return dropdown.open === true || dropdown.hasAttribute("open");
3048
+ }
3049
+ function elementsFromEventPath(event) {
3050
+ const fromComposedPath = event.composedPath().filter((node) => node instanceof Element);
3051
+ if (fromComposedPath.length > 0) return fromComposedPath;
3052
+ if (!(event.target instanceof Element)) return [];
3053
+ const path = [];
3054
+ let current = event.target;
3055
+ while (current) {
3056
+ path.push(current);
3057
+ const root = current.getRootNode();
3058
+ if (root instanceof ShadowRoot) {
3059
+ current = root.host;
3060
+ continue;
3061
+ }
3062
+ current = current.parentElement;
3063
+ }
3064
+ return path;
3065
+ }
3066
+ function elementTargetsOpenDropdown(element) {
3067
+ if (isOpenDropdown(element)) return true;
3068
+ if (element.localName !== "wa-dropdown-item") return false;
3069
+ const dropdown = element.closest("wa-dropdown");
3070
+ if (dropdown && isOpenDropdown(dropdown)) return true;
3071
+ const root = element.getRootNode();
3072
+ return root instanceof ShadowRoot && root.host instanceof Element && isOpenDropdown(root.host);
3073
+ }
3074
+ /** True when the event occurred inside a wa-dropdown that is currently open. */
3075
+ function eventTargetsOpenDropdown(event) {
3076
+ return elementsFromEventPath(event).some(elementTargetsOpenDropdown);
3077
+ }
3078
+ /** Prevents the browser context menu on open Docks popup lists (context menus, toolbar dropdowns). */
3079
+ function suppressNativeContextMenuInOpenDropdowns(event) {
3080
+ if (!event.cancelable || !eventTargetsOpenDropdown(event)) return;
3081
+ event.preventDefault();
3082
+ }
3083
+ var openDropdownContextMenuGuardInstalled = false;
3084
+ function installOpenDropdownNativeContextMenuGuard() {
3085
+ if (openDropdownContextMenuGuardInstalled || typeof document === "undefined") return;
3086
+ openDropdownContextMenuGuardInstalled = true;
3087
+ document.addEventListener("contextmenu", suppressNativeContextMenuInOpenDropdowns, { capture: true });
3088
+ }
3089
+ function visitElementTree(root, visit) {
3090
+ if (root instanceof Element) {
3091
+ visit(root);
3092
+ if (root.shadowRoot) visitElementTree(root.shadowRoot, visit);
3093
+ for (const child of root.children) visitElementTree(child, visit);
3094
+ } else if (root instanceof DocumentFragment) for (const child of root.children) visitElementTree(child, visit);
3095
+ }
3096
+ /** Collect wa-dropdown-item elements under a menu root, including shadow DOM. */
3097
+ function collectDropdownItems(root) {
3098
+ const items = [];
3099
+ visitElementTree(root, (element) => {
3100
+ if (element.localName === "wa-dropdown-item") items.push(element);
3101
+ });
3102
+ return items;
3103
+ }
3104
+ /** Close every open submenu except the one being activated. */
3105
+ function closeSiblingSubmenus(activeItem, menuRoot) {
3106
+ queueMicrotask(() => {
3107
+ for (const item of collectDropdownItems(menuRoot)) if (item !== activeItem && item.submenuOpen) item.submenuOpen = false;
3108
+ });
3109
+ }
3110
+ //#endregion
3031
3111
  //#region src/core/icon-utils.ts
3032
3112
  /**
3033
3113
  * Parses an icon spec string into `{ library, name }` for use with `wa-icon`.
@@ -3264,236 +3344,99 @@ _decorate([state()], DocksToolbar.prototype, "contributions", void 0);
3264
3344
  _decorate([state()], DocksToolbar.prototype, "compact", void 0);
3265
3345
  DocksToolbar = _decorate([customElement("docks-toolbar")], DocksToolbar);
3266
3346
  //#endregion
3267
- //#region src/core/dropdown-menu-utils.ts
3268
- function visitElementTree(root, visit) {
3269
- if (root instanceof Element) {
3270
- visit(root);
3271
- if (root.shadowRoot) visitElementTree(root.shadowRoot, visit);
3272
- for (const child of root.children) visitElementTree(child, visit);
3273
- } else if (root instanceof DocumentFragment) for (const child of root.children) visitElementTree(child, visit);
3347
+ //#region src/core/dropdown-item.ts
3348
+ /**
3349
+ * Shared render helpers for {@link https://webawesome.com/docs/components/dropdown-item | wa-dropdown-item}
3350
+ * rows inside any Docks popup list.
3351
+ *
3352
+ * **Docks surfaces** (distinct UX and contribution targets):
3353
+ * - **Toolbar dropdown** — anchored to a toolbar control (`docks-command`, `docks-toolbar`).
3354
+ * Part-level registry targets use the `toolbar:` prefix (e.g. `toolbar:view.filebrowser`).
3355
+ * - **Context menu** — opened at the pointer (`docks-contextmenu`).
3356
+ * Part-level registry targets use the `contextmenu:` prefix (e.g. `contextmenu:view.filebrowser`).
3357
+ *
3358
+ * A part can expose both surfaces with the same part id but different prefixes, registering
3359
+ * different contributions on each. Feature-scoped targets (e.g. `filebrowser.create`) may also
3360
+ * be referenced explicitly from either surface when several controls share the same item set.
3361
+ */
3362
+ function closeParentDropdown(event) {
3363
+ const dropdown = event.target?.closest("wa-dropdown");
3364
+ if (dropdown && dropdown.open !== void 0) dropdown.open = false;
3274
3365
  }
3275
- /** Collect wa-dropdown-item elements under a menu root, including shadow DOM. */
3276
- function collectDropdownItems(root) {
3277
- const items = [];
3278
- visitElementTree(root, (element) => {
3279
- if (element.localName === "wa-dropdown-item") items.push(element);
3280
- });
3281
- return items;
3366
+ function onDropdownItemClick(options) {
3367
+ return (event) => {
3368
+ if (readReactiveBoolean(options.disabled, false)) return;
3369
+ event.stopPropagation();
3370
+ closeParentDropdown(event);
3371
+ if (options.action) {
3372
+ options.action(event);
3373
+ return;
3374
+ }
3375
+ if (options.cmd) commandRegistry.execute(options.cmd, commandRegistry.createExecutionContext(options.params ?? {}));
3376
+ };
3282
3377
  }
3283
- /** Close every open submenu except the one being activated. */
3284
- function closeSiblingSubmenus(activeItem, menuRoot) {
3285
- queueMicrotask(() => {
3286
- for (const item of collectDropdownItems(menuRoot)) if (item !== activeItem && item.submenuOpen) item.submenuOpen = false;
3378
+ function keybindingDetails(cmd) {
3379
+ if (!cmd) return nothing;
3380
+ const bindings = keyBindingManager.getKeyBindingsForCommand(cmd);
3381
+ if (bindings.length === 0) return nothing;
3382
+ return html`<span slot="details">${bindings[0]}</span>`;
3383
+ }
3384
+ /** Renders a native {@link https://webawesome.com/docs/components/dropdown-item | wa-dropdown-item}. */
3385
+ function renderDropdownItem(options) {
3386
+ const iconSpec = options.icon ?? "";
3387
+ return html`
3388
+ <wa-dropdown-item
3389
+ slot=${options.slot ?? nothing}
3390
+ variant=${options.variant ?? "default"}
3391
+ ?disabled=${readReactiveBoolean(options.disabled, false)}
3392
+ @click=${onDropdownItemClick(options)}>
3393
+ ${iconSpec ? icon(iconSpec, {
3394
+ label: options.title ?? options.label,
3395
+ slot: "icon"
3396
+ }) : nothing}
3397
+ ${options.label}
3398
+ ${keybindingDetails(options.cmd)}
3399
+ </wa-dropdown-item>
3400
+ `;
3401
+ }
3402
+ function renderCommandContribution(contribution, options) {
3403
+ if (!getContributionVisible(contribution)) return nothing;
3404
+ return renderDropdownItem({
3405
+ cmd: contribution.command,
3406
+ icon: contribution.icon,
3407
+ label: contribution.label,
3408
+ params: contribution.params,
3409
+ disabled: contribution.disabled,
3410
+ slot: options?.slot
3287
3411
  });
3288
3412
  }
3289
- //#endregion
3290
- //#region src/components/command.ts
3291
- var DocksCommand = class DocksCommand extends DocksWidget {
3292
- constructor(..._args) {
3293
- super(..._args);
3294
- this.cmd = "";
3295
- this.title = "";
3296
- this.label = false;
3297
- this.disabled = false;
3298
- this.appearance = "plain";
3299
- this.variant = "neutral";
3300
- this.size = "s";
3301
- this.params = {};
3302
- this.withCaret = true;
3303
- this.placement = "bottom-start";
3304
- this.dropdownContributions = [];
3305
- }
3306
- closeDropdown(dropdown) {
3307
- if (dropdown && dropdown.open !== void 0) dropdown.open = false;
3308
- }
3309
- closeParentDropdown() {
3310
- this.closeDropdown(this.closest("wa-dropdown"));
3311
- }
3312
- handleClick(event) {
3313
- if (this.disabled) return;
3314
- if (event) event.stopPropagation();
3315
- this.closeParentDropdown();
3316
- if (this.action) {
3317
- this.action(event);
3318
- return;
3319
- }
3320
- if (this.cmd) this.executeCommand(this.cmd, this.params);
3321
- }
3322
- handleSelect(event) {
3323
- this.closeDropdown(event.target);
3324
- }
3325
- isInDropdown() {
3326
- return !!this.closest("wa-dropdown, wa-dropdown-menu");
3327
- }
3328
- getKeybinding() {
3329
- if (!this.cmd || this.action) return null;
3330
- const keybindings = keyBindingManager.getKeyBindingsForCommand(this.cmd);
3331
- return keybindings.length > 0 ? keybindings[0] : null;
3332
- }
3333
- doBeforeUI() {
3334
- if (this.dropdown) {
3335
- this.dropdownContributions = contributionRegistry.getContributions(this.dropdown);
3336
- subscribe(TOPIC_CONTRIBUTEIONS_CHANGED, (event) => {
3337
- if (this.dropdown && event.target === this.dropdown) this.dropdownContributions = event.contributions;
3338
- });
3339
- }
3340
- }
3341
- willUpdate(changedProperties) {
3342
- super.willUpdate?.(changedProperties);
3343
- if (this.dropdown && changedProperties.has("dropdown")) this.dropdownContributions = contributionRegistry.getContributions(this.dropdown);
3344
- }
3345
- renderContribution(contribution, slot) {
3346
- if ("command" in contribution) {
3347
- const commandContribution = contribution;
3348
- if (!getContributionVisible(commandContribution)) return nothing;
3349
- const disabled = getContributionDisabled(commandContribution);
3350
- return html`
3351
- <docks-command
3352
- slot=${slot ?? nothing}
3353
- cmd="${commandContribution.command}"
3354
- icon="${commandContribution.icon || ""}"
3355
- .params=${commandContribution.params || {}}
3356
- ?disabled="${disabled}">
3357
- ${commandContribution.label}
3358
- </docks-command>
3359
- `;
3360
- }
3361
- if ("component" in contribution) {
3362
- const contents = contribution.component;
3363
- if (contents instanceof Function) return contents();
3364
- return unsafeHTML(contents);
3365
- }
3366
- return nothing;
3367
- }
3368
- render() {
3369
- const keybinding = this.getKeybinding();
3370
- if (this.isInDropdown() && this.dropdown) return html`
3371
- <wa-dropdown-item ?disabled=${this.disabled}>
3372
- ${icon(this.icon, {
3373
- label: this.title,
3374
- slot: "icon"
3375
- })}
3376
- <slot></slot>
3377
- ${this.dropdownContributions.map((c) => this.renderContribution(c, "submenu"))}
3378
- </wa-dropdown-item>
3379
- `;
3380
- if (this.isInDropdown()) return html`
3381
- <wa-dropdown-item
3382
- ?disabled=${this.disabled}
3383
- @click=${(e) => this.handleClick(e)}>
3384
- ${icon(this.icon, {
3385
- label: this.title,
3386
- slot: "icon"
3387
- })}
3388
- <slot></slot>
3389
- ${keybinding ? html`<span class="keybinding">${keybinding}</span>` : ""}
3390
- </wa-dropdown-item>
3391
- `;
3392
- if (this.dropdown) return html`
3393
- <wa-dropdown
3394
- placement=${this.placement}
3395
- @wa-select=${(e) => this.handleSelect(e)}>
3396
- <wa-button
3397
- slot="trigger"
3398
- appearance=${this.appearance}
3399
- variant=${this.variant}
3400
- size=${this.size}
3401
- ?disabled=${this.disabled}
3402
- ?with-caret=${this.withCaret}
3403
- title=${keybinding ? `${this.title} (${keybinding})` : this.title}>
3404
- ${icon(this.icon, {
3405
- label: this.title,
3406
- slot: "start"
3407
- })}
3408
- <slot></slot>
3409
- ${this.label ? this.title : nothing}
3410
- </wa-button>
3411
-
3412
- ${this.title ? html`
3413
- <h6 style="padding: var(--wa-space-xs) var(--wa-space-s); margin: 0; color: var(--wa-color-neutral-50); font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em;">
3414
- ${this.title}
3415
- </h6>
3416
- ` : nothing}
3417
-
3418
- ${this.dropdownContributions.map((c) => this.renderContribution(c))}
3419
-
3420
- ${this.cmd ? html`
3421
- <wa-divider></wa-divider>
3422
- <docks-command
3423
- cmd="${this.cmd}"
3424
- icon="${this.icon || ""}"
3425
- .params=${this.params}
3426
- ?disabled=${this.disabled}>
3427
- <slot></slot>
3428
- ${this.title}
3429
- </docks-command>
3430
- ` : nothing}
3431
- </wa-dropdown>
3432
- `;
3433
- return html`
3434
- <wa-button
3435
- appearance=${this.appearance}
3436
- variant=${this.variant}
3437
- size=${this.size}
3438
- ?disabled=${this.disabled}
3439
- title=${keybinding ? `${this.title} (${keybinding})` : this.title}
3440
- @click=${(e) => this.handleClick(e)}>
3441
- ${icon(this.icon, {
3442
- label: this.title,
3443
- slot: "start"
3444
- })}
3445
- <slot></slot>
3446
- </wa-button>
3447
- `;
3448
- }
3449
- static {
3450
- this.styles = css`
3451
- :host {
3452
- display: inline-block;
3453
- }
3454
-
3455
- .keybinding {
3456
- margin-left: auto;
3457
- padding: 2px 6px;
3458
- background: var(--wa-color-neutral-15);
3459
- border: 1px solid var(--wa-color-neutral-25);
3460
- border-radius: 3px;
3461
- font-size: 10px;
3462
- font-family: monospace;
3463
- opacity: 0.7;
3464
- }
3465
-
3466
- :host-context(.wa-light) .keybinding {
3467
- background: var(--wa-color-neutral-85);
3468
- border: 1px solid var(--wa-color-neutral-75);
3469
- }
3413
+ function renderDropdownContribution(contribution, options) {
3414
+ if ("command" in contribution) return renderCommandContribution(contribution, options);
3415
+ if ("component" in contribution) {
3416
+ if (!getContributionVisible(contribution)) return nothing;
3417
+ const contents = contribution.component;
3418
+ if (contents instanceof Function) return contents();
3419
+ return html`${unsafeHTML(contents)}`;
3420
+ }
3421
+ return nothing;
3422
+ }
3423
+ /** Renders all visible contributions registered for a contribution target. */
3424
+ function renderDropdownContributions(target, options) {
3425
+ return html`${contributionRegistry.getContributions(target).map((c) => renderDropdownContribution(c, options)).filter((item) => item !== nothing)}`;
3426
+ }
3427
+ /** Renders a {@link wa-dropdown-item} with nested items from a contribution target in {@code slot="submenu"}. */
3428
+ function renderDropdownSubmenu(options) {
3429
+ return html`
3430
+ <wa-dropdown-item ?disabled=${readReactiveBoolean(options.disabled, false)}>
3431
+ ${options.icon ? icon(options.icon, {
3432
+ label: options.title ?? options.label,
3433
+ slot: "icon"
3434
+ }) : nothing}
3435
+ ${options.label}
3436
+ ${renderDropdownContributions(options.contributionTarget, { slot: "submenu" })}
3437
+ </wa-dropdown-item>
3470
3438
  `;
3471
- }
3472
- };
3473
- _decorate([property()], DocksCommand.prototype, "cmd", void 0);
3474
- _decorate([property({
3475
- type: Object,
3476
- attribute: false
3477
- })], DocksCommand.prototype, "action", void 0);
3478
- _decorate([property()], DocksCommand.prototype, "title", void 0);
3479
- _decorate([property()], DocksCommand.prototype, "label", void 0);
3480
- _decorate([property()], DocksCommand.prototype, "icon", void 0);
3481
- _decorate([property({ type: Boolean })], DocksCommand.prototype, "disabled", void 0);
3482
- _decorate([property()], DocksCommand.prototype, "appearance", void 0);
3483
- _decorate([property()], DocksCommand.prototype, "variant", void 0);
3484
- _decorate([property()], DocksCommand.prototype, "size", void 0);
3485
- _decorate([property({
3486
- type: Object,
3487
- attribute: false
3488
- })], DocksCommand.prototype, "params", void 0);
3489
- _decorate([property()], DocksCommand.prototype, "dropdown", void 0);
3490
- _decorate([property({
3491
- type: Boolean,
3492
- attribute: "with-caret"
3493
- })], DocksCommand.prototype, "withCaret", void 0);
3494
- _decorate([property()], DocksCommand.prototype, "placement", void 0);
3495
- _decorate([state()], DocksCommand.prototype, "dropdownContributions", void 0);
3496
- DocksCommand = _decorate([customElement("docks-command")], DocksCommand);
3439
+ }
3497
3440
  //#endregion
3498
3441
  //#region src/parts/contextmenu.ts
3499
3442
  var DocksContextMenu = class DocksContextMenu extends DocksElement {
@@ -3503,11 +3446,14 @@ var DocksContextMenu = class DocksContextMenu extends DocksElement {
3503
3446
  this.partContextMenuRenderer = void 0;
3504
3447
  this.contributions = [];
3505
3448
  this.isOpen = false;
3506
- this.position = {
3449
+ this.menuPosition = {
3507
3450
  x: 0,
3508
3451
  y: 0
3509
3452
  };
3510
- this.anchorRef = createRef();
3453
+ this.virtualAnchor = { getBoundingClientRect: () => {
3454
+ const { x, y } = this.menuPosition;
3455
+ return new DOMRect(x, y, 0, 0);
3456
+ } };
3511
3457
  this.dropdownRef = createRef();
3512
3458
  this.boundHandleDocumentPointerDown = this.handleDocumentPointerDown.bind(this);
3513
3459
  this.handleSubmenuOpening = (event) => {
@@ -3659,37 +3605,31 @@ var DocksContextMenu = class DocksContextMenu extends DocksElement {
3659
3605
  this.isOpen = false;
3660
3606
  await this.updateComplete;
3661
3607
  }
3662
- this.position = position;
3608
+ this.menuPosition = position;
3663
3609
  this.isOpen = true;
3664
3610
  await this.updateComplete;
3611
+ this.syncVirtualPopupAnchor();
3665
3612
  document.addEventListener("pointerdown", this.boundHandleDocumentPointerDown, { capture: true });
3666
3613
  return true;
3667
3614
  }
3615
+ /** Points wa-dropdown's internal wa-popup at the pointer via a VirtualElement anchor. */
3616
+ syncVirtualPopupAnchor() {
3617
+ const popup = this.dropdownRef.value?.shadowRoot?.querySelector("wa-popup");
3618
+ if (!popup) return;
3619
+ popup.anchor = this.virtualAnchor;
3620
+ popup.reposition();
3621
+ }
3668
3622
  onClose() {
3669
3623
  if (!this.isOpen) return;
3670
3624
  this.isOpen = false;
3671
3625
  document.removeEventListener("pointerdown", this.boundHandleDocumentPointerDown, { capture: true });
3672
3626
  }
3627
+ updated(changedProperties) {
3628
+ super.updated(changedProperties);
3629
+ if (changedProperties.has("isOpen") && this.isOpen) this.syncVirtualPopupAnchor();
3630
+ }
3673
3631
  renderContribution(contribution) {
3674
- if ("command" in contribution) {
3675
- const commandContribution = contribution;
3676
- if (!getContributionVisible(commandContribution)) return nothing;
3677
- const disabled = getContributionDisabled(commandContribution);
3678
- return html`
3679
- <docks-command
3680
- cmd="${commandContribution.command}"
3681
- icon="${commandContribution.icon ?? ""}"
3682
- .params=${commandContribution.params ?? {}}
3683
- ?disabled="${disabled}">
3684
- ${commandContribution.label}
3685
- </docks-command>
3686
- `;
3687
- } else if ("component" in contribution) {
3688
- const contents = contribution.component;
3689
- if (contents instanceof Function) return contents();
3690
- return unsafeHTML(contents);
3691
- }
3692
- return nothing;
3632
+ return renderDropdownContribution(contribution);
3693
3633
  }
3694
3634
  render() {
3695
3635
  const partContent = this.partContextMenuRenderer ? this.partContextMenuRenderer() : nothing;
@@ -3699,17 +3639,7 @@ var DocksContextMenu = class DocksContextMenu extends DocksElement {
3699
3639
  ?open=${this.isOpen}
3700
3640
  @submenu-opening=${this.handleSubmenuOpening}
3701
3641
  @wa-after-hide=${this.onClose}>
3702
-
3703
- <div
3704
- slot="trigger"
3705
- ${ref(this.anchorRef)}
3706
- style="position: fixed;
3707
- left: ${this.position.x}px;
3708
- top: ${this.position.y}px;
3709
- width: 1px;
3710
- height: 1px;
3711
- pointer-events: none;">
3712
- </div>
3642
+ <span slot="trigger" hidden aria-hidden="true"></span>
3713
3643
 
3714
3644
  ${partContent}
3715
3645
  ${this.contributions.map((c) => this.renderContribution(c))}
@@ -3747,7 +3677,6 @@ _decorate([property({ attribute: false })], DocksContextMenu.prototype, "scopeTo
3747
3677
  _decorate([property({ attribute: false })], DocksContextMenu.prototype, "partContextMenuRenderer", void 0);
3748
3678
  _decorate([state()], DocksContextMenu.prototype, "contributions", void 0);
3749
3679
  _decorate([state()], DocksContextMenu.prototype, "isOpen", void 0);
3750
- _decorate([state()], DocksContextMenu.prototype, "position", void 0);
3751
3680
  DocksContextMenu = _decorate([customElement("docks-contextmenu")], DocksContextMenu);
3752
3681
  //#endregion
3753
3682
  //#region src/parts/container.ts
@@ -3871,10 +3800,12 @@ var DocksPart = class DocksPart extends DocksContainer {
3871
3800
  renderContent() {
3872
3801
  return nothing;
3873
3802
  }
3803
+ /** Part-level toolbar contributions (`toolbar:${partId}`). */
3874
3804
  getToolbarTarget() {
3875
3805
  const contributionKey = this.tabContribution?.editorId ?? this.id ?? this.tabContribution?.name;
3876
3806
  return contributionKey ? `toolbar:${contributionKey}` : void 0;
3877
3807
  }
3808
+ /** Part-level context-menu contributions (`contextmenu:${partId}`). */
3878
3809
  getContextMenuTarget() {
3879
3810
  const contributionKey = this.tabContribution?.editorId ?? this.id ?? this.tabContribution?.name;
3880
3811
  return contributionKey ? `contextmenu:${contributionKey}` : void 0;
@@ -4831,6 +4762,9 @@ _decorate([state()], DocksResizableGrid.prototype, "gridSizes", void 0);
4831
4762
  _decorate([state()], DocksResizableGrid.prototype, "gridChildren", void 0);
4832
4763
  DocksResizableGrid = _DocksResizableGrid = _decorate([customElement("docks-resizable-grid")], DocksResizableGrid);
4833
4764
  //#endregion
4834
- export { EDITOR_AREA_MAIN as A, TOOLBAR_BOTTOM_CENTER as B, TOPIC_SETTINGS_CHANGED as C, MouseButton as D, HIDE_DOT_RESOURCE as E, SIDEBAR_MAIN_TOOLBAR as F, TOOLBAR_MAIN as H, SYSTEM_ATTRIBUTIONS as I, SYSTEM_LAYOUTS as L, SIDEBAR_AUXILIARY as M, SIDEBAR_MAIN as N, constants_exports as O, SIDEBAR_MAIN_BOTTOM as P, SYSTEM_VIEWS as R, taskService as S, COMMAND_SAVE as T, TOOLBAR_MAIN_CENTER as U, TOOLBAR_BOTTOM_END as V, TOOLBAR_MAIN_RIGHT as W, DocksDialogContent as _, versionInfoDialog as a, extensionRegistry as b, confirmDialog as c, formDialogRequired as d, validateFormDialogFields as f, dialogService as g, deleteIndexedDbWorkspaceData as h, parseIconSpec as i, PANEL_BOTTOM as j, ABOUT_TABS as k, infoDialog as l, appLoaderService as m, DocksContainer as n, filebrowserDialog as o, promptDialog as p, icon as r, navigableInfoDialog as s, DocksPart as t, formDialog as u, DocksElement as v, appSettings as w, esmShService as x, TOPIC_EXTENSIONS_CHANGED as y, TOOLBAR_BOTTOM as z };
4765
+ //#region src/parts/index.ts
4766
+ installOpenDropdownNativeContextMenuGuard();
4767
+ //#endregion
4768
+ export { taskService as A, SIDEBAR_AUXILIARY as B, DocksElement as C, TOPIC_EXTENSIONS_CHANGED as D, keyBindingManager as E, MouseButton as F, SYSTEM_LAYOUTS as G, SIDEBAR_MAIN_BOTTOM as H, constants_exports as I, TOOLBAR_BOTTOM_CENTER as J, SYSTEM_VIEWS as K, ABOUT_TABS as L, appSettings as M, COMMAND_SAVE as N, extensionRegistry as O, HIDE_DOT_RESOURCE as P, TOOLBAR_MAIN_RIGHT as Q, EDITOR_AREA_MAIN as R, DocksDialogContent as S, sanitizeHtml as T, SIDEBAR_MAIN_TOOLBAR as U, SIDEBAR_MAIN as V, SYSTEM_ATTRIBUTIONS as W, TOOLBAR_MAIN as X, TOOLBAR_BOTTOM_END as Y, TOOLBAR_MAIN_CENTER as Z, validateFormDialogFields as _, renderDropdownContributions as a, deleteIndexedDbWorkspaceData as b, icon as c, filebrowserDialog as d, navigableInfoDialog as f, formDialogRequired as g, formDialog as h, renderDropdownContribution as i, TOPIC_SETTINGS_CHANGED as j, esmShService as k, parseIconSpec as l, infoDialog as m, DocksContainer as n, renderDropdownItem as o, confirmDialog as p, TOOLBAR_BOTTOM as q, renderCommandContribution as r, renderDropdownSubmenu as s, DocksPart as t, versionInfoDialog as u, promptDialog as v, parseMarkdownHtml as w, dialogService as x, appLoaderService as y, PANEL_BOTTOM as z };
4835
4769
 
4836
- //# sourceMappingURL=parts-BRaXx8PD.js.map
4770
+ //# sourceMappingURL=parts-CRVxaDd-.js.map