UNPKG

pouncejs

Version:

A collection of UI components from Panther labs

223 lines (209 loc) 7.66 kB
import _extends from "@babel/runtime/helpers/extends"; import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose"; import React, { useState, useCallback } from 'react'; import dayjs from 'dayjs'; import Box from '../Box'; import Flex from '../Flex'; import Button from '../Button'; import Month from './Month'; import { IconButton } from '../../index'; import DateWrapper from './DateWrapper'; import Heading from '../Heading'; import TextInput from '../TextInput'; import TimePicker from './TimePicker'; import ClearButton from './ClearButton'; import { noop, dateToDayjs, now } from '../../utils/helpers'; import useDisclosure from '../../utils/useDisclosure'; import useEscapeKey from '../../utils/useEscapeKey'; import usePrevious from '../../utils/usePrevious'; import useOutsideClick from '../../utils/useOutsideClick'; /** * A component to help selecting dates in forms * * Apart from the props specified down below, you can pass any valid prop from the * <a href="/#/TextInput">TextInput</a> component (i.e. placeholder, etc.) * * */ var DateInput = function DateInput(_ref) { var value = _ref.value, _ref$format = _ref.format, format = _ref$format === void 0 ? 'MM/DD/YYYY' : _ref$format, alignment = _ref.alignment, withTime = _ref.withTime, _ref$mode = _ref.mode, mode = _ref$mode === void 0 ? '24h' : _ref$mode, _ref$disableReset = _ref.disableReset, disableReset = _ref$disableReset === void 0 ? false : _ref$disableReset, _ref$variant = _ref.variant, variant = _ref$variant === void 0 ? 'outline' : _ref$variant, _ref$onChange = _ref.onChange, onChange = _ref$onChange === void 0 ? noop : _ref$onChange, _ref$timezone = _ref.timezone, timezone = _ref$timezone === void 0 ? 'local' : _ref$timezone, rest = _objectWithoutPropertiesLoose(_ref, ["value", "format", "alignment", "withTime", "mode", "disableReset", "variant", "onChange", "timezone"]); var ref = React.useRef(null); var targetRef = React.useRef(null); var _useState = useState(dateToDayjs(value, timezone)), currentDate = _useState[0], setCurrentDate = _useState[1]; var _useState2 = useState(currentDate || now(timezone)), currentMonth = _useState2[0], setCurrentMonth = _useState2[1]; var resetLabel = React.useMemo(function () { return withTime ? 'Clear Date & Time' : 'Clear Date'; }, [withTime]); var _useDisclosure = useDisclosure(), isOpen = _useDisclosure.isOpen, open = _useDisclosure.open, close = _useDisclosure.close; var previousDate = usePrevious(dateToDayjs(value, timezone)); // Handles value & timezone updates outside of the component (i.e. a form has re-initialized or // has updated its values as a result of an API call) React.useEffect(function () { setCurrentDate(dateToDayjs(value, timezone)); }, [value, timezone]); var isDisabled = React.useMemo(function () { if (dayjs.isDayjs(currentDate) && dayjs.isDayjs(previousDate)) { return currentDate.isSame(previousDate, withTime ? 'minute' : 'day'); } return currentDate === previousDate; }, [currentDate, previousDate]); var onNextMonth = useCallback(function (e) { e.preventDefault(); var next = currentMonth.add(1, 'month'); setCurrentMonth(next); }, [currentMonth, setCurrentMonth]); var onPreviousMonth = useCallback(function (e) { e.preventDefault(); var next = currentMonth.subtract(1, 'month'); setCurrentMonth(next); }, [currentMonth, setCurrentMonth]); var onCancel = useCallback(function () { setCurrentDate(dateToDayjs(value, timezone)); close(); }, [close, value, timezone, setCurrentDate]); var onClear = useCallback(function () { return setCurrentDate(dateToDayjs(undefined)); }, [setCurrentDate]); var onApply = useCallback(function (e) { e.preventDefault(); onChange(currentDate == null ? void 0 : currentDate.startOf(withTime ? 'minute' : 'day').toDate()); close(); }, [close, onChange, currentDate, disableReset]); var onDaySelect = useCallback(function (dateChanged) { var updated = dateChanged; if (currentDate) { updated = dayjs(currentDate).year(dateChanged.year()).month(dateChanged.month()).date(dateChanged.date()); } setCurrentDate(updated); }, [currentDate, setCurrentDate]); var onTimeUpdate = useCallback(function (timeUpdated) { setCurrentDate(timeUpdated); }, []); // Close on ESC key presses useEscapeKey({ ref: ref, callback: onCancel, disabled: !isOpen }); // Close popover on clicks outside useOutsideClick({ refs: [ref, targetRef], callback: onCancel, disabled: !isOpen }); return /*#__PURE__*/React.createElement(Box, { position: "relative", ref: targetRef }, /*#__PURE__*/React.createElement(TextInput, _extends({}, rest, { variant: variant, value: currentDate ? currentDate.format(format) : '', onClick: open, autoComplete: "off", "aria-autocomplete": "none", tabIndex: -1, readOnly: true })), /*#__PURE__*/React.createElement(Box, { position: "absolute", top: 2, right: 3, zIndex: 2 }, /*#__PURE__*/React.createElement(IconButton, { variant: "unstyled", "aria-label": "Toggle picker", size: "medium", icon: "calendar", onClick: isOpen ? onCancel : open })), /*#__PURE__*/React.createElement(DateWrapper, { ref: ref, targetRef: targetRef, alignment: alignment, isExpanded: isOpen }, /*#__PURE__*/React.createElement(Flex, { align: "center", justify: "space-between", p: 4 }, /*#__PURE__*/React.createElement(IconButton, { onClick: onPreviousMonth, size: "medium", icon: "arrow-back", "aria-label": "Go to previous month" }), /*#__PURE__*/React.createElement(Box, { as: Heading, fontSize: "medium", fontWeight: "bold", tabIndex: "-1" }, currentMonth.format('MMMM YYYY')), /*#__PURE__*/React.createElement(IconButton, { onClick: onNextMonth, size: "medium", icon: "arrow-forward", "aria-label": "Go to next month" })), /*#__PURE__*/React.createElement(Box, { px: 4, pb: 4 }, /*#__PURE__*/React.createElement(Month, { onDaySelect: onDaySelect, daysSelected: currentDate && [currentDate], year: currentMonth.year(), month: currentMonth.month(), timezone: timezone })), withTime && /*#__PURE__*/React.createElement(Flex, { align: "center", justify: "center", borderTop: "1px solid", borderColor: "navyblue-300", p: 4 }, /*#__PURE__*/React.createElement(Flex, { align: "center", justify: "center", spacing: 3 }, /*#__PURE__*/React.createElement(TimePicker, { label: "Time", mode: mode, onTimeUpdate: onTimeUpdate, timezone: timezone, date: currentDate }))), /*#__PURE__*/React.createElement(Flex, { align: "center", justify: "center", borderTop: "1px solid", borderColor: "navyblue-300" }, /*#__PURE__*/React.createElement(Flex, { align: "center", justify: "center", p: 3, spacing: 3 }, /*#__PURE__*/React.createElement(Button, { onClick: onCancel, size: "medium", variantColor: "gray-500" }, "Cancel"), /*#__PURE__*/React.createElement(Button, { disabled: isDisabled, onClick: onApply, size: "medium" }, "Apply"))), !disableReset && /*#__PURE__*/React.createElement(Flex, { align: "center", justify: "center", pb: 3 }, /*#__PURE__*/React.createElement(ClearButton, { onClick: onClear }, resetLabel)))); }; export default /*#__PURE__*/React.memo(DateInput);