@tensor_1/react 2.34.0 → 2.36.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.
Files changed (48) hide show
  1. package/README.md +164 -15
  2. package/dist/{SchedulingCalendar-DSLQ6AY5.d.ts → SchedulingCalendar-B6TakO2h.d.ts} +13 -1
  3. package/dist/components/Avatar.d.ts +26 -4
  4. package/dist/components/Avatar.js +26 -3
  5. package/dist/components/CommandPalette.d.ts +6 -1
  6. package/dist/components/CommandPalette.js +9 -3
  7. package/dist/components/DateFieldParts.d.ts +61 -0
  8. package/dist/components/DateFieldParts.js +195 -0
  9. package/dist/components/DatePicker.d.ts +129 -0
  10. package/dist/components/DatePicker.js +340 -0
  11. package/dist/components/DateRangePicker.d.ts +34 -3
  12. package/dist/components/DateRangePicker.js +120 -17
  13. package/dist/components/EntityPicker.d.ts +29 -4
  14. package/dist/components/EntityPicker.js +20 -8
  15. package/dist/components/InlineEdit.d.ts +74 -0
  16. package/dist/components/InlineEdit.js +176 -0
  17. package/dist/components/List.d.ts +8 -1
  18. package/dist/components/List.js +3 -1
  19. package/dist/components/ListRoving.d.ts +12 -0
  20. package/dist/components/ListRoving.js +51 -0
  21. package/dist/components/Radio.d.ts +23 -2
  22. package/dist/components/Radio.js +18 -3
  23. package/dist/components/SchedulingAgenda.d.ts +1 -1
  24. package/dist/components/SchedulingAgenda.js +101 -4
  25. package/dist/components/SchedulingCalendar.d.ts +1 -1
  26. package/dist/components/SchedulingCalendar.js +89 -9
  27. package/dist/components/SchedulingTimeGrid.d.ts +1 -1
  28. package/dist/components/SchedulingTimeGrid.js +101 -4
  29. package/dist/components/SchedulingTimeline.d.ts +130 -15
  30. package/dist/components/SchedulingTimeline.js +765 -141
  31. package/dist/components/SearchSuggest.d.ts +12 -1
  32. package/dist/components/SearchSuggest.js +7 -2
  33. package/dist/components/Tree.d.ts +30 -2
  34. package/dist/components/Tree.js +135 -10
  35. package/dist/date-field-model.d.ts +40 -0
  36. package/dist/date-field-model.js +79 -0
  37. package/dist/index.cjs +4179 -2056
  38. package/dist/index.d.cts +829 -264
  39. package/dist/index.d.ts +10 -7
  40. package/dist/index.js +40 -4
  41. package/dist/labels-context.d.ts +15 -2
  42. package/dist/roving.d.ts +15 -0
  43. package/dist/roving.js +17 -0
  44. package/dist/scheduling-timeline-model.d.ts +61 -11
  45. package/dist/scheduling-timeline-model.js +85 -26
  46. package/dist/scheduling-timeline-rows.d.ts +40 -0
  47. package/dist/scheduling-timeline-rows.js +42 -0
  48. package/package.json +5 -3
@@ -39,6 +39,8 @@ const GridItem = memo(function GridItem2({ entry, segment, column, alone, name,
39
39
  ] });
40
40
  const shared = {
41
41
  className: "uix-scheduling-calendar__entry uix-scheduling-calendar__tg-item",
42
+ "data-highlight": entry.emphasis === "highlight" || void 0,
43
+ "data-dim": entry.emphasis === "dim" || void 0,
42
44
  "data-band": entry.band ?? "none",
43
45
  "data-status": status,
44
46
  "data-state": entry.state,
@@ -54,6 +56,7 @@ const GridItem = memo(function GridItem2({ entry, segment, column, alone, name,
54
56
  "button",
55
57
  {
56
58
  type: "button",
59
+ tabIndex: -1,
57
60
  ...shared,
58
61
  "data-item-id": entry.id,
59
62
  "aria-label": name,
@@ -101,6 +104,9 @@ function SchedulingTimeGrid({
101
104
  const [widthCap, setWidthCap] = useState(Infinity);
102
105
  const [ghost, setGhost] = useState(null);
103
106
  const [announcement, setAnnouncement] = useState("");
107
+ const [activeDay, setActiveDay] = useState(days[0]);
108
+ const enteredFrom = useRef(null);
109
+ const tabStop = days.includes(activeDay) ? activeDay : days[0];
104
110
  const moving = canMove && onProposeMove !== void 0;
105
111
  const step = Number.isFinite(givenStep) && givenStep > 0 ? givenStep : DEFAULT_STEP;
106
112
  const laneOptions = useMemo(() => ({ crossMidnightMinutes: topLaneCrossMidnightMinutes }), [topLaneCrossMidnightMinutes]);
@@ -334,6 +340,78 @@ function SchedulingTimeGrid({
334
340
  dragRef.current = null;
335
341
  }, []);
336
342
  const gridColumns = (span) => `${span.startCol + 2} / ${span.endCol + 3}`;
343
+ const headButton = (date) => rootRef.current?.querySelector(`.uix-scheduling-calendar__tg-dayhead[data-date="${date}"] [data-calendar-date]`) ?? null;
344
+ const dayRing = (date) => {
345
+ const root = rootRef.current;
346
+ const column = days.indexOf(date);
347
+ if (!root || column === -1) return [];
348
+ const covers = (element) => {
349
+ const [from, to] = element.style.gridColumn.split("/").map((part) => Number(part.trim()));
350
+ return from !== void 0 && to !== void 0 && from <= column + 2 && column + 2 < to;
351
+ };
352
+ const all = (selector) => Array.from(root.querySelectorAll(selector));
353
+ return [
354
+ ...all(".uix-scheduling-calendar__tg-strip > button.uix-scheduling-calendar__window").filter(covers),
355
+ ...all(".uix-scheduling-calendar__tg-top > button.uix-scheduling-calendar__tg-span").filter(covers),
356
+ ...all(`[data-tg-column="${date}"] > button[data-item-id]`),
357
+ ...all(`.uix-scheduling-calendar__tg-dayhead[data-date="${date}"] > button.uix-scheduling-calendar__more`),
358
+ // "+N windows" opens one day; it is reached from that day.
359
+ ...all(`.uix-scheduling-calendar__tg-strip > button.uix-scheduling-calendar__rowmore[data-more-date="${date}"]`)
360
+ ];
361
+ };
362
+ const dayOfItem = (item) => {
363
+ if (enteredFrom.current && dayRing(enteredFrom.current).includes(item)) return enteredFrom.current;
364
+ const inColumn = item.getAttribute("data-more-date") ?? item.closest("[data-tg-column]")?.getAttribute("data-tg-column") ?? item.closest("[data-date]")?.getAttribute("data-date");
365
+ if (inColumn) return inColumn;
366
+ const from = Number(item.style.gridColumn.split("/")[0]);
367
+ return Number.isFinite(from) ? days[Math.max(0, Math.min(days.length - 1, from - 2))] ?? null : days[days.length - 1] ?? null;
368
+ };
369
+ const onHeadKeyDown = (event, date) => {
370
+ const index = days.indexOf(date);
371
+ const target = event.key === "ArrowLeft" ? index - 1 : event.key === "ArrowRight" ? index + 1 : event.key === "Home" ? 0 : event.key === "End" ? days.length - 1 : null;
372
+ if (target !== null) {
373
+ event.preventDefault();
374
+ const next = days[Math.max(0, Math.min(days.length - 1, target))];
375
+ setActiveDay(next);
376
+ headButton(next)?.focus();
377
+ } else if (event.key === "Enter") {
378
+ const [first] = dayRing(date);
379
+ if (!first) return;
380
+ event.preventDefault();
381
+ enteredFrom.current = date;
382
+ first.focus();
383
+ }
384
+ };
385
+ const onGridKeyDown = (event) => {
386
+ const item = event.target;
387
+ if (event.defaultPrevented || event.shiftKey || item.hasAttribute("data-calendar-date") || !["ArrowDown", "ArrowUp", "Home", "End", "Escape"].includes(event.key)) return;
388
+ const date = dayOfItem(item);
389
+ if (!date) return;
390
+ const ring = dayRing(date);
391
+ const index = ring.indexOf(item);
392
+ if (index === -1) return;
393
+ event.preventDefault();
394
+ const to = event.key === "Escape" ? null : ring[Math.max(0, Math.min(ring.length - 1, event.key === "Home" ? 0 : event.key === "End" ? ring.length - 1 : index + (event.key === "ArrowDown" ? 1 : -1)))];
395
+ if (to !== item && ghost?.source === "keys") {
396
+ setGhost(null);
397
+ setAnnouncement(labels.moveCancelled);
398
+ }
399
+ if (event.key === "Escape") {
400
+ event.stopPropagation();
401
+ enteredFrom.current = null;
402
+ setActiveDay(date);
403
+ headButton(date)?.focus();
404
+ return;
405
+ }
406
+ enteredFrom.current = date;
407
+ to?.focus();
408
+ };
409
+ const onGridFocus = (event) => {
410
+ const item = event.target;
411
+ if (item.hasAttribute("data-calendar-date")) return;
412
+ const date = dayOfItem(item);
413
+ if (date && dayRing(date).includes(item)) setActiveDay(date);
414
+ };
337
415
  const nowAt = now === void 0 ? null : new Date(now).getTime();
338
416
  const nowColumn = nowAt === null || Number.isNaN(nowAt) ? -1 : days.indexOf(zonedDateKey(new Date(nowAt), timeZone));
339
417
  const topHiddenOn = (date) => top.hidden.filter((id) => {
@@ -358,6 +436,8 @@ function SchedulingTimeGrid({
358
436
  role: "group",
359
437
  "aria-label": gridLabel,
360
438
  style: vars({ "--uix-scheduling-calendar-days": days.length, "--uix-scheduling-calendar-hours": maxHours }),
439
+ onKeyDown: onGridKeyDown,
440
+ onFocus: onGridFocus,
361
441
  onClickCapture: (event) => {
362
442
  if (suppressClick.current) {
363
443
  suppressClick.current = false;
@@ -374,12 +454,25 @@ function SchedulingTimeGrid({
374
454
  const more = info ? info.overflowCount : hiddenIds.length;
375
455
  const moreText = fillLabel(labels.moreSpans, { count: more });
376
456
  const moreName = fillLabel(labels.moreEntriesLabel, { count: more, date: dateText(date, "day") });
377
- const headName = info ? info.label ?? `${dateText(date, "day")}, ${fillLabel(labels.dayCount, { count: info.count })}` : dateText(date, "day");
457
+ const headName = !info ? dateText(date, "day") : info.label ? fillLabel(labels.dayName, { date: dateText(date, "day"), label: info.label }) : `${dateText(date, "day")}, ${fillLabel(labels.dayCount, { count: info.count })}`;
378
458
  return /* @__PURE__ */ jsxs("div", { className: "uix-scheduling-calendar__tg-dayhead", role: "group", "aria-label": headName, "data-date": date, children: [
379
- /* @__PURE__ */ jsx("button", { type: "button", className: "uix-scheduling-calendar__date", "data-calendar-date": date, "aria-label": dateText(date, "day"), onClick: onSelectDate ? () => onSelectDate(date) : void 0, children: dateText(date, "column") }),
459
+ /* @__PURE__ */ jsx(
460
+ "button",
461
+ {
462
+ type: "button",
463
+ className: "uix-scheduling-calendar__date",
464
+ "data-calendar-date": date,
465
+ tabIndex: tabStop === date ? 0 : -1,
466
+ "aria-label": info?.label ? fillLabel(labels.dayName, { date: dateText(date, "day"), label: info.label }) : dateText(date, "day"),
467
+ onFocus: () => setActiveDay(date),
468
+ onKeyDown: (event) => onHeadKeyDown(event, date),
469
+ onClick: onSelectDate ? () => onSelectDate(date) : void 0,
470
+ children: dateText(date, "column")
471
+ }
472
+ ),
380
473
  info && /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__count", "aria-hidden": "true", children: info.count }),
381
474
  info?.markers && info.markers.length > 0 && /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__markers", children: info.markers.map((marker) => /* @__PURE__ */ jsx("span", { children: renderMarker(marker, true) }, marker.id)) }),
382
- more > 0 && (onShowMore ? /* @__PURE__ */ jsx("button", { type: "button", className: "uix-scheduling-calendar__more", "aria-label": moreName, onClick: () => onShowMore(date, hiddenIds.map((id) => entryById.get(id)).filter(Boolean)), children: moreText }) : /* @__PURE__ */ jsxs("span", { className: "uix-scheduling-calendar__more", children: [
475
+ more > 0 && (onShowMore ? /* @__PURE__ */ jsx("button", { type: "button", tabIndex: -1, className: "uix-scheduling-calendar__more", "aria-label": moreName, onClick: () => onShowMore(date, hiddenIds.map((id) => entryById.get(id)).filter(Boolean)), children: moreText }) : /* @__PURE__ */ jsxs("span", { className: "uix-scheduling-calendar__more", children: [
383
476
  /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: moreText }),
384
477
  /* @__PURE__ */ jsx("span", { className: "uix-visually-hidden", children: moreName })
385
478
  ] }))
@@ -394,6 +487,7 @@ function SchedulingTimeGrid({
394
487
  "button",
395
488
  {
396
489
  type: "button",
490
+ tabIndex: -1,
397
491
  className: "uix-scheduling-calendar__window",
398
492
  "data-overlay-id": overlay.id,
399
493
  "data-pattern": overlay.pattern ?? "solid",
@@ -413,7 +507,7 @@ function SchedulingTimeGrid({
413
507
  placed.id
414
508
  );
415
509
  }),
416
- moreWindows > 0 && (onShowMore ? /* @__PURE__ */ jsx("button", { type: "button", className: "uix-scheduling-calendar__rowmore", "aria-label": fillLabel(labels.moreWindowsLabel, { count: moreWindows, date: dateText(firstHiddenWindowDay, "day") }), onClick: () => onShowMore(firstHiddenWindowDay, []), children: fillLabel(labels.moreWindows, { count: moreWindows }) }) : /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__rowmore", children: fillLabel(labels.moreWindows, { count: moreWindows }) }))
510
+ moreWindows > 0 && (onShowMore ? /* @__PURE__ */ jsx("button", { type: "button", tabIndex: -1, className: "uix-scheduling-calendar__rowmore", "data-more-date": firstHiddenWindowDay, "aria-label": fillLabel(labels.moreWindowsLabel, { count: moreWindows, date: dateText(firstHiddenWindowDay, "day") }), onClick: () => onShowMore(firstHiddenWindowDay, []), children: fillLabel(labels.moreWindows, { count: moreWindows }) }) : /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__rowmore", children: fillLabel(labels.moreWindows, { count: moreWindows }) }))
417
511
  ] }),
418
512
  (topLanes > 0 || ghostSpan) && /* @__PURE__ */ jsxs("div", { className: "uix-scheduling-calendar__tg-strip uix-scheduling-calendar__tg-top", role: "group", "aria-label": labels.topLane, style: vars({ "--uix-scheduling-calendar-lanes": Math.max(topLanes, 1) }), children: [
419
513
  top.placed.map((placed) => {
@@ -425,8 +519,11 @@ function SchedulingTimeGrid({
425
519
  "button",
426
520
  {
427
521
  type: "button",
522
+ tabIndex: -1,
428
523
  className: "uix-scheduling-calendar__entry uix-scheduling-calendar__tg-span",
429
524
  "data-item-id": entry.id,
525
+ "data-highlight": entry.emphasis === "highlight" || void 0,
526
+ "data-dim": entry.emphasis === "dim" || void 0,
430
527
  "data-band": entry.band ?? "none",
431
528
  "data-status": entryStatus(entry),
432
529
  "data-state": entry.state,
@@ -1,9 +1,9 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
+ import { MoveProposal } from '../scheduling-calendar-model.js';
3
4
  import { TimelineRange, TimelineScale } from '../scheduling-timeline-model.js';
4
- import { j as SchedulingEntryState } from '../SchedulingCalendar-DSLQ6AY5.js';
5
+ import { j as SchedulingEntryState, p as SchedulingStatus, a as SchedulingBand, l as SchedulingMarker, o as SchedulingOverlayPattern } from '../SchedulingCalendar-B6TakO2h.js';
5
6
  import '../calendar-model.js';
6
- import '../scheduling-calendar-model.js';
7
7
 
8
8
  interface SchedulingTimelineLane {
9
9
  id: string;
@@ -11,6 +11,25 @@ interface SchedulingTimelineLane {
11
11
  /** A quieter second line under the lane name (an owner, a count). */
12
12
  meta?: ReactNode;
13
13
  }
14
+ /** A collapsible block of lanes. The consumer builds the groups and owns every number on them. */
15
+ interface SchedulingTimelineGroup {
16
+ id: string;
17
+ label: ReactNode;
18
+ /** A quieter text beside the group name. */
19
+ meta?: ReactNode;
20
+ /** The lanes of the group, in the order to draw them. A lane named by two groups is drawn in the first. */
21
+ laneIds: string[];
22
+ /**
23
+ * A collapsed group is one row. With `onToggleGroup` the consumer owns this value; without
24
+ * it, it is where the group starts and the timeline opens and closes the group itself.
25
+ */
26
+ collapsed?: boolean;
27
+ /** Shown on the one row of a collapsed group. The timeline derives neither the count nor a marker. */
28
+ summary?: {
29
+ count: number;
30
+ markers?: SchedulingMarker[];
31
+ };
32
+ }
14
33
  interface SchedulingTimelineItem {
15
34
  id: string;
16
35
  laneId: string;
@@ -18,34 +37,61 @@ interface SchedulingTimelineItem {
18
37
  /** ISO 8601 instants. */
19
38
  start: string;
20
39
  end: string;
40
+ /** @deprecated Use `band`, `status` and `markers`. The values keep working in 2.x; a bar is no longer tinted by them. */
21
41
  state?: SchedulingEntryState;
22
42
  meta?: string;
23
- /** `false` keeps this bar fixed even when `onMoveItem` is set. */
43
+ /** `false` keeps this bar fixed even when a move or resize callback is set. */
24
44
  movable?: boolean;
45
+ /** The one dimension that takes a hue: only `high` is filled. */
46
+ band?: SchedulingBand;
47
+ /** Drawn as a line style, never as a hue. */
48
+ status?: SchedulingStatus;
49
+ /** Shapes or icons with text. The text is in the accessible name. */
50
+ markers?: SchedulingMarker[];
51
+ /** The complete accessible name, built by the consumer from its own words. Replaces `labels.item`. */
52
+ accessibleName?: string;
25
53
  }
54
+ /** @deprecated Use `pattern` and `kindLabel` on the overlay. The values keep working in 2.x. */
26
55
  type SchedulingTimelineOverlayKind = 'freeze' | 'maintenance' | 'blackout';
27
56
  interface SchedulingTimelineOverlay {
28
57
  id: string;
58
+ /** The name of the window, shown as text. */
29
59
  label: string;
30
60
  start: string;
31
61
  end: string;
32
- kind: SchedulingTimelineOverlayKind;
33
- /** Only this lane; every lane when unset. */
62
+ /** @deprecated Use `pattern` and `kindLabel`. */
63
+ kind?: SchedulingTimelineOverlayKind;
64
+ /** Only this lane. For several lanes use `laneIds`. */
34
65
  laneId?: string;
66
+ /** Only these lanes; every lane when neither this nor `laneId` is set. The window is still one element. */
67
+ laneIds?: string[];
68
+ /** How the window is hatched. Windows are neutral: the pattern and the visible words tell them apart. */
69
+ pattern?: SchedulingOverlayPattern;
70
+ /** What kind of window this is, in the words of the consumer. Shown before the name. */
71
+ kindLabel?: string;
72
+ /** What the window applies to. Shown after the name. */
73
+ scopeLabel?: string;
74
+ /** The complete accessible name. Replaces `labels.overlay`. */
75
+ accessibleName?: string;
35
76
  }
36
77
  interface SchedulingTimelineMarker {
37
78
  id: string;
38
79
  label: string;
39
80
  /** ISO 8601 instant. */
40
81
  at: string;
82
+ /** Only this lane. For several lanes use `laneIds`. */
41
83
  laneId?: string;
84
+ /** Only these lanes; every lane when neither this nor `laneId` is set. */
85
+ laneIds?: string[];
42
86
  }
43
87
  interface SchedulingTimelineLabels {
44
88
  region: string;
45
89
  lanes: string;
46
- /** `{title}`, `{state}`, `{start}`, `{end}`, `{conflict}`. */
90
+ /** The accessible name of a bar unless it sets `accessibleName`. `{title}`, `{state}`, `{start}`, `{end}`, `{conflict}`. Its marker labels are appended. */
47
91
  item: string;
92
+ /** Read after a bar that shares time with another bar of its lane, while `flagOverlaps` is on. */
48
93
  conflict: string;
94
+ /** The hint of a timeline that has both `onMoveItem` and `onResizeItem` (the older sentence). */
49
95
  moveHint: string;
50
96
  /** Announced after a move. `{title}`, `{start}`, `{end}`. */
51
97
  moved: string;
@@ -57,8 +103,30 @@ interface SchedulingTimelineLabels {
57
103
  /** Heading of the screen-reader list of windows and markers. */
58
104
  windows: string;
59
105
  now: string;
106
+ /** @deprecated The words of `item.state`. Use `status` on the item, named by `statuses`. */
60
107
  states: Record<SchedulingEntryState, string>;
108
+ /** @deprecated The words of `overlay.kind`. Use `kindLabel` on the overlay. */
61
109
  overlays: Record<SchedulingTimelineOverlayKind, string>;
110
+ /** The words for `status`, used in the default accessible name. */
111
+ statuses?: Partial<Record<SchedulingStatus, string>>;
112
+ /** The accessible name of a window that can be selected. `{title}` is its kind, name and scope. */
113
+ overlay?: string;
114
+ /** The hint of a bar that `onMoveItem` moves, one step a key press. */
115
+ moveKeysHint?: string;
116
+ /** The hint of a bar whose end `onResizeItem` moves. */
117
+ resizeHint?: string;
118
+ /** The hint of a bar that `onProposeMove` moves. */
119
+ proposeHint?: string;
120
+ /** Announced for a pending move. `{start}` and `{end}` placeholders. */
121
+ moveProposed?: string;
122
+ /** Announced when a pending move is dropped. */
123
+ moveCancelled?: string;
124
+ /** Announced when the time asked for does not exist that day. `{time}` is the time used instead. */
125
+ gapForward?: string;
126
+ /** The count on the row of a collapsed group. `{count}` is the number the consumer gave; the wording, plural forms included, is this label. */
127
+ groupSummary?: string;
128
+ /** Announced when a move was handed to `onProposeMove`. `{start}` and `{end}` placeholders. */
129
+ moveSent?: string;
62
130
  }
63
131
  declare const DEFAULT_SCHEDULING_TIMELINE_LABELS: SchedulingTimelineLabels;
64
132
  interface SchedulingTimelineProps {
@@ -71,7 +139,16 @@ interface SchedulingTimelineProps {
71
139
  /** IANA zone for tick boundaries and every printed time. */
72
140
  timeZone: string;
73
141
  locale?: string;
142
+ /**
143
+ * Collapsible blocks of lanes, in the order given. Lanes that no group names are drawn after
144
+ * the groups. Unset keeps the flat list of lanes.
145
+ */
146
+ groups?: SchedulingTimelineGroup[];
147
+ /** Called by a group head. When set, the consumer flips `collapsed`; nothing opens until the props say so. */
148
+ onToggleGroup?: (id: string) => void;
74
149
  overlays?: SchedulingTimelineOverlay[];
150
+ /** Makes each window a button. Called by a click or Enter on it. */
151
+ onSelectOverlay?: (overlay: SchedulingTimelineOverlay) => void;
75
152
  markers?: SchedulingTimelineMarker[];
76
153
  /** Draws a "now" line at this instant (pass the current time; the component keeps no clock). */
77
154
  now?: string;
@@ -81,18 +158,53 @@ interface SchedulingTimelineProps {
81
158
  tickWidth?: string;
82
159
  /** Move/resize granularity in ms. Defaults: 15 min (hour), 1 h (day), 1 day (week, month). */
83
160
  step?: number;
84
- /** Tick label. Default: `Intl` in `locale` and `timeZone`. */
161
+ /** Local hours (0–23) that get a minor tick inside each day of a `day` axis, e.g. `[6, 12, 18]`. */
162
+ subTicks?: number[];
163
+ /** Tick label. Default: `Intl` in `locale` and `timeZone`. A sub-tick asks with the scale `'hour'`. */
85
164
  formatTick?: (at: Date, scale: TimelineScale) => string;
86
165
  /** Start/end text in names and announcements. Default: `Intl` medium date + short time in `timeZone`. */
87
166
  formatInstant?: (instant: string) => string;
88
- /** Bar content. Default: the title. */
167
+ /** Bar content. Default: the title. The text is cut at a word, never in one. */
89
168
  renderItem?: (item: SchedulingTimelineItem) => ReactNode;
90
169
  onSelectItem?: (item: SchedulingTimelineItem) => void;
91
- /** Makes bars draggable and keyboard-movable. Receives the snapped new start and end. */
170
+ /**
171
+ * Makes bars draggable and keyboard-movable, one call for every key press and every drop.
172
+ * Receives the snapped new start and end. Not called for moves while `onProposeMove` is set.
173
+ */
92
174
  onMoveItem?: (id: string, next: {
93
175
  start: string;
94
176
  end: string;
95
177
  }) => void;
178
+ /**
179
+ * Lets the user ask for a move: a drag, or Shift and an arrow key to build a pending move and
180
+ * Enter to send it (Escape drops it). Called once per finished gesture. The timeline never
181
+ * moves the bar: it draws items where the props say, so an item whose props do not change is
182
+ * back where it was. Return a promise to keep the outline until it settles.
183
+ */
184
+ onProposeMove?: (id: string, proposal: MoveProposal) => void | Promise<unknown>;
185
+ /** Lets Alt+Shift and an arrow key move the end of a bar. Without it there is no resize of any kind. */
186
+ onResizeItem?: (id: string, next: {
187
+ start: string;
188
+ end: string;
189
+ }) => void;
190
+ /**
191
+ * `false` keeps the stacking of bars that share time and drops the hatch and the words for
192
+ * it: the consumer says what clashes, with a reason, through `markers`. Default `true`.
193
+ */
194
+ flagOverlaps?: boolean;
195
+ /**
196
+ * Above this many rows only the rows near the viewport are mounted. The rows counted are
197
+ * the ones passed: `lanes` plus `groups`, whatever is collapsed and however the bars pack, so
198
+ * the answer does not move with the width. Default 150; `Infinity` mounts everything. It says
199
+ * when windowing starts, not how much is mounted: that is what the viewport shows, plus overscan.
200
+ */
201
+ virtualizeAbove?: number;
202
+ /** A CSS length. The lanes then scroll inside the timeline under the axis. Unset: the page scrolls. */
203
+ maxHeight?: string;
204
+ /** Shown above the axis, e.g. "Showing 500 of 1,240 items". */
205
+ notice?: ReactNode;
206
+ /** A note under the axis on the column of a day (`YYYY-MM-DD` in `timeZone`), e.g. a count the consumer knows. */
207
+ columnNotes?: Record<string, ReactNode>;
96
208
  loading?: boolean;
97
209
  error?: string;
98
210
  onRetry?: () => void;
@@ -100,11 +212,14 @@ interface SchedulingTimelineProps {
100
212
  className?: string;
101
213
  }
102
214
  /**
103
- * Lanes of bars on a time axis (HAR-1364; TENSOR C8): change schedules, rollout Gantt rows,
104
- * renewal markers. Overlapping bars in a lane stack and are hatched; freeze, maintenance and
105
- * blackout windows are bands; with `onMoveItem`, bars move by drag or Shift+arrows and their
106
- * end changes with Alt+Shift+arrows, snapped to `step`.
215
+ * Lanes of bars on a time axis (HAR-1364, HAR-1521): schedules by service, rollout rows,
216
+ * renewal markers. Lanes can sit in collapsible groups; bars that share time stack in sub-rows
217
+ * packed by `packLanes`; a window is one neutral, patterned element over the lanes it names;
218
+ * only `band="high"` takes a hue. With `onProposeMove` a move is a proposal handed to the
219
+ * consumer (drag, or Shift and an arrow key, then Enter); `onMoveItem` still commits every
220
+ * step; the end of a bar moves only with `onResizeItem`. Long timelines mount only the rows
221
+ * near the viewport.
107
222
  */
108
- declare function SchedulingTimeline({ lanes, items, range, scale, timeZone, locale, overlays, markers, now, weekStartsOn, tickWidth, step: stepProp, formatTick, formatInstant: formatInstantProp, renderItem, onSelectItem, onMoveItem, loading, error, onRetry, labels: labelOverrides, className, }: SchedulingTimelineProps): react.JSX.Element;
223
+ declare function SchedulingTimeline({ lanes, items, range, scale, timeZone, locale, groups, onToggleGroup, overlays, onSelectOverlay, markers, now, weekStartsOn, tickWidth, step: stepProp, subTicks, formatTick, formatInstant: formatInstantProp, renderItem, onSelectItem, onMoveItem, onProposeMove, onResizeItem, flagOverlaps, virtualizeAbove, maxHeight, notice, columnNotes, loading, error, onRetry, labels: labelOverrides, className, }: SchedulingTimelineProps): react.JSX.Element;
109
224
 
110
- export { DEFAULT_SCHEDULING_TIMELINE_LABELS, SchedulingTimeline, type SchedulingTimelineItem, type SchedulingTimelineLabels, type SchedulingTimelineLane, type SchedulingTimelineMarker, type SchedulingTimelineOverlay, type SchedulingTimelineOverlayKind, type SchedulingTimelineProps };
225
+ export { DEFAULT_SCHEDULING_TIMELINE_LABELS, SchedulingTimeline, type SchedulingTimelineGroup, type SchedulingTimelineItem, type SchedulingTimelineLabels, type SchedulingTimelineLane, type SchedulingTimelineMarker, type SchedulingTimelineOverlay, type SchedulingTimelineOverlayKind, type SchedulingTimelineProps };