/** * `materialRichTooltip`: shows an ``. * * Transient (the default): like a plain tooltip — after a short hover on a pointer that can hover, * at once on keyboard focus, and it stays while the pointer moves onto the bubble to reach its * actions. Persistent: a press on the trigger opens it as a light-dismiss popover. */ const HOVER_DELAY_MS = 500 const LEAVE_GRACE_MS = 200 document.addEventListener('alpine:init', () => { window.Alpine.data('materialRichTooltip', (persistent = false) => ({ timer: null, init() { const bubble = this.$refs.bubble const wrapper = this.$el const open = () => bubble.matches(':popover-open') if (persistent) { wrapper.addEventListener('click', (event) => { if (bubble.contains(event.target)) { return } open() ? bubble.hidePopover() : bubble.showPopover() }) return } const show = (delay) => { clearTimeout(this.timer) this.timer = setTimeout(() => !open() && bubble.showPopover(), delay) } const hide = (delay = 0) => { clearTimeout(this.timer) this.timer = setTimeout(() => open() && bubble.hidePopover(), delay) } wrapper.addEventListener('pointerenter', (event) => event.pointerType === 'mouse' && show(HOVER_DELAY_MS)) wrapper.addEventListener('pointerleave', () => hide(LEAVE_GRACE_MS)) wrapper.addEventListener('focusin', (event) => event.target.matches(':focus-visible') && show(0)) wrapper.addEventListener('focusout', (event) => !wrapper.contains(event.relatedTarget) && hide()) document.addEventListener('keydown', (event) => event.key === 'Escape' && hide()) }, destroy() { clearTimeout(this.timer) }, })) })