@progress/kendo-react-scheduler
Version:
React Scheduler brings the functionality of Outlook's Calendar to a single UI component. KendoReact Scheduler package
214 lines (213 loc) • 9.37 kB
JavaScript
/**
* @license
*-------------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the package root for more information
*-------------------------------------------------------------------------------------------
*/
import * as t from "react";
import { BaseView as re } from "../../components/BaseView.mjs";
import { MS_PER_DAY as oe, MS_PER_MINUTE as ne, ZonedDate as z, Day as B, getDate as ae, addDays as ie } from "@progress/kendo-date-math";
import { HorizontalResourceIterator as L } from "../common/HorizontalResourceIterator.mjs";
import { TimelineViewRowContent as se } from "./TimelineViewRowContent.mjs";
import { TimelineViewAllEventsRowContent as me } from "./TimelineViewAllEventsRowContent.mjs";
import { VerticalResourceIterator as Z } from "../common/VerticalResourceIterator.mjs";
import { isInTimeRange as S, mapItemsToSlots as le, mapSlotsToItems as ce, toUTCDateTime as H, isInDaysRange as de, intersects as X, last as Y, first as j, orderSort as ue } from "../../utils/index.mjs";
import { classNames as De } from "@progress/kendo-react-common";
import { toRanges as Te } from "../../services/rangeService.mjs";
import { toSlots as fe } from "../../services/slotsService.mjs";
import { toOccurrences as ge } from "../../services/occurrenceService.mjs";
import { toItems as ke } from "../../services/itemsService.mjs";
import { SchedulerEditSlot as we } from "../../slots/SchedulerEditSlot.mjs";
import { BORDER_WIDTH as he } from "../../constants/index.mjs";
import { useInternationalization as Se } from "@progress/kendo-react-intl";
import { SchedulerEditItem as Ee } from "../../items/SchedulerEditItem.mjs";
import { useSchedulerPropsContext as ye, useSchedulerDataContext as Re, useSchedulerOrientationContext as Ce, useSchedulerGroupsContext as We, useSchedulerDateRangeContext as ze, useSchedulerFieldsContext as ve } from "../../context/SchedulerContext.mjs";
import { SchedulerResourceIteratorContext as A } from "../../context/SchedulerResourceIteratorContext.mjs";
import { CurrentTimeMarker as q } from "../../components/CurrentTimeMarket.mjs";
import { DateHeaderCell as Me } from "../../components/DateHeaderCell.mjs";
import { TimeHeaderCell as xe } from "../../components/TimeHeaderCell.mjs";
import { useCellSync as Ie } from "../../hooks/useCellSync.mjs";
import { useRowSync as be } from "../../hooks/useRowSync.mjs";
const Ae = "t", He = 0, nt = (e) => {
const { group: D, timezone: n, resources: T } = ye(), f = t.useRef(null), v = t.useRef(null), E = e.editItem || Ee, y = e.editSlot || we, g = t.useRef(null), [R] = Re(), k = Ce(), h = We(), i = ze(), N = ve(), C = Se(), W = e.showWorkHours, _ = e.slotDivisions || m.slotDivisions, M = e.slotDuration || m.slotDuration, J = e.workWeekStart || m.workWeekStart, K = e.workWeekEnd || m.workWeekEnd, x = C.parseDate(
e.workDayStart || e.isWorkDayStart || m.isWorkDayStart
), I = C.parseDate(
e.workDayEnd || e.isWorkDayEnd || m.isWorkDayEnd
), $ = C.parseDate(e.startTime || m.startTime), F = C.parseDate(e.endTime || m.endTime), l = t.useMemo(
() => W ? x : $,
[W, x, $]
), c = t.useMemo(() => W ? I : F, [W, I, F]), o = t.useMemo(
() => Te(i, { step: oe, timezone: n }),
[i.start.getTime(), i.end.getTime(), n]
), s = t.useMemo(
() => fe(i, { step: M / _ * ne }, { groups: h, ranges: o }).filter(
(r) => S(r.zonedStart, l, c) || l.getTime() === c.getTime()
),
[
h,
o,
i.start.getTime(),
i.end.getTime(),
n,
M,
_,
l.getTime(),
c.getTime()
]
), U = t.useMemo(
() => ge(R, { dateRange: i, fields: N, timezone: n }),
[R, i.start.getTime(), i.end.getTime(), N, n]
), d = t.useMemo(
() => ke(U, { timezone: n }, { groups: h, ranges: o }).filter(
(r) => l.getTime() === c.getTime() || S(r.zonedStart, l, c) || S(r.zonedEnd, l, c) || S(
new Date(r.zonedEnd.getTime() - (r.zonedEnd.getTime() - r.zonedStart.getTime()) / 2),
l,
c
)
),
[U, n, h, o, l.getTime(), c.getTime()]
);
t.useMemo(() => le(d, s, !0), [d, s]), t.useMemo(() => ce(d, s, !0), [d, s]);
const V = (k === "horizontal" ? s.length : s.length / h.length) * ((e.columnWidth || m.columnWidth) + he), O = /* @__PURE__ */ t.createElement(A.Consumer, null, () => /* @__PURE__ */ t.createElement(t.Fragment, null, /* @__PURE__ */ t.createElement("div", { className: "k-scheduler-row" }, o.map((r, w) => /* @__PURE__ */ t.createElement(
Me,
{
as: e.dateHeaderCell,
key: w,
date: r.zonedStart,
start: r.start,
end: r.end,
format: "m"
}
))), /* @__PURE__ */ t.createElement("div", { className: "k-scheduler-row", ref: f }, o.map((r, w) => s.filter((a) => a.group.index === He && a.range.index === w).map(
(a) => a.zonedStart.getMinutes() % M === 0 ? /* @__PURE__ */ t.createElement(
xe,
{
key: a.index,
as: e.timeHeaderCell,
format: Ae,
date: a.zonedStart,
start: a.zonedStart,
end: a.zonedEnd
}
) : null
))))), P = /* @__PURE__ */ t.createElement(A.Consumer, null, ({ groupIndex: r }) => /* @__PURE__ */ t.createElement("div", { className: "k-scheduler-row" }, o.map((w, a) => s.filter((u) => u.group.index === r && u.range.index === a).map((u, G, b) => {
const ee = z.fromUTCDate(
H(u.zonedStart),
n
), te = de(
ee.getDay(),
J,
K
);
return /* @__PURE__ */ t.createElement(
y,
{
key: `${u.start.getTime()}:${u.group.index}`,
slot: e.slot,
viewSlot: e.viewSlot,
...u,
form: e.form,
onDataAction: e.onDataAction,
isWorkHour: S(u.zonedStart, x, I),
isWorkDay: te,
col: k === "horizontal" ? a * b.length + G + b.length * o.length * (r || 0) : a * b.length + G,
row: k === "horizontal" ? 0 : r || 0,
expandable: !0,
editable: e.editable
}
);
})))), Q = t.useMemo(() => De("k-scheduler-timelineview", e.className), [e.className]);
Ie({
element: g,
selector: ".k-resource-cell",
attribute: "data-depth-index",
explicitDepth: !0
});
const p = g.current ? g.current.closest(".k-scheduler-layout") : null;
return be({
element: p,
selector: ".k-resource-row",
horizontalAttribute: "data-depth-index",
verticalAttribute: "data-resource-index",
applyTo: ".k-resource-cell",
syncHeight: d && !d.length
}), /* @__PURE__ */ t.createElement(
re,
{
ref: g,
id: e.id,
style: { ...e.style },
className: Q,
props: e,
slots: s,
ranges: o
},
/* @__PURE__ */ t.createElement("div", { className: "k-scheduler-head", style: { width: V } }, k === "horizontal" ? /* @__PURE__ */ t.createElement(
L,
{
nested: !0,
group: D,
resources: T,
rowContent: se
},
O
) : /* @__PURE__ */ t.createElement(Z, { wrapGroup: !0, group: D, resources: T }, O)),
/* @__PURE__ */ t.createElement("div", { className: "k-scheduler-body", style: { width: V }, ref: v }, k === "horizontal" ? /* @__PURE__ */ t.createElement(
L,
{
group: D,
resources: T,
rowContent: me
},
P,
/* @__PURE__ */ t.createElement(A.Consumer, null, ({ groupIndex: r }) => e.currentTimeMarker && X(j(o).start, Y(o).end, /* @__PURE__ */ new Date(), /* @__PURE__ */ new Date(), !0) && /* @__PURE__ */ t.createElement(q, { groupIndex: r, attachArrow: f, vertical: !0 }))
) : /* @__PURE__ */ t.createElement(Z, { nested: !0, wrapGroup: !0, group: D, resources: T }, P), k === "vertical" && e.currentTimeMarker && X(j(o).start, Y(o).end, /* @__PURE__ */ new Date(), /* @__PURE__ */ new Date(), !0) && /* @__PURE__ */ t.createElement(q, { attachArrow: f, vertical: !0 }), d.sort(ue).map((r, w) => /* @__PURE__ */ t.createElement(
E,
{
key: r.isRecurring ? `${r.uid}:${r.group.index}:${r.range.index}:${r.originalStart}` : `${r.uid}:${r.group.index}:${r.range.index}`,
...r,
format: "t",
form: e.form,
onDataAction: e.onDataAction,
item: e.item,
viewItem: e.viewItem,
editable: e.editable,
ignoreIsAllDay: !0,
vertical: !1,
isLast: w === d.length - 1
}
)))
);
}, Ne = ({ date: e, numberOfDays: D = 1, timezone: n }) => {
const T = z.fromLocalDate(e, n), f = ae(T), v = ie(f, D), E = z.fromUTCDate(H(f), n), y = z.fromUTCDate(H(v), n), g = new Date(E.getTime()), R = new Date(y.getTime());
return {
start: g,
end: R,
zonedStart: E,
zonedEnd: y
};
}, m = {
name: "multi-day-timeline",
title: "Multi Day Timeline",
currentTimeMarker: !0,
dateRange: Ne,
selectedDateFormat: "{0:D} - {1:D}",
selectedShortDateFormat: "{0:d} - {1:d}",
numberOfDays: 1,
startTime: "00:00",
endTime: "00:00",
isWorkDayStart: "8:00",
isWorkDayEnd: "17:00",
workWeekStart: B.Monday,
workWeekEnd: B.Friday,
slotDivisions: 2,
slotDuration: 60,
// showCurrentTime: true // TODO: Phase 2
defaultShowWorkHours: !0,
columnWidth: 100
};
export {
nt as MultiDayTimelineView,
m as multiDayTimelineViewDefaultProps
};