Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@solid-aria/interactions

Package Overview
Dependencies
Maintainers
2
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@solid-aria/interactions - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

50

dist/index.d.ts
import { FocusEvents, FocusWithinEvents, HoverEvents, KeyboardEvents, PressEvents } from '@solid-aria/types';
import { MaybeAccessor } from '@solid-primitives/utils';
import { Accessor } from 'solid-js';
import * as solid_js from 'solid-js';
import { Accessor, JSX } from 'solid-js';

@@ -151,31 +152,52 @@ interface CreateFocusProps extends FocusEvents {

/**
* Whether the target is in a controlled press state (e.g. an overlay it triggers is open).
*/
isPressed?: MaybeAccessor<boolean | undefined>;
/**
* Whether the press events should be disabled.
*/
isDisabled?: MaybeAccessor<boolean | undefined>;
}
interface PressElementProps {
/**
* Handler that is called when a pointing device is both pressed and released while the pointer is over the target.
* Whether the target should not receive focus on press.
*/
onClick: (e: MouseEvent) => void;
preventFocusOnPress?: MaybeAccessor<boolean | undefined>;
/**
* Handler that is called when a pointing device is pressed while the pointer is over the target.
* Whether press events should be canceled when the pointer leaves the target while pressed.
* By default, this is `false`, which means if the pointer returns back over the target while
* still pressed, onPressStart will be fired again. If set to `true`, the press is canceled
* when the pointer leaves the target and onPressStart will not be fired if the pointer returns.
*/
onMouseDown: (e: MouseEvent) => void;
shouldCancelOnPointerExit?: MaybeAccessor<boolean | undefined>;
/**
* Handler that is called when a pointing device is released while the pointer is over the target.
* Whether text selection should be enabled on the pressable element.
*/
onMouseUp: (e: MouseEvent) => void;
allowTextSelectionOnPress?: MaybeAccessor<boolean | undefined>;
}
interface PressResult {
interface PressResult<T extends HTMLElement> {
/**
* Whether the target is currently pressed.
*/
isPressed: Accessor<boolean>;
/**
* Props to spread onto the target element.
*/
pressProps: Accessor<PressElementProps>;
pressProps: Accessor<JSX.HTMLAttributes<T>>;
}
interface PressResponderContextValue extends CreatePressProps {
register: () => void;
ref: Accessor<HTMLElement | undefined>;
}
declare const PressResponderContext: solid_js.Context<PressResponderContextValue | undefined>;
/**
* Handles press events for the target.
* Handles press interactions across mouse, touch, keyboard, and screen readers.
* It normalizes behavior across browsers and platforms, and handles many nuances
* of dealing with pointer and keyboard events.
* @param props - Props for the press primitive.
* @param ref - A ref for the HTML element.
*/
declare function createPress(props: CreatePressProps): PressResult;
declare function createPress<RefElement extends HTMLElement>(props: CreatePressProps, ref?: Accessor<RefElement | undefined>): PressResult<RefElement>;
export { CreateFocusProps, CreateFocusWithinProps, CreateHoverProps, CreateKeyboardProps, CreatePressProps, FocusElementProps, FocusResult, FocusWithinElementProps, FocusWithinResult, HoverElementProps, HoverResult, KeyboardElementProps, KeyboardResult, PressElementProps, PressResult, createFocus, createFocusVisible, createFocusVisibleListener, createFocusWithin, createHover, createInteractionModality, createKeyboard, createPress, getInteractionModality, isKeyboardFocusVisible, setInteractionModality, setupGlobalFocusEvents };
declare function disableTextSelection(target?: HTMLElement): void;
declare function restoreTextSelection(target?: HTMLElement): void;
export { CreateFocusProps, CreateFocusWithinProps, CreateHoverProps, CreateKeyboardProps, CreatePressProps, FocusElementProps, FocusResult, FocusWithinElementProps, FocusWithinResult, HoverElementProps, HoverResult, KeyboardElementProps, KeyboardResult, PressResponderContext, PressResult, createFocus, createFocusVisible, createFocusVisibleListener, createFocusWithin, createHover, createInteractionModality, createKeyboard, createPress, disableTextSelection, getInteractionModality, isKeyboardFocusVisible, restoreTextSelection, setInteractionModality, setupGlobalFocusEvents };

@@ -408,36 +408,590 @@ // src/createFocus.ts

// src/createPress.ts
import {
combineProps,
createGlobalListeners,
createSyncRef,
focusWithoutScrolling
} from "@solid-aria/utils";
import { access as access6 } from "@solid-primitives/utils";
import { createMemo as createMemo5 } from "solid-js";
function createPress(props) {
const onClick = (event) => {
var _a;
if (access6(props.isDisabled)) {
return;
import {
createContext,
createEffect as createEffect3,
createMemo as createMemo5,
createSignal as createSignal5,
on as on3,
onCleanup as onCleanup4,
splitProps,
useContext
} from "solid-js";
// src/textSelection.ts
import { isIOS, runAfterTransition } from "@solid-aria/utils";
var state = "default";
var savedUserSelect = "";
var modifiedElementMap = /* @__PURE__ */ new WeakMap();
function disableTextSelection(target) {
if (isIOS()) {
if (state === "default") {
savedUserSelect = document.documentElement.style.webkitUserSelect;
document.documentElement.style.webkitUserSelect = "none";
}
(_a = props.onClick) == null ? void 0 : _a.call(props, event);
};
const onMouseDown = (event) => {
var _a, _b;
if (access6(props.isDisabled)) {
state = "disabled";
} else if (target) {
modifiedElementMap.set(target, target.style.userSelect);
target.style.userSelect = "none";
}
}
function restoreTextSelection(target) {
var _a;
if (isIOS()) {
if (state !== "disabled") {
return;
}
(_a = props.onMouseDown) == null ? void 0 : _a.call(props, event);
(_b = props.onPressChange) == null ? void 0 : _b.call(props, true);
};
const onMouseUp = (event) => {
var _a, _b;
if (access6(props.isDisabled)) {
return;
state = "restoring";
setTimeout(() => {
runAfterTransition(() => {
if (state === "restoring") {
if (document.documentElement.style.webkitUserSelect === "none") {
document.documentElement.style.webkitUserSelect = savedUserSelect || "";
}
savedUserSelect = "";
state = "default";
}
});
}, 300);
} else {
if (target && modifiedElementMap.has(target)) {
const targetOldUserSelect = (_a = modifiedElementMap.get(target)) != null ? _a : "";
if (target.style.userSelect === "none") {
target.style.userSelect = targetOldUserSelect;
}
if (target.getAttribute("style") === "") {
target.removeAttribute("style");
}
modifiedElementMap.delete(target);
}
(_a = props.onMouseUp) == null ? void 0 : _a.call(props, event);
(_b = props.onPressChange) == null ? void 0 : _b.call(props, false);
};
const pressProps = createMemo5(() => ({
onClick,
onMouseDown,
onMouseUp
}
}
// src/createPress.ts
var PressResponderContext = createContext();
function usePressResponderContext(props, ref) {
const context = useContext(PressResponderContext);
if (context) {
const [, contextProps] = splitProps(context, ["register"]);
props = combineProps(contextProps, props);
context.register();
}
createSyncRef(context, ref);
return props;
}
function createPress(props, ref) {
const [local, domProps] = splitProps(usePressResponderContext(props, ref), [
"onPress",
"onPressChange",
"onPressStart",
"onPressEnd",
"onPressUp",
"isDisabled",
"isPressed",
"preventFocusOnPress",
"shouldCancelOnPointerExit",
"allowTextSelectionOnPress"
]);
const [isTriggerPressed, setIsTriggerPressed] = createSignal5(false);
const [_isPressed, _setIsPressed] = createSignal5(false);
const [ignoreEmulatedMouseEvents, setIgnoreEmulatedMouseEvents] = createSignal5(false);
const [ignoreClickAfterPress, setIgnoreClickAfterPress] = createSignal5(false);
const [didFirePressStart, setDidFirePressStart] = createSignal5(false);
const [activePointerId, setActivePointerId] = createSignal5(null);
const [target, setTarget] = createSignal5(null);
const [isOverTarget, setIsOverTarget] = createSignal5(false);
const [pointerType, setPointerType] = createSignal5(null);
const { addGlobalListener, removeAllGlobalListeners } = createGlobalListeners();
const pressProps = createMemo5(() => {
const triggerPressStart = (originalEvent, pointerType2) => {
var _a, _b;
if (access6(local.isDisabled) || didFirePressStart()) {
return;
}
(_a = local.onPressStart) == null ? void 0 : _a.call(local, {
type: "pressstart",
pointerType: pointerType2,
target: originalEvent.currentTarget,
shiftKey: originalEvent.shiftKey,
metaKey: originalEvent.metaKey,
ctrlKey: originalEvent.ctrlKey,
altKey: originalEvent.altKey
});
(_b = local.onPressChange) == null ? void 0 : _b.call(local, true);
setDidFirePressStart(true);
setIsTriggerPressed(true);
};
const triggerPressEnd = (originalEvent, pointerType2, wasPressed = true) => {
var _a, _b, _c;
if (!didFirePressStart()) {
return;
}
setIgnoreClickAfterPress(true);
setDidFirePressStart(false);
(_a = local.onPressEnd) == null ? void 0 : _a.call(local, {
type: "pressend",
pointerType: pointerType2,
target: originalEvent.currentTarget,
shiftKey: originalEvent.shiftKey,
metaKey: originalEvent.metaKey,
ctrlKey: originalEvent.ctrlKey,
altKey: originalEvent.altKey
});
(_b = local.onPressChange) == null ? void 0 : _b.call(local, false);
setIsTriggerPressed(false);
if (wasPressed && !access6(local.isDisabled)) {
(_c = local.onPress) == null ? void 0 : _c.call(local, {
type: "press",
pointerType: pointerType2,
target: originalEvent.currentTarget,
shiftKey: originalEvent.shiftKey,
metaKey: originalEvent.metaKey,
ctrlKey: originalEvent.ctrlKey,
altKey: originalEvent.altKey
});
}
};
const triggerPressUp = (originalEvent, pointerType2) => {
var _a;
if (access6(local.isDisabled)) {
return;
}
(_a = local.onPressUp) == null ? void 0 : _a.call(local, {
type: "pressup",
pointerType: pointerType2,
target: originalEvent.currentTarget,
shiftKey: originalEvent.shiftKey,
metaKey: originalEvent.metaKey,
ctrlKey: originalEvent.ctrlKey,
altKey: originalEvent.altKey
});
};
const cancel = (e) => {
if (!_isPressed()) {
return;
}
if (isOverTarget()) {
triggerPressEnd(createEvent(target(), e), pointerType(), false);
}
_setIsPressed(false);
setIsOverTarget(false);
setActivePointerId(null);
setPointerType(null);
removeAllGlobalListeners();
if (!access6(local.allowTextSelectionOnPress)) {
restoreTextSelection(target());
}
};
const pressProps2 = {
onKeyDown(e) {
if (isValidKeyboardEvent(e) && e.currentTarget.contains(e.target)) {
if (shouldPreventDefaultKeyboard(e.target)) {
e.preventDefault();
}
e.stopPropagation();
if (!_isPressed() && !e.repeat) {
setTarget(e.currentTarget);
_setIsPressed(true);
triggerPressStart(e, "keyboard");
addGlobalListener(document, "keyup", globalOnKeyUp, false);
}
}
},
onKeyUp(e) {
if (isValidKeyboardEvent(e) && !e.repeat && e.currentTarget.contains(e.target)) {
triggerPressUp(createEvent(target(), e), "keyboard");
}
},
onClick(e) {
if (e && !e.currentTarget.contains(e.target)) {
return;
}
if (e && e.button === 0) {
e.stopPropagation();
if (access6(local.isDisabled)) {
e.preventDefault();
}
if (!ignoreClickAfterPress() && !ignoreEmulatedMouseEvents() && (pointerType() === "virtual" || isVirtualClick(e))) {
if (!access6(local.isDisabled) && !access6(local.preventFocusOnPress)) {
focusWithoutScrolling(e.currentTarget);
}
triggerPressStart(e, "virtual");
triggerPressUp(e, "virtual");
triggerPressEnd(e, "virtual");
}
setIgnoreEmulatedMouseEvents(false);
setIgnoreClickAfterPress(false);
}
}
};
const globalOnKeyUp = (e) => {
var _a, _b, _c;
if (_isPressed() && isValidKeyboardEvent(e)) {
if (shouldPreventDefaultKeyboard(e.target)) {
e.preventDefault();
}
e.stopPropagation();
_setIsPressed(false);
const eventTarget = e.target;
triggerPressEnd(createEvent(target(), e), "keyboard", (_a = target()) == null ? void 0 : _a.contains(eventTarget));
removeAllGlobalListeners();
if (((_b = target()) == null ? void 0 : _b.contains(eventTarget)) && isHTMLAnchorLink(target()) || target().getAttribute("role") === "link") {
(_c = target()) == null ? void 0 : _c.click();
}
}
};
if (typeof PointerEvent !== "undefined") {
pressProps2.onPointerDown = (e) => {
if (e.button !== 0 || !e.currentTarget.contains(e.target)) {
return;
}
if (isVirtualPointerEvent(e)) {
setPointerType("virtual");
return;
}
if (shouldPreventDefault(e.currentTarget)) {
e.preventDefault();
}
const newPointerType = setPointerType(e.pointerType);
e.stopPropagation();
if (_isPressed()) {
return;
}
_setIsPressed(true);
setIsOverTarget(true);
setActivePointerId(e.pointerId);
const newTarget = setTarget(e.currentTarget);
if (!access6(local.isDisabled) && !access6(local.preventFocusOnPress)) {
focusWithoutScrolling(e.currentTarget);
}
if (!access6(local.allowTextSelectionOnPress)) {
disableTextSelection(newTarget);
}
triggerPressStart(e, newPointerType);
addGlobalListener(document, "pointermove", globalOnPointerMove, false);
addGlobalListener(document, "pointerup", globalOnPointerUp, false);
addGlobalListener(document, "pointercancel", globalOnPointerCancel, false);
};
pressProps2.onMouseDown = (e) => {
if (!e.currentTarget.contains(e.target)) {
return;
}
if (e.button === 0) {
if (shouldPreventDefault(e.currentTarget)) {
e.preventDefault();
}
e.stopPropagation();
}
};
pressProps2.onPointerUp = (e) => {
if (!e.currentTarget.contains(e.target) || pointerType() === "virtual") {
return;
}
if (e.button === 0 && isPointOverTarget(e, e.currentTarget)) {
triggerPressUp(e, pointerType() || e.pointerType);
}
};
const globalOnPointerMove = (e) => {
if (e.pointerId !== activePointerId()) {
return;
}
if (isPointOverTarget(e, target())) {
if (!isOverTarget()) {
setIsOverTarget(true);
triggerPressStart(createEvent(target(), e), pointerType());
}
} else if (isOverTarget()) {
setIsOverTarget(false);
triggerPressEnd(createEvent(target(), e), pointerType(), false);
if (access6(local.shouldCancelOnPointerExit)) {
cancel(e);
}
}
};
const globalOnPointerUp = (e) => {
if (e.pointerId === activePointerId() && _isPressed() && e.button === 0) {
if (isPointOverTarget(e, target())) {
triggerPressEnd(createEvent(target(), e), pointerType());
} else if (isOverTarget()) {
triggerPressEnd(createEvent(target(), e), pointerType(), false);
}
_setIsPressed(false);
setIsOverTarget(false);
setActivePointerId(null);
setPointerType(null);
removeAllGlobalListeners();
if (!access6(local.allowTextSelectionOnPress)) {
restoreTextSelection(target());
}
}
};
const globalOnPointerCancel = (e) => {
cancel(e);
};
pressProps2.onDragStart = (e) => {
if (!e.currentTarget.contains(e.target)) {
return;
}
cancel(e);
};
} else {
pressProps2.onMouseDown = (e) => {
if (e.button !== 0 || !e.currentTarget.contains(e.target)) {
return;
}
if (shouldPreventDefault(e.currentTarget)) {
e.preventDefault();
}
e.stopPropagation();
if (ignoreEmulatedMouseEvents()) {
return;
}
_setIsPressed(true);
setIsOverTarget(true);
setTarget(e.currentTarget);
const newPointerType = setPointerType(isVirtualClick(e) ? "virtual" : "mouse");
if (!access6(local.isDisabled) && !access6(local.preventFocusOnPress)) {
focusWithoutScrolling(e.currentTarget);
}
triggerPressStart(e, newPointerType);
addGlobalListener(document, "mouseup", globalOnMouseUp, false);
};
pressProps2.onMouseEnter = (e) => {
if (!e.currentTarget.contains(e.target)) {
return;
}
e.stopPropagation();
if (_isPressed() && !ignoreEmulatedMouseEvents()) {
setIsOverTarget(true);
triggerPressStart(e, pointerType());
}
};
pressProps2.onMouseLeave = (e) => {
if (!e.currentTarget.contains(e.target)) {
return;
}
e.stopPropagation();
if (_isPressed() && !ignoreEmulatedMouseEvents()) {
setIsOverTarget(false);
triggerPressEnd(e, pointerType(), false);
if (access6(local.shouldCancelOnPointerExit)) {
cancel(e);
}
}
};
pressProps2.onMouseUp = (e) => {
if (!e.currentTarget.contains(e.target)) {
return;
}
if (!ignoreEmulatedMouseEvents() && e.button === 0) {
triggerPressUp(e, pointerType());
}
};
const globalOnMouseUp = (e) => {
if (e.button !== 0) {
return;
}
_setIsPressed(false);
removeAllGlobalListeners();
if (ignoreEmulatedMouseEvents()) {
setIgnoreEmulatedMouseEvents(false);
return;
}
if (isPointOverTarget(e, target())) {
triggerPressEnd(createEvent(target(), e), pointerType());
} else if (isOverTarget()) {
triggerPressEnd(createEvent(target(), e), pointerType(), false);
}
setIsOverTarget(false);
};
pressProps2.onTouchStart = (e) => {
if (!e.currentTarget.contains(e.target)) {
return;
}
e.stopPropagation();
const touch = getTouchFromEvent(e);
if (!touch) {
return;
}
setActivePointerId(touch.identifier);
setIgnoreEmulatedMouseEvents(true);
setIsOverTarget(true);
_setIsPressed(true);
const newTarget = setTarget(e.currentTarget);
const newPointerType = setPointerType("touch");
if (!access6(local.isDisabled) && !access6(local.preventFocusOnPress)) {
focusWithoutScrolling(e.currentTarget);
}
if (!access6(local.allowTextSelectionOnPress)) {
disableTextSelection(newTarget);
}
triggerPressStart(e, newPointerType);
addGlobalListener(window, "scroll", globalOnScroll, true);
};
pressProps2.onTouchMove = (e) => {
if (!e.currentTarget.contains(e.target)) {
return;
}
e.stopPropagation();
if (!_isPressed()) {
return;
}
const touch = getTouchById(e, activePointerId());
if (touch && isPointOverTarget(touch, e.currentTarget)) {
if (!isOverTarget()) {
setIsOverTarget(true);
triggerPressStart(e, pointerType());
}
} else if (isOverTarget()) {
setIsOverTarget(false);
triggerPressEnd(e, pointerType(), false);
if (access6(local.shouldCancelOnPointerExit)) {
cancel(e);
}
}
};
pressProps2.onTouchEnd = (e) => {
if (!e.currentTarget.contains(e.target)) {
return;
}
e.stopPropagation();
if (!_isPressed()) {
return;
}
const touch = getTouchById(e, activePointerId());
if (touch && isPointOverTarget(touch, e.currentTarget)) {
triggerPressUp(e, pointerType());
triggerPressEnd(e, pointerType());
} else if (isOverTarget()) {
triggerPressEnd(e, pointerType(), false);
}
_setIsPressed(false);
setActivePointerId(null);
setIsOverTarget(false);
setIgnoreEmulatedMouseEvents(true);
if (!access6(local.allowTextSelectionOnPress)) {
restoreTextSelection(target());
}
removeAllGlobalListeners();
};
pressProps2.onTouchCancel = (e) => {
if (!e.currentTarget.contains(e.target)) {
return;
}
e.stopPropagation();
if (_isPressed()) {
cancel(e);
}
};
const globalOnScroll = (e) => {
if (_isPressed() && e.target.contains(target())) {
cancel({
currentTarget: target(),
shiftKey: false,
ctrlKey: false,
metaKey: false,
altKey: false
});
}
};
pressProps2.onDragStart = (e) => {
if (!e.currentTarget.contains(e.target)) {
return;
}
cancel(e);
};
}
return combineProps(domProps, pressProps2);
});
const isPressed = createMemo5(() => {
var _a;
return (_a = access6(local.isPressed)) != null ? _a : isTriggerPressed();
});
createEffect3(on3(() => access6(local.allowTextSelectionOnPress), (newValue) => {
onCleanup4(() => {
var _a;
if (!newValue) {
restoreTextSelection((_a = target()) != null ? _a : void 0);
}
});
}));
return { pressProps };
return { pressProps, isPressed };
}
function isHTMLAnchorLink(target) {
return target.tagName === "A" && target.hasAttribute("href");
}
function isValidKeyboardEvent(event) {
const { key, code, target } = event;
const element = target;
const { tagName, isContentEditable } = element;
const role = element.getAttribute("role");
return (key === "Enter" || key === " " || key === "Spacebar" || code === "Space") && tagName !== "INPUT" && tagName !== "TEXTAREA" && isContentEditable !== true && (!isHTMLAnchorLink(element) || role === "button" && key !== "Enter") && !(role === "link" && key !== "Enter");
}
function getTouchFromEvent(event) {
const { targetTouches } = event;
if (targetTouches.length > 0) {
return targetTouches[0];
}
return null;
}
function getTouchById(event, pointerId) {
const changedTouches = event.changedTouches;
for (let i = 0; i < changedTouches.length; i++) {
const touch = changedTouches[i];
if (touch.identifier === pointerId) {
return touch;
}
}
return null;
}
function createEvent(target, e) {
return {
currentTarget: target,
shiftKey: e.shiftKey,
ctrlKey: e.ctrlKey,
metaKey: e.metaKey,
altKey: e.altKey
};
}
function getPointClientRect(point) {
const offsetX = point.width && point.width / 2 || point.radiusX || 0;
const offsetY = point.height && point.height / 2 || point.radiusY || 0;
return {
top: point.clientY - offsetY,
right: point.clientX + offsetX,
bottom: point.clientY + offsetY,
left: point.clientX - offsetX
};
}
function areRectanglesOverlapping(a, b) {
if (a.left > b.right || b.left > a.right) {
return false;
}
if (a.top > b.bottom || b.top > a.bottom) {
return false;
}
return true;
}
function isPointOverTarget(point, target) {
const rect = target.getBoundingClientRect();
const pointRect = getPointClientRect(point);
return areRectanglesOverlapping(rect, pointRect);
}
function shouldPreventDefault(target) {
return !target.draggable;
}
function shouldPreventDefaultKeyboard(target) {
return !((target.tagName === "INPUT" || target.tagName === "BUTTON") && target.type === "submit");
}
function isVirtualPointerEvent(event) {
return event.width === 0 && event.height === 0 || event.width === 1 && event.height === 1 && event.pressure === 0 && event.detail === 0;
}
export {
PressResponderContext,
createFocus,

@@ -451,6 +1005,8 @@ createFocusVisible,

createPress,
disableTextSelection,
getInteractionModality,
isKeyboardFocusVisible,
restoreTextSelection,
setInteractionModality,
setupGlobalFocusEvents
};
{
"name": "@solid-aria/interactions",
"version": "0.0.2",
"version": "0.0.3",
"private": false,

@@ -34,4 +34,4 @@ "description": "A collection of low level user interactions primitives.",

"dependencies": {
"@solid-aria/types": "^0.0.2",
"@solid-aria/utils": "^0.0.2"
"@solid-aria/types": "^0.0.3",
"@solid-aria/utils": "^0.0.3"
},

@@ -38,0 +38,0 @@ "peerDependencies": {

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc