(anchor)
| 464 | } |
| 465 | |
| 466 | #showMenu(anchor) { |
| 467 | const hasSelection = this.#hasSelection(); |
| 468 | const items = filterSelectionMenuItems(selectionMenu(), { |
| 469 | readOnly: this.#isReadOnly(), |
| 470 | hasSelection, |
| 471 | }); |
| 472 | |
| 473 | this.$menu.innerHTML = ""; |
| 474 | if (!items.length) { |
| 475 | this.#menuRequested = false; |
| 476 | this.#hideMenu(true); |
| 477 | return; |
| 478 | } |
| 479 | |
| 480 | items.forEach(({ onclick, text }) => { |
| 481 | const $item = document.createElement("div"); |
| 482 | if (typeof text === "string") { |
| 483 | $item.textContent = text; |
| 484 | } else if (text instanceof Node) { |
| 485 | $item.append(text.cloneNode(true)); |
| 486 | } |
| 487 | let handled = false; |
| 488 | const runAction = (event) => { |
| 489 | if (handled) return; |
| 490 | handled = true; |
| 491 | event.preventDefault(); |
| 492 | event.stopPropagation(); |
| 493 | this.#handlingMenuAction = true; |
| 494 | try { |
| 495 | onclick?.(); |
| 496 | } finally { |
| 497 | this.#handlingMenuAction = false; |
| 498 | this.#menuRequested = false; |
| 499 | this.#hideMenu(); |
| 500 | this.#view.focus(); |
| 501 | } |
| 502 | }; |
| 503 | $item.addEventListener("pointerdown", runAction); |
| 504 | $item.addEventListener("click", runAction); |
| 505 | this.$menu.append($item); |
| 506 | }); |
| 507 | |
| 508 | if (!this.$menu.isConnected) { |
| 509 | this.#container.append(this.$menu); |
| 510 | } |
| 511 | |
| 512 | const containerRect = this.#container.getBoundingClientRect(); |
| 513 | this.$menu.style.left = "0px"; |
| 514 | this.$menu.style.top = "0px"; |
| 515 | this.$menu.style.visibility = "hidden"; |
| 516 | |
| 517 | const menuRect = this.$menu.getBoundingClientRect(); |
| 518 | const preferredLeft = anchor.x - menuRect.width / 2; |
| 519 | const aboveGap = anchor.hasSelection ? MENU_SELECTION_GAP : MENU_CARET_GAP; |
| 520 | const belowGap = anchor.hasSelection |
| 521 | ? MENU_HANDLE_CLEARANCE |
| 522 | : MENU_CARET_GAP; |
| 523 | const topAbove = anchor.top - menuRect.height - aboveGap; |
no test coverage detected