UNPKG

@appbuckets/react-ui

Version:
452 lines (445 loc) 12.6 kB
'use strict'; var tslib = require('tslib'); var React = require('react'); var clsx = require('clsx'); var reactUiCore = require('@appbuckets/react-ui-core'); var ReactDayPicker = require('react-day-picker/DayPicker'); var customHook = require('../utils/customHook.js'); var splitFieldProps = require('../utils/splitFieldProps.js'); require('../BucketTheme/BucketTheme.js'); var BucketContext = require('../BucketTheme/BucketContext.js'); var Button = require('../Button/Button.js'); var Input = require('../Input/Input.js'); var Modal = require('../Modal/Modal.js'); require('../Modal/Modal.context.js'); var Popup = require('../Popup/Popup.js'); function _interopDefaultLegacy(e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty( n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; }, } ); } }); } n['default'] = e; return Object.freeze(n); } var React__namespace = /*#__PURE__*/ _interopNamespace(React); var clsx__default = /*#__PURE__*/ _interopDefaultLegacy(clsx); var ReactDayPicker__default = /*#__PURE__*/ _interopDefaultLegacy(ReactDayPicker); /* -------- * Component Render * -------- */ var DayPicker = function (receivedProps) { var _a, _b, _c, _d; /** Get component default props */ var props = BucketContext.useWithDefaultProps('dayPicker', receivedProps); var _e = customHook.useSharedClassName(props), className = _e.className, _f = _e.rest, /** Strict DayPicker Props */ clearable = _f.clearable, clearButton = _f.clearButton, closeOnDayPicked = _f.closeOnDayPicked, userDefinedDate = _f.date, defaultDate = _f.defaultDate, defaultOpen = _f.defaultOpen, format = _f.format, onCalendarClose = _f.onCalendarClose, onCalendarOpen = _f.onCalendarOpen, onDayChange = _f.onDayChange, onInputChange = _f.onInputChange, userDefinedOpen = _f.open, parse = _f.parse; _f.showInputMask; var trigger = _f.trigger, triggerProps = _f.triggerProps, type = _f.type, /** Shared Field Props */ disabled = _f.disabled, readOnly = _f.readOnly, required = _f.required, /** Strict DayPicker Props */ userDefinedFixedWeeks = _f.fixedWeeks; _f.onTodayButtonClick; var todayButton = _f.todayButton; /** Strip useless props */ _f.ref; var /** All other DayPicker Props Props */ rawRest = tslib.__rest(_f, [ 'clearable', 'clearButton', 'closeOnDayPicked', 'date', 'defaultDate', 'defaultOpen', 'format', 'onCalendarClose', 'onCalendarOpen', 'onDayChange', 'onInputChange', 'open', 'parse', 'showInputMask', 'trigger', 'triggerProps', 'type', 'disabled', 'readOnly', 'required', 'fixedWeeks', 'onTodayButtonClick', 'todayButton', 'ref', ]); var _g = tslib.__read(customHook.useSplitStateClassName(rawRest), 3), allRest = _g[1], inputState = _g[2]; var _h = tslib.__read(splitFieldProps(allRest), 2), restFieldProps = _h[0], restDayPickerProps = _h[1]; /* -------- * Auto Controlled Component State * -------- */ var _j = tslib.__read( reactUiCore.useAutoControlledValue(null, { prop: userDefinedDate, defaultProp: defaultDate, }), 2 ), rawDate = _j[0], trySetRawDate = _j[1]; var _k = tslib.__read( reactUiCore.useAutoControlledValue(false, { prop: userDefinedOpen, defaultProp: defaultOpen, }), 2 ), open = _k[0], trySetOpen = _k[1]; /* -------- * Internal Function * -------- */ var getToday = React__namespace.useCallback(function () { var newDate = new Date(); newDate.setHours(0, 0, 0, 0); return newDate; }, []); /* -------- * Date Parsing and Formatting * -------- */ var castToDate = React__namespace.useCallback( function (date) { /** If no date, return null */ if (!date) { return null; } /** Initialize the Casted Date variable */ var castedDate; /** If a custom parse function exists, use to cast the date */ if (typeof parse === 'function') { castedDate = parse(date); } else if (date instanceof Date) { /** Else, if is a valid date, use as is */ castedDate = date; } else { /** Use the date constructor if rawDate is a primitive type */ castedDate = new Date(date); } /** If casted date is invalid, return null */ if ( castedDate === null || !(castedDate instanceof Date) || (castedDate === null || castedDate === void 0 ? void 0 : castedDate.toString()) === 'Invalid Date' ) { return null; } /** Set Hours */ castedDate.setHours(0, 0, 0, 0); return castedDate; }, [parse] ); var formatDate = React__namespace.useCallback( function (date) { /** If no date, return an empty string */ if (!date || date.toString() === 'Invalid Date') { return ''; } /** If a custom format function exists, use it */ if (typeof format === 'function') { return format(date); } return date.toLocaleDateString(); }, [format] ); var selectedDate = React__namespace.useMemo( function () { /** If no raw date exists, set as null */ if (rawDate === null || rawDate === undefined) { return { object: null, formatted: '' }; } /** Initialize the casted date variable, and formatted one */ var castedDate = castToDate(rawDate); /** Return data */ return { object: castedDate, formatted: formatDate(castedDate), }; }, [castToDate, formatDate, rawDate] ); var _l = tslib.__read( React__namespace.useState( (_a = selectedDate.formatted) !== null && _a !== void 0 ? _a : '' ), 2 ), inputValue = _l[0], setInputValue = _l[1]; /* -------- * Build Props Object used to pass to Event * -------- */ var propsForEvent = tslib.__assign(tslib.__assign({}, props), { date: (_b = selectedDate.object) !== null && _b !== void 0 ? _b : null, timestamp: (_d = (_c = selectedDate.object) === null || _c === void 0 ? void 0 : _c.valueOf()) !== null && _d !== void 0 ? _d : null, }); /* -------- * Component Handlers * -------- */ var handleCalendarOpen = function () { if (onCalendarOpen) { onCalendarOpen(null, propsForEvent); } trySetOpen(true); }; var handleCalendarClose = function () { if (onCalendarClose) { onCalendarClose(null, propsForEvent); } trySetOpen(false); }; var handleCalendarModalClose = function (e) { /** Stop event Propagation */ e.stopPropagation(); /** Close the Calendar */ handleCalendarClose(); }; var evalDayChange = function (value, triggeredByInput) { var _a, _b; /** Build new Date Object */ var newDate = castToDate(value); var currTimestamp = (_b = (_a = selectedDate.object) === null || _a === void 0 ? void 0 : _a.valueOf()) !== null && _b !== void 0 ? _b : null; var isValidNewDate = newDate && newDate.toString() !== 'Invalid Date'; var newDateObject = isValidNewDate ? newDate : null; var newTimestamp = isValidNewDate ? newDate.valueOf() : null; /** Check if date is changed */ if (currTimestamp !== newTimestamp && onDayChange) { onDayChange( null, tslib.__assign(tslib.__assign({}, propsForEvent), { date: newDate, timestamp: newTimestamp, }) ); } if (closeOnDayPicked) { handleCalendarClose(); } if (!triggeredByInput) { setInputValue(formatDate(newDate)); } trySetRawDate(newDateObject); }; var handleDayClick = function (day, modifiers, e) { /** If calendar is disabled, or day is disabled, return */ if (disabled || modifiers.disabled) { return; } /** Stop event Propagation */ e.stopPropagation(); /** Eval Day Change */ evalDayChange(day, false); }; var handleInputChange = function (e, inputProps) { /** Change Input Value */ setInputValue(inputProps.value); /** Trigger Handler */ if (onInputChange) { onInputChange(e, inputProps); } /** Eval day Change */ evalDayChange(inputProps.value, true); }; var handleTodayButtonClick = function () { evalDayChange(getToday(), false); }; var handleClearDate = function () { evalDayChange('', false); }; /** Build the element class list */ var classes = clsx__default['default']('day-picker', className); /* -------- * Build the Modal Trigger Memoized Element * -------- */ var modalTrigger = (function () { if (type === 'input') { return undefined; } if (trigger) { return trigger; } return React__namespace.createElement( Button, tslib.__assign( { icon: 'calendar', content: selectedDate.formatted }, triggerProps, { disabled: disabled, onClick: handleCalendarOpen } ) ); })(); var calendarAddon = (function () { /** In Portal no addons could be defined */ if (type === 'input') { return null; } /** Build clear Button */ var clearButtonElement = clearable && !!rawDate && Button.create(clearButton || 'Clear', { autoGenerateKey: false, defaultProps: { size: 'small', }, overrideProps: { className: 'clear', disabled: disabled, onClick: handleClearDate, }, }); /** Build today button */ var todayButtonElement = Button.create(todayButton, { autoGenerateKey: false, defaultProps: { primary: true, size: 'small', }, overrideProps: { className: 'today', disabled: disabled, onClick: handleTodayButtonClick, }, }); /** If no content, return */ if (!clearButtonElement && !todayButtonElement) { return null; } return React__namespace.createElement( 'div', { className: 'addons' }, todayButtonElement, clearButtonElement ); })(); /* -------- * Build the DayPicker Component * -------- */ var dayPickerElement = React__namespace.createElement( React__namespace.Fragment, null, React__namespace.createElement( ReactDayPicker__default['default'], // Component Props tslib.__assign({}, restDayPickerProps, { fixedWeeks: userDefinedFixedWeeks !== null && userDefinedFixedWeeks !== void 0 ? userDefinedFixedWeeks : type === 'modal', // Selected Days month: selectedDate.object || undefined, selectedDays: selectedDate.object || undefined, // Handlers onDayClick: handleDayClick, onTodayButtonClick: handleDayClick, }) ), calendarAddon ); /* -------- * Return the Calendar as Input * -------- */ if (type === 'input') { return React__namespace.createElement( Popup, { portalProps: { open: open, }, onOpen: handleCalendarOpen, onClose: handleCalendarClose, basic: false, inverted: false, position: 'bottom left', openOn: ['focus'], trigger: React__namespace.createElement( Input, tslib.__assign({}, inputState, restFieldProps, { className: classes, clearable: clearable && !!rawDate, disabled: disabled, readOnly: readOnly, required: required, value: inputValue, onChange: handleInputChange, }) ), }, dayPickerElement ); } return React__namespace.createElement(Modal, { className: classes, open: open, trigger: modalTrigger, content: dayPickerElement, onClose: handleCalendarModalClose, }); }; DayPicker.displayName = 'DayPicker'; module.exports = DayPicker;