import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties"; import _extends from "@babel/runtime/helpers/esm/extends"; var _excluded = ["PaperComponent", "popperPlacement", "ownerState", "children", "paperSlotProps", "paperClasses", "onPaperClick", "onPaperTouchStart"]; import * as React from 'react'; import { useSlotProps } from '@mui/base/utils'; import Grow from '@mui/material/Grow'; import Fade from '@mui/material/Fade'; import MuiPaper from '@mui/material/Paper'; import MuiPopper from '@mui/material/Popper'; import BaseFocusTrap from '@mui/material/Unstable_TrapFocus'; import { unstable_useForkRef as useForkRef, unstable_useEventCallback as useEventCallback, unstable_ownerDocument as ownerDocument, unstable_composeClasses as composeClasses } from '@mui/utils'; import { styled, useThemeProps } from '@mui/material/styles'; import { getPickersPopperUtilityClass } from './pickersPopperClasses'; import { getActiveElement } from '../utils/utils'; import { useDefaultReduceAnimations } from '../hooks/useDefaultReduceAnimations'; import { jsx as _jsx } from "react/jsx-runtime"; var useUtilityClasses = function useUtilityClasses(ownerState) { var classes = ownerState.classes; var slots = { root: ['root'], paper: ['paper'] }; return composeClasses(slots, getPickersPopperUtilityClass, classes); }; var PickersPopperRoot = styled(MuiPopper, { name: 'MuiPickersPopper', slot: 'Root', overridesResolver: function overridesResolver(_, styles) { return styles.root; } })(function (_ref) { var theme = _ref.theme; return { zIndex: theme.zIndex.modal }; }); var PickersPopperPaper = styled(MuiPaper, { name: 'MuiPickersPopper', slot: 'Paper', overridesResolver: function overridesResolver(_, styles) { return styles.paper; } })(function (_ref2) { var ownerState = _ref2.ownerState; return _extends({ outline: 0, transformOrigin: 'top center' }, ownerState.placement.includes('top') && { transformOrigin: 'bottom center' }); }); function clickedRootScrollbar(event, doc) { return doc.documentElement.clientWidth < event.clientX || doc.documentElement.clientHeight < event.clientY; } /** * Based on @mui/material/ClickAwayListener without the customization. * We can probably strip away even more since children won't be portaled. * @param {boolean} active Only listen to clicks when the popper is opened. * @param {(event: MouseEvent | TouchEvent) => void} onClickAway The callback to call when clicking outside the popper. * @returns {Array} The ref and event handler to listen to the outside clicks. */ function useClickAwayListener(active, onClickAway) { var movedRef = React.useRef(false); var syntheticEventRef = React.useRef(false); var nodeRef = React.useRef(null); var activatedRef = React.useRef(false); React.useEffect(function () { if (!active) { return undefined; } // Ensure that this hook is not "activated" synchronously. // https://github.com/facebook/react/issues/20074 function armClickAwayListener() { activatedRef.current = true; } document.addEventListener('mousedown', armClickAwayListener, true); document.addEventListener('touchstart', armClickAwayListener, true); return function () { document.removeEventListener('mousedown', armClickAwayListener, true); document.removeEventListener('touchstart', armClickAwayListener, true); activatedRef.current = false; }; }, [active]); // The handler doesn't take event.defaultPrevented into account: // // event.preventDefault() is meant to stop default behaviors like // clicking a checkbox to check it, hitting a button to submit a form, // and hitting left arrow to move the cursor in a text input etc. // Only special HTML elements have these default behaviors. var handleClickAway = useEventCallback(function (event) { if (!activatedRef.current) { return; } // Given developers can stop the propagation of the synthetic event, // we can only be confident with a positive value. var insideReactTree = syntheticEventRef.current; syntheticEventRef.current = false; var doc = ownerDocument(nodeRef.current); // 1. IE11 support, which trigger the handleClickAway even after the unbind // 2. The child might render null. // 3. Behave like a blur listener. if (!nodeRef.current || // is a TouchEvent? 'clientX' in event && clickedRootScrollbar(event, doc)) { return; } // Do not act if user performed touchmove if (movedRef.current) { movedRef.current = false; return; } var insideDOM; // If not enough, can use https://github.com/DieterHolvoet/event-propagation-path/blob/master/propagationPath.js if (event.composedPath) { insideDOM = event.composedPath().indexOf(nodeRef.current) > -1; } else { insideDOM = !doc.documentElement.contains(event.target) || nodeRef.current.contains(event.target); } if (!insideDOM && !insideReactTree) { onClickAway(event); } }); // Keep track of mouse/touch events that bubbled up through the portal. var handleSynthetic = function handleSynthetic() { syntheticEventRef.current = true; }; React.useEffect(function () { if (active) { var doc = ownerDocument(nodeRef.current); var handleTouchMove = function handleTouchMove() { movedRef.current = true; }; doc.addEventListener('touchstart', handleClickAway); doc.addEventListener('touchmove', handleTouchMove); return function () { doc.removeEventListener('touchstart', handleClickAway); doc.removeEventListener('touchmove', handleTouchMove); }; } return undefined; }, [active, handleClickAway]); React.useEffect(function () { // TODO This behavior is not tested automatically // It's unclear whether this is due to different update semantics in test (batched in act() vs discrete on click). // Or if this is a timing related issues due to different Transition components // Once we get rid of all the manual scheduling (e.g. setTimeout(update, 0)) we can revisit this code+test. if (active) { var doc = ownerDocument(nodeRef.current); doc.addEventListener('click', handleClickAway); return function () { doc.removeEventListener('click', handleClickAway); // cleanup `handleClickAway` syntheticEventRef.current = false; }; } return undefined; }, [active, handleClickAway]); return [nodeRef, handleSynthetic, handleSynthetic]; } var PickersPopperPaperWrapper = /*#__PURE__*/React.forwardRef(function (props, ref) { var PaperComponent = props.PaperComponent, popperPlacement = props.popperPlacement, inOwnerState = props.ownerState, children = props.children, paperSlotProps = props.paperSlotProps, paperClasses = props.paperClasses, onPaperClick = props.onPaperClick, onPaperTouchStart = props.onPaperTouchStart, other = _objectWithoutProperties(props, _excluded); var ownerState = _extends({}, inOwnerState, { placement: popperPlacement }); var paperProps = useSlotProps({ elementType: PaperComponent, externalSlotProps: paperSlotProps, additionalProps: { tabIndex: -1, elevation: 8, ref: ref }, className: paperClasses, ownerState: ownerState }); return /*#__PURE__*/_jsx(PaperComponent, _extends({}, other, paperProps, { onClick: function onClick(event) { var _paperProps$onClick; onPaperClick(event); (_paperProps$onClick = paperProps.onClick) == null || _paperProps$onClick.call(paperProps, event); }, onTouchStart: function onTouchStart(event) { var _paperProps$onTouchSt; onPaperTouchStart(event); (_paperProps$onTouchSt = paperProps.onTouchStart) == null || _paperProps$onTouchSt.call(paperProps, event); }, ownerState: ownerState, children: children })); }); export function PickersPopper(inProps) { var _slots$desktopTransit, _slots$desktopTrapFoc, _slots$desktopPaper, _slots$popper; var props = useThemeProps({ props: inProps, name: 'MuiPickersPopper' }); var anchorEl = props.anchorEl, _children = props.children, _props$containerRef = props.containerRef, containerRef = _props$containerRef === void 0 ? null : _props$containerRef, shouldRestoreFocus = props.shouldRestoreFocus, onBlur = props.onBlur, onDismiss = props.onDismiss, open = props.open, role = props.role, placement = props.placement, slots = props.slots, slotProps = props.slotProps, inReduceAnimations = props.reduceAnimations; React.useEffect(function () { function handleKeyDown(nativeEvent) { // IE11, Edge (prior to using Blink?) use 'Esc' if (open && (nativeEvent.key === 'Escape' || nativeEvent.key === 'Esc')) { onDismiss(); } } document.addEventListener('keydown', handleKeyDown); return function () { document.removeEventListener('keydown', handleKeyDown); }; }, [onDismiss, open]); var lastFocusedElementRef = React.useRef(null); React.useEffect(function () { if (role === 'tooltip' || shouldRestoreFocus && !shouldRestoreFocus()) { return; } if (open) { lastFocusedElementRef.current = getActiveElement(document); } else if (lastFocusedElementRef.current && lastFocusedElementRef.current instanceof HTMLElement) { // make sure the button is flushed with updated label, before returning focus to it // avoids issue, where screen reader could fail to announce selected date after selection setTimeout(function () { if (lastFocusedElementRef.current instanceof HTMLElement) { lastFocusedElementRef.current.focus(); } }); } }, [open, role, shouldRestoreFocus]); var _useClickAwayListener = useClickAwayListener(open, onBlur != null ? onBlur : onDismiss), _useClickAwayListener2 = _slicedToArray(_useClickAwayListener, 3), clickAwayRef = _useClickAwayListener2[0], onPaperClick = _useClickAwayListener2[1], onPaperTouchStart = _useClickAwayListener2[2]; var paperRef = React.useRef(null); var handleRef = useForkRef(paperRef, containerRef); var handlePaperRef = useForkRef(handleRef, clickAwayRef); var ownerState = props; var classes = useUtilityClasses(ownerState); var defaultReduceAnimations = useDefaultReduceAnimations(); var reduceAnimations = inReduceAnimations != null ? inReduceAnimations : defaultReduceAnimations; var handleKeyDown = function handleKeyDown(event) { if (event.key === 'Escape') { // stop the propagation to avoid closing parent modal event.stopPropagation(); onDismiss(); } }; var Transition = ((_slots$desktopTransit = slots == null ? void 0 : slots.desktopTransition) != null ? _slots$desktopTransit : reduceAnimations) ? Fade : Grow; var FocusTrap = (_slots$desktopTrapFoc = slots == null ? void 0 : slots.desktopTrapFocus) != null ? _slots$desktopTrapFoc : BaseFocusTrap; var Paper = (_slots$desktopPaper = slots == null ? void 0 : slots.desktopPaper) != null ? _slots$desktopPaper : PickersPopperPaper; var Popper = (_slots$popper = slots == null ? void 0 : slots.popper) != null ? _slots$popper : PickersPopperRoot; var popperProps = useSlotProps({ elementType: Popper, externalSlotProps: slotProps == null ? void 0 : slotProps.popper, additionalProps: { transition: true, role: role, open: open, anchorEl: anchorEl, placement: placement, onKeyDown: handleKeyDown }, className: classes.root, ownerState: props }); return /*#__PURE__*/_jsx(Popper, _extends({}, popperProps, { children: function children(_ref3) { var TransitionProps = _ref3.TransitionProps, popperPlacement = _ref3.placement; return /*#__PURE__*/_jsx(FocusTrap, _extends({ open: open, disableAutoFocus: true // pickers are managing focus position manually // without this prop the focus is returned to the button before `aria-label` is updated // which would force screen readers to read too old label , disableRestoreFocus: true, disableEnforceFocus: role === 'tooltip', isEnabled: function isEnabled() { return true; } }, slotProps == null ? void 0 : slotProps.desktopTrapFocus, { children: /*#__PURE__*/_jsx(Transition, _extends({}, TransitionProps, slotProps == null ? void 0 : slotProps.desktopTransition, { children: /*#__PURE__*/_jsx(PickersPopperPaperWrapper, { PaperComponent: Paper, ownerState: ownerState, popperPlacement: popperPlacement, ref: handlePaperRef, onPaperClick: onPaperClick, onPaperTouchStart: onPaperTouchStart, paperClasses: classes.paper, paperSlotProps: slotProps == null ? void 0 : slotProps.desktopPaper, children: _children }) })) })); } })); }