@tensor_1/react 2.47.0 → 2.49.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 (204) hide show
  1. package/README.md +540 -2
  2. package/dist/{SchedulingCalendar-B6TakO2h.d.ts → SchedulingCalendar-WWyFL3Eo.d.ts} +51 -2
  3. package/dist/announce.d.ts +10 -0
  4. package/dist/announce.js +30 -0
  5. package/dist/chart-analytic.cjs +33 -25
  6. package/dist/chart-preset.cjs +23 -15
  7. package/dist/chart.cjs +23 -15
  8. package/dist/combobox-model.d.ts +10 -1
  9. package/dist/combobox-model.js +15 -0
  10. package/dist/command-palette-model.d.ts +44 -0
  11. package/dist/command-palette-model.js +36 -0
  12. package/dist/components/AccountMenu.d.ts +44 -0
  13. package/dist/components/AccountMenu.js +43 -0
  14. package/dist/components/AppShell.d.ts +45 -2
  15. package/dist/components/AppShell.js +116 -5
  16. package/dist/components/AuditLog.d.ts +128 -0
  17. package/dist/components/AuditLog.js +196 -0
  18. package/dist/components/BrandProfiles.js +4 -3
  19. package/dist/components/Breadcrumbs.d.ts +9 -2
  20. package/dist/components/Breadcrumbs.js +3 -2
  21. package/dist/components/Button.d.ts +12 -5
  22. package/dist/components/Button.js +7 -3
  23. package/dist/components/Card.d.ts +18 -1
  24. package/dist/components/Card.js +5 -1
  25. package/dist/components/ChangeHighlight.d.ts +30 -0
  26. package/dist/components/ChangeHighlight.js +21 -0
  27. package/dist/components/ChartCore.js +2 -1
  28. package/dist/components/Checkbox.d.ts +27 -1
  29. package/dist/components/Checkbox.js +31 -2
  30. package/dist/components/Chip.d.ts +7 -3
  31. package/dist/components/Chip.js +2 -2
  32. package/dist/components/CodeDisplay.d.ts +65 -0
  33. package/dist/components/CodeDisplay.js +124 -0
  34. package/dist/components/Combobox.d.ts +27 -6
  35. package/dist/components/Combobox.js +195 -58
  36. package/dist/components/CommandPalette.d.ts +36 -1
  37. package/dist/components/CommandPalette.js +254 -2
  38. package/dist/components/ContactCard.d.ts +66 -0
  39. package/dist/components/ContactCard.js +74 -0
  40. package/dist/components/Count.d.ts +24 -0
  41. package/dist/components/Count.js +32 -0
  42. package/dist/components/DashboardCanvas.js +14 -0
  43. package/dist/components/DataWorkspace.d.ts +167 -0
  44. package/dist/components/DataWorkspace.js +380 -0
  45. package/dist/components/DateFieldParts.d.ts +2 -1
  46. package/dist/components/DateFieldParts.js +7 -0
  47. package/dist/components/DatePicker.d.ts +9 -2
  48. package/dist/components/DatePicker.js +67 -28
  49. package/dist/components/DateRangePicker.d.ts +12 -2
  50. package/dist/components/DateRangePicker.js +13 -12
  51. package/dist/components/DetailPage.d.ts +7 -1
  52. package/dist/components/DetailPage.js +2 -1
  53. package/dist/components/Dialogs.d.ts +71 -10
  54. package/dist/components/Dialogs.js +130 -30
  55. package/dist/components/DiffViewer.d.ts +23 -3
  56. package/dist/components/DiffViewer.js +26 -12
  57. package/dist/components/DiscardPrompt.js +16 -0
  58. package/dist/components/DisplayPreferences.d.ts +83 -0
  59. package/dist/components/DisplayPreferences.js +185 -0
  60. package/dist/components/EditorialHome.d.ts +23 -3
  61. package/dist/components/EditorialHome.js +16 -11
  62. package/dist/components/EntityPicker.d.ts +20 -3
  63. package/dist/components/EntityPicker.js +32 -13
  64. package/dist/components/FilterEditor.d.ts +18 -4
  65. package/dist/components/FilterEditor.js +141 -19
  66. package/dist/components/FocusOnMount.d.ts +282 -0
  67. package/dist/components/FocusOnMount.js +12 -0
  68. package/dist/components/InfoTip.js +11 -12
  69. package/dist/components/InlineEdit.d.ts +87 -20
  70. package/dist/components/InlineEdit.js +197 -54
  71. package/dist/components/Input.d.ts +12 -2
  72. package/dist/components/Input.js +5 -3
  73. package/dist/components/Kanban.d.ts +14 -3
  74. package/dist/components/Kanban.js +9 -4
  75. package/dist/components/Kbd.d.ts +6 -1
  76. package/dist/components/Kbd.js +6 -6
  77. package/dist/components/Lightbox.d.ts +41 -5
  78. package/dist/components/Lightbox.js +95 -9
  79. package/dist/components/MatchReview.d.ts +40 -1
  80. package/dist/components/MatchReview.js +130 -4
  81. package/dist/components/MetricInput.js +3 -2
  82. package/dist/components/Modal.d.ts +2 -1
  83. package/dist/components/Modal.js +13 -4
  84. package/dist/components/MotionList.d.ts +303 -0
  85. package/dist/components/MotionList.js +175 -0
  86. package/dist/components/NavFavourites.d.ts +5 -0
  87. package/dist/components/NavFavourites.js +7 -7
  88. package/dist/components/OtpInput.d.ts +33 -0
  89. package/dist/components/OtpInput.js +123 -0
  90. package/dist/components/PageHeader.d.ts +7 -1
  91. package/dist/components/PageHeader.js +2 -2
  92. package/dist/components/Pagination.js +6 -5
  93. package/dist/components/PasswordInput.d.ts +34 -0
  94. package/dist/components/PasswordInput.js +101 -0
  95. package/dist/components/Peek.js +3 -3
  96. package/dist/components/Popover.js +11 -0
  97. package/dist/components/PrintLayout.d.ts +63 -0
  98. package/dist/components/PrintLayout.js +114 -0
  99. package/dist/components/QrCode.d.ts +47 -0
  100. package/dist/components/QrCode.js +55 -0
  101. package/dist/components/QrScanner.d.ts +95 -0
  102. package/dist/components/QrScanner.js +266 -0
  103. package/dist/components/RelationshipGraph.d.ts +32 -1
  104. package/dist/components/RelationshipGraph.js +22 -6
  105. package/dist/components/RelationshipGraphLayered.d.ts +1 -1
  106. package/dist/components/RelationshipGraphLayered.js +268 -118
  107. package/dist/components/RelationshipGraphList.js +33 -6
  108. package/dist/components/RuleBuilder.js +39 -7
  109. package/dist/components/SchedulingAgenda.d.ts +3 -1
  110. package/dist/components/SchedulingCalendar.d.ts +3 -1
  111. package/dist/components/SchedulingCalendar.js +43 -4
  112. package/dist/components/SchedulingResourceDay.d.ts +57 -0
  113. package/dist/components/SchedulingResourceDay.js +287 -0
  114. package/dist/components/SchedulingTimeGrid.d.ts +3 -1
  115. package/dist/components/SchedulingTimeline.d.ts +3 -1
  116. package/dist/components/SearchSuggest.d.ts +23 -3
  117. package/dist/components/SearchSuggest.js +56 -18
  118. package/dist/components/Segmented.d.ts +39 -4
  119. package/dist/components/Segmented.js +39 -5
  120. package/dist/components/Select.d.ts +3 -2
  121. package/dist/components/Select.js +7 -1
  122. package/dist/components/ShortcutHint.d.ts +11 -10
  123. package/dist/components/ShortcutHint.js +44 -38
  124. package/dist/components/Sidebar.d.ts +36 -4
  125. package/dist/components/Sidebar.js +37 -12
  126. package/dist/components/SortableList.d.ts +45 -0
  127. package/dist/components/SortableList.js +147 -0
  128. package/dist/components/Stat.d.ts +28 -3
  129. package/dist/components/Stat.js +13 -3
  130. package/dist/components/States.d.ts +33 -1
  131. package/dist/components/States.js +43 -1
  132. package/dist/components/StatusPill.d.ts +14 -3
  133. package/dist/components/StatusPill.js +11 -3
  134. package/dist/components/Steps.js +2 -1
  135. package/dist/components/Table.d.ts +9 -2
  136. package/dist/components/Table.js +4 -2
  137. package/dist/components/TableControls.js +18 -58
  138. package/dist/components/TableOverflowProbe.d.ts +12 -0
  139. package/dist/components/TableOverflowProbe.js +27 -0
  140. package/dist/components/Tabs.d.ts +2 -1
  141. package/dist/components/Tabs.js +10 -2
  142. package/dist/components/TagInput.d.ts +67 -0
  143. package/dist/components/TagInput.js +342 -0
  144. package/dist/components/Textarea.d.ts +5 -0
  145. package/dist/components/Textarea.js +2 -2
  146. package/dist/components/TimePicker.d.ts +80 -0
  147. package/dist/components/TimePicker.js +347 -0
  148. package/dist/components/Toast.d.ts +1 -1
  149. package/dist/components/Toast.js +109 -4
  150. package/dist/components/Tooltip.d.ts +8 -4
  151. package/dist/components/Tooltip.js +86 -28
  152. package/dist/components/Tree.d.ts +8 -0
  153. package/dist/components/Tree.js +11 -5
  154. package/dist/display-preferences-model.d.ts +53 -0
  155. package/dist/display-preferences-model.js +64 -0
  156. package/dist/emoji.cjs +143 -49
  157. package/dist/filter-model.d.ts +59 -3
  158. package/dist/filter-model.js +67 -2
  159. package/dist/hooks/useAnchoredPosition.js +14 -2
  160. package/dist/hooks/useChangeHighlight.d.ts +33 -0
  161. package/dist/hooks/useChangeHighlight.js +44 -0
  162. package/dist/hooks/useDeferredReorder.d.ts +32 -0
  163. package/dist/hooks/useDeferredReorder.js +47 -0
  164. package/dist/hooks/useDialog.d.ts +5 -0
  165. package/dist/hooks/useDialog.js +17 -3
  166. package/dist/hooks/useKeyboardGrab.d.ts +58 -0
  167. package/dist/hooks/useKeyboardGrab.js +118 -0
  168. package/dist/hooks/useOptimisticValue.d.ts +51 -0
  169. package/dist/hooks/useOptimisticValue.js +61 -0
  170. package/dist/hooks/useReducedMotion.d.ts +4 -1
  171. package/dist/hooks/useReducedMotion.js +7 -1
  172. package/dist/hooks/useResolvedFilterLabels.d.ts +15 -0
  173. package/dist/hooks/useResolvedFilterLabels.js +34 -0
  174. package/dist/hooks/useSlidingIndicator.d.ts +18 -0
  175. package/dist/hooks/useSlidingIndicator.js +80 -0
  176. package/dist/hooks/useVirtualRows.d.ts +21 -2
  177. package/dist/hooks/useVirtualRows.js +30 -3
  178. package/dist/icons/Icon.d.ts +1 -1
  179. package/dist/index.cjs +19687 -13423
  180. package/dist/index.d.cts +3419 -651
  181. package/dist/index.d.ts +48 -18
  182. package/dist/index.js +153 -9
  183. package/dist/labels-context.d.ts +93 -3
  184. package/dist/motion.d.ts +11 -0
  185. package/dist/motion.js +35 -0
  186. package/dist/overlay-stack.d.ts +6 -0
  187. package/dist/overlay-stack.js +13 -0
  188. package/dist/qr-model.d.ts +65 -0
  189. package/dist/qr-model.js +323 -0
  190. package/dist/relationship-graph-model.d.ts +92 -3
  191. package/dist/relationship-graph-model.js +134 -15
  192. package/dist/reorder.d.ts +30 -0
  193. package/dist/reorder.js +74 -0
  194. package/dist/rich-text.cjs +46 -4
  195. package/dist/scheduling-resource-model.d.ts +76 -0
  196. package/dist/scheduling-resource-model.js +74 -0
  197. package/dist/search-suggest-model.js +3 -1
  198. package/dist/shell-context.d.ts +11 -0
  199. package/dist/shell-context.js +7 -0
  200. package/dist/time-field-model.d.ts +46 -0
  201. package/dist/time-field-model.js +152 -0
  202. package/dist/toast-store.d.ts +22 -3
  203. package/dist/toast-store.js +26 -9
  204. package/package.json +2 -1
@@ -1,4 +1,6 @@
1
1
  import 'react';
2
2
  import '../calendar-model.js';
3
3
  import '../scheduling-calendar-model.js';
4
- export { D as DEFAULT_SCHEDULING_CALENDAR_LABELS, S as SchedulingAgendaGroup, a as SchedulingBand, b as SchedulingCalendar, c as SchedulingCalendarDay, d as SchedulingCalendarEntry, e as SchedulingCalendarLabels, f as SchedulingCalendarOverlay, g as SchedulingCalendarProps, h as SchedulingCalendarView, i as SchedulingDatePart, j as SchedulingEntryState, k as SchedulingLegendItem, l as SchedulingMarker, m as SchedulingMarkerEmphasis, n as SchedulingOverlayKind, o as SchedulingOverlayPattern, p as SchedulingStatus } from '../SchedulingCalendar-B6TakO2h.js';
4
+ import './SchedulingResourceDay.js';
5
+ import '../scheduling-resource-model.js';
6
+ export { D as DEFAULT_SCHEDULING_CALENDAR_LABELS, S as SchedulingAgendaGroup, a as SchedulingBand, b as SchedulingCalendar, c as SchedulingCalendarDay, d as SchedulingCalendarEntry, e as SchedulingCalendarLabels, f as SchedulingCalendarOverlay, g as SchedulingCalendarProps, h as SchedulingCalendarView, i as SchedulingDatePart, j as SchedulingEntryState, k as SchedulingLegendItem, l as SchedulingMarker, m as SchedulingMarkerEmphasis, n as SchedulingOverlayKind, o as SchedulingOverlayPattern, p as SchedulingStatus } from '../SchedulingCalendar-WWyFL3Eo.js';
@@ -6,6 +6,7 @@ import { addCalendarDays, addCalendarMonths, buildMonthGrid, cachedDateTimeForma
6
6
  import { TOP_LANE_CROSS_MIDNIGHT_MINUTES, itemDaySpan, layoutMonthSpans } from "../scheduling-calendar-model.js";
7
7
  import { SchedulingAgenda } from "./SchedulingAgenda.js";
8
8
  import { SchedulingTimeGrid } from "./SchedulingTimeGrid.js";
9
+ import { SchedulingResourceDay } from "./SchedulingResourceDay.js";
9
10
  import { cx } from "../cx.js";
10
11
  import { useUixLabels } from "../labels-context.js";
11
12
  import { StatusPill } from "./StatusPill.js";
@@ -54,7 +55,13 @@ const DEFAULT_SCHEDULING_CALENDAR_LABELS = {
54
55
  moveHint: "Hold Shift and press an arrow key to move it. Enter confirms, Escape cancels.",
55
56
  moveProposed: "Move to {start} \u2013 {end}. Enter confirms, Escape cancels.",
56
57
  moveCancelled: "Move cancelled.",
57
- gapForward: "That time does not exist on this day. Moved forward to {time}."
58
+ gapForward: "That time does not exist on this day. Moved forward to {time}.",
59
+ resourceGrid: "Schedule by person for {date}",
60
+ availability: { free: "Free", booked: "Booked", off: "Off" },
61
+ noSchedule: "No schedule",
62
+ slotName: "{resource}, {start} \u2013 {end}, {kind}, {label}",
63
+ resourceHint: "Arrow keys move between times and people. Enter selects.",
64
+ noResources: "No one to show for this day."
58
65
  };
59
66
  const stateTone = (state) => state === "scheduled" ? "info" : state === "in-progress" ? "success" : "danger";
60
67
  const utcDate = (date) => /* @__PURE__ */ new Date(`${date}T00:00:00Z`);
@@ -67,6 +74,7 @@ const INTL_PARTS = {
67
74
  const EMPTY_OVERLAYS = [];
68
75
  const EMPTY_ENTRIES = [];
69
76
  const EMPTY_IDS = [];
77
+ const EMPTY_SPANS = [];
70
78
  const DEFAULT_LANE_CAP = 2;
71
79
  const DEFAULT_CHIP_ROWS = 3;
72
80
  function coveredDays(start, end, timeZone) {
@@ -126,6 +134,15 @@ function SchedulingCalendar({
126
134
  topLaneCrossMidnightMinutes = TOP_LANE_CROSS_MIDNIGHT_MINUTES,
127
135
  topLaneCap = 3,
128
136
  maxLanes = 4,
137
+ resources,
138
+ resourceSpans = EMPTY_SPANS,
139
+ slotMinutes,
140
+ dayStart,
141
+ dayEnd,
142
+ onSelectSlot,
143
+ selectedSlot,
144
+ resourceLayout = "auto",
145
+ resourceListBelow = 480,
129
146
  loading,
130
147
  error,
131
148
  onRetry,
@@ -138,12 +155,14 @@ function SchedulingCalendar({
138
155
  ...DEFAULT_SCHEDULING_CALENDAR_LABELS,
139
156
  ...overrides,
140
157
  states: { ...DEFAULT_SCHEDULING_CALENDAR_LABELS.states, ...uixLabels.schedulingCalendar?.states, ...labelOverrides?.states },
141
- statuses: { ...DEFAULT_SCHEDULING_CALENDAR_LABELS.statuses, ...uixLabels.schedulingCalendar?.statuses, ...labelOverrides?.statuses }
158
+ statuses: { ...DEFAULT_SCHEDULING_CALENDAR_LABELS.statuses, ...uixLabels.schedulingCalendar?.statuses, ...labelOverrides?.statuses },
159
+ availability: { ...DEFAULT_SCHEDULING_CALENDAR_LABELS.availability, ...uixLabels.schedulingCalendar?.availability, ...labelOverrides?.availability }
142
160
  };
143
161
  const stateLabel = labels.states;
144
162
  const viewLabel = { month: labels.viewMonth, week: labels.viewWeek, day: labels.viewDay, agenda: labels.viewAgenda };
145
163
  const [internalView, setInternalView] = useState("month");
146
164
  const view = controlledView ?? internalView;
165
+ const resourceDay = view === "day" && resources !== void 0;
147
166
  const [activeDate, setActiveDate] = useState(anchorDate);
148
167
  const [expandedDates, setExpandedDates] = useState(() => /* @__PURE__ */ new Set());
149
168
  const dateText = (date, part) => formatDate?.(date, part) ?? cachedDateTimeFormat(locale, INTL_PARTS[part]).format(utcDate(date));
@@ -444,10 +463,30 @@ function SchedulingCalendar({
444
463
  /* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => movePeriod(1), disabled: !onAnchorDateChange, children: periodLabel("next") })
445
464
  ] }),
446
465
  /* @__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")}` }),
447
- /* @__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)) })
466
+ /* @__PURE__ */ jsx("div", { className: "uix-segmented", role: "group", "aria-label": labels.viewGroup, children: (timeGrid || view === "day" || resources !== void 0 ? ["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)) })
448
467
  ] }),
449
468
  notice != null && notice !== false && /* @__PURE__ */ jsx("div", { className: "uix-scheduling-calendar__notice", children: notice }),
450
- 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: [
469
+ resourceDay && !error ? /* @__PURE__ */ jsx(
470
+ SchedulingResourceDay,
471
+ {
472
+ date: anchorDate,
473
+ timeZone,
474
+ resources,
475
+ spans: resourceSpans,
476
+ dayStart,
477
+ dayEnd,
478
+ slotMinutes,
479
+ layout: resourceLayout,
480
+ listBelow: resourceListBelow,
481
+ loading,
482
+ selected: selectedSlot,
483
+ onSelectSlot,
484
+ labels,
485
+ dateText: dateText(anchorDate, "day"),
486
+ headingLevel: agendaHeadingLevel,
487
+ emptyNote
488
+ }
489
+ ) : 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: [
451
490
  /* @__PURE__ */ jsx("p", { children: error }),
452
491
  onRetry && /* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: labels.retry })
453
492
  ] }) : view === "agenda" && agendaGroups ? /* @__PURE__ */ jsx(
@@ -0,0 +1,57 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { SchedulingAvailabilityKind, SchedulingResourceSpan, SchedulingResource } from '../scheduling-resource-model.js';
4
+
5
+ /** What `onSelectSlot` receives: the resource, the piece's own start and end, and the span it belongs to. */
6
+ interface SchedulingSlotSelection {
7
+ resourceId: string;
8
+ /** ISO 8601 instants of the piece: one slot of a free span, or the whole booking. */
9
+ start: string;
10
+ end: string;
11
+ kind: Exclude<SchedulingAvailabilityKind, 'off'>;
12
+ span: SchedulingResourceSpan;
13
+ }
14
+ /** The words of the resource day. Every one is optional in `SchedulingCalendarLabels`. */
15
+ interface SchedulingResourceLabels {
16
+ /** Names the view. `{date}` placeholder. */
17
+ resourceGrid: string;
18
+ /** The words for the kinds, in names and in the list. */
19
+ availability: Record<SchedulingAvailabilityKind, string>;
20
+ /** Time no span covers. */
21
+ noSchedule: string;
22
+ /** A slot's or a booking's accessible name. `{resource}`, `{start}`, `{end}`, `{kind}`, `{label}`. */
23
+ slotName: string;
24
+ /** How to move, read once with the view. */
25
+ resourceHint: string;
26
+ /** When `resources` is empty. */
27
+ noResources: string;
28
+ /** While `loading` and nothing is shown yet. */
29
+ loading: string;
30
+ /** The time-zone corner of the axis. `{timeZone}`. */
31
+ timeZone: string;
32
+ }
33
+ interface SchedulingResourceDayProps {
34
+ date: string;
35
+ timeZone: string;
36
+ resources: readonly SchedulingResource[];
37
+ spans: readonly SchedulingResourceSpan[];
38
+ dayStart?: string;
39
+ dayEnd?: string;
40
+ slotMinutes?: number;
41
+ layout: 'auto' | 'columns' | 'list';
42
+ listBelow: number;
43
+ loading?: boolean;
44
+ selected?: {
45
+ resourceId: string;
46
+ start: string;
47
+ };
48
+ onSelectSlot?: (slot: SchedulingSlotSelection) => void;
49
+ labels: SchedulingResourceLabels;
50
+ dateText: string;
51
+ headingLevel: 2 | 3 | 4 | 5 | 6;
52
+ emptyNote?: ReactNode;
53
+ }
54
+ /** The resource day: columns where there is room, a list where there is not. */
55
+ declare function SchedulingResourceDay({ date, timeZone, resources, spans, dayStart, dayEnd, slotMinutes, layout, listBelow, loading, selected, onSelectSlot, labels, dateText, headingLevel, emptyNote, }: SchedulingResourceDayProps): react.JSX.Element;
56
+
57
+ export { SchedulingResourceDay, type SchedulingResourceDayProps, type SchedulingResourceLabels, type SchedulingSlotSelection };
@@ -0,0 +1,287 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { memo, useEffect, useId, useMemo, useRef, useState } from "react";
4
+ import { zonedTimeOfDay } from "../calendar-model.js";
5
+ import { fillLabel } from "../fill-label.js";
6
+ import { PlusIcon } from "../icons/components.js";
7
+ import { useDelayedPending } from "../hooks/useDelayedPending.js";
8
+ import { layoutResourceColumn, resourceDayGaps, resourceDaySlots } from "../scheduling-resource-model.js";
9
+ const vars = (values) => values;
10
+ const iso = (ms) => new Date(ms).toISOString();
11
+ const stopKey = (column, item) => `${column}:${item.key}`;
12
+ function itemName(resource, item, timeZone, labels) {
13
+ if (item.span.accessibleName && item.kind !== "free") return item.span.accessibleName;
14
+ const name = fillLabel(labels.slotName, {
15
+ resource: resource.label,
16
+ start: zonedTimeOfDay(item.start, timeZone),
17
+ end: zonedTimeOfDay(item.end, timeZone),
18
+ kind: labels.availability[item.kind],
19
+ label: item.span.label ?? ""
20
+ });
21
+ return name.replace(/,\s*$/, "").replace(/,\s*,/g, ",");
22
+ }
23
+ const Column = memo(function Column2({ index, resource, items, slots, timeZone, labels, tabStop, selectedKey, skeleton, onSelect }) {
24
+ return /* @__PURE__ */ jsxs("div", { className: "uix-scheduling-calendar__rs-column", role: "group", "aria-label": resource.label, "data-resource-id": resource.id, style: vars({ "--uix-scheduling-calendar-rs-slots": slots.length }), children: [
25
+ skeleton && [0.2, 0.45, 0.7].map((at) => /* @__PURE__ */ jsx("span", { className: "uix-skeleton uix-scheduling-calendar__rs-skeleton", "aria-hidden": "true", style: vars({ "--uix-scheduling-calendar-rs-offset": Math.floor(slots.length * at), "--uix-scheduling-calendar-rs-length": 3 }) }, at)),
26
+ items.map((item) => {
27
+ const key = stopKey(index, item);
28
+ const time = zonedTimeOfDay(item.start, timeZone);
29
+ const selected = selectedKey === key;
30
+ const shared = {
31
+ "data-kind": item.kind,
32
+ "data-span-id": item.span.id,
33
+ "data-continues-before": item.continuesBefore || void 0,
34
+ "data-continues-after": item.continuesAfter || void 0
35
+ };
36
+ const interactive = {
37
+ tabIndex: tabStop === key ? 0 : -1,
38
+ "data-rs-col": index,
39
+ "data-rs-key": key,
40
+ "data-rs-start": item.start,
41
+ "data-selected": selected || void 0,
42
+ "aria-current": selected ? "true" : void 0,
43
+ "aria-label": itemName(resource, item, timeZone, labels),
44
+ onClick: () => onSelect(resource, item)
45
+ };
46
+ if (item.kind === "free") {
47
+ return /* @__PURE__ */ jsx(
48
+ "button",
49
+ {
50
+ type: "button",
51
+ ...shared,
52
+ ...interactive,
53
+ className: "uix-scheduling-calendar__rs-item",
54
+ style: vars({ "--uix-scheduling-calendar-rs-offset": item.offset, "--uix-scheduling-calendar-rs-length": item.length }),
55
+ children: /* @__PURE__ */ jsxs("span", { className: "uix-scheduling-calendar__rs-add", "aria-hidden": "true", children: [
56
+ /* @__PURE__ */ jsx(PlusIcon, {}),
57
+ time
58
+ ] })
59
+ },
60
+ item.key
61
+ );
62
+ }
63
+ const entryStyle = vars({ "--uix-scheduling-calendar-offset": item.offset, "--uix-scheduling-calendar-length": item.length, "--uix-scheduling-calendar-lane": item.lane, "--uix-scheduling-calendar-lanes": item.lanes });
64
+ if (item.kind === "off") {
65
+ return /* @__PURE__ */ jsxs("div", { ...shared, className: "uix-scheduling-calendar__rs-off", style: entryStyle, children: [
66
+ /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__rs-text", children: item.span.label ?? labels.availability.off }),
67
+ /* @__PURE__ */ jsx("span", { className: "uix-visually-hidden", children: itemName(resource, item, timeZone, labels) })
68
+ ] }, item.key);
69
+ }
70
+ return /* @__PURE__ */ jsx("button", { type: "button", ...shared, ...interactive, className: "uix-scheduling-calendar__entry uix-scheduling-calendar__tg-item uix-scheduling-calendar__rs-booking", style: entryStyle, children: /* @__PURE__ */ jsxs("span", { className: "uix-scheduling-calendar__entry-text", children: [
71
+ /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__time", children: time }),
72
+ " ",
73
+ /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__title", children: item.span.label ?? labels.availability.booked })
74
+ ] }) }, item.key);
75
+ })
76
+ ] });
77
+ });
78
+ function SchedulingResourceDay({
79
+ date,
80
+ timeZone,
81
+ resources,
82
+ spans,
83
+ dayStart,
84
+ dayEnd,
85
+ slotMinutes,
86
+ layout,
87
+ listBelow,
88
+ loading = false,
89
+ selected,
90
+ onSelectSlot,
91
+ labels,
92
+ dateText,
93
+ headingLevel,
94
+ emptyNote
95
+ }) {
96
+ const rootRef = useRef(null);
97
+ const hintId = useId();
98
+ const [narrow, setNarrow] = useState(false);
99
+ const slots = useMemo(() => resourceDaySlots(date, timeZone, { dayStart, dayEnd, slotMinutes }), [date, timeZone, dayStart, dayEnd, slotMinutes]);
100
+ const byResource = useMemo(() => {
101
+ const map = /* @__PURE__ */ new Map();
102
+ for (const span of spans) {
103
+ const list2 = map.get(span.resourceId);
104
+ if (list2) list2.push(span);
105
+ else map.set(span.resourceId, [span]);
106
+ }
107
+ return map;
108
+ }, [spans]);
109
+ const columns = useMemo(() => resources.map((resource) => layoutResourceColumn(byResource.get(resource.id) ?? [], slots)), [resources, byResource, slots]);
110
+ const interactive = useMemo(() => columns.flatMap((items, column) => items.filter((item) => item.kind !== "off").map((item) => stopKey(column, item))), [columns]);
111
+ const [active, setActive] = useState(null);
112
+ const tabStop = active && interactive.includes(active) ? active : interactive[0] ?? null;
113
+ const selectedKey = useMemo(() => {
114
+ if (!selected) return null;
115
+ const column = resources.findIndex((resource) => resource.id === selected.resourceId);
116
+ const at = new Date(selected.start).getTime();
117
+ const hit = columns[column]?.find((item) => item.kind !== "off" && item.start <= at && at < item.end);
118
+ return hit ? stopKey(column, hit) : null;
119
+ }, [selected, resources, columns]);
120
+ useEffect(() => {
121
+ const root = rootRef.current;
122
+ if (layout !== "auto" || !root || typeof ResizeObserver === "undefined") return void 0;
123
+ let frame = 0;
124
+ const measure = () => {
125
+ frame = 0;
126
+ setNarrow(root.getBoundingClientRect().width < listBelow);
127
+ };
128
+ const observer = new ResizeObserver(() => {
129
+ if (!frame) frame = requestAnimationFrame(measure);
130
+ });
131
+ observer.observe(root);
132
+ measure();
133
+ return () => {
134
+ observer.disconnect();
135
+ if (frame) cancelAnimationFrame(frame);
136
+ };
137
+ }, [layout, listBelow]);
138
+ const list = layout === "list" || layout === "auto" && narrow;
139
+ const live = useRef({ onSelectSlot });
140
+ live.current = { onSelectSlot };
141
+ const onSelect = useMemo(() => (resource, item) => {
142
+ setActive(stopKey(resources.indexOf(resource), item));
143
+ if (item.kind === "off") return;
144
+ live.current.onSelectSlot?.({ resourceId: resource.id, start: iso(item.start), end: iso(item.end), kind: item.kind, span: item.span });
145
+ }, [resources]);
146
+ const onKeyDown = (event) => {
147
+ const target = event.target;
148
+ if (!target.hasAttribute("data-rs-col") || !["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End"].includes(event.key)) return;
149
+ const all = Array.from(rootRef.current?.querySelectorAll("[data-rs-col]") ?? []);
150
+ const column = Number(target.dataset.rsCol);
151
+ const start = Number(target.dataset.rsStart);
152
+ const inColumn = (c) => all.filter((el) => Number(el.dataset.rsCol) === c).sort((a, b) => Number(a.dataset.rsStart) - Number(b.dataset.rsStart));
153
+ const own = inColumn(column);
154
+ const index = own.indexOf(target);
155
+ let next;
156
+ if (event.key === "ArrowUp") next = own[index - 1];
157
+ else if (event.key === "ArrowDown") next = own[index + 1];
158
+ else if (event.key === "Home") next = own[0];
159
+ else if (event.key === "End") next = own[own.length - 1];
160
+ else {
161
+ const direction = event.key === "ArrowLeft" ? -1 : 1;
162
+ for (let c = column + direction; c >= 0 && c < resources.length && !next; c += direction) {
163
+ const candidates = inColumn(c);
164
+ next = candidates.reduce((best, el) => !best || Math.abs(Number(el.dataset.rsStart) - start) < Math.abs(Number(best.dataset.rsStart) - start) ? el : best, void 0);
165
+ }
166
+ }
167
+ event.preventDefault();
168
+ if (!next) return;
169
+ setActive(next.dataset.rsKey ?? null);
170
+ next.focus();
171
+ };
172
+ const showPending = useDelayedPending(loading);
173
+ const firstLoad = loading && spans.length === 0;
174
+ const skeleton = showPending && spans.length === 0;
175
+ const Heading = `h${headingLevel}`;
176
+ const gridLabel = fillLabel(labels.resourceGrid, { date: dateText });
177
+ const status = showPending ? /* @__PURE__ */ jsx("span", { role: "status", className: skeleton ? "uix-visually-hidden" : "uix-scheduling-calendar__rs-busy", children: labels.loading }) : null;
178
+ if (resources.length === 0) {
179
+ return /* @__PURE__ */ jsx("div", { ref: rootRef, className: "uix-scheduling-calendar__resources", "data-empty": true, children: /* @__PURE__ */ jsx("div", { className: "uix-scheduling-calendar__empty", children: loading ? labels.loading : emptyNote ?? labels.noResources }) });
180
+ }
181
+ if (list) {
182
+ return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: "uix-scheduling-calendar__resources", "data-layout": "list", role: "group", "aria-label": gridLabel, "aria-describedby": hintId, "aria-busy": loading || void 0, "data-loading": loading || void 0, "data-first-load": firstLoad || void 0, onKeyDown, children: [
183
+ status,
184
+ resources.map((resource, column) => {
185
+ const items = columns[column];
186
+ const rows = [
187
+ ...items.map((item) => ({ key: item.key, start: item.start, end: item.end, item })),
188
+ ...resourceDayGaps(items, slots).map((gap) => ({ key: `gap-${gap.start}`, start: gap.start, end: gap.end }))
189
+ ].sort((a, b) => a.start - b.start);
190
+ const headingId = `${hintId}-r${column}`;
191
+ return /* @__PURE__ */ jsxs("section", { className: "uix-scheduling-calendar__rs-section", "aria-labelledby": headingId, "data-resource-id": resource.id, children: [
192
+ /* @__PURE__ */ jsxs(Heading, { id: headingId, className: "uix-scheduling-calendar__rs-heading", children: [
193
+ resource.label,
194
+ resource.description && /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__rs-description", children: resource.description })
195
+ ] }),
196
+ skeleton ? /* @__PURE__ */ jsx("span", { className: "uix-skeleton uix-scheduling-calendar__rs-skeleton", "aria-hidden": "true" }) : /* @__PURE__ */ jsx("ol", { className: "uix-scheduling-calendar__rs-list", children: rows.map((row) => {
197
+ const range = `${zonedTimeOfDay(row.start, timeZone)} \u2013 ${zonedTimeOfDay(row.end, timeZone)}`;
198
+ if (!row.item) return /* @__PURE__ */ jsxs("li", { className: "uix-scheduling-calendar__rs-row", "data-kind": "none", children: [
199
+ /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__rs-range", children: range }),
200
+ /* @__PURE__ */ jsx("span", { children: labels.noSchedule })
201
+ ] }, row.key);
202
+ const item = row.item;
203
+ const key = stopKey(column, item);
204
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
205
+ /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__rs-range", children: range }),
206
+ /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__rs-kind", children: labels.availability[item.kind] }),
207
+ item.span.label && /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__rs-label", children: item.span.label })
208
+ ] });
209
+ if (item.kind === "off") return /* @__PURE__ */ jsx("li", { className: "uix-scheduling-calendar__rs-row", "data-kind": "off", children: content }, row.key);
210
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
211
+ "button",
212
+ {
213
+ type: "button",
214
+ className: "uix-scheduling-calendar__rs-row",
215
+ "data-kind": item.kind,
216
+ tabIndex: tabStop === key ? 0 : -1,
217
+ "data-rs-col": column,
218
+ "data-rs-key": key,
219
+ "data-rs-start": item.start,
220
+ "data-selected": selectedKey === key || void 0,
221
+ "aria-current": selectedKey === key ? "true" : void 0,
222
+ "aria-label": itemName(resource, item, timeZone, labels),
223
+ onClick: () => onSelect(resource, item),
224
+ children: content
225
+ }
226
+ ) }, row.key);
227
+ }) })
228
+ ] }, resource.id);
229
+ }),
230
+ /* @__PURE__ */ jsx("p", { id: hintId, className: "uix-visually-hidden", children: labels.resourceHint }),
231
+ emptyNote != null && emptyNote !== false && !loading && spans.length === 0 && /* @__PURE__ */ jsx("div", { className: "uix-scheduling-calendar__empty", children: emptyNote })
232
+ ] });
233
+ }
234
+ const zoneBreakable = timeZone.replace(/\//g, "/\u200B");
235
+ const showAll = slots.length > 1 && slots[1].start - slots[0].start >= 30 * 6e4;
236
+ const slotMs = slots.length > 1 ? slots[1].start - slots[0].start : 60 * 6e4;
237
+ const perHour = Math.max(1, Math.round(36e5 / slotMs));
238
+ const hourAt = Math.max(0, slots.findIndex((slot) => slot.label.endsWith(":00")));
239
+ return /* @__PURE__ */ jsxs(
240
+ "div",
241
+ {
242
+ ref: rootRef,
243
+ className: "uix-scheduling-calendar__resources",
244
+ "data-layout": "columns",
245
+ role: "group",
246
+ "aria-label": gridLabel,
247
+ "aria-describedby": hintId,
248
+ "aria-busy": loading || void 0,
249
+ "data-loading": loading || void 0,
250
+ "data-first-load": firstLoad || void 0,
251
+ onKeyDown,
252
+ style: vars({ "--uix-scheduling-calendar-rs-columns": resources.length, "--uix-scheduling-calendar-rs-slots": slots.length, "--uix-scheduling-calendar-rs-per-hour": perHour, "--uix-scheduling-calendar-rs-hour-at": hourAt % perHour }),
253
+ children: [
254
+ status,
255
+ /* @__PURE__ */ jsx("div", { className: "uix-scheduling-calendar__rs-scroll", tabIndex: interactive.length === 0 ? 0 : void 0, children: /* @__PURE__ */ jsxs("div", { className: "uix-scheduling-calendar__rs-grid", children: [
256
+ /* @__PURE__ */ jsx("div", { className: "uix-scheduling-calendar__rs-corner", children: fillLabel(labels.timeZone, { timeZone: zoneBreakable }) }),
257
+ resources.map((resource) => /* @__PURE__ */ jsxs("div", { className: "uix-scheduling-calendar__rs-head", "aria-hidden": "true", children: [
258
+ /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__rs-name", children: resource.label }),
259
+ resource.description && /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__rs-description", children: resource.description })
260
+ ] }, resource.id)),
261
+ /* @__PURE__ */ jsx("div", { className: "uix-scheduling-calendar__rs-gutter", "aria-hidden": "true", style: vars({ "--uix-scheduling-calendar-rs-slots": slots.length }), children: slots.map((slot, index) => (showAll || slot.label.endsWith(":00")) && /* @__PURE__ */ jsx("span", { className: "uix-scheduling-calendar__rs-tick", style: vars({ "--uix-scheduling-calendar-rs-offset": index }), children: slot.label }, slot.start)) }),
262
+ resources.map((resource, column) => /* @__PURE__ */ jsx(
263
+ Column,
264
+ {
265
+ index: column,
266
+ resource,
267
+ items: columns[column],
268
+ slots,
269
+ timeZone,
270
+ labels,
271
+ tabStop: tabStop?.startsWith(`${column}:`) ? tabStop : null,
272
+ selectedKey: selectedKey?.startsWith(`${column}:`) ? selectedKey : null,
273
+ skeleton,
274
+ onSelect
275
+ },
276
+ resource.id
277
+ ))
278
+ ] }) }),
279
+ /* @__PURE__ */ jsx("p", { id: hintId, className: "uix-visually-hidden", children: labels.resourceHint }),
280
+ emptyNote != null && emptyNote !== false && !loading && spans.length === 0 && /* @__PURE__ */ jsx("div", { className: "uix-scheduling-calendar__empty", children: emptyNote })
281
+ ]
282
+ }
283
+ );
284
+ }
285
+ export {
286
+ SchedulingResourceDay
287
+ };
@@ -1,4 +1,6 @@
1
1
  import 'react';
2
2
  import '../scheduling-calendar-model.js';
3
- export { q as SchedulingTimeGrid, r as SchedulingTimeGridProps, T as TimeGridEntryContext } from '../SchedulingCalendar-B6TakO2h.js';
3
+ export { q as SchedulingTimeGrid, r as SchedulingTimeGridProps, T as TimeGridEntryContext } from '../SchedulingCalendar-WWyFL3Eo.js';
4
4
  import '../calendar-model.js';
5
+ import './SchedulingResourceDay.js';
6
+ import '../scheduling-resource-model.js';
@@ -2,8 +2,10 @@ import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
  import { MoveProposal } from '../scheduling-calendar-model.js';
4
4
  import { TimelineRange, TimelineScale } from '../scheduling-timeline-model.js';
5
- import { j as SchedulingEntryState, p as SchedulingStatus, a as SchedulingBand, l as SchedulingMarker, o as SchedulingOverlayPattern } from '../SchedulingCalendar-B6TakO2h.js';
5
+ import { j as SchedulingEntryState, p as SchedulingStatus, a as SchedulingBand, l as SchedulingMarker, o as SchedulingOverlayPattern } from '../SchedulingCalendar-WWyFL3Eo.js';
6
6
  import '../calendar-model.js';
7
+ import './SchedulingResourceDay.js';
8
+ import '../scheduling-resource-model.js';
7
9
 
8
10
  interface SchedulingTimelineLane {
9
11
  id: string;
@@ -29,8 +29,19 @@ interface SearchSuggestProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onCha
29
29
  onValueChange: (value: string) => void;
30
30
  /** The suggestions to show, best first. The consumer filters; this component only renders. */
31
31
  options: readonly SearchSuggestOption[];
32
- /** Called when a row is chosen by click or Enter. The list closes afterwards. */
33
- onSelect: (id: string, option: SearchSuggestOption) => void;
32
+ /**
33
+ * Called when a row is chosen by click or Enter. The list closes afterwards. Optional with
34
+ * `freeText`, where choosing a row also puts its title in the field.
35
+ */
36
+ onSelect?: (id: string, option: SearchSuggestOption) => void;
37
+ /**
38
+ * A text field with suggestions, not a search (HAR-2465): the value is the text. Enter keeps
39
+ * what was typed and never submits the surrounding form; no row is picked unless the person
40
+ * moves to it (ArrowDown / ArrowUp, then Enter) or clicks it, and then its title replaces the
41
+ * text (`onValueChange`) without submitting either. Blur, Tab and Escape keep the text; while
42
+ * `loading`, Enter does nothing. No magnifier is drawn.
43
+ */
44
+ freeText?: boolean;
34
45
  /** Accessible name of the field (there is no visible label; the placeholder is not a label). */
35
46
  label: string;
36
47
  placeholder?: string;
@@ -89,6 +100,15 @@ interface SearchSuggestProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onCha
89
100
  inputId?: string;
90
101
  /** `aria-describedby` of the input (hint and error text from a `Field`). */
91
102
  inputDescribedBy?: string;
103
+ /**
104
+ * Ids of the visible label(s) that name the input (HAR-1834). With them, or with a
105
+ * `<label for={inputId}>`, the input gets no `aria-label`, so the visible label is its name.
106
+ */
107
+ inputLabelledBy?: string;
108
+ /** The field cannot be typed in and the list never opens (HAR-1834). */
109
+ disabled?: boolean;
110
+ /** Marks the input `aria-invalid` (an empty required field with an error, HAR-1834). */
111
+ invalid?: boolean;
92
112
  }
93
113
  /**
94
114
  * A search field with a suggestion list underneath: the "search and jump" pattern of Windows
@@ -97,6 +117,6 @@ interface SearchSuggestProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onCha
97
117
  * (`aria-activedescendant`), Enter opens it (the first row when none is active), Escape closes the
98
118
  * list and a second Escape clears the text.
99
119
  */
100
- declare function SearchSuggest({ value, onValueChange, options, onSelect, label, placeholder, highlight, heading, headingAction, footer, loading, loadingLabel, empty, idle, note, error, shortcutHint, clearLabel: clearLabelProp, status, size, open: openProp, strategy, onOpenChange, inputRef, autoFocus, name, inputId, inputDescribedBy, className, onBlur, ...props }: SearchSuggestProps): react.JSX.Element;
120
+ declare function SearchSuggest({ value, onValueChange, options, onSelect, freeText, label, placeholder, highlight, heading, headingAction, footer, loading, loadingLabel, empty, idle, note, error, shortcutHint, clearLabel: clearLabelProp, status, size, open: openProp, strategy, onOpenChange, inputRef, autoFocus, name, inputId, inputDescribedBy, inputLabelledBy, disabled, invalid, className, onBlur, ...props }: SearchSuggestProps): react.JSX.Element;
101
121
 
102
122
  export { SearchSuggest, type SearchSuggestAction, type SearchSuggestOption, type SearchSuggestProps };