`;
render(tpl, this.#overlay);
}
#positionOverlay() {
if (!this.#overlay) return;
const panel = this.#overlay.querySelector(
".panel",
) as HTMLElement | null;
if (!panel) return;
const rect = this.getBoundingClientRect();
// Start below-left.
let top = rect.bottom + 6;
let left = rect.left;
// Temporarily set position for measurement.
panel.style.top = `${Math.round(top)}px`;
panel.style.left = `${Math.round(left)}px`;
panel.style.right = "auto";
panel.style.bottom = "auto";
// Next frame, measure and adjust to viewport.
if (this.#raf) cancelAnimationFrame(this.#raf);
this.#raf = requestAnimationFrame(() => {
const vw = globalThis.innerWidth;
const vh = globalThis.innerHeight;
const pr = panel.getBoundingClientRect();
// Horizontal clamping
if (pr.right > vw - 8) {
left = Math.max(8, vw - pr.width - 8);
}
if (left < 8) left = 8;
// Vertical flip if overflow bottom
if (pr.bottom > vh - 8) {
const above = rect.top - pr.height - 6;
if (above >= 8) top = above; // place above if space
else top = Math.max(8, vh - pr.height - 8); // clamp
}
panel.style.top = `${Math.round(top)}px`;
panel.style.left = `${Math.round(left)}px`;
});
}
#repositionActive() {
this.#positionOverlay();
}
override render() {
const label = this.label || "Tools";
const count = Array.isArray(this.tools)
? (this.tools?.length ?? 0)
: (this.tools ? Object.keys(this.tools as any).length : 0);
return html`