UNPKG

@amaui/ui-react

Version:
514 lines (513 loc) 27.2 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = __importDefault(require("react")); const style_react_1 = require("@amaui/style-react"); const utils_1 = require("@amaui/utils"); const date_1 = require("@amaui/date"); const Line_1 = __importDefault(require("../Line")); const Surface_1 = __importDefault(require("../Surface")); const Type_1 = __importDefault(require("../Type")); const PaginationItem_1 = __importDefault(require("../PaginationItem")); const Transitions_1 = __importDefault(require("../Transitions")); const Transition_1 = __importDefault(require("../Transition")); const utils_2 = require("../utils"); const useStyle = (0, style_react_1.style)(theme => ({ root: { // for transition overflow: 'hidden', position: 'relative' }, size_small: { height: '250px' }, size_regular: { height: '300px' }, size_large: { height: '370px' }, root_no_labels: { height: '260px' }, dayNames: { width: '100%' }, dayName: { flex: '1 1 auto', userSelect: 'none' }, dayName_size_small: { width: '30px', height: '30px' }, dayName_size_regular: { width: '40px', height: '40px' }, dayName_size_large: { width: '50px', height: '50px' }, day: { flex: '1 1 auto', position: 'relative' }, day_size_small: { width: '30px', height: '30px' }, day_size_regular: { width: '40px', height: '40px' }, day_size_large: { width: '50px', height: '50px' }, day_out: { opacity: '0.4' }, day_out_no: { visibility: 'hidden', opacity: '0' }, dayStart: { borderRadius: `${theme.methods.shape.radius.value(40, 'px')} 0 0 ${theme.methods.shape.radius.value(40, 'px')}` }, dayEnd: { borderRadius: `0 ${theme.methods.shape.radius.value(40, 'px')} ${theme.methods.shape.radius.value(40, 'px')} 0` }, dayStartEnd: { borderRadius: theme.methods.shape.radius.value(40, 'px') }, dayStartSelected: { '&::before': { content: '""', position: 'absolute', left: '50%', top: '0', height: '100%', width: '50%', background: 'currentColor' } }, dayEndSelected: { '&::before': { content: '""', position: 'absolute', left: '0', right: '50%', top: '0', height: '100%', width: '50%', background: 'currentColor' } }, weeks: { width: '100%', position: 'absolute', left: '0px', transition: theme.methods.transitions.make(['opacity', 'transform']) }, weeks_size_small: { top: '30px' }, weeks_size_regular: { top: '40px' }, weeks_size_large: { top: '50px' }, weeks_no_labels: { top: '0px' }, week: { width: '100%' }, move_previous: { '& .weeks_enter': { opacity: '0', transform: 'translateX(100%)', }, '& .weeks_entering': { opacity: '1', transform: 'translateX(0%)' }, '& .weeks_exit': { opacity: '1', transform: 'translateX(0%)', }, '& .weeks_exiting': { opacity: '0', transform: 'translateX(-100%)' } }, move_next: { '& .weeks_enter': { opacity: '0', transform: 'translateX(-100%)', }, '& .weeks_entering': { opacity: '1', transform: 'translateX(0%)' }, '& .weeks_exit': { opacity: '1', transform: 'translateX(0%)', }, '& .weeks_exiting': { opacity: '0', transform: 'translateX(100%)' } }, dayValue: { '&:hover': { boxShadow: 'inset 0px 0px 0px 1px currentColor' } }, disabled: { opacity: '0.54', pointerEvents: 'none' } }), { name: 'amaui-CalendarMonth' }); const CalendarMonth = react_1.default.forwardRef((props__, ref) => { var _a, _b, _c; const theme = (0, style_react_1.useAmauiTheme)(); const props = react_1.default.useMemo(() => { var _a, _b, _c, _d, _e, _f, _g, _h; return (Object.assign(Object.assign(Object.assign({}, (_d = (_c = (_b = (_a = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _a === void 0 ? void 0 : _a.elements) === null || _b === void 0 ? void 0 : _b.all) === null || _c === void 0 ? void 0 : _c.props) === null || _d === void 0 ? void 0 : _d.default), (_h = (_g = (_f = (_e = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _e === void 0 ? void 0 : _e.elements) === null || _f === void 0 ? void 0 : _f.amauiCalendarMonth) === null || _g === void 0 ? void 0 : _g.props) === null || _h === void 0 ? void 0 : _h.default), props__)); }, [props__]); const Line = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Line) || Line_1.default; }, [theme]); const Surface = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Surface) || Surface_1.default; }, [theme]); const Type = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Type) || Type_1.default; }, [theme]); const PaginationItem = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.PaginationItem) || PaginationItem_1.default; }, [theme]); const Transitions = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Transitions) || Transitions_1.default; }, [theme]); const Transition = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Transition) || Transition_1.default; }, [theme]); const { tonal = true, color = 'primary', size = 'regular', value: value_, valueDefault, onChange, calendar: calendar_, calendarDefault, onChangeCalendar, onTimeClick, range, offset = 0, outside = true, weekStartDay: weekStartDay_ = 'Monday', now = true, min, max, validate, labels = true, dayNamesFull, noTransition = true, valid: valid_, renderDay, renderDayName, disabled, DayNameProps, PaginationItemProps, TransitionProps, TransitionsProps, className } = props, other = __rest(props, ["tonal", "color", "size", "value", "valueDefault", "onChange", "calendar", "calendarDefault", "onChangeCalendar", "onTimeClick", "range", "offset", "outside", "weekStartDay", "now", "min", "max", "validate", "labels", "dayNamesFull", "noTransition", "valid", "renderDay", "renderDayName", "disabled", "DayNameProps", "PaginationItemProps", "TransitionProps", "TransitionsProps", "className"]); const { classes } = useStyle(); const [value, setValue] = react_1.default.useState(() => { const valueResult = (valueDefault !== undefined ? valueDefault : value_) || (now && (range ? [new date_1.AmauiDate(), new date_1.AmauiDate()] : [new date_1.AmauiDate()])); return ((0, utils_1.is)('array', valueResult) ? valueResult : [valueResult]).filter(Boolean); }); const [calendar, setCalendar] = react_1.default.useState((calendarDefault !== undefined ? calendarDefault : calendar_) || new date_1.AmauiDate()); let month = calendar || value[0] || new date_1.AmauiDate(); if (!(month === null || month === void 0 ? void 0 : month.valid)) month = new date_1.AmauiDate(); const refs = { id: react_1.default.useRef(`${(month).year} ${(month).month}`), previous: react_1.default.useRef(month), previousTheme: react_1.default.useRef(theme.palette.light), move: react_1.default.useRef(), noTransition: react_1.default.useRef(undefined) }; const weekStartDay = !['Monday', 'Sunday'].includes(weekStartDay_) ? 'Monday' : weekStartDay_; // Value react_1.default.useEffect(() => { if (value_ !== undefined && value_ !== value) setValue((((0, utils_1.is)('array', value_) ? value_ : [value_]).filter(Boolean))); }, [value_]); // Calendar react_1.default.useEffect(() => { if (calendar_ !== undefined && calendar_ !== calendar) setCalendar(calendar_); }, [calendar_]); const valid = react_1.default.useCallback((...args) => { if ((0, utils_1.is)('function', valid_)) return valid_(...args); const amauiDate = args[0]; if (min || max || validate) { let response = true; if ((0, utils_1.is)('function', validate)) response = validate(amauiDate); if (min !== undefined) response = response && (0, date_1.is)(amauiDate, 'after or same', min); if (max !== undefined) response = response && (0, date_1.is)(amauiDate, 'before or same', max); return response; } return true; }, [valid_, min, max, validate]); const onUpdateCalendar = react_1.default.useCallback((valueNew) => { // Inner update if (!props.hasOwnProperty('calendar')) setCalendar(valueNew); if ((0, utils_1.is)('function', onChangeCalendar)) onChangeCalendar(valueNew); }, [onChangeCalendar]); const onUpdate = react_1.default.useCallback((valueUpdated, offsetMultiplier) => { let valueNew = [valueUpdated, value[1]].filter(Boolean); // Previous // Range reset // If value is range, and is the same (in terms of day, month, year as from and/or to) // make a reset, ie. make both values that same date if (range) { if (value.filter(Boolean) .some(item => valueUpdated.year === item.year && valueUpdated.month === item.month && valueUpdated.day === item.day)) valueNew = [valueUpdated, valueUpdated]; else { // Update the value closest to from, to value let index; // Update from or to // based on if value is closer to the middle from, or middle to if (!value[0]) index = 0; else if (!value[1]) index = 1; else if (valueUpdated.milliseconds < value[0].milliseconds) index = 0; else if (valueUpdated.milliseconds > value[1].milliseconds) index = 1; else { const middle = Math.abs(value[1].milliseconds - value[0].milliseconds) / 2; index = valueUpdated.milliseconds <= (value[0].milliseconds + middle) ? 0 : 1; } valueNew = [...value]; valueNew[index] = valueUpdated; } // start of the day if (valueNew[0]) { valueNew[0] = (0, date_1.startOf)(valueNew[0], 'day'); } // end of the day if (valueNew[1]) { valueNew[1] = (0, date_1.endOf)(valueNew[1], 'day'); } } // If value isnt's same as the calendar // update calendar to the value if (!(valueUpdated.year === calendar.year && valueUpdated.month === calendar.month)) { onUpdateCalendar((0, date_1.add)(offsetMultiplier !== undefined ? (offsetMultiplier * offset) : 0, 'month', valueUpdated)); } // Inner value update if (!props.hasOwnProperty('value')) setValue(valueNew); if ((0, utils_1.is)('function', onChange)) onChange((!range ? valueNew[0] : valueNew)); }, [value, range, offset, calendar, onChange]); const dayNames = [1, 2, 3, 4, 5, 6]; if (weekStartDay === 'Monday') dayNames.push(7); else dayNames.unshift(7); const renderDayNameMethod = (0, utils_1.is)('function', renderDayName) ? renderDayName : (order_) => { const values = { 1: dayNamesFull ? 'Monday' : 'M', 2: dayNamesFull ? 'Tuesday' : 'T', 3: dayNamesFull ? 'Wednesday' : 'W', 4: dayNamesFull ? 'Thursday' : 'T', 5: dayNamesFull ? 'Friday' : 'F', 6: dayNamesFull ? 'Saturday' : 'S', 7: dayNamesFull ? 'Sunday' : 'S' }; return values[order_]; }; const days = []; const monthNow = new date_1.AmauiDate(); // value or value range selected value let id = `${month.year} ${month.month} ${month.day} ${theme.palette.light}`; value.forEach(item => id += ` ${item.year} ${item.month} ${item.day}`); const monthStart = (0, date_1.startOf)(month, 'month'); const previousMonth = (0, date_1.remove)(1, 'month', month); const previousMonthEnd = (0, date_1.endOf)(previousMonth, 'month'); const nextMonth = (0, date_1.add)(1, 'month', month); const monthSame = ((_a = refs.previous.current) === null || _a === void 0 ? void 0 : _a.year) === (calendar === null || calendar === void 0 ? void 0 : calendar.year) && ((_b = refs.previous.current) === null || _b === void 0 ? void 0 : _b.month) === (calendar === null || calendar === void 0 ? void 0 : calendar.month); const isBetween = (day) => { var _a, _b; return day.milliseconds >= ((_a = value[0]) === null || _a === void 0 ? void 0 : _a.milliseconds) && day.milliseconds <= (((_b = value[1]) === null || _b === void 0 ? void 0 : _b.milliseconds) + 4000); }; const isSelected = (day) => value.some((item) => item.year === day.year && item.month === day.month && item.day === day.day); const selectedIndex = (day) => value.findIndex((item) => item.year === day.year && item.month === day.month && item.day === day.day); const selectedSame = (day) => value.filter((item) => item.year === day.year && item.month === day.month && item.day === day.day).length === 2; let isMonthFrom = false; let isMonthTo = false; // Add all month days for (let i = 0; i < month.daysInMonth; i++) { let day = (0, date_1.set)(i + 1, 'day', month); day = (0, date_1.set)(14, 'hour', day); const selectedIndex_ = selectedIndex(day); if (selectedIndex_ === 0) isMonthFrom = true; else if (selectedIndex_ === 1) isMonthTo = true; days.push({ value: i + 1, in: true, dayWeek: day.dayWeek, weekend: [0, 6].includes(day.dayWeek), today: day.year === monthNow.year && day.dayYear === monthNow.dayYear, between: isBetween(day), selected: isSelected(day), selectedIndex: selectedIndex_, selectedSame: selectedSame(day), amauiDate: day }); } days[0].start = true; days[days.length - 1].end = true; // Add to start if ((weekStartDay === 'Sunday' && monthStart.dayWeek !== 0) || (weekStartDay === 'Monday' && monthStart.dayWeek !== 1)) { let toAdd = monthStart.dayWeek === 0 ? 6 : monthStart.dayWeek - 1; if (weekStartDay === 'Sunday') toAdd++; for (let i = 0; i < toAdd; i++) { const day = (0, date_1.set)(previousMonthEnd.day - i, 'day', previousMonth); days.unshift({ value: day.day, in: false, dayWeek: day.dayWeek, weekend: [0, 6].includes(day.dayWeek), today: day.year === monthNow.year && day.dayYear === monthNow.dayYear, between: isBetween(day), selected: isSelected(day), selectedIndex: selectedIndex(day), selectedSame: selectedSame(day), start: true, amauiDate: day }); } } // Add to end const dayLast = days[days.length - 1]; if (dayLast.dayWeek < 7) { let toAdd = 7 - dayLast.dayWeek; if (days.length + toAdd - 1 < 42) toAdd += 41 - (days.length + toAdd - 1); for (let i = 0; i < toAdd; i++) { const day = (0, date_1.set)(i + 1, 'day', nextMonth); days.push({ value: i + 1, in: false, dayWeek: day.dayWeek, weekend: [0, 6].includes(day.dayWeek), today: day.year === monthNow.year && day.dayYear === monthNow.dayYear, between: isBetween(day), selected: isSelected(day), selectedIndex: selectedIndex(day), selectedSame: selectedSame(day), end: true, amauiDate: day }); } } // noTransition refs.noTransition.current = monthSame; // Update previous if (refs.id.current !== `${month.year} ${month.month}`) { refs.move.current = ((_c = refs.previous.current) === null || _c === void 0 ? void 0 : _c.milliseconds) > month.milliseconds ? 'next' : 'previous'; refs.id.current = `${month.year} ${month.month}`; refs.previous.current = month; refs.noTransition.current = false; } const weeks = (0, utils_1.arrayToParts)(days, 7); const getCalendar = (status) => { return ((0, jsx_runtime_1.jsx)(Surface, { children: ({ palette }) => ((0, jsx_runtime_1.jsx)(Line, Object.assign({ gap: 0.5, direction: 'column', align: 'unset', justify: 'unset', className: (0, style_react_1.classNames)([ (0, utils_2.staticClassName)('CalendarMonth', theme) && [ 'amaui-CalendarMonth-weeks' ], classes.weeks, classes[`weeks_size_${size}`], status && [`weeks_${status}`], !labels && classes.weeks_no_labels ]) }, { children: weeks.map((week, index) => ( // Week (0, jsx_runtime_1.jsx)(Line, Object.assign({ gap: 0, direction: 'row', align: 'unset', justify: 'space-between', className: (0, style_react_1.classNames)([ (0, utils_2.staticClassName)('CalendarMonth', theme) && [ 'amaui-CalendarMonth-week' ], classes.week ]) }, { children: week.map((day, index_) => { const propsDay = { onClick: () => onUpdate(day.amauiDate, day.start || day.end ? -1 : undefined), disabled: ((!day.in && !outside) || !valid(day.amauiDate, 'day') || // not prior to 1970, we may potentially update this in the future day.amauiDate.year < 1970) }; return ((0, jsx_runtime_1.jsx)(Line, Object.assign({ direction: 'row', align: 'center', justify: 'center', onClick: (event) => { const timeDate = (0, date_1.startOf)(day.amauiDate, 'hour'); onTimeClick === null || onTimeClick === void 0 ? void 0 : onTimeClick(timeDate, 'month', event); }, className: (0, style_react_1.classNames)([ (0, utils_2.staticClassName)('CalendarMonth', theme) && [ 'amaui-CalendarMonth-day', `amaui-CalendarMonth-day-${day.in ? 'in' : 'out'}` ], classes.day, classes[`day_size_${size}`], classes[`day_${day.in ? 'in' : 'out'}`], (!day.in && !outside) && classes.day_out_no, !day.selectedSame && range && [ (day.dayWeek === 1 || (day.selected && day.selectedIndex === 0) || (day.start && !outside)) && classes.dayStart, (day.dayWeek === 0 || (day.selected && day.selectedIndex === 1) || (day.end && !outside)) && classes.dayEnd, ((day.dayWeek === 1 || (day.selected && day.selectedIndex === 0) || (day.start && !outside)) && (day.dayWeek === 0 || (day.selected && day.selectedIndex === 1) || (day.end && !outside))) && classes.dayStartEnd, (day.selected && day.selectedIndex === 0 && !day.selectedSame) && classes.dayStartSelected, (day.selected && day.selectedIndex === 1 && !day.selectedSame) && classes.dayEndSelected ] ]), style: Object.assign(Object.assign({}, (range && !day.selected && !day.selectedSame && day.between ? { background: theme.methods.palette.color.value(undefined, 60, true, palette) } : undefined)), (range && day.selected && !day.selectedSame ? { color: theme.methods.palette.color.value(undefined, 60, true, palette) } : undefined)) }, { children: (0, utils_1.is)('function', renderDay) ? renderDay(day.amauiDate, propsDay, day, outside) : ((0, jsx_runtime_1.jsx)(PaginationItem, Object.assign({ tonal: tonal, color: 'inherit', size: size, InteractionProps: { background: false }, TypeProps: { version: size === 'large' ? 'b1' : size === 'regular' ? 'b2' : 'b3', priority: !day.selected ? !day.weekend ? 'primary' : 'secondary' : undefined }, "aria-label": (0, date_1.format)(day.amauiDate, 'DD-MM-YYYY') }, PaginationItemProps, { className: (0, style_react_1.classNames)([ (0, utils_2.staticClassName)('CalendarMonth', theme) && [ 'amaui-CalendarMonth-day-value', day.in && 'amaui-CalendarMonth-day-in', day.dayWeek && 'amaui-CalendarMonth-day-day-week', day.weekend && 'amaui-CalendarMonth-day-weekend', day.today && 'amaui-CalendarMonth-day-today', day.between && 'amaui-CalendarMonth-day-between', day.selected && 'amaui-CalendarMonth-day-selected', day.start && 'amaui-CalendarMonth-day-start', day.end && 'amaui-CalendarMonth-day-end' ], PaginationItemProps === null || PaginationItemProps === void 0 ? void 0 : PaginationItemProps.className, classes.dayValue ]), style: Object.assign(Object.assign(Object.assign({}, (day.today ? { boxShadow: `inset 0px 0px 0px 1px ${palette[40]}` } : undefined)), (day.selected ? { color: theme.methods.palette.color.value(undefined, 90, true, palette), backgroundColor: theme.methods.palette.color.value(undefined, 40, true, palette) } : undefined)), PaginationItemProps === null || PaginationItemProps === void 0 ? void 0 : PaginationItemProps.style) }, propsDay, { children: day.value }))) }), index_)); }) }), index))) }))) })); }; return ((0, jsx_runtime_1.jsxs)(Line, Object.assign({ ref: ref, gap: 0, direction: 'column', className: (0, style_react_1.classNames)([ (0, utils_2.staticClassName)('CalendarMonth', theme) && [ 'amaui-CalendarMonth-root', `amaui-CalendarMonth-size-${size}` ], className, classes.root, classes[`size_${size}`], classes[`move_${refs.move.current}`], !labels && classes.root_no_labels, disabled && classes.disabled ]) }, (isMonthFrom && { 'data-month-from': true }), (isMonthTo && { 'data-month-to': true }), other, { children: [labels && ((0, jsx_runtime_1.jsx)(Line, Object.assign({ gap: 0, direction: 'row', align: 'center', justify: 'space-between', className: (0, style_react_1.classNames)([ (0, utils_2.staticClassName)('CalendarMonth', theme) && [ 'amaui-CalendarMonth-day-names' ], classes.dayNames ]) }, { children: dayNames.map((day, index) => ((0, jsx_runtime_1.jsx)(Line, Object.assign({ direction: 'column', align: 'center', justify: 'center', className: (0, style_react_1.classNames)([ (0, utils_2.staticClassName)('CalendarMonth', theme) && [ 'amaui-CalendarMonth-day-name' ], classes.dayName, classes[`dayName_size_${size}`] ]) }, { children: (0, jsx_runtime_1.jsx)(Type, Object.assign({ version: size === 'large' ? 'b1' : size === 'regular' ? 'b2' : 'b3', align: 'center' }, DayNameProps, { children: renderDayNameMethod(day) })) }), index))) }))), noTransition && (getCalendar()), !noTransition && ((0, jsx_runtime_1.jsx)(Transitions, Object.assign({ id: refs.id.current, mode: 'in-out-follow', switch: true }, TransitionsProps, { children: (0, jsx_runtime_1.jsx)(Transition, Object.assign({ in: true }, TransitionProps, { children: getCalendar }), id) })))] }))); }); CalendarMonth.displayName = 'amaui-CalendarMonth'; exports.default = CalendarMonth;