Files
Webklar.com/node_modules/motion-dom/dist/es/gestures/press/index.mjs
Basilosaurusrex f027651f9b main repo
2025-11-24 18:09:40 +01:00

84 lines
3.3 KiB
JavaScript

import { isHTMLElement } from '../../utils/is-html-element.mjs';
import { isDragActive } from '../drag/state/is-active.mjs';
import { isNodeOrChild } from '../utils/is-node-or-child.mjs';
import { isPrimaryPointer } from '../utils/is-primary-pointer.mjs';
import { setupGesture } from '../utils/setup.mjs';
import { isElementKeyboardAccessible } from './utils/is-keyboard-accessible.mjs';
import { enableKeyboardPress } from './utils/keyboard.mjs';
import { isPressing } from './utils/state.mjs';
/**
* Filter out events that are not primary pointer events, or are triggering
* while a Motion gesture is active.
*/
function isValidPressEvent(event) {
return isPrimaryPointer(event) && !isDragActive();
}
/**
* Create a press gesture.
*
* Press is different to `"pointerdown"`, `"pointerup"` in that it
* automatically filters out secondary pointer events like right
* click and multitouch.
*
* It also adds accessibility support for keyboards, where
* an element with a press gesture will receive focus and
* trigger on Enter `"keydown"` and `"keyup"` events.
*
* This is different to a browser's `"click"` event, which does
* respond to keyboards but only for the `"click"` itself, rather
* than the press start and end/cancel. The element also needs
* to be focusable for this to work, whereas a press gesture will
* make an element focusable by default.
*
* @public
*/
function press(targetOrSelector, onPressStart, options = {}) {
const [targets, eventOptions, cancelEvents] = setupGesture(targetOrSelector, options);
const startPress = (startEvent) => {
const target = startEvent.currentTarget;
if (!isValidPressEvent(startEvent))
return;
isPressing.add(target);
const onPressEnd = onPressStart(target, startEvent);
const onPointerEnd = (endEvent, success) => {
window.removeEventListener("pointerup", onPointerUp);
window.removeEventListener("pointercancel", onPointerCancel);
if (isPressing.has(target)) {
isPressing.delete(target);
}
if (!isValidPressEvent(endEvent)) {
return;
}
if (typeof onPressEnd === "function") {
onPressEnd(endEvent, { success });
}
};
const onPointerUp = (upEvent) => {
onPointerEnd(upEvent, target === window ||
target === document ||
options.useGlobalTarget ||
isNodeOrChild(target, upEvent.target));
};
const onPointerCancel = (cancelEvent) => {
onPointerEnd(cancelEvent, false);
};
window.addEventListener("pointerup", onPointerUp, eventOptions);
window.addEventListener("pointercancel", onPointerCancel, eventOptions);
};
targets.forEach((target) => {
const pointerDownTarget = options.useGlobalTarget ? window : target;
pointerDownTarget.addEventListener("pointerdown", startPress, eventOptions);
if (isHTMLElement(target)) {
target.addEventListener("focus", (event) => enableKeyboardPress(event, eventOptions));
if (!isElementKeyboardAccessible(target) &&
!target.hasAttribute("tabindex")) {
target.tabIndex = 0;
}
}
});
return cancelEvents;
}
export { press };