UNPKG

@razorpay/blade

Version:

The Design System that powers Razorpay

520 lines (516 loc) 23.5 kB
import _typeof from '@babel/runtime/helpers/typeof'; import _defineProperty from '@babel/runtime/helpers/defineProperty'; import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray'; import _slicedToArray from '@babel/runtime/helpers/slicedToArray'; import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties'; import { DatesProvider } from '@mantine/dates'; import React__default from 'react'; import { FloatingPortal, FloatingFocusManager } from '@floating-ui/react'; import { useI18nContext } from '@razorpay/i18nify-react'; import { MantineProvider } from '@mantine/core'; import dayjs from 'dayjs'; import { Calendar } from './Calendar.web.js'; import { PresetSideBar } from './QuickSelection/PresetSideBar.web.js'; import { useDatesState } from './useDatesState.js'; import { usePopup } from './usePopup.js'; import { CalendarFooter } from './CalendarFooter.web.js'; import { convertIntlToDayjsLocale, loadScript } from './utils.js'; import { shiftTimezone } from './shiftTimezone.js'; import { DatePickerInput } from './DateInput.web.js'; import { DatePickerFilterChip } from './FilterChipDatePicker/DatePickerFilterChip.web.js'; import '../Box/BaseBox/index.js'; import { useControllableState } from '../../utils/useControllable.js'; import '../../utils/index.js'; import { useId } from '../../utils/useId.js'; import '../../utils/makeAccessible/index.js'; import { useIsMobile } from '../../utils/useIsMobile.js'; import '../BottomSheet/index.js'; import '../../utils/logger/index.js'; import '../Box/styledProps/index.js'; import '../../utils/metaAttribute/index.js'; import { componentZIndices } from '../../utils/componentZIndices.js'; import '../../utils/makeAnalyticsAttribute/index.js'; import '../../utils/fireNativeEvent/index.js'; import { useListViewFilterContext } from '../ListView/ListViewFiltersContext.web.js'; import { useFilterChipGroupContext } from '../Dropdown/FilterChipGroupContext.web.js'; import { jsxs, Fragment, jsx } from 'react/jsx-runtime'; import useTheme from '../BladeProvider/useTheme.js'; import { fireNativeEvent } from '../../utils/fireNativeEvent/fireNativeEvent.web.js'; import { BaseBox } from '../Box/BaseBox/BaseBox.web.js'; import { logger } from '../../utils/logger/logger.js'; import { getStyledProps } from '../Box/styledProps/getStyledProps.js'; import { metaAttribute } from '../../utils/metaAttribute/metaAttribute.web.js'; import { MetaConstants } from '../../utils/metaAttribute/metaConstants.js'; import { makeAnalyticsAttribute } from '../../utils/makeAnalyticsAttribute/makeAnalyticsAttribute.js'; import { BottomSheet } from '../BottomSheet/BottomSheet.web.js'; import { BottomSheetHeader } from '../BottomSheet/BottomSheetHeader.web.js'; import { BottomSheetBody } from '../BottomSheet/BottomSheetBody.web.js'; import { BottomSheetFooter } from '../BottomSheet/BottomSheetFooter.web.js'; import { makeAccessible } from '../../utils/makeAccessible/makeAccessible.web.js'; var _excluded = ["selectionType", "allowSingleDateInRange", "value", "defaultValue", "onChange", "onApply", "presets", "isOpen", "defaultIsOpen", "onOpenChange", "label", "labelPosition", "accessibilityLabel", "errorText", "helpText", "isDisabled", "isRequired", "successText", "validationState", "size", "autoFocus", "necessityIndicator", "name", "defaultPicker", "picker", "onPickerChange", "zIndex", "format", "inputPlaceHolder", "inputElementType", "onClearButtonClick"]; function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } var BaseDatePicker = function BaseDatePicker(_ref) { var selectionType = _ref.selectionType, allowSingleDateInRange = _ref.allowSingleDateInRange, value = _ref.value, defaultValue = _ref.defaultValue, _onChange = _ref.onChange, onApply = _ref.onApply, presets = _ref.presets, isOpen = _ref.isOpen, defaultIsOpen = _ref.defaultIsOpen, onOpenChange = _ref.onOpenChange, label = _ref.label, _ref$labelPosition = _ref.labelPosition, labelPosition = _ref$labelPosition === void 0 ? 'top' : _ref$labelPosition, accessibilityLabel = _ref.accessibilityLabel, errorText = _ref.errorText, helpText = _ref.helpText, isDisabled = _ref.isDisabled, isRequired = _ref.isRequired, successText = _ref.successText, validationState = _ref.validationState, size = _ref.size, autoFocus = _ref.autoFocus, necessityIndicator = _ref.necessityIndicator, name = _ref.name, _ref$defaultPicker = _ref.defaultPicker, defaultPicker = _ref$defaultPicker === void 0 ? 'day' : _ref$defaultPicker, picker = _ref.picker, onPickerChange = _ref.onPickerChange, _ref$zIndex = _ref.zIndex, zIndex = _ref$zIndex === void 0 ? componentZIndices.popover : _ref$zIndex, _ref$format = _ref.format, format = _ref$format === void 0 ? 'DD/MM/YYYY' : _ref$format, inputPlaceHolder = _ref.inputPlaceHolder, _ref$inputElementType = _ref.inputElementType, inputElementType = _ref$inputElementType === void 0 ? 'datePickerInput' : _ref$inputElementType, onClearButtonClick = _ref.onClearButtonClick, props = _objectWithoutProperties(_ref, _excluded); var _useI18nContext = useI18nContext(), i18nState = _useI18nContext.i18nState; var _selectionType = selectionType !== null && selectionType !== void 0 ? selectionType : 'single'; var _useTheme = useTheme(), theme = _useTheme.theme; var isSingle = _selectionType === 'single'; var _React$useReducer = React__default.useReducer(function (x) { return x + 1; }, 0), _React$useReducer2 = _slicedToArray(_React$useReducer, 2), _ = _React$useReducer2[0], forceRerender = _React$useReducer2[1]; var _React$useState = React__default.useState(null), _React$useState2 = _slicedToArray(_React$useState, 2), selectedPreset = _React$useState2[0], setSelectedPreset = _React$useState2[1]; var referenceRef = React__default.useRef(null); var _useControllableState = useControllableState({ defaultValue: defaultPicker, value: picker, onChange: function onChange(picker) { onPickerChange === null || onPickerChange === void 0 ? void 0 : onPickerChange(picker); } }), _useControllableState2 = _slicedToArray(_useControllableState, 2), _picker = _useControllableState2[0], setPicker = _useControllableState2[1]; var finalFormat = React__default.useMemo(function () { if (format) { return format; } if (picker === 'month') { return 'MMMM'; } if (picker === 'year') { return 'YYYY'; } return 'DD/MM/YYYY'; }, [format, picker]); var finalInputPlaceHolder = React__default.useMemo(function () { if (inputPlaceHolder) { return inputPlaceHolder; } if (picker === 'month') { return 'Month'; } if (picker === 'year') { return 'Year'; } return 'DD/MM/YYYY'; }, [inputPlaceHolder, picker]); var _useDatesState = useDatesState({ level: _picker, type: isSingle ? 'default' : 'range', allowDeselect: false, allowSingleDateInRange: allowSingleDateInRange, value: value, defaultValue: defaultValue, onChange: function onChange(date) { _onChange === null || _onChange === void 0 ? void 0 : _onChange(date); fireNativeEvent(referenceRef, ['input']); if (isSingle) return; // sync selected preset with value setSelectedPreset(date); } }), onDateChange = _useDatesState.onDateChange, onRootMouseLeave = _useDatesState.onRootMouseLeave, onHoveredDateChange = _useDatesState.onHoveredDateChange, getControlProps = _useDatesState.getControlProps, setPickedDate = _useDatesState.setPickedDate, controlledValue = _useDatesState.controlledValue, setControlledValue = _useDatesState.setControlledValue, handleReset = _useDatesState.handleReset; var _React$useState3 = React__default.useState(controlledValue), _React$useState4 = _slicedToArray(_React$useState3, 2), oldValue = _React$useState4[0], setOldValue = _React$useState4[1]; var _useControllableState3 = useControllableState({ value: isOpen, defaultValue: defaultIsOpen, onChange: function onChange(isOpen) { onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange({ isOpen: isOpen }); // we need to update old value everytime datepicker is opened or closed setOldValue(controlledValue); setPicker(function () { return defaultPicker; }); } }), _useControllableState4 = _slicedToArray(_useControllableState3, 2), controllableIsOpen = _useControllableState4[0], controllableSetIsOpen = _useControllableState4[1]; var currentDate = shiftTimezone('add', new Date()); var hasBothDatesSelected = (controlledValue === null || controlledValue === void 0 ? void 0 : controlledValue[0]) && (controlledValue === null || controlledValue === void 0 ? void 0 : controlledValue[1]); var _useListViewFilterCon = useListViewFilterContext(), listViewSelectedFilters = _useListViewFilterCon.listViewSelectedFilters, setListViewSelectedFilters = _useListViewFilterCon.setListViewSelectedFilters; var _useFilterChipGroupCo = useFilterChipGroupContext(), clearFilterCallbackTriggerer = _useFilterChipGroupCo.clearFilterCallbackTriggerer, setFilterChipGroupSelectedFilters = _useFilterChipGroupCo.setFilterChipGroupSelectedFilters; var applyButtonDisabled = !hasBothDatesSelected; if (isSingle) { applyButtonDisabled = !Boolean(controlledValue); } var close = React__default.useCallback(function () { controllableSetIsOpen(function () { return false; }); }, [controllableSetIsOpen]); var handleApply = function handleApply() { var updateSelectedFilters = function updateSelectedFilters() { setFilterChipGroupSelectedFilters(function (prev) { return [].concat(_toConsumableArray(prev), [label]); }); }; var storeSelectedFiltersAndValueInListViewContext = function storeSelectedFiltersAndValueInListViewContext() { setListViewSelectedFilters(function (prev) { if (isSingle) { return _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, label, [controlledValue])); } return _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, label, controlledValue)); }); }; if (isSingle) { _onChange === null || _onChange === void 0 ? void 0 : _onChange(controlledValue); fireNativeEvent(referenceRef, ['change']); setOldValue(controlledValue); onApply === null || onApply === void 0 ? void 0 : onApply(controlledValue); close(); storeSelectedFiltersAndValueInListViewContext(); updateSelectedFilters(); return; } // only apply if both dates are selected if (hasBothDatesSelected) { _onChange === null || _onChange === void 0 ? void 0 : _onChange(controlledValue); fireNativeEvent(referenceRef, ['change']); setOldValue(controlledValue); onApply === null || onApply === void 0 ? void 0 : onApply(controlledValue); close(); } storeSelectedFiltersAndValueInListViewContext(); updateSelectedFilters(); }; var handleCancel = function handleCancel() { setControlledValue(oldValue); fireNativeEvent(referenceRef, ['change']); setPickedDate(null); close(); }; var handleClear = function handleClear() { fireNativeEvent(referenceRef, ['change']); handleReset(); close(); setFilterChipGroupSelectedFilters(function (prev) { return prev.filter(function (filter) { return filter !== label; }); }); setListViewSelectedFilters(function (prev) { var _ref2 = label, _ = prev[_ref2], rest = _objectWithoutProperties(prev, [_ref2].map(_toPropertyKey)); return rest; }); onClearButtonClick === null || onClearButtonClick === void 0 ? void 0 : onClearButtonClick(); }; React__default.useEffect(function () { if (listViewSelectedFilters[label]) { setControlledValue(listViewSelectedFilters[label]); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); React__default.useEffect(function () { if (clearFilterCallbackTriggerer) { handleClear(); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [clearFilterCallbackTriggerer]); var isMobile = useIsMobile(); var defaultInitialFocusRef = React__default.useRef(null); var titleId = useId('datepicker-title'); var _usePopup = usePopup({ enabled: !isMobile, placement: 'bottom-start', open: controllableIsOpen, onOpenChange: function onOpenChange(isOpen, _, reason) { controllableSetIsOpen(function () { return isOpen; }); if (reason === 'escape-key' || reason === 'outside-press') { handleCancel(); } }, referenceRef: referenceRef }), context = _usePopup.context, refs = _usePopup.refs, isMounted = _usePopup.isMounted, floatingStyles = _usePopup.floatingStyles, animationStyles = _usePopup.animationStyles, getReferenceProps = _usePopup.getReferenceProps, getFloatingProps = _usePopup.getFloatingProps; var shouldRenderPresets = !isSingle && !isMobile; var content = /*#__PURE__*/jsxs(Fragment, { children: [shouldRenderPresets ? /*#__PURE__*/jsx(PresetSideBar, { presets: presets, date: currentDate, selectedPreset: selectedPreset, onSelection: function onSelection(preset) { var presetValue = preset === null || preset === void 0 ? void 0 : preset(currentDate); setControlledValue(presetValue); setSelectedPreset(presetValue); } }) : null, /*#__PURE__*/jsxs(BaseBox, { width: "100%", display: "flex", flexDirection: "column", gap: "spacing.5", padding: { m: 'spacing.6', s: 'spacing.0' } /* We only need to set height for day picker, for year picker or month it should be auto. */, height: _picker === 'day' ? '447px' : 'auto', backgroundColor: "surface.background.gray.intense", justifyContent: "space-between", children: [/*#__PURE__*/jsx(Calendar, _objectSpread(_objectSpread({}, props), {}, { selectionType: _selectionType, defaultValue: defaultValue, onMouseLeave: onRootMouseLeave, __onDayMouseEnter: function __onDayMouseEnter(_event, date) { onHoveredDateChange(date); }, __onDayClick: function __onDayClick(_event, date) { onDateChange(date, 'day'); }, getMonthControlProps: function getMonthControlProps(date) { return getControlProps(date); }, getYearControlProps: function getYearControlProps(date) { return getControlProps(date); }, getDayProps: function getDayProps(date) { return getControlProps(date); }, onMonthSelect: function onMonthSelect(date) { var _props$onMonthSelect; props === null || props === void 0 ? void 0 : (_props$onMonthSelect = props.onMonthSelect) === null || _props$onMonthSelect === void 0 ? void 0 : _props$onMonthSelect.call(props, date); onDateChange(date, 'month'); }, onYearSelect: function onYearSelect(date) { var _props$onYearSelect; props === null || props === void 0 ? void 0 : (_props$onYearSelect = props.onYearSelect) === null || _props$onYearSelect === void 0 ? void 0 : _props$onYearSelect.call(props, date); onDateChange(date, 'year'); }, onNext: function onNext(data) { var _props$onNext; props === null || props === void 0 ? void 0 : (_props$onNext = props.onNext) === null || _props$onNext === void 0 ? void 0 : _props$onNext.call(props, data); forceRerender(); }, onPrevious: function onPrevious(data) { var _props$onPrevious; props === null || props === void 0 ? void 0 : (_props$onPrevious = props.onPrevious) === null || _props$onPrevious === void 0 ? void 0 : _props$onPrevious.call(props, data); forceRerender(); }, picker: _picker, showLevelChangeLink: !picker, onPickerChange: function onPickerChange(picker) { setPicker(function () { return picker; }); forceRerender(); }, selectedValue: controlledValue })), isMobile ? null : /*#__PURE__*/jsx(CalendarFooter, { isButtonDisabled: applyButtonDisabled, onApply: handleApply, onCancel: handleCancel })] })] }); var dateProviderValue = React__default.useMemo(function () { var _i18nState$locale; var locale = convertIntlToDayjsLocale((_i18nState$locale = i18nState === null || i18nState === void 0 ? void 0 : i18nState.locale) !== null && _i18nState$locale !== void 0 ? _i18nState$locale : 'en-IN'); return { locale: locale }; }, [i18nState === null || i18nState === void 0 ? void 0 : i18nState.locale]); // Dynamically load dayjs locales React__default.useLayoutEffect(function () { try { var _i18nState$locale2; var locale = convertIntlToDayjsLocale((_i18nState$locale2 = i18nState === null || i18nState === void 0 ? void 0 : i18nState.locale) !== null && _i18nState$locale2 !== void 0 ? _i18nState$locale2 : 'en-IN'); // dayjs needs to be loaded into window so that once the locale is loaded it can be parsed if (!window.dayjs) { window.dayjs = dayjs; } loadScript("https://cdn.jsdelivr.net/npm/dayjs@1/locale/".concat(locale, ".js"), function () { forceRerender(); }); } catch (e) { logger({ type: 'warn', message: 'Failed to load dayjs locale' }); } }, [i18nState === null || i18nState === void 0 ? void 0 : i18nState.locale]); return /*#__PURE__*/jsx(MantineProvider, { children: /*#__PURE__*/jsx(DatesProvider, { settings: dateProviderValue, children: /*#__PURE__*/jsxs(BaseBox, _objectSpread(_objectSpread(_objectSpread({ width: inputElementType === 'chip' ? 'fit-content' : '100%' }, getStyledProps(props)), metaAttribute({ name: MetaConstants.DatePicker })), {}, { children: [inputElementType === 'chip' ? /*#__PURE__*/jsx(DatePickerFilterChip, _objectSpread({ selectionType: _selectionType, date: controlledValue, ref: referenceRef, inputRef: refs.reference, referenceProps: getReferenceProps(), name: name, label: label, labelPosition: labelPosition, accessibilityLabel: accessibilityLabel, size: size, errorText: errorText, helpText: helpText, successText: successText, isDisabled: isDisabled, isRequired: isRequired, validationState: validationState, autoFocus: autoFocus, necessityIndicator: necessityIndicator, format: finalFormat, placeholder: finalInputPlaceHolder, onClearButtonChange: handleClear }, makeAnalyticsAttribute(props))) : /*#__PURE__*/jsx(DatePickerInput, _objectSpread({ selectionType: _selectionType, date: controlledValue, ref: referenceRef, inputRef: refs.reference, referenceProps: getReferenceProps(), name: name, label: label, labelPosition: labelPosition, accessibilityLabel: accessibilityLabel, size: size, errorText: errorText, helpText: helpText, successText: successText, isDisabled: isDisabled, isRequired: isRequired, validationState: validationState, autoFocus: autoFocus, necessityIndicator: necessityIndicator, format: finalFormat, placeholder: finalInputPlaceHolder }, makeAnalyticsAttribute(props))), isMobile ? /*#__PURE__*/jsxs(BottomSheet, { snapPoints: [0.9, 0.9, 1], isOpen: controllableIsOpen, onDismiss: function onDismiss() { handleCancel(); }, children: [/*#__PURE__*/jsx(BottomSheetHeader, { title: isSingle ? 'Select Date' : 'Select Date Range' }), /*#__PURE__*/jsxs(BottomSheetBody, { children: [content, !isSingle && /*#__PURE__*/jsx(PresetSideBar, { isMobile: true, presets: presets, date: currentDate, selectedPreset: selectedPreset, onSelection: function onSelection(preset) { var presetValue = preset === null || preset === void 0 ? void 0 : preset(currentDate); setControlledValue(presetValue); setSelectedPreset(presetValue); } })] }), /*#__PURE__*/jsx(BottomSheetFooter, { children: /*#__PURE__*/jsx(CalendarFooter, { onCancel: handleCancel, onApply: handleApply }) })] }) : isMounted && /*#__PURE__*/jsx(FloatingPortal, { children: /*#__PURE__*/jsx(FloatingFocusManager, { initialFocus: defaultInitialFocusRef, context: context, guards: true, children: /*#__PURE__*/jsx(BaseBox, _objectSpread(_objectSpread(_objectSpread({ ref: refs.setFloating, style: floatingStyles, zIndex: zIndex }, getFloatingProps()), makeAccessible({ labelledBy: titleId })), {}, { children: /*#__PURE__*/jsx(BaseBox, { display: "flex", flexDirection: "row", borderColor: "surface.border.gray.subtle", borderWidth: "thin", borderStyle: "solid", borderRadius: "medium", overflow: "hidden", minWidth: "320px", style: _objectSpread(_objectSpread({}, animationStyles), {}, { boxShadow: "".concat(theme.elevation.lowRaised) }), children: content }) })) }) })] })) }) }); }; export { BaseDatePicker }; //# sourceMappingURL=BaseDatePicker.web.js.map