UNPKG

@onesy/ui-react

Version:
558 lines (554 loc) 24 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _utils = require("@onesy/utils"); var _styleReact = require("@onesy/style-react"); var _date = require("@onesy/date"); var _Line = _interopRequireDefault(require("../Line")); var _Type = _interopRequireDefault(require("../Type")); var _Tooltip = _interopRequireDefault(require("../Tooltip")); var _utils2 = require("../utils"); var _jsxRuntime = require("react/jsx-runtime"); const _excluded = ["date", "times", "events", "onOpen", "onTimeClick", "render", "statuses", "displayTime", "day", "className", "children"]; 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) { (0, _defineProperty2.default)(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; } const useStyle = (0, _styleReact.style)(theme => ({ root: { color: theme.methods.palette.color.value('primary', 10), background: theme.palette.background.default.primary, paddingLeft: '12px' }, weekDay: { width: '44px', height: '44px', borderRadius: '50%' }, today: { background: theme.palette.color.primary[40], color: '#fff' }, days: { overflow: 'auto hidden' }, day: { minWidth: '184px', height: '134vh', width: 'calc((100% / 7) - 106px)' }, dayBody: { position: 'relative', borderLeft: `1px solid ${theme.palette.light ? '#dadada' : '#575757'}` }, dayHeader: { height: '78px', padding: '4px' }, hours: { position: 'sticky', top: '0px', left: '0px', width: '44px', height: '134vh', flex: '0 0 auto', marginRight: '8px', background: theme.palette.background.default.primary, zIndex: 14 }, hourWrapper: { position: 'relative' }, hour: { width: '50px', alignSelf: 'flex-start', left: '0px', position: 'absolute', top: '0', marginTop: '-8px', zIndex: '40', borderRadius: theme.methods.shape.radius.value(0.5) }, guide: { position: 'absolute', left: '-9px', height: '1px', width: 'calc(100% + 9px)', background: theme.palette.light ? '#dadada' : '#575757' }, guidelineHour: { position: 'absolute', left: '0px', height: '2px', transform: 'translateY(-50%)', background: theme.palette.color.tertiary[50], zIndex: 14, '&::before': { position: 'absolute', content: "''", width: '12px', height: '12px', borderRadius: '50%', background: theme.palette.color.tertiary[50], top: '-5px', left: '-6.5px' } }, range: { position: 'absolute', left: 0, right: 0, cursor: 'pointer', zIndex: 1, transition: theme.methods.transitions.make('box-shadow'), overflow: 'hidden', '& > *': { whiteSpace: 'pre-wrap', transition: theme.methods.transitions.make('opacity') }, '& > .onesy-work-day-time': { opacity: 0 }, '&:hover': { zIndex: 14, boxShadow: theme.shadows.values.default[2], '& > .onesy-work-day-time': { opacity: 1 } } }, time: { position: 'relative', zIndex: 1, padding: '0px 2px', borderRadius: 2 } }), { name: 'onesy-CalendarWeek' }); const CalendarWeek = props_ => { var _theme$ui, _theme$ui2, _theme$elements, _theme$elements2, _theme$elements3; const theme = (0, _styleReact.useOnesyTheme)(); const l = theme.l; const props = _objectSpread(_objectSpread(_objectSpread({}, theme === null || theme === void 0 || (_theme$ui = theme.ui) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.elements) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.all) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.props) === null || _theme$ui === void 0 ? void 0 : _theme$ui.default), theme === null || theme === void 0 || (_theme$ui2 = theme.ui) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.elements) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.onesyCalendarWeek) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.props) === null || _theme$ui2 === void 0 ? void 0 : _theme$ui2.default), props_); const Line = (theme === null || theme === void 0 || (_theme$elements = theme.elements) === null || _theme$elements === void 0 ? void 0 : _theme$elements.Line) || _Line.default; const Type = (theme === null || theme === void 0 || (_theme$elements2 = theme.elements) === null || _theme$elements2 === void 0 ? void 0 : _theme$elements2.Type) || _Type.default; const Tooltip = (theme === null || theme === void 0 || (_theme$elements3 = theme.elements) === null || _theme$elements3 === void 0 ? void 0 : _theme$elements3.Tooltip) || _Tooltip.default; const { date, times: timesProps, events, onOpen, onTimeClick, render, statuses = {}, displayTime = true, day: dayProp, className, children } = props, other = (0, _objectWithoutProperties2.default)(props, _excluded); const { classes } = useStyle(); const [now, setNow] = _react.default.useState(new _date.OnesyDate()); const refs = { date: _react.default.useRef(date), displayTime: _react.default.useRef(displayTime), interval: _react.default.useRef(undefined), days: _react.default.useRef({}), overlaping: _react.default.useRef({}), statuses: _react.default.useRef(statuses) }; refs.date.current = date; refs.displayTime.current = displayTime; refs.statuses.current = statuses; const times = _react.default.useMemo(() => { if (events) { return [{ dates: { active: true, values: ((0, _utils.is)('array', events) ? events : [events]).filter(Boolean) } }]; } return ((0, _utils.is)('array', timesProps) ? timesProps : [timesProps]).filter(Boolean); }, [events, timesProps]); const rangeShade = theme.palette.light ? 60 : 40; _react.default.useEffect(() => { // 1 minute refs.interval.current = setInterval(() => { setNow(new _date.OnesyDate()); }, 60 * 1e3); return () => { clearInterval(refs.interval.current); }; }, []); const getDates = available => { var _available$dates; const values = ((_available$dates = available.dates) === null || _available$dates === void 0 ? void 0 : _available$dates.values) || []; return values.map(item => { if (item.entire) { if (item.from) { let from = new _date.OnesyDate(item.from); let to; if (['day', 'week', 'month', 'year'].includes(item.entire)) from = (0, _date.startOf)(from, 'day'); if (item.entire === 'minute') from = (0, _date.startOf)(from, 'minute'); if (item.entire === 'hour') from = (0, _date.startOf)(from, 'hour'); to = (0, _date.endOf)(from, item.entire); item.from = from.milliseconds; item.to = to.milliseconds; } } return item; }); }; const optionsStatus = _react.default.useMemo(() => { return [{ name: l('Working'), value: 'working' }, { name: l('Not working'), value: 'not-working' }, { name: l('On a break'), value: 'break' }, { name: l('Scheduled'), value: 'pending' }, { name: l('Rescheduled'), value: 'rescheduled' }, { name: l('Cancelled'), value: 'canceled' }, { name: l('Other'), value: 'other' }]; }, []); const getColor = item_0 => { let palette = theme.palette.color.neutral; if ((item_0 === null || item_0 === void 0 ? void 0 : item_0.status) === 'working') palette = theme.palette.color.success; if ((item_0 === null || item_0 === void 0 ? void 0 : item_0.status) === 'not-working') palette = theme.palette.color.info; if ((item_0 === null || item_0 === void 0 ? void 0 : item_0.status) === 'break') palette = theme.palette.color.warning; if ((item_0 === null || item_0 === void 0 ? void 0 : item_0.status) === 'pending') palette = theme.methods.color(_styleReact.colors.yellow[50]); if ((item_0 === null || item_0 === void 0 ? void 0 : item_0.status) === 'rescheduled') palette = theme.methods.color(_styleReact.colors.purple[50]); if ((item_0 === null || item_0 === void 0 ? void 0 : item_0.status) === 'canceled') palette = theme.palette.color.error; if ((item_0 === null || item_0 === void 0 ? void 0 : item_0.status) === 'other') palette = theme.palette.color.neutral; if (item_0.color) palette = theme.methods.color(item_0.color); return palette[rangeShade]; }; const itemToText = item_1 => { var _optionsStatus$find$n, _optionsStatus$find; if (item_1 === 'pending') return l('Scheduled'); if (item_1 === 'not-count-workout-session') return l(`Don't count workout session`); return (_optionsStatus$find$n = optionsStatus === null || optionsStatus === void 0 || (_optionsStatus$find = optionsStatus.find(itemStatus => itemStatus.value === item_1)) === null || _optionsStatus$find === void 0 ? void 0 : _optionsStatus$find.name) !== null && _optionsStatus$find$n !== void 0 ? _optionsStatus$find$n : l(item_1); }; const renderTimes = (day, valuesAll, weekly = true, itemDay) => { if (itemDay !== undefined && !(itemDay !== null && itemDay !== void 0 && itemDay.active)) return null; if (weekly) { const ends_at = itemDay !== null && itemDay !== void 0 && itemDay.ends_at ? new _date.OnesyDate(itemDay.ends_at) : undefined; if (ends_at) { const day_StartDay = (0, _date.startOf)(day, 'day'); const ends_at_StartDay = (0, _date.startOf)(ends_at, 'day'); if (day_StartDay.milliseconds >= ends_at_StartDay.milliseconds) return null; } } const dayStartOfDay = (0, _date.startOf)(day, 'day'); const dayDate = (0, _date.format)(day, _utils2.formats.date); const values_0 = valuesAll === null || valuesAll === void 0 ? void 0 : valuesAll.filter(item_2 => { const from_0 = new _date.OnesyDate(item_2.from); const fromStartOfDay = (0, _date.startOf)(from_0, 'day'); const to_0 = new _date.OnesyDate(item_2.to); const toStartOfDay = (0, _date.startOf)(to_0, 'day'); return [undefined, true].includes(refs.statuses.current[item_2.status || 'working']) && (weekly ? weekly : // from (dayDate === (0, _date.format)(from_0, _utils2.formats.date) || dayStartOfDay.milliseconds > fromStartOfDay.milliseconds) && ( // to dayDate === (0, _date.format)(to_0, _utils2.formats.date) || dayStartOfDay.milliseconds < toStartOfDay.milliseconds)); }); const elements = []; const renderTo = valueNew => { if (valueNew === '23:59') return '24:00'; return valueNew; }; values_0 === null || values_0 === void 0 || values_0.forEach((item_3, index) => { var _elementRendered$prop, _elementRendered$prop2; if (!(item_3.from && item_3.to)) return; let from_1 = new _date.OnesyDate(item_3.from); let to_1 = new _date.OnesyDate(item_3.to); if (!weekly) { const fromStartOfDay_0 = (0, _date.startOf)(from_1, 'day'); const toStartOfDay_0 = (0, _date.startOf)(to_1, 'day'); if ((dayStartOfDay === null || dayStartOfDay === void 0 ? void 0 : dayStartOfDay.milliseconds) > (fromStartOfDay_0 === null || fromStartOfDay_0 === void 0 ? void 0 : fromStartOfDay_0.milliseconds) && (dayDate === (0, _date.format)(to_1, _utils2.formats.date) || dayStartOfDay.milliseconds < toStartOfDay_0.milliseconds)) item_3.from = (0, _date.startOf)(from_1, 'day').milliseconds; if ((dayDate === (0, _date.format)(from_1, _utils2.formats.date) || dayStartOfDay.milliseconds > fromStartOfDay_0.milliseconds) && (dayStartOfDay === null || dayStartOfDay === void 0 ? void 0 : dayStartOfDay.milliseconds) < (toStartOfDay_0 === null || toStartOfDay_0 === void 0 ? void 0 : toStartOfDay_0.milliseconds)) item_3.to = (0, _date.endOf)(to_1, 'day').milliseconds; } from_1 = new _date.OnesyDate(item_3.from); to_1 = new _date.OnesyDate(item_3.to); const itemDate = (0, _date.format)(day, _utils2.formats.date); const top = +(100 * ((from_1.hour * 60 + from_1.minute) / (24 * 60))).toFixed(4); const bottom = +(100 - 100 * ((to_1.hour * 60 + (to_1.minute === 59 ? 60 : to_1.minute)) / (24 * 60))).toFixed(4); if (!refs.days.current[itemDate]) refs.days.current[itemDate] = []; if (!refs.overlaping.current[itemDate]) refs.overlaping.current[itemDate] = []; const bottom_ = 100 - bottom; // intersections const overlaps = refs.days.current[itemDate].filter(([itemTop, itemBottom]) => { return !(top >= itemBottom || bottom_ <= itemTop); }); let level = 0; if (overlaps.length) { level = refs.overlaping.current[itemDate].filter(([itemTop_0, itemBottom_0]) => { return !(top >= itemBottom_0 || bottom_ <= itemTop_0); }).length + 1; refs.overlaping.current[itemDate].push([top, bottom_]); } refs.days.current[itemDate].push([top, bottom_]); const minimal = 100 - bottom - top < 5; const background = getColor(item_3); const WrapperElement = item_3.status ? Tooltip : _react.default.Fragment; const WrapperElementProps = item_3.status ? { name: (0, _utils.cleanValue)(itemToText(item_3.status), { capitalize: true }), color: getColor(item_3) } : undefined; const itemProps = { onClick: event => onOpen(_objectSpread(_objectSpread({}, item_3), {}, { day, weekly }), event), className: classes.range }; const style = _objectSpread({ top: `${top}%`, bottom: `${bottom}%`, color: theme.methods.palette.color.text(background), background, left: `calc(0px + ${level * 10}px)` }, top === 0 && bottom === 0 && { border: 'none' }); const elementRendered = (0, _utils.is)('function', render) ? render(item_3, dayProp ? 'day' : 'week') : /*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, _objectSpread(_objectSpread({ gap: 0.5, align: "center", justify: "center" }, itemProps), {}, { children: [!minimal && refs.displayTime.current && /*#__PURE__*/(0, _jsxRuntime.jsxs)(Type, { version: "l2", weight: 300, align: "center", className: classes.time, style: { background: getColor(item_3) }, children: [(0, _date.format)(from_1, 'hh:mm a', { l }), " - ", renderTo((0, _date.format)(to_1, 'hh:mm a', { l }))] }), item_3.description && /*#__PURE__*/(0, _jsxRuntime.jsx)(Type, { version: "b2", dangerouslySetInnerHTML: { __html: (0, _utils.textToInnerHTML)(item_3.description) }, style: { maxHeight: 24, maxWidth: '90%' } })] }), index); elements.push(/*#__PURE__*/(0, _jsxRuntime.jsx)(WrapperElement, _objectSpread(_objectSpread({}, WrapperElementProps), {}, { children: /*#__PURE__*/_react.default.cloneElement(elementRendered, _objectSpread(_objectSpread({}, itemProps), {}, { className: (0, _styleReact.classNames)([itemProps.className, (_elementRendered$prop = elementRendered.props) === null || _elementRendered$prop === void 0 ? void 0 : _elementRendered$prop.className]), style: _objectSpread(_objectSpread({}, style), (_elementRendered$prop2 = elementRendered.props) === null || _elementRendered$prop2 === void 0 ? void 0 : _elementRendered$prop2.style) })) }))); }); return elements; }; const onTimeClickMethod = (itemDay_0, event_0) => { const rect = event_0.currentTarget.getBoundingClientRect(); const relativeY = event_0.clientY - rect.top; const relativePercentage = relativeY / rect.height * 100; let timeDate = (0, _date.set)(Math.floor(24 * (relativePercentage / 100)), 'hour', itemDay_0); // start of the hour timeDate = (0, _date.startOf)(timeDate, 'hour'); onTimeClick === null || onTimeClick === void 0 || onTimeClick(timeDate, dayProp ? 'day' : 'week', event_0); }; const timesUI = dayDate_0 => { // clean up refs.days.current = {}; refs.overlaping.current = {}; const day_0 = dayDate_0.dayWeek === 0 ? 7 : dayDate_0.dayWeek; return /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, { children: times.map(item_4 => { var _day_; return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [item_4.weekly && renderTimes(dayDate_0, (_day_ = item_4.weekly.days[day_0]) === null || _day_ === void 0 ? void 0 : _day_.values, true, item_4.weekly.days[day_0]), item_4.dates && renderTimes(dayDate_0, getDates(item_4), false)] }); }) }); }; const hours = _react.default.useMemo(() => { return Array.from({ length: 24 }).map((item_5, index_0) => (0, _date.set)(index_0, 'hour', date)); }, [date]); const days = _react.default.useMemo(() => { const weekStartDate = (0, _date.set)(4, 'hour', (0, _date.startOf)(date, 'week')); return Array.from({ length: 7 }).map((_, index_1) => (0, _date.add)(index_1, 'day', weekStartDate)); }, [date]); return /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, _objectSpread(_objectSpread({ gap: 1.5, flex: true, fullWidth: true, className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('CalendarWeek', theme) && ['onesy-CalendarWeek-root', dayProp && 'onesy-CalendarWeek-prop-day'], className, classes.root]) }, other), {}, { children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, { gap: 0, direction: "row", align: "stretch", flex: true, fullWidth: true, className: classes.days, children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, { gap: 0, align: "center", fullWidth: true, className: (0, _styleReact.classNames)(['onesy-hours', classes.hours]), children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Line, { className: classes.dayHeader }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, { gap: 0, flex: true, fullWidth: true, className: classes.hourWrapper, children: hours.map((itemHour, index_2) => /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, { gap: 1, align: "unset", className: classes.hour, style: { top: `${100 / 24 * index_2}%` }, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Type, { version: "b3", whiteSpace: "nowrap", children: (0, _date.format)(itemHour, 'h A', { l }) }) }, index_2)) })] }), dayProp && /*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, { gap: 0, direction: "column", align: "center", flex: true, className: (0, _styleReact.classNames)(['onesy-day', classes.day]), children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, { gap: 0, align: "center", fullWidth: true, className: classes.dayHeader, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Type, { version: "l1", weight: 200, children: (0, _date.format)(date, 'd', { l }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, { align: "center", justify: "center", className: (0, _styleReact.classNames)([classes.weekDay, date.year === now.year && date.dayYear === now.dayYear && classes.today]), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Type, { version: "h3", weight: 400, align: "center", children: (0, _date.format)(date, 'D', { l }) }) })] }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, { className: classes.dayBody, flex: true, fullWidth: true, onClick: event_1 => onTimeClickMethod(date, event_1), children: [timesUI(date), hours.map((itemGuide, indexGuide) => /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, { className: classes.guide, fullWidth: true, style: { top: `${100 / 24 * indexGuide}%` } }, indexGuide)), (0, _date.format)(now, _utils2.formats.date) === (0, _date.format)(date, _utils2.formats.date) && /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, { className: classes.guidelineHour, fullWidth: true, style: { top: `${(now.hour * 60 + now.minute) / (24 * 60) * 100}%` } })] })] }), !dayProp && days.map((itemDay_1, index_3) => { return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, { gap: 0, direction: "column", align: "center", flex: true, className: (0, _styleReact.classNames)(['onesy-day', classes.day]), children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, { gap: 0, align: "center", fullWidth: true, className: classes.dayHeader, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Type, { version: "l1", weight: 200, children: (0, _date.format)(itemDay_1, 'd', { l }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, { align: "center", justify: "center", className: (0, _styleReact.classNames)([classes.weekDay, itemDay_1.year === now.year && itemDay_1.dayYear === now.dayYear && classes.today]), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Type, { version: "h3", weight: 400, align: "center", children: (0, _date.format)(itemDay_1, 'D', { l }) }) })] }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, { className: classes.dayBody, flex: true, fullWidth: true, onClick: event_2 => onTimeClickMethod(itemDay_1, event_2), children: [timesUI(itemDay_1), hours.map((itemGuide_0, indexGuide_0) => /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, { className: classes.guide, fullWidth: true, style: { top: `${100 / 24 * indexGuide_0}%` } }, indexGuide_0)), (0, _date.format)(now, _utils2.formats.date) === (0, _date.format)(itemDay_1, _utils2.formats.date) && /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, { className: classes.guidelineHour, fullWidth: true, style: { top: `${(now.hour * 60 + now.minute) / (24 * 60) * 100}%` } })] })] }, index_3); })] }) })); }; CalendarWeek.displayName = 'onesy-CalendarWeek'; var _default = exports.default = CalendarWeek;