@react-aria/interactions
Version:
Spectrum UI components in React
965 lines (939 loc) • 80.6 kB
JavaScript
import {mergeProps as $bx7SL$mergeProps, useSyncRef as $bx7SL$useSyncRef, useGlobalListeners as $bx7SL$useGlobalListeners, isVirtualClick as $bx7SL$isVirtualClick, focusWithoutScrolling as $bx7SL$focusWithoutScrolling, isVirtualPointerEvent as $bx7SL$isVirtualPointerEvent, isIOS as $bx7SL$isIOS, runAfterTransition as $bx7SL$runAfterTransition, useLayoutEffect as $bx7SL$useLayoutEffect, isMac as $bx7SL$isMac, useEvent as $bx7SL$useEvent, useDescription as $bx7SL$useDescription} from "@react-aria/utils";
import $bx7SL$react, {useRef as $bx7SL$useRef, useContext as $bx7SL$useContext, useState as $bx7SL$useState, useMemo as $bx7SL$useMemo, useEffect as $bx7SL$useEffect, useCallback as $bx7SL$useCallback} from "react";
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/ /*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/ // Portions of the code in this file are based on code from react.
// Original licensing for the following can be found in the
// NOTICE file in the root directory of this source tree.
// See https://github.com/facebook/react/tree/cc7c1aece46a6b69b41958d731e0fd27c94bfc6c/packages/react-interactions
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
// Note that state only matters here for iOS. Non-iOS gets user-select: none applied to the target element
// rather than at the document level so we just need to apply/remove user-select: none for each pressed element individually
let $14c0b72509d70225$var$state = "default";
let $14c0b72509d70225$var$savedUserSelect = "";
let $14c0b72509d70225$var$modifiedElementMap = new WeakMap();
function $14c0b72509d70225$export$16a4697467175487(target) {
if ((0, $bx7SL$isIOS)()) {
if ($14c0b72509d70225$var$state === "default") {
$14c0b72509d70225$var$savedUserSelect = document.documentElement.style.webkitUserSelect;
document.documentElement.style.webkitUserSelect = "none";
}
$14c0b72509d70225$var$state = "disabled";
} else if (target instanceof HTMLElement || target instanceof SVGElement) {
// If not iOS, store the target's original user-select and change to user-select: none
// Ignore state since it doesn't apply for non iOS
$14c0b72509d70225$var$modifiedElementMap.set(target, target.style.userSelect);
target.style.userSelect = "none";
}
}
function $14c0b72509d70225$export$b0d6fa1ab32e3295(target) {
if ((0, $bx7SL$isIOS)()) {
// If the state is already default, there's nothing to do.
// If it is restoring, then there's no need to queue a second restore.
if ($14c0b72509d70225$var$state !== "disabled") return;
$14c0b72509d70225$var$state = "restoring";
// There appears to be a delay on iOS where selection still might occur
// after pointer up, so wait a bit before removing user-select.
setTimeout(()=>{
// Wait for any CSS transitions to complete so we don't recompute style
// for the whole page in the middle of the animation and cause jank.
(0, $bx7SL$runAfterTransition)(()=>{
// Avoid race conditions
if ($14c0b72509d70225$var$state === "restoring") {
if (document.documentElement.style.webkitUserSelect === "none") document.documentElement.style.webkitUserSelect = $14c0b72509d70225$var$savedUserSelect || "";
$14c0b72509d70225$var$savedUserSelect = "";
$14c0b72509d70225$var$state = "default";
}
});
}, 300);
} else if (target instanceof HTMLElement || target instanceof SVGElement) // If not iOS, restore the target's original user-select if any
// Ignore state since it doesn't apply for non iOS
{
if (target && $14c0b72509d70225$var$modifiedElementMap.has(target)) {
let targetOldUserSelect = $14c0b72509d70225$var$modifiedElementMap.get(target);
if (target.style.userSelect === "none") target.style.userSelect = targetOldUserSelect;
if (target.getAttribute("style") === "") target.removeAttribute("style");
$14c0b72509d70225$var$modifiedElementMap.delete(target);
}
}
}
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
const $ae1eeba8b9eafd08$export$5165eccb35aaadb5 = (0, $bx7SL$react).createContext(null);
$ae1eeba8b9eafd08$export$5165eccb35aaadb5.displayName = "PressResponderContext";
function $f6c31cce2adf654f$var$usePressResponderContext(props) {
// Consume context from <PressResponder> and merge with props.
let context = (0, $bx7SL$useContext)((0, $ae1eeba8b9eafd08$export$5165eccb35aaadb5));
if (context) {
let { register: register , ...contextProps } = context;
props = (0, $bx7SL$mergeProps)(contextProps, props);
register();
}
(0, $bx7SL$useSyncRef)(context, props.ref);
return props;
}
function $f6c31cce2adf654f$export$45712eceda6fad21(props) {
let { onPress: onPress , onPressChange: onPressChange , onPressStart: onPressStart , onPressEnd: onPressEnd , onPressUp: onPressUp , isDisabled: isDisabled , isPressed: isPressedProp , preventFocusOnPress: preventFocusOnPress , shouldCancelOnPointerExit: shouldCancelOnPointerExit , allowTextSelectionOnPress: allowTextSelectionOnPress , // eslint-disable-next-line @typescript-eslint/no-unused-vars
ref: _ , ...domProps } = $f6c31cce2adf654f$var$usePressResponderContext(props);
let propsRef = (0, $bx7SL$useRef)(null);
propsRef.current = {
onPress: onPress,
onPressChange: onPressChange,
onPressStart: onPressStart,
onPressEnd: onPressEnd,
onPressUp: onPressUp,
isDisabled: isDisabled,
shouldCancelOnPointerExit: shouldCancelOnPointerExit
};
let [isPressed, setPressed] = (0, $bx7SL$useState)(false);
let ref = (0, $bx7SL$useRef)({
isPressed: false,
ignoreEmulatedMouseEvents: false,
ignoreClickAfterPress: false,
didFirePressStart: false,
activePointerId: null,
target: null,
isOverTarget: false,
pointerType: null
});
let { addGlobalListener: addGlobalListener , removeAllGlobalListeners: removeAllGlobalListeners } = (0, $bx7SL$useGlobalListeners)();
let pressProps = (0, $bx7SL$useMemo)(()=>{
let state = ref.current;
let triggerPressStart = (originalEvent, pointerType)=>{
let { onPressStart: onPressStart , onPressChange: onPressChange , isDisabled: isDisabled } = propsRef.current;
if (isDisabled || state.didFirePressStart) return;
if (onPressStart) onPressStart({
type: "pressstart",
pointerType: pointerType,
target: originalEvent.currentTarget,
shiftKey: originalEvent.shiftKey,
metaKey: originalEvent.metaKey,
ctrlKey: originalEvent.ctrlKey,
altKey: originalEvent.altKey
});
if (onPressChange) onPressChange(true);
state.didFirePressStart = true;
setPressed(true);
};
let triggerPressEnd = (originalEvent, pointerType, wasPressed = true)=>{
let { onPressEnd: onPressEnd , onPressChange: onPressChange , onPress: onPress , isDisabled: isDisabled } = propsRef.current;
if (!state.didFirePressStart) return;
state.ignoreClickAfterPress = true;
state.didFirePressStart = false;
if (onPressEnd) onPressEnd({
type: "pressend",
pointerType: pointerType,
target: originalEvent.currentTarget,
shiftKey: originalEvent.shiftKey,
metaKey: originalEvent.metaKey,
ctrlKey: originalEvent.ctrlKey,
altKey: originalEvent.altKey
});
if (onPressChange) onPressChange(false);
setPressed(false);
if (onPress && wasPressed && !isDisabled) onPress({
type: "press",
pointerType: pointerType,
target: originalEvent.currentTarget,
shiftKey: originalEvent.shiftKey,
metaKey: originalEvent.metaKey,
ctrlKey: originalEvent.ctrlKey,
altKey: originalEvent.altKey
});
};
let triggerPressUp = (originalEvent, pointerType)=>{
let { onPressUp: onPressUp , isDisabled: isDisabled } = propsRef.current;
if (isDisabled) return;
if (onPressUp) onPressUp({
type: "pressup",
pointerType: pointerType,
target: originalEvent.currentTarget,
shiftKey: originalEvent.shiftKey,
metaKey: originalEvent.metaKey,
ctrlKey: originalEvent.ctrlKey,
altKey: originalEvent.altKey
});
};
let cancel = (e)=>{
if (state.isPressed) {
if (state.isOverTarget) triggerPressEnd($f6c31cce2adf654f$var$createEvent(state.target, e), state.pointerType, false);
state.isPressed = false;
state.isOverTarget = false;
state.activePointerId = null;
state.pointerType = null;
removeAllGlobalListeners();
if (!allowTextSelectionOnPress) (0, $14c0b72509d70225$export$b0d6fa1ab32e3295)(state.target);
}
};
let pressProps = {
onKeyDown (e) {
if ($f6c31cce2adf654f$var$isValidKeyboardEvent(e.nativeEvent, e.currentTarget) && e.currentTarget.contains(e.target)) {
if ($f6c31cce2adf654f$var$shouldPreventDefaultKeyboard(e.target, e.key)) e.preventDefault();
e.stopPropagation();
// If the event is repeating, it may have started on a different element
// after which focus moved to the current element. Ignore these events and
// only handle the first key down event.
if (!state.isPressed && !e.repeat) {
state.target = e.currentTarget;
state.isPressed = true;
triggerPressStart(e, "keyboard");
// Focus may move before the key up event, so register the event on the document
// instead of the same element where the key down event occurred.
addGlobalListener(document, "keyup", onKeyUp, false);
}
} else if (e.key === "Enter" && $f6c31cce2adf654f$var$isHTMLAnchorLink(e.currentTarget)) // If the target is a link, we won't have handled this above because we want the default
// browser behavior to open the link when pressing Enter. But we still need to prevent
// default so that elements above do not also handle it (e.g. table row).
e.stopPropagation();
},
onKeyUp (e) {
if ($f6c31cce2adf654f$var$isValidKeyboardEvent(e.nativeEvent, e.currentTarget) && !e.repeat && e.currentTarget.contains(e.target)) triggerPressUp($f6c31cce2adf654f$var$createEvent(state.target, e), "keyboard");
},
onClick (e) {
if (e && !e.currentTarget.contains(e.target)) return;
if (e && e.button === 0) {
e.stopPropagation();
if (isDisabled) e.preventDefault();
// If triggered from a screen reader or by using element.click(),
// trigger as if it were a keyboard click.
if (!state.ignoreClickAfterPress && !state.ignoreEmulatedMouseEvents && (state.pointerType === "virtual" || (0, $bx7SL$isVirtualClick)(e.nativeEvent))) {
// Ensure the element receives focus (VoiceOver on iOS does not do this)
if (!isDisabled && !preventFocusOnPress) (0, $bx7SL$focusWithoutScrolling)(e.currentTarget);
triggerPressStart(e, "virtual");
triggerPressUp(e, "virtual");
triggerPressEnd(e, "virtual");
}
state.ignoreEmulatedMouseEvents = false;
state.ignoreClickAfterPress = false;
}
}
};
let onKeyUp = (e)=>{
if (state.isPressed && $f6c31cce2adf654f$var$isValidKeyboardEvent(e, state.target)) {
if ($f6c31cce2adf654f$var$shouldPreventDefaultKeyboard(e.target, e.key)) e.preventDefault();
e.stopPropagation();
state.isPressed = false;
let target = e.target;
triggerPressEnd($f6c31cce2adf654f$var$createEvent(state.target, e), "keyboard", state.target.contains(target));
removeAllGlobalListeners();
// If the target is a link, trigger the click method to open the URL,
// but defer triggering pressEnd until onClick event handler.
if (state.target instanceof HTMLElement && state.target.contains(target) && ($f6c31cce2adf654f$var$isHTMLAnchorLink(state.target) || state.target.getAttribute("role") === "link")) state.target.click();
}
};
if (typeof PointerEvent !== "undefined") {
pressProps.onPointerDown = (e)=>{
// Only handle left clicks, and ignore events that bubbled through portals.
if (e.button !== 0 || !e.currentTarget.contains(e.target)) return;
// iOS safari fires pointer events from VoiceOver with incorrect coordinates/target.
// Ignore and let the onClick handler take care of it instead.
// https://bugs.webkit.org/show_bug.cgi?id=222627
// https://bugs.webkit.org/show_bug.cgi?id=223202
if ((0, $bx7SL$isVirtualPointerEvent)(e.nativeEvent)) {
state.pointerType = "virtual";
return;
}
// Due to browser inconsistencies, especially on mobile browsers, we prevent
// default on pointer down and handle focusing the pressable element ourselves.
if ($f6c31cce2adf654f$var$shouldPreventDefault(e.currentTarget)) e.preventDefault();
state.pointerType = e.pointerType;
e.stopPropagation();
if (!state.isPressed) {
state.isPressed = true;
state.isOverTarget = true;
state.activePointerId = e.pointerId;
state.target = e.currentTarget;
if (!isDisabled && !preventFocusOnPress) (0, $bx7SL$focusWithoutScrolling)(e.currentTarget);
if (!allowTextSelectionOnPress) (0, $14c0b72509d70225$export$16a4697467175487)(state.target);
triggerPressStart(e, state.pointerType);
addGlobalListener(document, "pointermove", onPointerMove, false);
addGlobalListener(document, "pointerup", onPointerUp, false);
addGlobalListener(document, "pointercancel", onPointerCancel, false);
}
};
pressProps.onMouseDown = (e)=>{
if (!e.currentTarget.contains(e.target)) return;
if (e.button === 0) {
// Chrome and Firefox on touch Windows devices require mouse down events
// to be canceled in addition to pointer events, or an extra asynchronous
// focus event will be fired.
if ($f6c31cce2adf654f$var$shouldPreventDefault(e.currentTarget)) e.preventDefault();
e.stopPropagation();
}
};
pressProps.onPointerUp = (e)=>{
// iOS fires pointerup with zero width and height, so check the pointerType recorded during pointerdown.
if (!e.currentTarget.contains(e.target) || state.pointerType === "virtual") return;
// Only handle left clicks
// Safari on iOS sometimes fires pointerup events, even
// when the touch isn't over the target, so double check.
if (e.button === 0 && $f6c31cce2adf654f$var$isOverTarget(e, e.currentTarget)) triggerPressUp(e, state.pointerType || e.pointerType);
};
// Safari on iOS < 13.2 does not implement pointerenter/pointerleave events correctly.
// Use pointer move events instead to implement our own hit testing.
// See https://bugs.webkit.org/show_bug.cgi?id=199803
let onPointerMove = (e)=>{
if (e.pointerId !== state.activePointerId) return;
if ($f6c31cce2adf654f$var$isOverTarget(e, state.target)) {
if (!state.isOverTarget) {
state.isOverTarget = true;
triggerPressStart($f6c31cce2adf654f$var$createEvent(state.target, e), state.pointerType);
}
} else if (state.isOverTarget) {
state.isOverTarget = false;
triggerPressEnd($f6c31cce2adf654f$var$createEvent(state.target, e), state.pointerType, false);
if (propsRef.current.shouldCancelOnPointerExit) cancel(e);
}
};
let onPointerUp = (e)=>{
if (e.pointerId === state.activePointerId && state.isPressed && e.button === 0) {
if ($f6c31cce2adf654f$var$isOverTarget(e, state.target)) triggerPressEnd($f6c31cce2adf654f$var$createEvent(state.target, e), state.pointerType);
else if (state.isOverTarget) triggerPressEnd($f6c31cce2adf654f$var$createEvent(state.target, e), state.pointerType, false);
state.isPressed = false;
state.isOverTarget = false;
state.activePointerId = null;
state.pointerType = null;
removeAllGlobalListeners();
if (!allowTextSelectionOnPress) (0, $14c0b72509d70225$export$b0d6fa1ab32e3295)(state.target);
}
};
let onPointerCancel = (e)=>{
cancel(e);
};
pressProps.onDragStart = (e)=>{
if (!e.currentTarget.contains(e.target)) return;
// Safari does not call onPointerCancel when a drag starts, whereas Chrome and Firefox do.
cancel(e);
};
} else {
pressProps.onMouseDown = (e)=>{
// Only handle left clicks
if (e.button !== 0 || !e.currentTarget.contains(e.target)) return;
// Due to browser inconsistencies, especially on mobile browsers, we prevent
// default on mouse down and handle focusing the pressable element ourselves.
if ($f6c31cce2adf654f$var$shouldPreventDefault(e.currentTarget)) e.preventDefault();
e.stopPropagation();
if (state.ignoreEmulatedMouseEvents) return;
state.isPressed = true;
state.isOverTarget = true;
state.target = e.currentTarget;
state.pointerType = (0, $bx7SL$isVirtualClick)(e.nativeEvent) ? "virtual" : "mouse";
if (!isDisabled && !preventFocusOnPress) (0, $bx7SL$focusWithoutScrolling)(e.currentTarget);
triggerPressStart(e, state.pointerType);
addGlobalListener(document, "mouseup", onMouseUp, false);
};
pressProps.onMouseEnter = (e)=>{
if (!e.currentTarget.contains(e.target)) return;
e.stopPropagation();
if (state.isPressed && !state.ignoreEmulatedMouseEvents) {
state.isOverTarget = true;
triggerPressStart(e, state.pointerType);
}
};
pressProps.onMouseLeave = (e)=>{
if (!e.currentTarget.contains(e.target)) return;
e.stopPropagation();
if (state.isPressed && !state.ignoreEmulatedMouseEvents) {
state.isOverTarget = false;
triggerPressEnd(e, state.pointerType, false);
if (propsRef.current.shouldCancelOnPointerExit) cancel(e);
}
};
pressProps.onMouseUp = (e)=>{
if (!e.currentTarget.contains(e.target)) return;
if (!state.ignoreEmulatedMouseEvents && e.button === 0) triggerPressUp(e, state.pointerType);
};
let onMouseUp = (e)=>{
// Only handle left clicks
if (e.button !== 0) return;
state.isPressed = false;
removeAllGlobalListeners();
if (state.ignoreEmulatedMouseEvents) {
state.ignoreEmulatedMouseEvents = false;
return;
}
if ($f6c31cce2adf654f$var$isOverTarget(e, state.target)) triggerPressEnd($f6c31cce2adf654f$var$createEvent(state.target, e), state.pointerType);
else if (state.isOverTarget) triggerPressEnd($f6c31cce2adf654f$var$createEvent(state.target, e), state.pointerType, false);
state.isOverTarget = false;
};
pressProps.onTouchStart = (e)=>{
if (!e.currentTarget.contains(e.target)) return;
e.stopPropagation();
let touch = $f6c31cce2adf654f$var$getTouchFromEvent(e.nativeEvent);
if (!touch) return;
state.activePointerId = touch.identifier;
state.ignoreEmulatedMouseEvents = true;
state.isOverTarget = true;
state.isPressed = true;
state.target = e.currentTarget;
state.pointerType = "touch";
// Due to browser inconsistencies, especially on mobile browsers, we prevent default
// on the emulated mouse event and handle focusing the pressable element ourselves.
if (!isDisabled && !preventFocusOnPress) (0, $bx7SL$focusWithoutScrolling)(e.currentTarget);
if (!allowTextSelectionOnPress) (0, $14c0b72509d70225$export$16a4697467175487)(state.target);
triggerPressStart(e, state.pointerType);
addGlobalListener(window, "scroll", onScroll, true);
};
pressProps.onTouchMove = (e)=>{
if (!e.currentTarget.contains(e.target)) return;
e.stopPropagation();
if (!state.isPressed) return;
let touch = $f6c31cce2adf654f$var$getTouchById(e.nativeEvent, state.activePointerId);
if (touch && $f6c31cce2adf654f$var$isOverTarget(touch, e.currentTarget)) {
if (!state.isOverTarget) {
state.isOverTarget = true;
triggerPressStart(e, state.pointerType);
}
} else if (state.isOverTarget) {
state.isOverTarget = false;
triggerPressEnd(e, state.pointerType, false);
if (propsRef.current.shouldCancelOnPointerExit) cancel(e);
}
};
pressProps.onTouchEnd = (e)=>{
if (!e.currentTarget.contains(e.target)) return;
e.stopPropagation();
if (!state.isPressed) return;
let touch = $f6c31cce2adf654f$var$getTouchById(e.nativeEvent, state.activePointerId);
if (touch && $f6c31cce2adf654f$var$isOverTarget(touch, e.currentTarget)) {
triggerPressUp(e, state.pointerType);
triggerPressEnd(e, state.pointerType);
} else if (state.isOverTarget) triggerPressEnd(e, state.pointerType, false);
state.isPressed = false;
state.activePointerId = null;
state.isOverTarget = false;
state.ignoreEmulatedMouseEvents = true;
if (!allowTextSelectionOnPress) (0, $14c0b72509d70225$export$b0d6fa1ab32e3295)(state.target);
removeAllGlobalListeners();
};
pressProps.onTouchCancel = (e)=>{
if (!e.currentTarget.contains(e.target)) return;
e.stopPropagation();
if (state.isPressed) cancel(e);
};
let onScroll = (e)=>{
if (state.isPressed && e.target.contains(state.target)) cancel({
currentTarget: state.target,
shiftKey: false,
ctrlKey: false,
metaKey: false,
altKey: false
});
};
pressProps.onDragStart = (e)=>{
if (!e.currentTarget.contains(e.target)) return;
cancel(e);
};
}
return pressProps;
}, [
addGlobalListener,
isDisabled,
preventFocusOnPress,
removeAllGlobalListeners,
allowTextSelectionOnPress
]);
// Remove user-select: none in case component unmounts immediately after pressStart
// eslint-disable-next-line arrow-body-style
(0, $bx7SL$useEffect)(()=>{
return ()=>{
if (!allowTextSelectionOnPress) // eslint-disable-next-line react-hooks/exhaustive-deps
(0, $14c0b72509d70225$export$b0d6fa1ab32e3295)(ref.current.target);
};
}, [
allowTextSelectionOnPress
]);
return {
isPressed: isPressedProp || isPressed,
pressProps: (0, $bx7SL$mergeProps)(domProps, pressProps)
};
}
function $f6c31cce2adf654f$var$isHTMLAnchorLink(target) {
return target.tagName === "A" && target.hasAttribute("href");
}
function $f6c31cce2adf654f$var$isValidKeyboardEvent(event, currentTarget) {
const { key: key , code: code } = event;
const element = currentTarget;
const role = element.getAttribute("role");
// Accessibility for keyboards. Space and Enter only.
// "Spacebar" is for IE 11
return (key === "Enter" || key === " " || key === "Spacebar" || code === "Space") && !(element instanceof HTMLInputElement && !$f6c31cce2adf654f$var$isValidInputKey(element, key) || element instanceof HTMLTextAreaElement || element.isContentEditable) && // A link with a valid href should be handled natively,
// unless it also has role='button' and was triggered using Space.
(!$f6c31cce2adf654f$var$isHTMLAnchorLink(element) || role === "button" && key !== "Enter") && // An element with role='link' should only trigger with Enter key
!(role === "link" && key !== "Enter");
}
function $f6c31cce2adf654f$var$getTouchFromEvent(event) {
const { targetTouches: targetTouches } = event;
if (targetTouches.length > 0) return targetTouches[0];
return null;
}
function $f6c31cce2adf654f$var$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 $f6c31cce2adf654f$var$createEvent(target, e) {
return {
currentTarget: target,
shiftKey: e.shiftKey,
ctrlKey: e.ctrlKey,
metaKey: e.metaKey,
altKey: e.altKey
};
}
function $f6c31cce2adf654f$var$getPointClientRect(point) {
let offsetX = point.width / 2 || point.radiusX || 0;
let offsetY = point.height / 2 || point.radiusY || 0;
return {
top: point.clientY - offsetY,
right: point.clientX + offsetX,
bottom: point.clientY + offsetY,
left: point.clientX - offsetX
};
}
function $f6c31cce2adf654f$var$areRectanglesOverlapping(a, b) {
// check if they cannot overlap on x axis
if (a.left > b.right || b.left > a.right) return false;
// check if they cannot overlap on y axis
if (a.top > b.bottom || b.top > a.bottom) return false;
return true;
}
function $f6c31cce2adf654f$var$isOverTarget(point, target) {
let rect = target.getBoundingClientRect();
let pointRect = $f6c31cce2adf654f$var$getPointClientRect(point);
return $f6c31cce2adf654f$var$areRectanglesOverlapping(rect, pointRect);
}
function $f6c31cce2adf654f$var$shouldPreventDefault(target) {
// We cannot prevent default if the target is a draggable element.
return !(target instanceof HTMLElement) || !target.draggable;
}
function $f6c31cce2adf654f$var$shouldPreventDefaultKeyboard(target, key) {
if (target instanceof HTMLInputElement) return !$f6c31cce2adf654f$var$isValidInputKey(target, key);
if (target instanceof HTMLButtonElement) return target.type !== "submit";
return true;
}
const $f6c31cce2adf654f$var$nonTextInputTypes = new Set([
"checkbox",
"radio",
"range",
"color",
"file",
"image",
"button",
"submit",
"reset"
]);
function $f6c31cce2adf654f$var$isValidInputKey(target, key) {
// Only space should toggle checkboxes and radios, not enter.
return target.type === "checkbox" || target.type === "radio" ? key === " " : $f6c31cce2adf654f$var$nonTextInputTypes.has(target.type);
}
const $3b117e43dc0ca95d$export$27c701ed9e449e99 = /*#__PURE__*/ (0, $bx7SL$react).forwardRef(({ children: children , ...props }, ref)=>{
let newRef = (0, $bx7SL$useRef)();
ref = ref !== null && ref !== void 0 ? ref : newRef;
let { pressProps: pressProps } = (0, $f6c31cce2adf654f$export$45712eceda6fad21)({
...props,
ref: ref
});
let child = (0, $bx7SL$react).Children.only(children);
return /*#__PURE__*/ (0, $bx7SL$react).cloneElement(child, // @ts-ignore
{
ref: ref,
...(0, $bx7SL$mergeProps)(child.props, pressProps)
});
});
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
const $f1ab8c75478c6f73$export$3351871ee4b288b8 = /*#__PURE__*/ (0, $bx7SL$react).forwardRef(({ children: children , ...props }, ref)=>{
let isRegistered = (0, $bx7SL$useRef)(false);
let prevContext = (0, $bx7SL$useContext)((0, $ae1eeba8b9eafd08$export$5165eccb35aaadb5));
let context = (0, $bx7SL$mergeProps)(prevContext || {}, {
...props,
ref: ref || (prevContext === null || prevContext === void 0 ? void 0 : prevContext.ref),
register () {
isRegistered.current = true;
if (prevContext) prevContext.register();
}
});
(0, $bx7SL$useSyncRef)(prevContext, ref);
(0, $bx7SL$useEffect)(()=>{
if (!isRegistered.current) console.warn("A PressResponder was rendered without a pressable child. Either call the usePress hook, or wrap your DOM node with <Pressable> component.");
}, []);
return /*#__PURE__*/ (0, $bx7SL$react).createElement((0, $ae1eeba8b9eafd08$export$5165eccb35aaadb5).Provider, {
value: context
}, children);
});
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/ // Portions of the code in this file are based on code from react.
// Original licensing for the following can be found in the
// NOTICE file in the root directory of this source tree.
// See https://github.com/facebook/react/tree/cc7c1aece46a6b69b41958d731e0fd27c94bfc6c/packages/react-interactions
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
class $8a9cb279dc87e130$export$905e7fc544a71f36 {
isDefaultPrevented() {
return this.nativeEvent.defaultPrevented;
}
preventDefault() {
this.defaultPrevented = true;
this.nativeEvent.preventDefault();
}
stopPropagation() {
this.nativeEvent.stopPropagation();
this.isPropagationStopped = ()=>true;
}
isPropagationStopped() {
return false;
}
persist() {}
constructor(type, nativeEvent){
this.nativeEvent = nativeEvent;
this.target = nativeEvent.target;
this.currentTarget = nativeEvent.currentTarget;
this.relatedTarget = nativeEvent.relatedTarget;
this.bubbles = nativeEvent.bubbles;
this.cancelable = nativeEvent.cancelable;
this.defaultPrevented = nativeEvent.defaultPrevented;
this.eventPhase = nativeEvent.eventPhase;
this.isTrusted = nativeEvent.isTrusted;
this.timeStamp = nativeEvent.timeStamp;
this.type = type;
}
}
function $8a9cb279dc87e130$export$715c682d09d639cc(onBlur) {
let stateRef = (0, $bx7SL$useRef)({
isFocused: false,
onBlur: onBlur,
observer: null
});
stateRef.current.onBlur = onBlur;
// Clean up MutationObserver on unmount. See below.
// eslint-disable-next-line arrow-body-style
(0, $bx7SL$useLayoutEffect)(()=>{
const state = stateRef.current;
return ()=>{
if (state.observer) {
state.observer.disconnect();
state.observer = null;
}
};
}, []);
// This function is called during a React onFocus event.
return (0, $bx7SL$useCallback)((e)=>{
// React does not fire onBlur when an element is disabled. https://github.com/facebook/react/issues/9142
// Most browsers fire a native focusout event in this case, except for Firefox. In that case, we use a
// MutationObserver to watch for the disabled attribute, and dispatch these events ourselves.
// For browsers that do, focusout fires before the MutationObserver, so onBlur should not fire twice.
if (e.target instanceof HTMLButtonElement || e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement || e.target instanceof HTMLSelectElement) {
stateRef.current.isFocused = true;
let target = e.target;
let onBlurHandler = (e)=>{
var // For backward compatibility, dispatch a (fake) React synthetic event.
_stateRef_current, _stateRef_current_onBlur;
stateRef.current.isFocused = false;
if (target.disabled) (_stateRef_current_onBlur = (_stateRef_current = stateRef.current).onBlur) === null || _stateRef_current_onBlur === void 0 ? void 0 : _stateRef_current_onBlur.call(_stateRef_current, new $8a9cb279dc87e130$export$905e7fc544a71f36("blur", e));
// We no longer need the MutationObserver once the target is blurred.
if (stateRef.current.observer) {
stateRef.current.observer.disconnect();
stateRef.current.observer = null;
}
};
target.addEventListener("focusout", onBlurHandler, {
once: true
});
stateRef.current.observer = new MutationObserver(()=>{
if (stateRef.current.isFocused && target.disabled) {
stateRef.current.observer.disconnect();
target.dispatchEvent(new FocusEvent("blur"));
target.dispatchEvent(new FocusEvent("focusout", {
bubbles: true
}));
}
});
stateRef.current.observer.observe(target, {
attributes: true,
attributeFilter: [
"disabled"
]
});
}
}, []);
}
function $a1ea59d68270f0dd$export$f8168d8dd8fd66e6(props) {
let { isDisabled: isDisabled , onFocus: onFocusProp , onBlur: onBlurProp , onFocusChange: onFocusChange } = props;
const onBlur = (0, $bx7SL$useCallback)((e)=>{
if (e.target === e.currentTarget) {
if (onBlurProp) onBlurProp(e);
if (onFocusChange) onFocusChange(false);
return true;
}
}, [
onBlurProp,
onFocusChange
]);
const onSyntheticFocus = (0, $8a9cb279dc87e130$export$715c682d09d639cc)(onBlur);
const onFocus = (0, $bx7SL$useCallback)((e)=>{
if (e.target === e.currentTarget) {
if (onFocusProp) onFocusProp(e);
if (onFocusChange) onFocusChange(true);
onSyntheticFocus(e);
}
}, [
onFocusChange,
onFocusProp,
onSyntheticFocus
]);
return {
focusProps: {
onFocus: !isDisabled && (onFocusProp || onFocusChange || onBlurProp) ? onFocus : undefined,
onBlur: !isDisabled && (onBlurProp || onFocusChange) ? onBlur : undefined
}
};
}
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/ // Portions of the code in this file are based on code from react.
// Original licensing for the following can be found in the
// NOTICE file in the root directory of this source tree.
// See https://github.com/facebook/react/tree/cc7c1aece46a6b69b41958d731e0fd27c94bfc6c/packages/react-interactions
let $507fabe10e71c6fb$var$currentModality = null;
let $507fabe10e71c6fb$var$changeHandlers = new Set();
let $507fabe10e71c6fb$var$hasSetupGlobalListeners = false;
let $507fabe10e71c6fb$var$hasEventBeforeFocus = false;
let $507fabe10e71c6fb$var$hasBlurredWindowRecently = false;
// Only Tab or Esc keys will make focus visible on text input elements
const $507fabe10e71c6fb$var$FOCUS_VISIBLE_INPUT_KEYS = {
Tab: true,
Escape: true
};
function $507fabe10e71c6fb$var$triggerChangeHandlers(modality, e) {
for (let handler of $507fabe10e71c6fb$var$changeHandlers)handler(modality, e);
}
/**
* Helper function to determine if a KeyboardEvent is unmodified and could make keyboard focus styles visible.
*/ function $507fabe10e71c6fb$var$isValidKey(e) {
// Control and Shift keys trigger when navigating back to the tab with keyboard.
return !(e.metaKey || !(0, $bx7SL$isMac)() && e.altKey || e.ctrlKey || e.key === "Control" || e.key === "Shift" || e.key === "Meta");
}
function $507fabe10e71c6fb$var$handleKeyboardEvent(e) {
$507fabe10e71c6fb$var$hasEventBeforeFocus = true;
if ($507fabe10e71c6fb$var$isValidKey(e)) {
$507fabe10e71c6fb$var$currentModality = "keyboard";
$507fabe10e71c6fb$var$triggerChangeHandlers("keyboard", e);
}
}
function $507fabe10e71c6fb$var$handlePointerEvent(e) {
$507fabe10e71c6fb$var$currentModality = "pointer";
if (e.type === "mousedown" || e.type === "pointerdown") {
$507fabe10e71c6fb$var$hasEventBeforeFocus = true;
$507fabe10e71c6fb$var$triggerChangeHandlers("pointer", e);
}
}
function $507fabe10e71c6fb$var$handleClickEvent(e) {
if ((0, $bx7SL$isVirtualClick)(e)) {
$507fabe10e71c6fb$var$hasEventBeforeFocus = true;
$507fabe10e71c6fb$var$currentModality = "virtual";
}
}
function $507fabe10e71c6fb$var$handleFocusEvent(e) {
// Firefox fires two extra focus events when the user first clicks into an iframe:
// first on the window, then on the document. We ignore these events so they don't
// cause keyboard focus rings to appear.
if (e.target === window || e.target === document) return;
// If a focus event occurs without a preceding keyboard or pointer event, switch to virtual modality.
// This occurs, for example, when navigating a form with the next/previous buttons on iOS.
if (!$507fabe10e71c6fb$var$hasEventBeforeFocus && !$507fabe10e71c6fb$var$hasBlurredWindowRecently) {
$507fabe10e71c6fb$var$currentModality = "virtual";
$507fabe10e71c6fb$var$triggerChangeHandlers("virtual", e);
}
$507fabe10e71c6fb$var$hasEventBeforeFocus = false;
$507fabe10e71c6fb$var$hasBlurredWindowRecently = false;
}
function $507fabe10e71c6fb$var$handleWindowBlur() {
// When the window is blurred, reset state. This is necessary when tabbing out of the window,
// for example, since a subsequent focus event won't be fired.
$507fabe10e71c6fb$var$hasEventBeforeFocus = false;
$507fabe10e71c6fb$var$hasBlurredWindowRecently = true;
}
/**
* Setup global event listeners to control when keyboard focus style should be visible.
*/ function $507fabe10e71c6fb$var$setupGlobalFocusEvents() {
if (typeof window === "undefined" || $507fabe10e71c6fb$var$hasSetupGlobalListeners) return;
// Programmatic focus() calls shouldn't affect the current input modality.
// However, we need to detect other cases when a focus event occurs without
// a preceding user event (e.g. screen reader focus). Overriding the focus
// method on HTMLElement.prototype is a bit hacky, but works.
let focus = HTMLElement.prototype.focus;
HTMLElement.prototype.focus = function() {
$507fabe10e71c6fb$var$hasEventBeforeFocus = true;
focus.apply(this, arguments);
};
document.addEventListener("keydown", $507fabe10e71c6fb$var$handleKeyboardEvent, true);
document.addEventListener("keyup", $507fabe10e71c6fb$var$handleKeyboardEvent, true);
document.addEventListener("click", $507fabe10e71c6fb$var$handleClickEvent, true);
// Register focus events on the window so they are sure to happen
// before React's event listeners (registered on the document).
window.addEventListener("focus", $507fabe10e71c6fb$var$handleFocusEvent, true);
window.addEventListener("blur", $507fabe10e71c6fb$var$handleWindowBlur, false);
if (typeof PointerEvent !== "undefined") {
document.addEventListener("pointerdown", $507fabe10e71c6fb$var$handlePointerEvent, true);
document.addEventListener("pointermove", $507fabe10e71c6fb$var$handlePointerEvent, true);
document.addEventListener("pointerup", $507fabe10e71c6fb$var$handlePointerEvent, true);
} else {
document.addEventListener("mousedown", $507fabe10e71c6fb$var$handlePointerEvent, true);
document.addEventListener("mousemove", $507fabe10e71c6fb$var$handlePointerEvent, true);
document.addEventListener("mouseup", $507fabe10e71c6fb$var$handlePointerEvent, true);
}
$507fabe10e71c6fb$var$hasSetupGlobalListeners = true;
}
if (typeof document !== "undefined") {
if (document.readyState !== "loading") $507fabe10e71c6fb$var$setupGlobalFocusEvents();
else document.addEventListener("DOMContentLoaded", $507fabe10e71c6fb$var$setupGlobalFocusEvents);
}
function $507fabe10e71c6fb$export$b9b3dfddab17db27() {
return $507fabe10e71c6fb$var$currentModality !== "pointer";
}
function $507fabe10e71c6fb$export$630ff653c5ada6a9() {
return $507fabe10e71c6fb$var$currentModality;
}
function $507fabe10e71c6fb$export$8397ddfc504fdb9a(modality) {
$507fabe10e71c6fb$var$currentModality = modality;
$507fabe10e71c6fb$var$triggerChangeHandlers(modality, null);
}
function $507fabe10e71c6fb$export$98e20ec92f614cfe() {
$507fabe10e71c6fb$var$setupGlobalFocusEvents();
let [modality, setModality] = (0, $bx7SL$useState)($507fabe10e71c6fb$var$currentModality);
(0, $bx7SL$useEffect)(()=>{
let handler = ()=>{
setModality($507fabe10e71c6fb$var$currentModality);
};
$507fabe10e71c6fb$var$changeHandlers.add(handler);
return ()=>{
$507fabe10e71c6fb$var$changeHandlers.delete(handler);
};
}, []);
return modality;
}
/**
* If this is attached to text input component, return if the event is a focus event (Tab/Escape keys pressed) so that
* focus visible style can be properly set.
*/ function $507fabe10e71c6fb$var$isKeyboardFocusEvent(isTextInput, modality, e) {
return !(isTextInput && modality === "keyboard" && e instanceof KeyboardEvent && !$507fabe10e71c6fb$var$FOCUS_VISIBLE_INPUT_KEYS[e.key]);
}
function $507fabe10e71c6fb$export$ffd9e5021c1fb2d6(props = {}) {
let { isTextInput: isTextInput , autoFocus: autoFocus } = props;
let [isFocusVisibleState, setFocusVisible] = (0, $bx7SL$useState)(autoFocus || $507fabe10e71c6fb$export$b9b3dfddab17db27());
$507fabe10e71c6fb$export$ec71b4b83ac08ec3((isFocusVisible)=>{
setFocusVisible(isFocusVisible);
}, [
isTextInput
], {
isTextInput: isTextInput
});
return {
isFocusVisible: isFocusVisibleState
};
}
function $507fabe10e71c6fb$export$ec71b4b83ac08ec3(fn, deps, opts) {
$507fabe10e71c6fb$var$setupGlobalFocusEvents();
(0, $bx7SL$useEffect)(()=>{
let handler = (modality, e)=>{
if (!$507fabe10e71c6fb$var$isKeyboardFocusEvent(opts === null || opts === void 0 ? void 0 : opts.isTextInput, modality, e)) return;
fn($507fabe10e71c6fb$export$b9b3dfddab17db27());
};
$507fabe10e71c6fb$var$changeHandlers.add(handler);
return ()=>{
$507fabe10e71c6fb$var$changeHandlers.delete(handler);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, deps);
}
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You