@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.
@@ -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__ */ 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: [
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 })
@@ -0,0 +1,4 @@
1
+ import 'react';
2
+ import '../scheduling-calendar-model.js';
3
+ export { p as SchedulingTimeGrid, q as SchedulingTimeGridProps, T as TimeGridEntryContext } from '../SchedulingCalendar-C4XVbqZr.js';
4
+ import '../calendar-model.js';