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