import { html } from "lit"; import { property } from "lit/decorators.js"; import { t } from "../i18n/index.ts"; import { OpenClawLightDomElement } from "../lit/openclaw-element.ts"; import { DropdownMenuController } from "./dropdown-menu-controller.ts"; import { icons } from "./icons.ts"; import { activateMenuShortcut, menuShortcutHint } from "./menu-shortcuts.ts"; import "./web-awesome.ts"; export type NativeLinkMenuAction = "inline" | "external" | "copy"; export class NativeLinkMenu extends OpenClawLightDomElement { @property({ attribute: false }) x = 0; @property({ attribute: false }) y = 0; @property({ attribute: false }) trigger: HTMLAnchorElement | null = null; @property({ attribute: false }) onAction: (action: NativeLinkMenuAction) => void = () => {}; @property({ attribute: false }) onClose: () => void = () => {}; readonly menuLifecycle = new DropdownMenuController(this, { getTrigger: () => this.trigger, onClose: () => this.onClose(), onKeydown: (event) => activateMenuShortcut(this, event), }); private runAction(action: NativeLinkMenuAction) { this.onClose(); this.onAction(action); } override render() { const menuWidth = 264; const menuMaxHeight = 136; const clampedX = Math.max(8, Math.min(this.x, window.innerWidth - menuWidth - 8)); const clampedY = Math.max(8, Math.min(this.y, window.innerHeight - menuMaxHeight - 8)); return html` ) => { event.preventDefault(); const action = event.detail.item.value; if (action) { this.trigger?.focus(); this.runAction(action); } }} @wa-after-hide=${() => { this.onClose(); }} > ${t("nativeLinkMenu.openInline")} ${menuShortcutHint("s")} ${t("nativeLinkMenu.openExternal")} ${menuShortcutHint("b")} ${t("nativeLinkMenu.copy")} ${menuShortcutHint("c")} `; } } if (!customElements.get("openclaw-native-link-menu")) { customElements.define("openclaw-native-link-menu", NativeLinkMenu); }