/// /// /// export type Button = { text: string; onClick?: () => void; }; /** * PopupMenuから三角形を取り除いたようなものをカーソルのすぐ下に表示する */ export function createPopupMenuBar() { const { popupMenu, render } = createPopupContainer(); const editor = document.getElementById("editor"); editor?.append(popupMenu); const cursor = document.getElementsByClassName("cursor")[0] as HTMLElement; const observer = new MutationObserver(() => popupMenu.style.top = `${parseInt(cursor.style.top) + parseInt(cursor.style.height) + 4}px` ); observer.observe(document.getElementsByClassName("lines")[0], { attributes: true, subtree: true, attributeFilter: ["class"], }); return { render, visible: () => !popupMenu.hidden, open: () => popupMenu.hidden = false, close: () => popupMenu.hidden = true, toggle: () => popupMenu.hidden = !popupMenu.hidden, }; } function createPopupContainer() { const popupMenu = document.createElement("div"); const shadowRoot = popupMenu.attachShadow({ mode: "open" }); shadowRoot.innerHTML = `
`; const buttonContainer = shadowRoot.lastElementChild!; return { popupMenu, render(buttons: Button[]) { buttonContainer.textContent = ""; buttonContainer.append(...buttons.map(({ text, onClick }) => { const div = document.createElement("div"); div.classList.add("button"); div.textContent = text; if (onClick) div.addEventListener("click", () => onClick()); return div; })); }, }; }