@lookwe/lui
Version:
Lookwe UI web components
63 lines (60 loc) • 2.14 kB
JavaScript
import { nextMicrotask } from '@lookwe/utils/event-loop';
function isActivationClick(event) {
// Event must start at the event target.
if (event.currentTarget !== event.target) {
return false;
}
// Event must not be retargeted from shadowRoot.
if (event.composedPath()[0] !== event.target) {
return false;
}
// Target must not be disabled; this should only occur for a synthetically
// dispatched click.
if (event.target.disabled) {
return false;
}
return true;
}
function dispatchActivationClick(element) {
const event = new MouseEvent('click', { bubbles: true });
element.dispatchEvent(event);
return event;
}
function addActivationListener(root, delegateElement, options = {}) {
root.addEventListener('click', (event) => {
if (options.check?.(event) === false)
return;
if (event.defaultPrevented)
return;
const element = delegateElement();
if (!isActivationClick(event) || squelchEventFix(event) || !element)
return;
if (options.focus !== false)
root.focus();
dispatchActivationClick(element);
}, { capture: true });
}
// TODO(https://bugzilla.mozilla.org/show_bug.cgi?id=1804576)
// Remove when Firefox bug is addressed.
const isSquelchingEventTargets = new Set();
function squelchEventFix(event) {
// `Event.explicitOriginalTarget` only exists in Firefox
const eventTarget = event.explicitOriginalTarget ?? null;
if (!eventTarget)
return false;
const squelched = isSquelchingEventTargets.has(eventTarget);
if (squelched) {
event.preventDefault();
event.stopImmediatePropagation();
}
squelchEventsForMicrotask(eventTarget);
return squelched;
}
// Ignore events for one microtask only.
async function squelchEventsForMicrotask(eventTarget) {
isSquelchingEventTargets.add(eventTarget);
// Need to pause for just one microtask.
await nextMicrotask();
isSquelchingEventTargets.delete(eventTarget);
}
export { addActivationListener, dispatchActivationClick, isActivationClick };