@onesy/ui-react
Version:
UI for React
409 lines (408 loc) • 15.8 kB
JavaScript
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;