UNPKG

@material-ui/lab

Version:
279 lines (254 loc) 7.35 kB
import _extends from "@babel/runtime/helpers/esm/extends"; var _ClockPin, _Typography, _Typography2; import * as React from 'react'; import IconButton from '@material-ui/core/IconButton'; import Typography from '@material-ui/core/Typography'; import { styled } from '@material-ui/core/styles'; import { unstable_useEnhancedEffect as useEnhancedEffect } from '@material-ui/utils'; import ClockPointer from './ClockPointer'; import { useUtils } from '../internal/pickers/hooks/useUtils'; import { WrapperVariantContext } from '../internal/pickers/wrappers/WrapperVariantContext'; import { getHours, getMinutes } from './shared'; import { jsx as _jsx } from "react/jsx-runtime"; import { jsxs as _jsxs } from "react/jsx-runtime"; const ClockRoot = styled('div', { skipSx: true })(({ theme }) => ({ display: 'flex', justifyContent: 'center', alignItems: 'center', margin: theme.spacing(2) })); const ClockClock = styled('div', { skipSx: true })({ backgroundColor: 'rgba(0,0,0,.07)', borderRadius: '50%', height: 220, width: 220, flexShrink: 0, position: 'relative', pointerEvents: 'none' }); const ClockSquareMask = styled('div', { skipSx: true })({ width: '100%', height: '100%', position: 'absolute', pointerEvents: 'auto', outline: 0, // Disable scroll capabilities. touchAction: 'none', userSelect: 'none', '@media (pointer: fine)': { cursor: 'pointer', borderRadius: '50%' }, '&:active': { cursor: 'move' } }); const ClockPin = styled('div', { skipSx: true })(({ theme }) => ({ width: 6, height: 6, borderRadius: '50%', backgroundColor: theme.palette.primary.main, position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)' })); const ClockAmButton = styled(IconButton, { skipSx: true })(({ theme, styleProps }) => _extends({ zIndex: 1, position: 'absolute', bottom: 8, left: 8 }, styleProps.meridiemMode === 'am' && { backgroundColor: theme.palette.primary.main, color: theme.palette.primary.contrastText, '&:hover': { backgroundColor: theme.palette.primary.light } })); const ClockPmButton = styled(IconButton, { skipSx: true })(({ theme, styleProps }) => _extends({ zIndex: 1, position: 'absolute', bottom: 8, right: 8 }, styleProps.meridiemMode === 'pm' && { backgroundColor: theme.palette.primary.main, color: theme.palette.primary.contrastText, '&:hover': { backgroundColor: theme.palette.primary.light } })); /** * @ignore - internal component. */ function Clock(props) { const { ampm, ampmInClock, autoFocus, children, date, getClockLabelText, handleMeridiemChange, isTimeDisabled, meridiemMode, minutesStep = 1, onChange, selectedId, type, value } = props; const styleProps = props; const utils = useUtils(); const wrapperVariant = React.useContext(WrapperVariantContext); const isMoving = React.useRef(false); const isSelectedTimeDisabled = isTimeDisabled(value, type); const isPointerInner = !ampm && type === 'hours' && (value < 1 || value > 12); const handleValueChange = (newValue, isFinish) => { if (isTimeDisabled(newValue, type)) { return; } onChange(newValue, isFinish); }; const setTime = (event, isFinish) => { let { offsetX, offsetY } = event; if (offsetX === undefined) { const rect = event.target.getBoundingClientRect(); offsetX = event.changedTouches[0].clientX - rect.left; offsetY = event.changedTouches[0].clientY - rect.top; } const newSelectedValue = type === 'seconds' || type === 'minutes' ? getMinutes(offsetX, offsetY, minutesStep) : getHours(offsetX, offsetY, Boolean(ampm)); handleValueChange(newSelectedValue, isFinish); }; const handleTouchMove = event => { isMoving.current = true; setTime(event, 'shallow'); }; const handleTouchEnd = event => { if (isMoving.current) { setTime(event, 'finish'); isMoving.current = false; } }; const handleMouseMove = event => { // event.buttons & PRIMARY_MOUSE_BUTTON if (event.buttons > 0) { setTime(event.nativeEvent, 'shallow'); } }; const handleMouseUp = event => { if (isMoving.current) { isMoving.current = false; } setTime(event.nativeEvent, 'finish'); }; const hasSelected = React.useMemo(() => { if (type === 'hours') { return true; } return value % 5 === 0; }, [type, value]); const keyboardControlStep = type === 'minutes' ? minutesStep : 1; const listboxRef = React.useRef(null); // Since this is rendered when a Popper is opened we can't use passive effects. // Focusing in passive effects in Popper causes scroll jump. useEnhancedEffect(() => { if (autoFocus) { // The ref not being resolved would be a bug in Material-UI. listboxRef.current.focus(); } }, [autoFocus]); const handleKeyDown = event => { // TODO: Why this early exit? if (isMoving.current) { return; } switch (event.key) { case 'Home': // annulate both hours and minutes handleValueChange(0, 'partial'); event.preventDefault(); break; case 'End': handleValueChange(type === 'minutes' ? 59 : 23, 'partial'); event.preventDefault(); break; case 'ArrowUp': handleValueChange(value + keyboardControlStep, 'partial'); event.preventDefault(); break; case 'ArrowDown': handleValueChange(value - keyboardControlStep, 'partial'); event.preventDefault(); break; default: // do nothing } }; return /*#__PURE__*/_jsxs(ClockRoot, { children: [/*#__PURE__*/_jsxs(ClockClock, { children: [/*#__PURE__*/_jsx(ClockSquareMask, { onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd, onMouseUp: handleMouseUp, onMouseMove: handleMouseMove }), !isSelectedTimeDisabled && /*#__PURE__*/_jsxs(React.Fragment, { children: [_ClockPin || (_ClockPin = /*#__PURE__*/_jsx(ClockPin, {})), date && /*#__PURE__*/_jsx(ClockPointer, { type: type, value: value, isInner: isPointerInner, hasSelected: hasSelected })] }), /*#__PURE__*/_jsx("div", { "aria-activedescendant": selectedId, "aria-label": getClockLabelText(type, date, utils), ref: listboxRef, role: "listbox", onKeyDown: handleKeyDown, tabIndex: 0, children: children })] }), ampm && (wrapperVariant === 'desktop' || ampmInClock) && /*#__PURE__*/_jsxs(React.Fragment, { children: [/*#__PURE__*/_jsx(ClockAmButton, { onClick: () => handleMeridiemChange('am'), disabled: meridiemMode === null, styleProps: styleProps, children: _Typography || (_Typography = /*#__PURE__*/_jsx(Typography, { variant: "caption", children: "AM" })) }), /*#__PURE__*/_jsx(ClockPmButton, { disabled: meridiemMode === null, onClick: () => handleMeridiemChange('pm'), styleProps: styleProps, children: _Typography2 || (_Typography2 = /*#__PURE__*/_jsx(Typography, { variant: "caption", children: "PM" })) })] })] }); } export default Clock;