@tensor_1/react 2.32.0 → 2.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/dist/SchedulingCalendar-C4XVbqZr.d.ts +339 -0
- package/dist/components/SchedulingCalendar.d.ts +4 -241
- package/dist/components/SchedulingCalendar.js +73 -14
- package/dist/components/SchedulingTimeGrid.d.ts +4 -0
- package/dist/components/SchedulingTimeGrid.js +521 -0
- package/dist/components/SchedulingTimeline.d.ts +1 -1
- package/dist/index.cjs +1144 -471
- package/dist/index.d.cts +174 -7
- package/dist/index.d.ts +2 -2
- package/dist/index.js +15 -1
- package/dist/labels-context.d.ts +1 -1
- package/dist/scheduling-calendar-model.d.ts +104 -1
- package/dist/scheduling-calendar-model.js +95 -1
- package/package.json +1 -1
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { addCalendarDays, addCalendarMonths, buildMonthGrid, cachedDateTimeFormat, startOfMonth, zonedDateKey, zonedTimeOfDay } from "../calendar-model.js";
|
|
5
|
-
import { itemDaySpan, layoutMonthSpans } from "../scheduling-calendar-model.js";
|
|
5
|
+
import { TOP_LANE_CROSS_MIDNIGHT_MINUTES, itemDaySpan, layoutMonthSpans } from "../scheduling-calendar-model.js";
|
|
6
|
+
import { SchedulingTimeGrid } from "./SchedulingTimeGrid.js";
|
|
6
7
|
import { cx } from "../cx.js";
|
|
7
8
|
import { useUixLabels } from "../labels-context.js";
|
|
8
9
|
import { StatusPill } from "./StatusPill.js";
|
|
@@ -15,9 +16,12 @@ const DEFAULT_SCHEDULING_CALENDAR_LABELS = {
|
|
|
15
16
|
nextMonth: "Next month",
|
|
16
17
|
previousWeek: "Previous week",
|
|
17
18
|
nextWeek: "Next week",
|
|
19
|
+
previousDay: "Previous day",
|
|
20
|
+
nextDay: "Next day",
|
|
18
21
|
viewGroup: "Calendar view",
|
|
19
22
|
viewMonth: "Month",
|
|
20
23
|
viewWeek: "Week",
|
|
24
|
+
viewDay: "Day",
|
|
21
25
|
viewAgenda: "Agenda",
|
|
22
26
|
loading: "Loading schedule\u2026",
|
|
23
27
|
retry: "Try again",
|
|
@@ -34,14 +38,25 @@ const DEFAULT_SCHEDULING_CALENDAR_LABELS = {
|
|
|
34
38
|
moreSpansLabel: "{count} more spanning this week, from {date}",
|
|
35
39
|
dayCount: "{count} entries",
|
|
36
40
|
states: { scheduled: "Scheduled", conflicted: "Conflicted", "in-progress": "In progress", "blackout-violation": "Blackout violation" },
|
|
37
|
-
statuses: { tentative: "Tentative", committed: "Scheduled", live: "In progress", done: "Done", dead: "Cancelled" }
|
|
41
|
+
statuses: { tentative: "Tentative", committed: "Scheduled", live: "In progress", done: "Done", dead: "Cancelled" },
|
|
42
|
+
timeZone: "{timeZone}",
|
|
43
|
+
windows: "Windows",
|
|
44
|
+
moreWindows: "+{count} windows",
|
|
45
|
+
moreWindowsLabel: "{count} more windows, from {date}",
|
|
46
|
+
topLane: "All-day and longer entries",
|
|
47
|
+
continuesFrom: "from {time}",
|
|
48
|
+
moveHint: "Hold Shift and press an arrow key to move it. Enter confirms, Escape cancels.",
|
|
49
|
+
moveProposed: "Move to {start} \u2013 {end}. Enter confirms, Escape cancels.",
|
|
50
|
+
moveCancelled: "Move cancelled.",
|
|
51
|
+
gapForward: "That time does not exist on this day. Moved forward to {time}."
|
|
38
52
|
};
|
|
39
53
|
const stateTone = (state) => state === "scheduled" ? "info" : state === "in-progress" ? "success" : "danger";
|
|
40
54
|
const utcDate = (date) => /* @__PURE__ */ new Date(`${date}T00:00:00Z`);
|
|
41
55
|
const INTL_PARTS = {
|
|
42
56
|
day: { dateStyle: "full", timeZone: "UTC" },
|
|
43
57
|
weekday: { weekday: "short", timeZone: "UTC" },
|
|
44
|
-
month: { month: "long", year: "numeric", timeZone: "UTC" }
|
|
58
|
+
month: { month: "long", year: "numeric", timeZone: "UTC" },
|
|
59
|
+
column: { weekday: "short", day: "2-digit", month: "2-digit", timeZone: "UTC" }
|
|
45
60
|
};
|
|
46
61
|
const EMPTY_OVERLAYS = [];
|
|
47
62
|
const EMPTY_ENTRIES = [];
|
|
@@ -54,13 +69,14 @@ function coveredDays(start, end, timeZone) {
|
|
|
54
69
|
return itemDaySpan(start, start, timeZone);
|
|
55
70
|
}
|
|
56
71
|
}
|
|
57
|
-
function Marker({ marker }) {
|
|
72
|
+
function Marker({ marker, showLabel }) {
|
|
58
73
|
const emphasis = marker.emphasis ?? "neutral";
|
|
59
74
|
return /* @__PURE__ */ jsxs("span", { className: "uix-scheduling-calendar__marker", "data-emphasis": emphasis, "data-glyph": marker.icon == null ? emphasis : void 0, children: [
|
|
60
75
|
marker.icon != null && /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__marker-icon", "aria-hidden": "true", children: marker.icon }),
|
|
61
|
-
/* @__PURE__ */ jsx("span", { className: "uix-visually-hidden", children: marker.label })
|
|
76
|
+
/* @__PURE__ */ jsx("span", { className: showLabel ? "uix-scheduling-calendar__marker-label" : "uix-visually-hidden", children: marker.label })
|
|
62
77
|
] });
|
|
63
78
|
}
|
|
79
|
+
const renderMarker = (marker, showLabel) => /* @__PURE__ */ jsx(Marker, { marker, showLabel });
|
|
64
80
|
function SchedulingCalendar({
|
|
65
81
|
entries,
|
|
66
82
|
anchorDate,
|
|
@@ -91,6 +107,14 @@ function SchedulingCalendar({
|
|
|
91
107
|
notice,
|
|
92
108
|
emptyNote,
|
|
93
109
|
onSelectDate,
|
|
110
|
+
timeGrid = false,
|
|
111
|
+
now,
|
|
112
|
+
canMove = false,
|
|
113
|
+
step = 15,
|
|
114
|
+
onProposeMove,
|
|
115
|
+
topLaneCrossMidnightMinutes = TOP_LANE_CROSS_MIDNIGHT_MINUTES,
|
|
116
|
+
topLaneCap = 3,
|
|
117
|
+
maxLanes = 4,
|
|
94
118
|
loading,
|
|
95
119
|
error,
|
|
96
120
|
onRetry,
|
|
@@ -106,7 +130,7 @@ function SchedulingCalendar({
|
|
|
106
130
|
statuses: { ...DEFAULT_SCHEDULING_CALENDAR_LABELS.statuses, ...uixLabels.schedulingCalendar?.statuses, ...labelOverrides?.statuses }
|
|
107
131
|
};
|
|
108
132
|
const stateLabel = labels.states;
|
|
109
|
-
const viewLabel = { month: labels.viewMonth, week: labels.viewWeek, agenda: labels.viewAgenda };
|
|
133
|
+
const viewLabel = { month: labels.viewMonth, week: labels.viewWeek, day: labels.viewDay, agenda: labels.viewAgenda };
|
|
110
134
|
const [internalView, setInternalView] = useState("month");
|
|
111
135
|
const view = controlledView ?? internalView;
|
|
112
136
|
const [activeDate, setActiveDate] = useState(anchorDate);
|
|
@@ -124,7 +148,8 @@ function SchedulingCalendar({
|
|
|
124
148
|
const weekday = (utcDate(anchorDate).getUTCDay() - weekStartsOn + 7) % 7;
|
|
125
149
|
const weekStart = addCalendarDays(anchorDate, -weekday);
|
|
126
150
|
const weekDays = useMemo(() => Array.from({ length: 7 }, (_, index) => addCalendarDays(weekStart, index)), [weekStart]);
|
|
127
|
-
const days = useMemo(() => view === "month" ? monthDays.map((day) => day.date) : weekDays, [view, monthDays, weekDays]);
|
|
151
|
+
const days = useMemo(() => view === "month" ? monthDays.map((day) => day.date) : view === "day" ? [anchorDate] : weekDays, [view, monthDays, weekDays, anchorDate]);
|
|
152
|
+
const timeGridView = view === "day" || view === "week" && timeGrid;
|
|
128
153
|
const { singles, multiDay, coverage } = useMemo(() => {
|
|
129
154
|
const byDay = /* @__PURE__ */ new Map();
|
|
130
155
|
const spans = [];
|
|
@@ -144,7 +169,7 @@ function SchedulingCalendar({
|
|
|
144
169
|
const overlayById = useMemo(() => new Map([...overlays].reverse().map((overlay) => [overlay.id, overlay])), [overlays]);
|
|
145
170
|
const layout = useMemo(() => {
|
|
146
171
|
if (spanLayout) return spanLayout;
|
|
147
|
-
if (view === "agenda") return { placed: [], hiddenByRow: {}, firstHiddenDayByRow: {} };
|
|
172
|
+
if (view === "agenda" || timeGridView) return { placed: [], hiddenByRow: {}, firstHiddenDayByRow: {} };
|
|
148
173
|
const inputs = [];
|
|
149
174
|
const windowIds = /* @__PURE__ */ new Set();
|
|
150
175
|
const itemIds = /* @__PURE__ */ new Set();
|
|
@@ -159,7 +184,7 @@ function SchedulingCalendar({
|
|
|
159
184
|
inputs.push({ id: entry.id, start: entry.start, end: entry.end, group: "item" });
|
|
160
185
|
}
|
|
161
186
|
return layoutMonthSpans(inputs, days, { timeZone, laneCap: { window: windowCap, item: spanCap } });
|
|
162
|
-
}, [spanLayout, view, overlays, multiDay, days, timeZone, windowCap, spanCap]);
|
|
187
|
+
}, [spanLayout, view, timeGridView, overlays, multiDay, days, timeZone, windowCap, spanCap]);
|
|
163
188
|
const placedByRow = useMemo(() => {
|
|
164
189
|
const rows = /* @__PURE__ */ new Map();
|
|
165
190
|
for (const placed of layout.placed) {
|
|
@@ -178,9 +203,9 @@ function SchedulingCalendar({
|
|
|
178
203
|
if (controlledView === void 0) setInternalView(next);
|
|
179
204
|
onViewChange?.(next);
|
|
180
205
|
};
|
|
181
|
-
const movePeriod = (direction) => onAnchorDateChange?.(view === "month" ? addCalendarMonths(anchorDate, direction) : addCalendarDays(anchorDate, direction * 7));
|
|
206
|
+
const movePeriod = (direction) => onAnchorDateChange?.(view === "month" ? addCalendarMonths(anchorDate, direction) : addCalendarDays(anchorDate, view === "day" ? direction : direction * 7));
|
|
182
207
|
const periodLabel = (direction) => {
|
|
183
|
-
const key = `${direction}${view === "month" ? "Month" : "Week"}`;
|
|
208
|
+
const key = `${direction}${view === "month" ? "Month" : view === "day" ? "Day" : "Week"}`;
|
|
184
209
|
return overrides[key] ?? overrides[direction] ?? labels[key];
|
|
185
210
|
};
|
|
186
211
|
const focusDate = (date) => {
|
|
@@ -326,8 +351,8 @@ function SchedulingCalendar({
|
|
|
326
351
|
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => movePeriod(-1), disabled: !onAnchorDateChange, children: periodLabel("previous") }),
|
|
327
352
|
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => movePeriod(1), disabled: !onAnchorDateChange, children: periodLabel("next") })
|
|
328
353
|
] }),
|
|
329
|
-
/* @__PURE__ */ jsx("strong", { children: view === "month" ? dateText(startOfMonth(anchorDate), "month") : `${dateText(weekStart, "day")} \u2013 ${dateText(weekDays[weekDays.length - 1], "day")}` }),
|
|
330
|
-
/* @__PURE__ */ jsx("div", { className: "uix-segmented", role: "group", "aria-label": labels.viewGroup, children: ["month", "week", "agenda"].map((option) => /* @__PURE__ */ jsx("button", { type: "button", className: "uix-segmented__option", "aria-pressed": view === option, "data-selected": view === option || void 0, onClick: () => setView(option), children: viewLabel[option] }, option)) })
|
|
354
|
+
/* @__PURE__ */ jsx("strong", { children: view === "month" ? dateText(startOfMonth(anchorDate), "month") : view === "day" ? dateText(anchorDate, "day") : `${dateText(weekStart, "day")} \u2013 ${dateText(weekDays[weekDays.length - 1], "day")}` }),
|
|
355
|
+
/* @__PURE__ */ jsx("div", { className: "uix-segmented", role: "group", "aria-label": labels.viewGroup, children: (timeGrid || view === "day" ? ["month", "week", "day", "agenda"] : ["month", "week", "agenda"]).map((option) => /* @__PURE__ */ jsx("button", { type: "button", className: "uix-segmented__option", "aria-pressed": view === option, "data-selected": view === option || void 0, onClick: () => setView(option), children: viewLabel[option] }, option)) })
|
|
331
356
|
] }),
|
|
332
357
|
notice != null && notice !== false && /* @__PURE__ */ jsx("div", { className: "uix-scheduling-calendar__notice", children: notice }),
|
|
333
358
|
loading ? /* @__PURE__ */ jsx("div", { className: "uix-scheduling-calendar__state", role: "status", children: labels.loading }) : error ? /* @__PURE__ */ jsxs("div", { className: "uix-scheduling-calendar__state", role: "alert", children: [
|
|
@@ -348,7 +373,41 @@ function SchedulingCalendar({
|
|
|
348
373
|
markers.length > 0 && /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__markers", children: markers.map((marker) => /* @__PURE__ */ jsx(Marker, { marker }, marker.id)) }),
|
|
349
374
|
entry.state ? /* @__PURE__ */ jsx(StatusPill, { tone: stateTone(entry.state), children: stateLabel[entry.state] }) : /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__status", children: stateText(entry) })
|
|
350
375
|
] }) }, entry.id);
|
|
351
|
-
}) }) }) : /* @__PURE__ */
|
|
376
|
+
}) }) }) : timeGridView ? /* @__PURE__ */ jsx(
|
|
377
|
+
SchedulingTimeGrid,
|
|
378
|
+
{
|
|
379
|
+
view: view === "day" ? "day" : "week",
|
|
380
|
+
days,
|
|
381
|
+
timeZone,
|
|
382
|
+
entries: visibleEntries,
|
|
383
|
+
overlays,
|
|
384
|
+
dayInfo,
|
|
385
|
+
labels,
|
|
386
|
+
gridLabel: fillLabel(labels.grid, { view: viewLabel[view] }),
|
|
387
|
+
dateText,
|
|
388
|
+
formatInstant,
|
|
389
|
+
entryName,
|
|
390
|
+
entryStatus: statusOf,
|
|
391
|
+
entryMarkers: markersOf,
|
|
392
|
+
overlayName,
|
|
393
|
+
renderEntry,
|
|
394
|
+
renderMarker,
|
|
395
|
+
onSelectEntry,
|
|
396
|
+
onSelectOverlay,
|
|
397
|
+
onSelectDate,
|
|
398
|
+
onShowMore,
|
|
399
|
+
now,
|
|
400
|
+
canMove,
|
|
401
|
+
step,
|
|
402
|
+
onProposeMove,
|
|
403
|
+
topLaneCrossMidnightMinutes,
|
|
404
|
+
topLaneCap,
|
|
405
|
+
windowLaneCap: windowLaneCap ?? DEFAULT_LANE_CAP,
|
|
406
|
+
maxLanes,
|
|
407
|
+
emptyNote,
|
|
408
|
+
nothingToShow
|
|
409
|
+
}
|
|
410
|
+
) : /* @__PURE__ */ jsxs("div", { ref: gridRef, className: cx("uix-scheduling-calendar__grid", view === "week" && "uix-scheduling-calendar__grid--week"), "data-fixed": fixed || void 0, style: gridStyle, role: "group", "aria-label": fillLabel(labels.grid, { view: viewLabel[view] }), children: [
|
|
352
411
|
days.slice(0, 7).map((date) => /* @__PURE__ */ jsx("div", { className: "uix-scheduling-calendar__weekday", "aria-hidden": "true", children: dateText(date, "weekday") }, `weekday-${date}`)),
|
|
353
412
|
Array.from({ length: days.length / 7 }, (_, row) => renderWeek(row)),
|
|
354
413
|
emptyNote != null && emptyNote !== false && nothingToShow && /* @__PURE__ */ jsx("div", { className: "uix-scheduling-calendar__empty", children: emptyNote })
|