/** * `materialTooltip`: shows an `` popover for the control it belongs to. * * The trigger is the popover's parent element (the button, or the standalone wrapper). Hover * counts only for a pointer that can hover, after a short delay so a pointer passing over a * toolbar does not flash every label; keyboard focus shows it at once. A press, leaving, blur * and Escape hide it. */ const HOVER_DELAY_MS = 500 document.addEventListener('alpine:init', () => { window.Alpine.data('materialTooltip', () => ({ timer: null, listeners: [], init() { const tip = this.$el const trigger = tip.parentElement const open = () => tip.matches(':popover-open') const show = (delay) => { clearTimeout(this.timer) this.timer = setTimeout(() => { if (tip.isConnected && !open()) { tip.showPopover() } }, delay) } const hide = () => { clearTimeout(this.timer) if (open()) { tip.hidePopover() } } this.listen(trigger, 'pointerenter', (event) => event.pointerType === 'mouse' && show(HOVER_DELAY_MS)) this.listen(trigger, 'pointerleave', hide) this.listen(trigger, 'pointerdown', hide) this.listen(trigger, 'focusin', () => trigger.matches(':focus-within:has(:focus-visible), :focus-visible') && show(0)) this.listen(trigger, 'focusout', hide) this.listen(document, 'keydown', (event) => event.key === 'Escape' && hide()) }, listen(target, type, handler) { target.addEventListener(type, handler) this.listeners.push(() => target.removeEventListener(type, handler)) }, destroy() { clearTimeout(this.timer) this.listeners.forEach((remove) => remove()) }, })) })