UNPKG

@onesy/ui-react

Version:
409 lines (408 loc) 15.8 kB
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; const _excluded = ["value", "dateProperty", "menuOpen", "menuOpenDefault", "timeMenuOpen", "timeMenuOpenDefault", "onChange", "onRemove", "closeOnChange", "startBottom", "endBottom", "noRemove", "TimePickerProps", "children", "className"]; 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; } import React from 'react'; import { hash, is } from '@onesy/utils'; import { classNames, style, useOnesyTheme } from '@onesy/style-react'; import { OnesyDate, add, diff, format, is as isDate } from '@onesy/date'; import IconMaterialScheduleRounded from '@onesy/icons-material-rounded-react/IconMaterialScheduleW100'; import IconMaterialWbSunnyRounded from '@onesy/icons-material-rounded-react/IconMaterialWbSunnyW100'; import IconMaterialWbTwilightRounded from '@onesy/icons-material-rounded-react/IconMaterialWbTwilightW100'; import IconMaterialCounter7Rounded from '@onesy/icons-material-rounded-react/IconMaterialCounter7W100'; import IconMaterialCalendarMonthRounded from '@onesy/icons-material-rounded-react/IconMaterialCalendarMonthW100'; import IconMaterialDeleteRounded from '@onesy/icons-material-rounded-react/IconMaterialDeleteW100'; import MenuElement from '../Menu'; import CalendarElement from '../Calendar'; import LineElement from '../Line'; import TooltipElement from '../Tooltip'; import IconButtonElement from '../IconButton'; import ButtonElement from '../Button'; import ListItemElement from '../ListItem'; import PaginationItemElement from '../PaginationItem'; import TimePickerElement from '../TimePicker'; import TypeElement from '../Type'; import { formats, staticClassName } from '../utils'; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; const useStyle = style(theme => ({ root: {}, weekday: { cursor: 'pointer' }, dayValue: { '&:hover': { boxShadow: 'inset 0px 0px 0px 1px currentColor' } }, dayValueRepeating: { background: theme.palette.background.secondary.quaternary }, calendar: { boxShadow: '0px 4px 32px 0px rgba(0, 0, 0, 0.04)', '& .onesy-Calendar-header': { paddingTop: '0px' }, '& .onesy-Calendar-calendars': { paddingBottom: '4px' } }, calendarShortcuts: { padding: '14px 16px 2px' }, end: { padding: '0 12px 12px', '& .onesy-ListItem-root': { minHeight: '24px !important', padding: '0 8px', borderRadius: theme.methods.shape.radius.value(0.5, 'px') } }, minorMenu: { '& .onesy-List-root': { width: '100%' } }, repeatEndMenu: { '& .onesy-List-root': { width: '100%' } }, menuMore: { width: '100%', padding: '12px', borderRadius: theme.methods.shape.radius.value(0.5, 'px'), '& .onesy-TextField-input-wrapper': { paddingBlock: '12px', height: '40px' }, '& .onesy-TextField-icon-end': { paddingBlock: '8px' } }, item: { '& .onesy-ListItem-root': { minHeight: '30px !important' }, '&.onesy-Surface-root': { background: 'transparent' } }, iconInactive: { opacity: '0', pointerEvents: 'none' }, menuFooter: { marginTop: '8px' } }), { name: 'onesy-CalendarMenu' }); const CalendarMenu = props_ => { const theme = useOnesyTheme(); const l = theme.l; const props = _objectSpread(_objectSpread(_objectSpread({}, theme?.ui?.elements?.all?.props?.default), theme?.ui?.elements?.onesyCalendarAvailability?.props?.default), props_); const Line = theme?.elements?.Line || LineElement; const Menu = theme?.elements?.Menu || MenuElement; const Calendar = theme?.elements?.Calendar || CalendarElement; const Tooltip = theme?.elements?.Tooltip || TooltipElement; const IconButton = theme?.elements?.IconButton || IconButtonElement; const Button = theme?.elements?.Button || ButtonElement; const ListItem = theme?.elements?.ListItem || ListItemElement; const PaginationItem = theme?.elements?.PaginationItem || PaginationItemElement; const TimePicker = theme?.elements?.TimePicker || TimePickerElement; const Type = theme?.elements?.Type || TypeElement; const { value, dateProperty = 'ends_at', menuOpen: menuOpen_, menuOpenDefault, timeMenuOpen: timeMenuOpen_, timeMenuOpenDefault, onChange: onChange_, onRemove: onRemove_, closeOnChange = true, startBottom, endBottom, noRemove, TimePickerProps, children, className } = props, other = _objectWithoutProperties(props, _excluded); const { classes } = useStyle(); const [menuOpen, setMenuOpen] = React.useState(menuOpenDefault !== undefined ? menuOpenDefault : menuOpen_ !== undefined ? menuOpen_ : false); const [timeMenuOpen, setTimeMenuOpen] = React.useState(timeMenuOpenDefault !== undefined ? timeMenuOpenDefault : timeMenuOpen_ !== undefined ? timeMenuOpen_ : false); const refs = { value: React.useRef(value), dateProperty: React.useRef(dateProperty), time: React.useRef(undefined), repeat: React.useRef(undefined), repeatEnd: React.useRef(undefined), onChange: React.useRef(onChange_), repeatCount: React.useRef({}) }; refs.dateProperty.current = dateProperty; refs.value.current = value; refs.onChange.current = onChange_; const onChange = async (...args) => { if (is('function', onChange_)) onChange_(...args); }; React.useEffect(() => { if (menuOpen !== menuOpen_ && menuOpen_ !== undefined) setMenuOpen(menuOpen_); }, [menuOpen_]); React.useEffect(() => { if (timeMenuOpen !== timeMenuOpen_ && timeMenuOpen_ !== undefined) setTimeMenuOpen(timeMenuOpen_); }, [timeMenuOpen_]); const onMenuOpen = () => { setMenuOpen(true); }; const onMenuClose = () => { setMenuOpen(false); }; const onTimeMenuOpen = () => { setTimeMenuOpen(true); }; const onTimeMenuClose = () => { setTimeMenuOpen(false); }; const onChangeDate = valueNew => { if (closeOnChange) onMenuClose(); onChange(refs.dateProperty.current, valueNew?.milliseconds); }; const onChangeTime = valueNew_0 => { onTimeMenuClose(); onChange(refs.dateProperty.current, valueNew_0?.milliseconds); }; const onRemove = () => { if (is('function', onRemove_)) onRemove_(value); }; React.useEffect(() => { // reset refs.repeatCount.current = {}; }, [hash(value)]); const iconProps = { size: 'regular' }; const shortcuts = [{ name: l('Today'), onClick: () => onChangeDate(new OnesyDate()), icon: /*#__PURE__*/_jsx(IconMaterialWbSunnyRounded, _objectSpread({}, iconProps)) }, { name: l('Tomorrow'), onClick: () => onChangeDate(add(1, 'day')), icon: /*#__PURE__*/_jsx(IconMaterialWbTwilightRounded, _objectSpread({}, iconProps)) }, { name: l('7 days'), onClick: () => onChangeDate(add(7, 'day')), icon: /*#__PURE__*/_jsx(IconMaterialCounter7Rounded, _objectSpread({}, iconProps)) }, { name: l('1 month'), onClick: () => onChangeDate(add(1, 'month')), icon: /*#__PURE__*/_jsx(IconMaterialCalendarMonthRounded, _objectSpread({}, iconProps)) }]; const onClear = event => { onChange(refs.dateProperty.current, null); }; const date = React.useMemo(() => new OnesyDate(value?.[dateProperty] || undefined), [value, dateProperty]); const repeats = day => { if (!value?.repeat?.active) return; let unit = value?.repeat?.unit; let valueRepeat = value?.repeat?.value; if (unit === 'day') unit = 'days'; if (unit === 'week') { unit = 'days'; valueRepeat *= 7; } if (unit === 'month') unit = 'months'; let difference = diff(day, date, unit); let repeating = false; if (['day', 'week'].includes(value?.repeat?.unit)) { if (value?.repeat.unit === 'week' && !!value?.repeat?.weekdays?.length) { difference = diff(day, date.dayWeek === 0 ? add(-1, 'week', date) : date, 'weeks'); if (day.dayWeek === 0) difference -= 1; const modulus = difference % value?.repeat?.value; repeating = isDate(day, 'after or same', date) && !modulus && value?.repeat.weekdays?.includes(day.dayWeek); } else { const modulus_0 = difference % valueRepeat; repeating = isDate(day, 'after or same', date) && !modulus_0; } } if (['month'].includes(value?.repeat?.unit)) { const modulus_1 = difference % valueRepeat; const monthDate = add(difference, 'month', date); repeating = monthDate.year === day.year && monthDate.dayYear === day.dayYear && !modulus_1; } if (['year'].includes(value?.repeat?.unit)) { const modulus_2 = difference % valueRepeat; const yearDate = add(difference, 'year', date); repeating = isDate(day, 'after', date) && yearDate.year === day.year && yearDate.dayYear === day.dayYear && !modulus_2; } if (value?.repeat?.skip_weekends && [0, 6].includes(day.dayWeek)) repeating = false; if (repeating) { const formatted = format(day, formats.date); if (value?.repeat?.ends?.active) { // date if (value?.repeat.ends.version === 'date') { const endsDate = new OnesyDate(value?.repeat.ends.value); repeating = repeating && (day.year < endsDate.year || day.year === endsDate.year && (day.month < endsDate.month || day.month === endsDate.month && day.dayYear <= endsDate.dayYear)); } } if (repeating) { if (!refs.repeatCount.current[value?.id]) refs.repeatCount.current[value?.id] = []; if (!refs.repeatCount.current[value?.id].includes(formatted)) refs.repeatCount.current[value?.id].push(formatted); } if (value?.repeat?.ends?.active) { const indexRepeated = refs.repeatCount.current[value?.id]?.indexOf(formatted); // count if (value?.repeat.ends.version === 'count') repeating = repeating && value?.repeat.ends.value >= (indexRepeated === -1 ? 0 : indexRepeated) + 1; } repeating = !value?.repeat.ends?.active || repeating; } return repeating; }; const onContextMenu = event_0 => { event_0.stopPropagation(); }; const palette = theme.palette.color.primary; return /*#__PURE__*/_jsx(Menu, _objectSpread(_objectSpread({ open: menuOpen, onOpen: onMenuOpen, onClose: onMenuClose, onContextMenu: onContextMenu, name: /*#__PURE__*/_jsx(Calendar, { tonal: true, color: "themed", calendarDefault: date, start: /*#__PURE__*/_jsx(Line, { gap: 1, direction: "row", align: "center", justify: "center", className: classes.calendarShortcuts, children: shortcuts.map((item, index) => /*#__PURE__*/_jsx(Tooltip, { name: item.name, children: /*#__PURE__*/_jsx(IconButton, { onClick: () => { item.onClick(); onMenuClose(); }, size: "small", children: item.icon }) }, index)) }), value: value?.[dateProperty] ? date : null, onChange: onChangeDate, onContextMenu: onContextMenu, size: "small", end: /*#__PURE__*/_jsxs(Line, { gap: 0.5, fullWidth: true, className: classes.end, children: [startBottom, value?.[dateProperty] && /*#__PURE__*/_jsx(Menu, { open: timeMenuOpen, onOpen: onTimeMenuOpen, onClose: onTimeMenuClose, name: () => /*#__PURE__*/_jsx(Line, { gap: 1, align: "center", fullWidth: true, children: /*#__PURE__*/_jsx(TimePicker, _objectSpread({ value: date, onChange: onChangeTime, clear: false, MainProps: { elevation: theme.palette.light ? 8 : 0 }, size: "small", static: true }, TimePickerProps)) }), className: classNames([classes.timeMenu, 'onesy-time']), style: { width: refs.time.current?.clientWidth }, children: /*#__PURE__*/_jsx(ListItem, { ref: refs.time, start: /*#__PURE__*/_jsx(IconMaterialScheduleRounded, _objectSpread({}, iconProps)), primary: /*#__PURE__*/_jsx(Type, { version: "b2", color: "inherit", children: format(date, 'HH:mm', { l }) }), startAlign: "center", size: "small", button: true, Component: "div", className: classes.item }) }), endBottom, /*#__PURE__*/_jsxs(Line, { gap: 0.4, direction: "row", align: "center", justify: "space-between", fullWidth: true, className: classes.menuFooter, children: [/*#__PURE__*/_jsx(Button, { onClick: onClear, version: "text", size: "small", disabled: !value?.[dateProperty], children: l('Clear') }), !noRemove && /*#__PURE__*/_jsx(Tooltip, { name: l('Remove'), children: /*#__PURE__*/_jsx(IconButton, { size: "small", onClick: onRemove, children: /*#__PURE__*/_jsx(IconMaterialDeleteRounded, _objectSpread({}, iconProps)) }) })] })] }), CalendarMonthProps: { renderDay: (dayOnesyDate, propsDay, day_0, outside) => { const repeating_0 = repeats(dayOnesyDate); return /*#__PURE__*/_jsx(PaginationItem, _objectSpread(_objectSpread({ tonal: true, color: "inherit", size: "small", InteractionProps: { background: false }, TypeProps: { version: 'b3', priority: !day_0.selected ? !day_0.weekend ? 'primary' : 'secondary' : undefined }, "aria-label": format(dayOnesyDate, 'DD-MM-YYYY', { l }), className: classNames([classes.dayValue, repeating_0 && classes.dayValueRepeating]), style: _objectSpread(_objectSpread({}, day_0.today ? { boxShadow: `inset 0px 0px 0px 1px ${palette[40]}` } : undefined), day_0.selected ? { color: theme.methods.palette.color.value(undefined, 90, true, palette), backgroundColor: theme.methods.palette.color.value(undefined, 40, true, palette) } : undefined) }, propsDay), {}, { children: day_0.value })); }, noTransition: true }, className: classNames(['onesy-ObjectCalendar-root', classes.calendar]) }), ClickListenerProps: { contextMenu: false }, className: classNames([staticClassName('CalendarMenu', theme) && ['onesy-CalendarMenu-root'], className, classes.root]) }, other), {}, { children: children })); }; CalendarMenu.displayName = 'onesy-CalendarMenu'; export default CalendarMenu;