@tensor_1/react 2.35.0 → 2.37.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 (39) hide show
  1. package/README.md +154 -15
  2. package/dist/components/Avatar.d.ts +26 -4
  3. package/dist/components/Avatar.js +26 -3
  4. package/dist/components/CommandPalette.d.ts +6 -1
  5. package/dist/components/CommandPalette.js +9 -3
  6. package/dist/components/DateFieldParts.d.ts +61 -0
  7. package/dist/components/DateFieldParts.js +195 -0
  8. package/dist/components/DatePicker.d.ts +129 -0
  9. package/dist/components/DatePicker.js +340 -0
  10. package/dist/components/DateRangePicker.d.ts +34 -3
  11. package/dist/components/DateRangePicker.js +120 -17
  12. package/dist/components/EntityPicker.d.ts +29 -4
  13. package/dist/components/EntityPicker.js +20 -8
  14. package/dist/components/InlineEdit.d.ts +74 -0
  15. package/dist/components/InlineEdit.js +176 -0
  16. package/dist/components/Radio.d.ts +23 -2
  17. package/dist/components/Radio.js +18 -3
  18. package/dist/components/SchedulingAgenda.js +3 -1
  19. package/dist/components/SchedulingTimeGrid.js +6 -4
  20. package/dist/components/SchedulingTimeline.d.ts +130 -15
  21. package/dist/components/SchedulingTimeline.js +768 -141
  22. package/dist/components/SearchSuggest.d.ts +12 -1
  23. package/dist/components/SearchSuggest.js +7 -2
  24. package/dist/components/Tree.d.ts +30 -2
  25. package/dist/components/Tree.js +135 -10
  26. package/dist/date-field-model.d.ts +40 -0
  27. package/dist/date-field-model.js +79 -0
  28. package/dist/hooks/usePrinting.d.ts +15 -0
  29. package/dist/hooks/usePrinting.js +29 -0
  30. package/dist/index.cjs +3890 -2070
  31. package/dist/index.d.cts +808 -262
  32. package/dist/index.d.ts +9 -6
  33. package/dist/index.js +40 -4
  34. package/dist/labels-context.d.ts +14 -1
  35. package/dist/scheduling-timeline-model.d.ts +61 -11
  36. package/dist/scheduling-timeline-model.js +85 -26
  37. package/dist/scheduling-timeline-rows.d.ts +40 -0
  38. package/dist/scheduling-timeline-rows.js +42 -0
  39. package/package.json +5 -3
package/dist/index.d.ts CHANGED
@@ -11,12 +11,13 @@ export { Input, InputGroup, InputGroupProps, InputProps } from './components/Inp
11
11
  export { Combobox, ComboboxProps } from './components/Combobox.js';
12
12
  export { ComboboxOption, filterComboboxOptions } from './combobox-model.js';
13
13
  export { SearchSuggest, SearchSuggestAction, SearchSuggestOption, SearchSuggestProps } from './components/SearchSuggest.js';
14
- export { DEFAULT_ENTITY_PICKER_LABELS, EntityPicker, EntityPickerLabels, EntityPickerProps } from './components/EntityPicker.js';
14
+ export { DEFAULT_ENTITY_PICKER_LABELS, EntityPicker, EntityPickerLabels, EntityPickerProps, EntityPickerSearchResult } from './components/EntityPicker.js';
15
15
  export { FoldedText, SearchSegment, foldForSearch, searchSegments } from './search-suggest-model.js';
16
16
  export { Textarea, TextareaProps } from './components/Textarea.js';
17
+ export { DEFAULT_INLINE_EDIT_LABELS, InlineEdit, InlineEditEditorProps, InlineEditLabels, InlineEditProps } from './components/InlineEdit.js';
17
18
  export { Select, SelectLabels, SelectProps } from './components/Select.js';
18
19
  export { Checkbox, CheckboxProps } from './components/Checkbox.js';
19
- export { Radio, RadioGroup, RadioGroupProps, RadioProps } from './components/Radio.js';
20
+ export { Radio, RadioCard, RadioCardProps, RadioGroup, RadioGroupProps, RadioProps } from './components/Radio.js';
20
21
  export { Switch, SwitchProps } from './components/Switch.js';
21
22
  export { Field, FieldProps } from './components/Field.js';
22
23
  export { Modal, ModalProps } from './components/Modal.js';
@@ -66,7 +67,7 @@ export { RelativeTime, RelativeTimeFormatContext, RelativeTimeProps } from './co
66
67
  export { RelativeTimeUnit, RelativeTimeValue, parseDateValue, relativeTimeValue } from './relative-time-model.js';
67
68
  export { AsyncOperationState, AsyncOperationStatus, AsyncOperationStatusProps } from './components/AsyncOperationStatus.js';
68
69
  export { Label, LabelProps } from './components/Label.js';
69
- export { Avatar, AvatarGroup, AvatarGroupProps, AvatarProps, UserChip, UserChipProps } from './components/Avatar.js';
70
+ export { Avatar, AvatarGroup, AvatarGroupProps, AvatarPresence, AvatarProps, DEFAULT_PRESENCE_LABELS, PresenceDot, PresenceDotProps, UserChip, UserChipProps } from './components/Avatar.js';
70
71
  export { Comment, CommentProps, Comments, CommentsProps } from './components/Comments.js';
71
72
  export { DEFAULT_SAVE_STATUS_LABELS, SaveStatus, SaveStatusLabels, SaveStatusProps, SaveStatusState } from './components/SaveStatus.js';
72
73
  export { Composer, ComposerBar, ComposerBarProps, ComposerProps } from './components/Composer.js';
@@ -83,7 +84,7 @@ export { Menu, MenuGroup, MenuGroupProps, MenuItem, MenuItemAttributes, MenuItem
83
84
  export { CommandGroup, CommandGroupProps, CommandItem, CommandItemProps, CommandPalette, CommandPaletteProps } from './components/CommandPalette.js';
84
85
  export { Inbox, InboxDetail, InboxDetailProps, InboxItem, InboxItemProps, InboxList, InboxListProps, InboxProps } from './components/Inbox.js';
85
86
  export { Kanban, KanbanCard, KanbanCardProps, KanbanColumn, KanbanColumnProps, KanbanMoveDirection, KanbanProps } from './components/Kanban.js';
86
- export { Tree, TreeNodeData, TreeNodeProps, TreeProps } from './components/Tree.js';
87
+ export { DEFAULT_TREE_LABELS, Tree, TreeLabels, TreeNodeData, TreeNodeProps, TreeProps } from './components/Tree.js';
87
88
  export { FlatNode, TreeLike, TreeNavAction, flattenTree, treeNav } from './tree-model.js';
88
89
  export { ContentList, ContentListItem, ContentListItemProps, ContentListProps, EventRow, EventRowProps, FeaturedRundown, FeaturedRundownItem, FeaturedRundownItemProps, FeaturedRundownProps, FeaturedStage, FeaturedStageProps, NewsLead, NewsLeadProps, NoticeQueue, NoticeQueueProps, PageIntro, PageIntroProps, ResourceGrid, ResourceGridProps, SectionHead, SectionHeadProps, StatLine, StatLineItem, StatLineProps, StatusRow, StatusRowProps } from './components/EditorialHome.js';
89
90
  export { JsonPrimitive, JsonValue } from './json-value.js';
@@ -92,9 +93,11 @@ export { DEFAULT_RULE_SUMMARY_WORDS, DEFAULT_RULE_VALIDATION_MESSAGES, RuleActio
92
93
  export { BuilderCanvas, BuilderCanvasItem, BuilderCanvasLabels, BuilderCanvasProps, BuilderPaletteItem, DEFAULT_BUILDER_CANVAS_LABELS } from './components/BuilderCanvas.js';
93
94
  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, T as TimeGridEntryContext } from './SchedulingCalendar-B6TakO2h.js';
94
95
  export { DaySpanLayout, LayoutMonthSpansOptions, MonthSpanGroup, MonthSpanInput, MonthSpanLayout, MoveProposal, PlacedDaySpan, PlacedMonthSpan, TOP_LANE_CROSS_MIDNIGHT_MINUTES, TimeGridDayLayout, TimeGridEntryInput, TimeGridPart, TimeGridSegment, itemDaySpan, layoutDaySpans, layoutMonthSpans, layoutTimeGridDay, placesInTopLane, proposeMove, schedulingGridDays } from './scheduling-calendar-model.js';
95
- export { DEFAULT_SCHEDULING_TIMELINE_LABELS, SchedulingTimeline, SchedulingTimelineItem, SchedulingTimelineLabels, SchedulingTimelineLane, SchedulingTimelineMarker, SchedulingTimelineOverlay, SchedulingTimelineOverlayKind, SchedulingTimelineProps } from './components/SchedulingTimeline.js';
96
- export { DAY, HOUR, PlacedSpan, TimelineRange, TimelineScale, TimelineSpan, TimelineTick, defaultTimelineStep, layoutLane, pixelsToMs, placeSpan, shiftSpan, snapToStep, timelineTicks } from './scheduling-timeline-model.js';
96
+ export { DEFAULT_SCHEDULING_TIMELINE_LABELS, SchedulingTimeline, SchedulingTimelineGroup, SchedulingTimelineItem, SchedulingTimelineLabels, SchedulingTimelineLane, SchedulingTimelineMarker, SchedulingTimelineOverlay, SchedulingTimelineOverlayKind, SchedulingTimelineProps } from './components/SchedulingTimeline.js';
97
+ export { DAY, HOUR, LayoutLaneOptions, PlacedSpan, TimelineRange, TimelineScale, TimelineSpan, TimelineSubTick, TimelineTick, defaultTimelineStep, layoutLane, pixelsToMs, placeSpan, shiftSpan, snapToStep, timelineRepeatedHourOffset, timelineStepDelta, timelineSubTicks, timelineTicks } from './scheduling-timeline-model.js';
97
98
  export { DEFAULT_DATE_RANGE_PICKER_LABELS, DateRangePicker, DateRangePickerLabels, DateRangePickerProps } from './components/DateRangePicker.js';
99
+ export { DEFAULT_DATE_PICKER_LABELS, DEFAULT_DATE_TIME_PICKER_LABELS, DateInputProblem, DatePicker, DatePickerLabels, DatePickerProps, DateTimePicker, DateTimePickerLabels, DateTimePickerProps } from './components/DatePicker.js';
100
+ export { DatePart, dateOrder, datePattern, formatDateKey, isValidDateKey, joinDateTime, parseDateInput, splitDateTime, timeZoneName } from './date-field-model.js';
98
101
  export { CalendarDay, CalendarWeekday, DateRangeValue, LaneCluster, LaneInterval, LanePlacement, PackLanesOptions, PackedLanes, ZonedDateSpan, ZonedDayBounds, ZonedDayShift, ZonedDaySpan, ZonedHourSlot, addCalendarDays, addCalendarMonths, addZonedDays, buildMonthGrid, cachedDateTimeFormat, enumerateDateKeys, enumerateDateSpan, isDateInRange, isDateUnavailable, packLanes, rankOverflow, selectRangeDate, startOfMonth, toDateKey, zonedDateKey, zonedDateSpan, zonedDayBounds, zonedDaySpan, zonedHourSlots, zonedTimeOfDay } from './calendar-model.js';
99
102
  export { DEFAULT_RELATIONSHIP_GRAPH_LABELS, RelationshipGraph, RelationshipGraphLabels, RelationshipGraphLegendItem, RelationshipGraphProps } from './components/RelationshipGraph.js';
100
103
  export { BoundedRelationshipGraph, LayeredColumn, LayeredEdgeClassification, LayeredEdgeKind, LayeredItem, LayeredLayout, LayeredLayoutOptions, LayeredNavigationKey, PositionedRelationshipNode, RelationshipGraphArrow, RelationshipGraphCluster, RelationshipGraphEdge, RelationshipGraphNode, RoutedEdge, boundRelationshipGraph, classifyLayeredEdges, clusterIdFor, layeredNeighbor, layoutLayeredGraph, layoutRelationshipGraph, relationshipNeighbors, traverseRelationshipNode, wrapEdgeLabel } from './relationship-graph-model.js';
package/dist/index.js CHANGED
@@ -14,9 +14,10 @@ import { SearchSuggest } from "./components/SearchSuggest.js";
14
14
  import { EntityPicker, DEFAULT_ENTITY_PICKER_LABELS } from "./components/EntityPicker.js";
15
15
  import { searchSegments, foldForSearch } from "./search-suggest-model.js";
16
16
  import { Textarea } from "./components/Textarea.js";
17
+ import { InlineEdit, DEFAULT_INLINE_EDIT_LABELS } from "./components/InlineEdit.js";
17
18
  import { Select } from "./components/Select.js";
18
19
  import { Checkbox } from "./components/Checkbox.js";
19
- import { Radio, RadioGroup } from "./components/Radio.js";
20
+ import { Radio, RadioCard, RadioGroup } from "./components/Radio.js";
20
21
  import { Switch } from "./components/Switch.js";
21
22
  import { Field } from "./components/Field.js";
22
23
  import { Modal } from "./components/Modal.js";
@@ -80,7 +81,7 @@ import { RelativeTime } from "./components/RelativeTime.js";
80
81
  import { parseDateValue, relativeTimeValue } from "./relative-time-model.js";
81
82
  import { AsyncOperationStatus } from "./components/AsyncOperationStatus.js";
82
83
  import { Label } from "./components/Label.js";
83
- import { Avatar, AvatarGroup, UserChip } from "./components/Avatar.js";
84
+ import { Avatar, AvatarGroup, PresenceDot, UserChip, DEFAULT_PRESENCE_LABELS } from "./components/Avatar.js";
84
85
  import { Comments, Comment } from "./components/Comments.js";
85
86
  import { SaveStatus, DEFAULT_SAVE_STATUS_LABELS } from "./components/SaveStatus.js";
86
87
  import { Composer, ComposerBar } from "./components/Composer.js";
@@ -105,7 +106,7 @@ import { Menu, MenuItem, MenuItemRadio, MenuItemCheckbox, MenuRadioGroup, MenuGr
105
106
  import { CommandPalette, CommandGroup, CommandItem } from "./components/CommandPalette.js";
106
107
  import { Inbox, InboxList, InboxItem, InboxDetail } from "./components/Inbox.js";
107
108
  import { Kanban, KanbanColumn, KanbanCard } from "./components/Kanban.js";
108
- import { Tree } from "./components/Tree.js";
109
+ import { Tree, DEFAULT_TREE_LABELS } from "./components/Tree.js";
109
110
  import { flattenTree, treeNav } from "./tree-model.js";
110
111
  import {
111
112
  PageIntro,
@@ -159,9 +160,23 @@ import {
159
160
  placeSpan,
160
161
  shiftSpan,
161
162
  snapToStep,
162
- timelineTicks
163
+ timelineTicks,
164
+ timelineRepeatedHourOffset,
165
+ timelineStepDelta,
166
+ timelineSubTicks
163
167
  } from "./scheduling-timeline-model.js";
164
168
  import { DateRangePicker, DEFAULT_DATE_RANGE_PICKER_LABELS } from "./components/DateRangePicker.js";
169
+ import { DatePicker, DateTimePicker, DEFAULT_DATE_PICKER_LABELS, DEFAULT_DATE_TIME_PICKER_LABELS } from "./components/DatePicker.js";
170
+ import {
171
+ dateOrder,
172
+ datePattern,
173
+ formatDateKey,
174
+ isValidDateKey,
175
+ joinDateTime,
176
+ parseDateInput,
177
+ splitDateTime,
178
+ timeZoneName
179
+ } from "./date-field-model.js";
165
180
  import {
166
181
  addCalendarDays,
167
182
  addCalendarMonths,
@@ -239,15 +254,19 @@ export {
239
254
  DEFAULT_BRAND_PROFILE_EDITOR_LABELS,
240
255
  DEFAULT_BUILDER_CANVAS_LABELS,
241
256
  DEFAULT_COLOR_PICKER_LABELS,
257
+ DEFAULT_DATE_PICKER_LABELS,
242
258
  DEFAULT_DATE_RANGE_PICKER_LABELS,
259
+ DEFAULT_DATE_TIME_PICKER_LABELS,
243
260
  DEFAULT_DIFF_VIEWER_LABELS,
244
261
  DEFAULT_ENTITY_PICKER_LABELS,
245
262
  DEFAULT_FILE_UPLOAD_LABELS,
246
263
  DEFAULT_FILTER_EDITOR_LABELS,
247
264
  DEFAULT_FILTER_SUMMARY_LABELS,
265
+ DEFAULT_INLINE_EDIT_LABELS,
248
266
  DEFAULT_LIGHTBOX_LABELS,
249
267
  DEFAULT_MATCH_REVIEW_LABELS,
250
268
  DEFAULT_PAGINATION_LABELS,
269
+ DEFAULT_PRESENCE_LABELS,
251
270
  DEFAULT_RELATIONSHIP_GRAPH_LABELS,
252
271
  DEFAULT_RULE_BUILDER_LABELS,
253
272
  DEFAULT_RULE_SUMMARY_WORDS,
@@ -257,9 +276,12 @@ export {
257
276
  DEFAULT_SCHEDULING_TIMELINE_LABELS,
258
277
  DEFAULT_STEP_STATE_LABELS,
259
278
  DEFAULT_TEXT_DIFF_LABELS,
279
+ DEFAULT_TREE_LABELS,
260
280
  DashboardGrid,
261
281
  DashboardGridItem,
282
+ DatePicker,
262
283
  DateRangePicker,
284
+ DateTimePicker,
263
285
  DescriptionItem,
264
286
  DescriptionList,
265
287
  DetailLayout,
@@ -290,6 +312,7 @@ export {
290
312
  InboxItem,
291
313
  InboxList,
292
314
  InfoTip,
315
+ InlineEdit,
293
316
  Input,
294
317
  InputGroup,
295
318
  Kanban,
@@ -332,10 +355,12 @@ export {
332
355
  PipelineStage,
333
356
  Popconfirm,
334
357
  Popover,
358
+ PresenceDot,
335
359
  Progress,
336
360
  PromptDialog,
337
361
  Prose,
338
362
  Radio,
363
+ RadioCard,
339
364
  RadioGroup,
340
365
  RelatedLinks,
341
366
  RelationshipGraph,
@@ -408,6 +433,8 @@ export {
408
433
  cx,
409
434
  dashboardGridClassName,
410
435
  dashboardGridItemClassName,
436
+ dateOrder,
437
+ datePattern,
411
438
  defaultTimelineStep,
412
439
  diffText,
413
440
  diffTokens,
@@ -420,6 +447,7 @@ export {
420
447
  findRuleNodeDepth,
421
448
  flattenTree,
422
449
  foldForSearch,
450
+ formatDateKey,
423
451
  formatFileSize,
424
452
  hexToRgb,
425
453
  hsvToHex,
@@ -428,7 +456,9 @@ export {
428
456
  isDateUnavailable,
429
457
  isFilterEmpty,
430
458
  isRuleGroup,
459
+ isValidDateKey,
431
460
  itemDaySpan,
461
+ joinDateTime,
432
462
  layeredNeighbor,
433
463
  layoutDaySpans,
434
464
  layoutLane,
@@ -442,6 +472,7 @@ export {
442
472
  moveRuleNode,
443
473
  normalizeHex,
444
474
  packLanes,
475
+ parseDateInput,
445
476
  parseDateValue,
446
477
  parseMetricValue,
447
478
  partitionFiles,
@@ -464,12 +495,17 @@ export {
464
495
  setRuleCombinator,
465
496
  shiftSpan,
466
497
  snapToStep,
498
+ splitDateTime,
467
499
  startOfMonth,
468
500
  stepMetricValue,
469
501
  summarizeDiff,
470
502
  summarizeFilter,
471
503
  summarizeRule,
472
504
  textDiffRows,
505
+ timeZoneName,
506
+ timelineRepeatedHourOffset,
507
+ timelineStepDelta,
508
+ timelineSubTicks,
473
509
  timelineTicks,
474
510
  toDateKey,
475
511
  toast,
@@ -3,6 +3,7 @@ import { ReactNode } from 'react';
3
3
  import { PaginationLabels } from './components/Pagination.js';
4
4
  import { e as SchedulingCalendarLabels } from './SchedulingCalendar-B6TakO2h.js';
5
5
  import { DateRangePickerLabels } from './components/DateRangePicker.js';
6
+ import { DatePickerLabels, DateTimePickerLabels } from './components/DatePicker.js';
6
7
  import { SchedulingTimelineLabels } from './components/SchedulingTimeline.js';
7
8
  import { TextDiffLabels } from './components/TextDiff.js';
8
9
  import { FilterEditorLabels } from './components/FilterEditor.js';
@@ -10,17 +11,21 @@ import { SelectLabels } from './components/Select.js';
10
11
  import { RuleBuilderLabels } from './components/RuleBuilder.js';
11
12
  import { FileUploadLabels } from './components/FileUpload.js';
12
13
  import { AttachmentLabels } from './attachment-labels.js';
14
+ import { EntityPickerLabels } from './components/EntityPicker.js';
15
+ import { TreeLabels } from './components/Tree.js';
16
+ import { InlineEditLabels } from './components/InlineEdit.js';
13
17
  import './link.js';
14
18
  import './calendar-model.js';
15
19
  import './scheduling-calendar-model.js';
20
+ import './overlay-position.js';
16
21
  import './scheduling-timeline-model.js';
17
22
  import './text-diff-model.js';
18
23
  import './filter-model.js';
19
- import './overlay-position.js';
20
24
  import './select-model.js';
21
25
  import './json-value.js';
22
26
  import './rule-builder-model.js';
23
27
  import './file-model.js';
28
+ import './components/SearchSuggest.js';
24
29
 
25
30
  /**
26
31
  * Kit chrome strings by component (HAR-1358; TENSOR C20, MOTUS executive summary #3).
@@ -60,15 +65,23 @@ interface UixLabels {
60
65
  searchSuggest?: {
61
66
  clear?: string;
62
67
  };
68
+ /** `resultsOne` / `resultsMany`: the polite result count; `{count}`. */
63
69
  commandPalette?: {
64
70
  input?: string;
71
+ resultsOne?: string;
72
+ resultsMany?: string;
65
73
  };
74
+ entityPicker?: Partial<EntityPickerLabels>;
75
+ tree?: Partial<TreeLabels>;
76
+ inlineEdit?: Partial<InlineEditLabels>;
66
77
  confirmDialog?: {
67
78
  typeToConfirm?: string;
68
79
  compensation?: string;
69
80
  };
70
81
  schedulingCalendar?: Partial<SchedulingCalendarLabels>;
71
82
  dateRangePicker?: Partial<DateRangePickerLabels>;
83
+ datePicker?: Partial<DatePickerLabels>;
84
+ dateTimePicker?: Partial<DateTimePickerLabels>;
72
85
  schedulingTimeline?: Partial<SchedulingTimelineLabels>;
73
86
  textDiff?: Partial<TextDiffLabels>;
74
87
  filterEditor?: Partial<FilterEditorLabels>;
@@ -1,9 +1,4 @@
1
- /**
2
- * Pure model for `SchedulingTimeline` (HAR-1364; TENSOR C8): ticks on a time axis, where a
3
- * bar sits on it, which bars in a lane overlap (and so stack and are flagged), and how a
4
- * keyboard or pointer move snaps. Instants are ISO 8601 strings or epoch milliseconds; the
5
- * axis is linear in real time, and only labels depend on the time zone.
6
- */
1
+ /** The unit of one tick of the axis. */
7
2
  type TimelineScale = 'hour' | 'day' | 'week' | 'month';
8
3
  interface TimelineRange {
9
4
  start: string;
@@ -16,6 +11,22 @@ interface TimelineTick {
16
11
  offset: number;
17
12
  /** A major tick starts a larger unit (a new day on an hour axis, a new month on a day axis). */
18
13
  major: boolean;
14
+ /**
15
+ * On an hour axis, the UTC offset (`'+02:00'`) of an hour that occurs twice that day (the
16
+ * clocks went back), on both occurrences. Not set otherwise.
17
+ */
18
+ offsetLabel?: string;
19
+ }
20
+ /** A minor tick inside a day: a local hour the consumer asked for. */
21
+ interface TimelineSubTick {
22
+ /** Epoch ms of the tick. */
23
+ at: number;
24
+ /** Position on the axis, 0–100. */
25
+ offset: number;
26
+ /** The local hour (0–23). */
27
+ hour: number;
28
+ /** The local hour, two digits (`'06'`). */
29
+ label: string;
19
30
  }
20
31
  interface TimelineSpan {
21
32
  id: string;
@@ -32,9 +43,19 @@ interface PlacedSpan<T extends TimelineSpan = TimelineSpan> {
32
43
  clippedEnd: boolean;
33
44
  /** Sub-row inside the lane, so overlapping bars stack instead of covering each other. */
34
45
  row: number;
35
- /** Overlaps at least one other bar in the same lane. */
46
+ /** Overlaps at least one other bar in the same lane. Always `false` with `flagOverlaps: false`. */
36
47
  conflict: boolean;
37
48
  }
49
+ interface LayoutLaneOptions {
50
+ /** `false` keeps the stacking and flags nothing: the consumer says what clashes, with a reason. Default `true`. */
51
+ flagOverlaps?: boolean;
52
+ /**
53
+ * The time (ms) the narrowest drawn bar covers on this axis. A bar is packed as at least
54
+ * this long from where it is drawn, so two short bars whose drawn boxes would cover each
55
+ * other get a sub-row each. It changes the rows only, never the `conflict` flag. Default 0.
56
+ */
57
+ minSpan?: number;
58
+ }
38
59
  declare const HOUR = 3600000;
39
60
  declare const DAY: number;
40
61
  /** The default move/resize step for a scale: 15 min on an hour axis, 1 h on a day axis, 1 day otherwise. */
@@ -45,16 +66,30 @@ declare const defaultTimelineStep: (scale: TimelineScale) => number;
45
66
  * year walks ~8,800 hours, so keep ranges to what fits on screen.
46
67
  */
47
68
  declare function timelineTicks(range: TimelineRange, scale: TimelineScale, timeZone: string, weekStartsOn?: number): TimelineTick[];
69
+ /**
70
+ * Minor ticks for a day axis: one per local hour in `hours` (0–23) on every day of the range,
71
+ * strictly inside it. The instants come from the zone, so on a day the clocks change 06:00 is
72
+ * still local 06:00; an hour that does not exist that day has no tick, and one that occurs
73
+ * twice is ticked at its first occurrence.
74
+ */
75
+ declare function timelineSubTicks(range: TimelineRange, hours: readonly number[], timeZone: string): TimelineSubTick[];
48
76
  /** Position of one span on the axis, clamped to it; null when it is entirely outside. */
49
77
  declare function placeSpan(span: {
50
78
  start: string;
51
79
  end: string;
52
80
  }, range: TimelineRange): Omit<PlacedSpan, 'item' | 'row' | 'conflict'> | null;
53
81
  /**
54
- * Places a lane's spans: sorted by start, each in the first sub-row where it does not overlap
55
- * the previous bar, and flagged `conflict` when it overlaps any other span in the lane.
82
+ * Places a lane's spans: sorted by start, each in the first sub-row where it overlaps no
83
+ * earlier bar, and flagged `conflict` when it shares time with any other span in the lane
84
+ * (unless `flagOverlaps` is `false`). The rows come from `packLanes`, uncapped: every bar gets
85
+ * one. With `minSpan` a bar is packed as at least that long from where it is drawn, so bars
86
+ * drawn at their minimum width do not cover each other. Spans equal in start and end keep the
87
+ * order given. A span that ends before it starts is a point at its start, and a repeated id is
88
+ * placed each time. One difference from before the shared packer, with no options at all: a
89
+ * point at the instant a bar starts takes a sub-row of its own (it used to be drawn over the
90
+ * start of the bar), because the packer gives a zero-length interval its start instant.
56
91
  */
57
- declare function layoutLane<T extends TimelineSpan>(items: readonly T[], range: TimelineRange): PlacedSpan<T>[];
92
+ declare function layoutLane<T extends TimelineSpan>(items: readonly T[], range: TimelineRange, options?: LayoutLaneOptions): PlacedSpan<T>[];
58
93
  /** Rounds a millisecond offset to the nearest step. */
59
94
  declare const snapToStep: (ms: number, step: number) => number;
60
95
  /** A span moved (both ends) or resized (end only) by `delta` ms, as ISO strings; never shorter than one step. */
@@ -67,5 +102,20 @@ declare function shiftSpan(span: {
67
102
  };
68
103
  /** Converts a horizontal pointer distance on a track of `trackWidth` px to snapped milliseconds. */
69
104
  declare function pixelsToMs(px: number, trackWidth: number, range: TimelineRange, step: number): number;
105
+ /**
106
+ * The UTC offset (`'+02:00'`) of an instant whose wall-clock time occurs twice that day in
107
+ * `timeZone` (the clocks went back), else `null`. Such a time is not a time until it says which
108
+ * of the two it is. It holds for a repeat at the end of a day and for one of half an hour too.
109
+ */
110
+ declare function timelineRepeatedHourOffset(instant: string | number, timeZone: string): string | null;
111
+ /**
112
+ * A move step as `proposeMove` takes it: a whole number of `DAY`s is that many calendar days
113
+ * (the wall-clock time is kept, whatever the length of the days in between); anything else is
114
+ * real minutes.
115
+ */
116
+ declare function timelineStepDelta(step: number): {
117
+ days: number;
118
+ minutes: number;
119
+ };
70
120
 
71
- export { DAY, HOUR, type PlacedSpan, type TimelineRange, type TimelineScale, type TimelineSpan, type TimelineTick, defaultTimelineStep, layoutLane, pixelsToMs, placeSpan, shiftSpan, snapToStep, timelineTicks };
121
+ export { DAY, HOUR, type LayoutLaneOptions, type PlacedSpan, type TimelineRange, type TimelineScale, type TimelineSpan, type TimelineSubTick, type TimelineTick, defaultTimelineStep, layoutLane, pixelsToMs, placeSpan, shiftSpan, snapToStep, timelineRepeatedHourOffset, timelineStepDelta, timelineSubTicks, timelineTicks };
@@ -1,3 +1,4 @@
1
+ import { addCalendarDays, enumerateDateKeys, packLanes, zonedDateKey, zonedDayBounds, zonedDaySpan, zonedHourSlots, zonedTimeOfDay } from "./calendar-model.js";
1
2
  const HOUR = 36e5;
2
3
  const DAY = 24 * HOUR;
3
4
  const toMs = (value) => {
@@ -42,7 +43,32 @@ function timelineTicks(range, scale, timeZone, weekStartsOn = 1) {
42
43
  }
43
44
  prev = p;
44
45
  }
45
- return ticks;
46
+ if (scale !== "hour") return ticks;
47
+ const repeated = new Map(rangeHourSlots(start, end, timeZone).flat().filter((slot) => slot.offsetLabel !== null).map((slot) => [slot.instant.getTime(), slot.offsetLabel]));
48
+ return repeated.size === 0 ? ticks : ticks.map((tick) => repeated.has(tick.at) ? { ...tick, offsetLabel: repeated.get(tick.at) } : tick);
49
+ }
50
+ const SLOT_DAY_LIMIT = 400;
51
+ function rangeHourSlots(start, end, timeZone) {
52
+ if (!(end > start)) return [];
53
+ const { dates } = enumerateDateKeys(zonedDaySpan(new Date(start), new Date(end), timeZone), { limit: SLOT_DAY_LIMIT });
54
+ return dates.map((date) => zonedHourSlots(date, timeZone));
55
+ }
56
+ function timelineSubTicks(range, hours, timeZone) {
57
+ const start = toMs(range.start);
58
+ const end = toMs(range.end);
59
+ if (!(end > start) || hours.length === 0) return [];
60
+ const wanted = new Set(hours);
61
+ const span = end - start;
62
+ return rangeHourSlots(start, end, timeZone).flatMap((day) => {
63
+ const ticked = /* @__PURE__ */ new Set();
64
+ return day.flatMap((slot) => {
65
+ const hour = Number(slot.label);
66
+ const at = slot.instant.getTime();
67
+ if (!wanted.has(hour) || ticked.has(hour)) return [];
68
+ ticked.add(hour);
69
+ return at > start && at < end ? [{ at, offset: (at - start) / span * 100, hour, label: slot.label }] : [];
70
+ });
71
+ });
46
72
  }
47
73
  function placeSpan(span, range) {
48
74
  const start = toMs(range.start);
@@ -55,34 +81,32 @@ function placeSpan(span, range) {
55
81
  const right = (Math.min(e, end) - start) / total * 100;
56
82
  return { left, width: Math.max(right - left, 0), clippedStart: s < start, clippedEnd: e > end };
57
83
  }
58
- function layoutLane(items, range) {
59
- const sorted = [...items].sort((a, b) => toMs(a.start) - toMs(b.start) || toMs(a.end) - toMs(b.end));
60
- const rowEnds = [];
61
- const placed = [];
62
- for (const item of sorted) {
63
- const pos = placeSpan(item, range);
64
- if (!pos) continue;
65
- const s = toMs(item.start);
66
- let row = rowEnds.findIndex((end) => end <= s);
67
- if (row === -1) {
68
- row = rowEnds.length;
69
- rowEnds.push(0);
70
- }
71
- rowEnds[row] = Math.max(toMs(item.end), s);
72
- placed.push({ item, ...pos, row, conflict: false });
73
- }
74
- for (let i = 0; i < placed.length; i++) {
75
- for (let j = i + 1; j < placed.length; j++) {
76
- const a = placed[i].item;
77
- const b = placed[j].item;
78
- if (toMs(b.start) >= toMs(a.end)) continue;
79
- if (toMs(a.start) < toMs(b.end)) {
80
- placed[i].conflict = true;
81
- placed[j].conflict = true;
84
+ function sharedTimeFlags(spans) {
85
+ const flags = spans.map(() => false);
86
+ for (let i = 0; i < spans.length; i++) {
87
+ for (let j = i + 1; j < spans.length; j++) {
88
+ if (spans[j].start >= spans[i].givenEnd) break;
89
+ if (spans[i].start < spans[j].givenEnd) {
90
+ flags[i] = true;
91
+ flags[j] = true;
82
92
  }
83
93
  }
84
94
  }
85
- return placed;
95
+ return flags;
96
+ }
97
+ function layoutLane(items, range, options = {}) {
98
+ const flag = options.flagOverlaps !== false;
99
+ const minSpan = Math.max(0, options.minSpan ?? 0);
100
+ const rangeStart = toMs(range.start);
101
+ const visible = [...items].sort((a, b) => toMs(a.start) - toMs(b.start) || toMs(a.end) - toMs(b.end)).flatMap((item) => {
102
+ const pos = placeSpan(item, range);
103
+ const start = toMs(item.start);
104
+ const givenEnd = toMs(item.end);
105
+ return pos ? [{ item, pos, start, givenEnd, end: Math.max(givenEnd, start) }] : [];
106
+ });
107
+ const packed = packLanes(visible.map(({ start, end }, index) => ({ id: String(index), start, end: Math.max(end, Math.max(start, rangeStart) + minSpan) })), Infinity, { order: "given" });
108
+ const shares = flag ? sharedTimeFlags(visible) : [];
109
+ return visible.map(({ item, pos }, index) => ({ item, ...pos, row: packed.lanes[String(index)].lane ?? 0, conflict: flag && shares[index] }));
86
110
  }
87
111
  const snapToStep = (ms, step) => Math.round(ms / step) * step;
88
112
  function shiftSpan(span, delta, mode, step) {
@@ -95,6 +119,38 @@ function pixelsToMs(px, trackWidth, range, step) {
95
119
  if (trackWidth <= 0) return 0;
96
120
  return snapToStep(px / trackWidth * (toMs(range.end) - toMs(range.start)), step);
97
121
  }
122
+ const MINUTE = 6e4;
123
+ const REPEAT_SHIFTS = [30, 60, 90, 120];
124
+ const longDays = /* @__PURE__ */ new Map();
125
+ const LONG_DAY_CACHE_LIMIT = 512;
126
+ function mayRepeat(date, timeZone) {
127
+ const key = `${timeZone} ${date}`;
128
+ let long = longDays.get(key);
129
+ if (long === void 0) {
130
+ const length = (day) => {
131
+ const bounds = zonedDayBounds(day, timeZone);
132
+ return bounds.end.getTime() - bounds.start.getTime();
133
+ };
134
+ long = length(date) > Math.min(length(addCalendarDays(date, -1)), length(addCalendarDays(date, 1)));
135
+ if (longDays.size >= LONG_DAY_CACHE_LIMIT) longDays.delete(longDays.keys().next().value);
136
+ longDays.set(key, long);
137
+ }
138
+ return long;
139
+ }
140
+ function timelineRepeatedHourOffset(instant, timeZone) {
141
+ const at = toMs(instant);
142
+ if (!mayRepeat(zonedDateKey(new Date(at), timeZone), timeZone)) return null;
143
+ const wall = (ms) => `${zonedDateKey(new Date(ms), timeZone)}T${zonedTimeOfDay(ms, timeZone)}`;
144
+ const here = wall(at);
145
+ if (!REPEAT_SHIFTS.some((minutes) => wall(at + minutes * MINUTE) === here || wall(at - minutes * MINUTE) === here)) return null;
146
+ const offset = Math.round((Date.parse(`${here}:00Z`) - Math.floor(at / MINUTE) * MINUTE) / MINUTE);
147
+ const size = Math.abs(offset);
148
+ return `${offset < 0 ? "-" : "+"}${String(Math.floor(size / 60)).padStart(2, "0")}:${String(size % 60).padStart(2, "0")}`;
149
+ }
150
+ function timelineStepDelta(step) {
151
+ if (step !== 0 && step % DAY === 0) return { days: step / DAY, minutes: 0 };
152
+ return { days: 0, minutes: step / 6e4 };
153
+ }
98
154
  export {
99
155
  DAY,
100
156
  HOUR,
@@ -104,5 +160,8 @@ export {
104
160
  placeSpan,
105
161
  shiftSpan,
106
162
  snapToStep,
163
+ timelineRepeatedHourOffset,
164
+ timelineStepDelta,
165
+ timelineSubTicks,
107
166
  timelineTicks
108
167
  };
@@ -0,0 +1,40 @@
1
+ type TimelineRowKind = 'lane' | 'head';
2
+ interface TimelineRowSize {
3
+ kind: TimelineRowKind;
4
+ /**
5
+ * Sub-rows of a lane (at least 1). For a head, the sub-rows of the strip under it (0 or
6
+ * unset: none): a collapsed group that carries a window is a head and one such strip.
7
+ */
8
+ subRows?: number;
9
+ }
10
+ /** A height as counts of the three row units: sub-rows, lane paddings and group heads. */
11
+ interface TimelineExtent {
12
+ subRows: number;
13
+ lanes: number;
14
+ heads: number;
15
+ }
16
+ /**
17
+ * Where each row starts, as a `TimelineExtent` from the top of the body. One more entry than
18
+ * rows: the last is the height of the whole body.
19
+ */
20
+ declare function timelineRowExtents(rows: readonly TimelineRowSize[]): TimelineExtent[];
21
+ /** The half-open index runs `[from, to)` of consecutive `true` entries. */
22
+ declare function timelineRuns(targets: readonly boolean[]): Array<{
23
+ from: number;
24
+ to: number;
25
+ }>;
26
+ /**
27
+ * The rows `[start, end)` to mount: those that touch `[top - overscan, bottom + overscan]`,
28
+ * given where each row starts (`offsets`, one more entry than rows, in the unit of `top`).
29
+ * Never more than `cap` rows, and never none while there are rows: a viewport past the end
30
+ * mounts the last rows.
31
+ */
32
+ declare function timelineWindow(offsets: readonly number[], top: number, bottom: number, options?: {
33
+ overscan?: number;
34
+ cap?: number;
35
+ }): {
36
+ start: number;
37
+ end: number;
38
+ };
39
+
40
+ export { type TimelineExtent, type TimelineRowKind, type TimelineRowSize, timelineRowExtents, timelineRuns, timelineWindow };
@@ -0,0 +1,42 @@
1
+ function timelineRowExtents(rows) {
2
+ const extents = [{ subRows: 0, lanes: 0, heads: 0 }];
3
+ for (const row of rows) {
4
+ const above = extents[extents.length - 1];
5
+ extents.push(row.kind === "head" ? { subRows: above.subRows + Math.max(0, row.subRows ?? 0), lanes: above.lanes, heads: above.heads + 1 } : { subRows: above.subRows + Math.max(1, row.subRows ?? 1), lanes: above.lanes + 1, heads: above.heads });
6
+ }
7
+ return extents;
8
+ }
9
+ function timelineRuns(targets) {
10
+ const runs = [];
11
+ targets.forEach((target, index) => {
12
+ if (!target) return;
13
+ const last = runs[runs.length - 1];
14
+ if (last && last.to === index) last.to = index + 1;
15
+ else runs.push({ from: index, to: index + 1 });
16
+ });
17
+ return runs;
18
+ }
19
+ function timelineWindow(offsets, top, bottom, options = {}) {
20
+ const count = Math.max(0, offsets.length - 1);
21
+ if (count === 0) return { start: 0, end: 0 };
22
+ const overscan = Math.max(0, options.overscan ?? 0);
23
+ const cap = Math.max(1, options.cap ?? Infinity);
24
+ const from = top - overscan;
25
+ const to = bottom + overscan;
26
+ let lo = 0;
27
+ let hi = count;
28
+ while (lo < hi) {
29
+ const mid = lo + hi >> 1;
30
+ if (offsets[mid + 1] > from) hi = mid;
31
+ else lo = mid + 1;
32
+ }
33
+ const start = Math.min(lo, count - 1);
34
+ let end = start + 1;
35
+ while (end < count && offsets[end] < to && end - start < cap) end++;
36
+ return { start, end };
37
+ }
38
+ export {
39
+ timelineRowExtents,
40
+ timelineRuns,
41
+ timelineWindow
42
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tensor_1/react",
3
- "version": "2.35.0",
3
+ "version": "2.37.0",
4
4
  "description": "Thin React wrappers over the UIx v2 CSS component library.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -55,10 +55,12 @@
55
55
  }
56
56
  },
57
57
  "scripts": {
58
- "build": "tsup",
59
- "dev": "tsup --watch",
58
+ "build": "node scripts/clean-dist.mjs && tsup && node scripts/check-dist.mjs",
59
+ "dev": "node scripts/clean-dist.mjs && tsup --watch",
60
60
  "typecheck": "tsc --noEmit",
61
61
  "test": "node --test",
62
+ "test:dist": "node scripts/check-dist.mjs",
63
+ "prepublishOnly": "node scripts/check-dist.mjs",
62
64
  "test:performance": "node scripts/table-performance.mjs",
63
65
  "size": "node scripts/check-chart-preset-size.mjs"
64
66
  },