@primeui/scheduler-core 0.0.1-alpha.1 → 1.0.0-rc.1

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 (53) hide show
  1. package/LICENSE.md +35 -0
  2. package/README.md +12 -0
  3. package/THIRD-PARTY-NOTICES.txt +191 -0
  4. package/dist/{overlay-BYM9B6nC.d.mts → appointment-slots-DCiNFFed.d.mts} +2 -13
  5. package/dist/calendar/index.mjs +1 -1
  6. package/dist/{chunk-NMX4BW42.mjs → chunks/chunk-2YXHUV2A.mjs} +2 -2
  7. package/dist/{chunk-FIBAZFC4.mjs → chunks/chunk-6Q5FR4PN.mjs} +1 -1
  8. package/dist/{chunk-NX46LPLF.mjs → chunks/chunk-BJFVXDZC.mjs} +2 -2
  9. package/dist/{chunk-6PK5WSKT.mjs → chunks/chunk-EHH5ARHF.mjs} +29 -35
  10. package/dist/{chunk-TNKJPFGI.mjs → chunks/chunk-F2LYNUXG.mjs} +1 -1
  11. package/dist/{chunk-ZUKUKGNK.mjs → chunks/chunk-G7F2OBHW.mjs} +30 -34
  12. package/dist/{chunk-KQGRXTP5.mjs → chunks/chunk-HF32DKZY.mjs} +26 -270
  13. package/dist/chunks/chunk-HWGXSE6Q.mjs +269 -0
  14. package/dist/{chunk-HPC5B3AR.mjs → chunks/chunk-JCNXNPGM.mjs} +3 -3
  15. package/dist/{chunk-6OZAPQZ5.mjs → chunks/chunk-LMZ2J5Z5.mjs} +3 -3
  16. package/dist/{chunk-F5W5HD7S.mjs → chunks/chunk-LYPP7W7B.mjs} +79 -7
  17. package/dist/{chunk-W2SJW3QQ.mjs → chunks/chunk-NKSMQCWJ.mjs} +21 -50
  18. package/dist/{chunk-6VYWVIGM.mjs → chunks/chunk-QBTFRSZM.mjs} +5 -5
  19. package/dist/{chunk-NZGJN7HG.mjs → chunks/chunk-RM6OQCEO.mjs} +2 -2
  20. package/dist/{chunk-2THQAZ26.mjs → chunks/chunk-URRTAW2Q.mjs} +7 -54
  21. package/dist/{chunk-WFUJWDST.mjs → chunks/chunk-XQAYO7CQ.mjs} +1 -1
  22. package/dist/controllers/index.d.mts +3 -3
  23. package/dist/controllers/index.mjs +946 -13
  24. package/dist/event/index.mjs +8 -8
  25. package/dist/index.d.mts +6 -13
  26. package/dist/index.mjs +32 -34
  27. package/dist/interaction/index.d.mts +2 -63
  28. package/dist/interaction/index.mjs +9 -9
  29. package/dist/month/index.mjs +6 -6
  30. package/dist/resource/index.mjs +1 -1
  31. package/dist/time-grid/index.d.mts +9 -2
  32. package/dist/time-grid/index.mjs +12 -13
  33. package/dist/timeline/index.d.mts +11 -1
  34. package/dist/timeline/index.mjs +7 -6
  35. package/dist/{touch-BhsMWsjf.d.mts → touch-B6xcJlyY.d.mts} +1 -1
  36. package/dist/utils/index.d.mts +2 -27
  37. package/dist/utils/index.mjs +16 -17
  38. package/dist/views/index.mjs +8 -8
  39. package/dist/views/timeline/index.mjs +4 -4
  40. package/dist/year/index.mjs +6 -6
  41. package/package.json +61 -10
  42. package/LICENSE +0 -23
  43. package/dist/chunk-5N4ZOBJV.mjs +0 -866
  44. package/dist/chunk-AAVM7UCG.mjs +0 -100
  45. /package/dist/{chunk-DYW6WUHE.mjs → chunks/chunk-6OTDPEJM.mjs} +0 -0
  46. /package/dist/{chunk-UMAMDBU4.mjs → chunks/chunk-73ID2V6E.mjs} +0 -0
  47. /package/dist/{chunk-C7ADJGNV.mjs → chunks/chunk-7TCZNLG7.mjs} +0 -0
  48. /package/dist/{chunk-5KORIWDT.mjs → chunks/chunk-AZRI6PHU.mjs} +0 -0
  49. /package/dist/{chunk-XUBQ2IQS.mjs → chunks/chunk-B4YDYPVO.mjs} +0 -0
  50. /package/dist/{chunk-SYJ5O4KH.mjs → chunks/chunk-IJH6YR4N.mjs} +0 -0
  51. /package/dist/{chunk-QDMZBJDV.mjs → chunks/chunk-P7CIUMQZ.mjs} +0 -0
  52. /package/dist/{chunk-2B3YLWHA.mjs → chunks/chunk-UKD2NVDC.mjs} +0 -0
  53. /package/dist/{chunk-QR2SVYAD.mjs → chunks/chunk-XMU4WSAX.mjs} +0 -0
@@ -1,7 +1,6 @@
1
- import { getDatePartsInTimezone, isSameDayInTimezone } from './chunk-QDMZBJDV.mjs';
2
- import { startOfDay, addDays, isSameDay } from './chunk-WFUJWDST.mjs';
3
- import { resolveSchedulerCalendarModeForView, getSchedulerCalendarAdapter } from './chunk-DYW6WUHE.mjs';
4
- import { calculateResourceRowLayouts, getTotalResourceHeight } from './chunk-QR2SVYAD.mjs';
1
+ import { getDatePartsInTimezone, isSameDayInTimezone } from './chunk-P7CIUMQZ.mjs';
2
+ import { startOfDay, addDays, isSameDay } from './chunk-XQAYO7CQ.mjs';
3
+ import { resolveSchedulerCalendarModeForView, getSchedulerCalendarAdapter } from './chunk-6OTDPEJM.mjs';
5
4
 
6
5
  // src/timeline/layout.ts
7
6
  var DEFAULT_TIMELINE_EVENT_MIN_HEIGHT = 36;
@@ -301,6 +300,28 @@ function timeToTimelinePixels(input) {
301
300
  }
302
301
  return totalWidth;
303
302
  }
303
+ function timelinePixelsToTime(input) {
304
+ const { x, view, visibleDayStarts, dayWidth, minTimeMin, visibleMinutesPerDay, totalWidth, snapDurationMin } = input;
305
+ const clampedX = Math.min(Math.max(x, 0), totalWidth);
306
+ if (visibleDayStarts.length === 0) {
307
+ return /* @__PURE__ */ new Date();
308
+ }
309
+ if (isTimelineMonthGranularityView(view)) {
310
+ const dayIndex2 = Math.min(Math.max(Math.round(clampedX / dayWidth), 0), visibleDayStarts.length - 1);
311
+ return new Date(visibleDayStarts[dayIndex2]);
312
+ }
313
+ const dayIndex = Math.min(Math.floor(clampedX / dayWidth), visibleDayStarts.length - 1);
314
+ const dayStart = new Date(visibleDayStarts[dayIndex]);
315
+ const offsetWithinDay = clampedX - dayIndex * dayWidth;
316
+ const dayProgress = dayWidth > 0 ? offsetWithinDay / dayWidth : 0;
317
+ let minutesIntoDay = minTimeMin + dayProgress * visibleMinutesPerDay;
318
+ if (snapDurationMin && snapDurationMin > 0) {
319
+ minutesIntoDay = minTimeMin + Math.round((minutesIntoDay - minTimeMin) / snapDurationMin) * snapDurationMin;
320
+ }
321
+ minutesIntoDay = Math.min(Math.max(minutesIntoDay, minTimeMin), minTimeMin + visibleMinutesPerDay);
322
+ dayStart.setHours(0, Math.round(minutesIntoDay), 0, 0);
323
+ return dayStart;
324
+ }
304
325
  function getTimelineDayGranularityEventRect(event, input) {
305
326
  const firstDay = input.visibleDayStarts[0];
306
327
  if (!firstDay) {
@@ -382,269 +403,4 @@ function computeTimelineLaneAssignment(events, stackingMode) {
382
403
  return { assignment, laneCount: Math.max(1, lanes.length) };
383
404
  }
384
405
 
385
- // src/timeline/view-model.ts
386
- var TIMELINE_VIEWS_WITH_RESOURCES = /* @__PURE__ */ new Set(["timelineDay", "timelineWeek", "timelineMonth", "resourceTimelineDay", "resourceTimelineWeek", "resourceTimelineMonth"]);
387
- function getEffectiveViewStart(cells, fallback) {
388
- return cells[0]?.startDate ?? fallback;
389
- }
390
- function getEffectiveViewEnd(cells, fallback) {
391
- return cells[cells.length - 1]?.endDate ?? fallback;
392
- }
393
- function buildDescendantIdMap(resources) {
394
- const map = /* @__PURE__ */ new Map();
395
- const collect = (resource) => {
396
- const ids = /* @__PURE__ */ new Set([resource.id]);
397
- for (const child of resource.children ?? []) {
398
- const childIds = collect(child);
399
- childIds.forEach((id) => ids.add(id));
400
- }
401
- map.set(resource.id, ids);
402
- return ids;
403
- };
404
- for (const resource of resources) {
405
- collect(resource);
406
- }
407
- return map;
408
- }
409
- function buildVisibleHeaderTiers(input) {
410
- const { headerTiers, visibleCells, virtualRange } = input;
411
- if (!virtualRange) return headerTiers;
412
- const visibleWidth = visibleCells.reduce((sum, cell) => sum + cell.width, 0);
413
- const windowStart = virtualRange.startOffset;
414
- const windowEnd = windowStart + visibleWidth;
415
- return headerTiers.map((tier) => {
416
- let offset = 0;
417
- return {
418
- cells: tier.cells.flatMap((cell) => {
419
- const cellStart = Number.isFinite(cell.left) ? cell.left : offset;
420
- const cellEnd = cellStart + cell.width;
421
- offset = cellEnd;
422
- if (cellEnd <= windowStart || cellStart >= windowEnd) {
423
- return [];
424
- }
425
- return [
426
- {
427
- ...cell,
428
- left: Math.max(cellStart, windowStart),
429
- width: Math.max(0, Math.min(cellEnd, windowEnd) - Math.max(cellStart, windowStart))
430
- }
431
- ];
432
- })
433
- };
434
- });
435
- }
436
- function eventIntersectsRange(event, viewStart, viewEnd) {
437
- const eventStart = event.start instanceof Date ? event.start : new Date(event.start);
438
- const eventEnd = event.end ? event.end instanceof Date ? event.end : new Date(event.end) : eventStart;
439
- return eventStart < viewEnd && eventEnd > viewStart;
440
- }
441
- function computeVisualLaneAssignment(events, getRect, stackingMode) {
442
- if (stackingMode === "collapse" || stackingMode === "expand") {
443
- return computeTimelineLaneAssignment(events, stackingMode);
444
- }
445
- const sorted = [...events].map((event) => ({ event, rect: getRect(event) })).sort((a, b) => {
446
- if (a.rect.left !== b.rect.left) return a.rect.left - b.rect.left;
447
- return b.rect.width - a.rect.width;
448
- });
449
- const assignment = /* @__PURE__ */ new Map();
450
- const lanes = [];
451
- for (const item of sorted) {
452
- const start = item.rect.left;
453
- const end = item.rect.left + item.rect.width;
454
- let laneIndex = -1;
455
- for (let index = 0; index < lanes.length; index++) {
456
- const overlaps = lanes[index].some((occupant) => !(occupant.end <= start || occupant.start >= end));
457
- if (!overlaps) {
458
- laneIndex = index;
459
- break;
460
- }
461
- }
462
- if (laneIndex < 0) {
463
- laneIndex = lanes.length;
464
- lanes.push([]);
465
- }
466
- lanes[laneIndex].push({ start, end });
467
- if (item.event.id != null) {
468
- assignment.set(item.event.id, laneIndex);
469
- }
470
- }
471
- return { assignment, laneCount: Math.max(1, lanes.length) };
472
- }
473
- function buildTimelineViewModel(input) {
474
- const monthGranularity = isTimelineMonthGranularityView(input.view);
475
- const slotsPerDay = monthGranularity ? 1 : Math.max(1, Math.ceil((input.maxTimeMin - input.minTimeMin) / input.slotDurationMin));
476
- const slotWidth = Math.max(20, input.slotWidth);
477
- const dayWidth = monthGranularity ? slotWidth : slotsPerDay * slotWidth;
478
- const cells = buildTimelineCells({
479
- view: input.view,
480
- start: input.viewStart,
481
- end: input.viewEnd,
482
- now: input.now,
483
- slotsPerDay,
484
- slotDurationMin: input.slotDurationMin,
485
- slotWidth,
486
- minTimeMin: input.minTimeMin,
487
- dayWidth,
488
- timezone: input.timezone,
489
- locale: input.locale,
490
- calendar: input.calendar,
491
- labels: input.labels
492
- });
493
- const visibleDayStarts = getTimelineVisibleDayStarts(input.view, input.viewStart, input.viewEnd);
494
- const effectiveViewStart = getEffectiveViewStart(cells, input.viewStart);
495
- const effectiveViewEnd = getEffectiveViewEnd(cells, input.viewEnd);
496
- const totalWidth = cells.reduce((sum, cell) => sum + cell.width, 0);
497
- const visibleMinutesPerDay = Math.max(1, input.maxTimeMin - input.minTimeMin);
498
- const resources = TIMELINE_VIEWS_WITH_RESOURCES.has(input.view) ? input.resources ?? [] : [];
499
- const visibleResources = resources.length > 0 ? input.visibleResources ?? [] : [];
500
- const descendantIdMap = buildDescendantIdMap(resources);
501
- const timelineEventMinHeight = resolveTimelineEventMinHeight(input.timelineEventMinHeight);
502
- const rowAutoHeight = input.rowAutoHeight ?? input.view.startsWith("resourceTimeline");
503
- const rowHeightMode = rowAutoHeight ? "auto" : "fixed";
504
- const headerTiers = buildTimelineHeaderTiers({
505
- view: input.view,
506
- cells,
507
- visibleDayStarts,
508
- dayWidth,
509
- labels: {
510
- day: input.labels.day,
511
- monthYear: input.labels.monthYear,
512
- quarter: input.labels.quarter
513
- },
514
- locale: input.locale,
515
- calendar: input.calendar
516
- });
517
- const positionInput = {
518
- view: input.view,
519
- cells,
520
- visibleDayStarts,
521
- dayWidth,
522
- minTimeMin: input.minTimeMin,
523
- visibleMinutesPerDay,
524
- totalWidth
525
- };
526
- const getEventsForLane = (resourceId) => filterTimelineLaneEvents(input.events, {
527
- resourceId,
528
- matchIds: null,
529
- viewStart: effectiveViewStart,
530
- viewEnd: effectiveViewEnd
531
- });
532
- const isAggregatedRow = (resourceId) => {
533
- if (resourceId === void 0 || !input.showAggregatedEvents) return false;
534
- const descendants = descendantIdMap.get(resourceId);
535
- if (!descendants || descendants.size <= 1) return false;
536
- return !(input.isResourceExpanded?.(resourceId) ?? true);
537
- };
538
- const getAggregateEvents = (resourceId) => {
539
- if (resourceId === void 0 || !isAggregatedRow(resourceId)) return [];
540
- return filterTimelineLaneEvents(input.events, {
541
- resourceId,
542
- matchIds: descendantIdMap.get(resourceId) ?? /* @__PURE__ */ new Set([resourceId]),
543
- viewStart: effectiveViewStart,
544
- viewEnd: effectiveViewEnd
545
- });
546
- };
547
- const getTimelineEventPosition = (event) => getTimelineEventRect(event, {
548
- ...positionInput,
549
- fallbackDurationMinutes: input.slotDurationMin
550
- });
551
- const laneModels = /* @__PURE__ */ new Map();
552
- const laneResourceIds = visibleResources.length > 0 ? visibleResources.map((resource) => resource.id) : [void 0];
553
- for (const resourceId of laneResourceIds) {
554
- const events = getEventsForLane(resourceId);
555
- const { assignment, laneCount } = monthGranularity ? computeVisualLaneAssignment(events, getTimelineEventPosition, input.stackingMode) : computeTimelineLaneAssignment(events, input.stackingMode);
556
- const aggregateEvents = getAggregateEvents(resourceId);
557
- laneModels.set(resourceId, {
558
- resourceId,
559
- events,
560
- assignment,
561
- laneCount,
562
- aggregateEvents,
563
- aggregateCount: aggregateEvents.length,
564
- isAggregated: isAggregatedRow(resourceId)
565
- });
566
- }
567
- const laneCounts = /* @__PURE__ */ new Map();
568
- const expandedRowHeights = /* @__PURE__ */ new Map();
569
- const baseRowHeight = resolveTimelineResourceRowHeight({
570
- laneCount: 1,
571
- eventHeight: timelineEventMinHeight,
572
- minRowHeight: input.resourceRowHeight,
573
- mode: rowHeightMode
574
- });
575
- for (const resource of visibleResources) {
576
- const laneCount = laneModels.get(resource.id)?.laneCount ?? 1;
577
- laneCounts.set(resource.id, laneCount);
578
- expandedRowHeights.set(
579
- resource.id,
580
- resolveTimelineResourceRowHeight({
581
- laneCount,
582
- eventHeight: timelineEventMinHeight,
583
- minRowHeight: input.resourceRowHeight,
584
- mode: rowHeightMode
585
- })
586
- );
587
- }
588
- const resourceLayouts = visibleResources.length > 0 ? calculateResourceRowLayouts(visibleResources, baseRowHeight, expandedRowHeights, laneCounts) : [];
589
- const totalResourceHeight = getTotalResourceHeight(resourceLayouts);
590
- const virtualScrollCells = cells.map((cell, index) => ({
591
- date: cell.startDate,
592
- startTime: cell.startDate,
593
- endTime: cell.endDate,
594
- isToday: cell.isToday,
595
- isWeekend: cell.isWeekend,
596
- isBusinessHour: false,
597
- width: cell.width,
598
- index
599
- }));
600
- const virtualScrollEvents = input.events.filter((event) => eventIntersectsRange(event, input.viewStart, input.viewEnd)).map((event) => {
601
- const rect = getTimelineEventPosition(event);
602
- return {
603
- left: rect.left,
604
- width: rect.width,
605
- row: 0,
606
- event,
607
- continuesBefore: false,
608
- continuesAfter: false
609
- };
610
- });
611
- const visibleCells = input.virtualRange ? cells.slice(input.virtualRange.startIndex, input.virtualRange.endIndex + 1) : cells;
612
- const visibleHeaderTiers = buildVisibleHeaderTiers({
613
- headerTiers,
614
- visibleCells,
615
- virtualRange: input.virtualRange
616
- });
617
- return {
618
- cells,
619
- visibleDayStarts,
620
- effectiveViewStart,
621
- effectiveViewEnd,
622
- totalWidth,
623
- visibleMinutesPerDay,
624
- resources,
625
- visibleResources,
626
- headerTiers,
627
- visibleCells,
628
- visibleHeaderTiers,
629
- laneModels,
630
- resourceLayouts,
631
- totalResourceHeight,
632
- virtualScrollCells,
633
- virtualScrollEvents,
634
- getEventsForLane,
635
- getAggregateEvents,
636
- getAggregateCount: (resourceId) => getAggregateEvents(resourceId).length,
637
- getEventLeft: (event) => getTimelineEventPosition(event).left,
638
- getEventWidth: (event) => getTimelineEventPosition(event).width,
639
- getEventLane: (event, resourceId) => {
640
- const entry = laneModels.get(resourceId);
641
- if (!entry || event.id == null) return 0;
642
- return entry.assignment.get(event.id) ?? 0;
643
- },
644
- getLaneCount: (resourceId) => laneModels.get(resourceId)?.laneCount ?? 1,
645
- isAggregatedRow,
646
- timeToPixels: (date) => timeToTimelinePixels({ ...positionInput, date })
647
- };
648
- }
649
-
650
- export { DEFAULT_TIMELINE_EVENT_MIN_HEIGHT, TIMELINE_LANE_BASE_PADDING, TIMELINE_LANE_GAP, buildTimelineCells, buildTimelineHeaderTiers, buildTimelineViewModel, computeTimelineLaneAssignment, filterTimelineLaneEvents, getTimelineEventRect, getTimelineLaneStackHeight, getTimelineVisibleDayStarts, isTimelineMonthGranularityView, resolveTimelineEventMinHeight, resolveTimelineResourceRowHeight, timeToTimelinePixels };
406
+ export { DEFAULT_TIMELINE_EVENT_MIN_HEIGHT, TIMELINE_LANE_BASE_PADDING, TIMELINE_LANE_GAP, buildTimelineCells, buildTimelineHeaderTiers, computeTimelineLaneAssignment, filterTimelineLaneEvents, getTimelineEventRect, getTimelineLaneStackHeight, getTimelineVisibleDayStarts, isTimelineMonthGranularityView, resolveTimelineEventMinHeight, resolveTimelineResourceRowHeight, timeToTimelinePixels, timelinePixelsToTime };
@@ -0,0 +1,269 @@
1
+ import { isTimelineMonthGranularityView, buildTimelineCells, getTimelineVisibleDayStarts, resolveTimelineEventMinHeight, buildTimelineHeaderTiers, computeTimelineLaneAssignment, resolveTimelineResourceRowHeight, timeToTimelinePixels, filterTimelineLaneEvents, getTimelineEventRect } from './chunk-HF32DKZY.mjs';
2
+ import { calculateResourceRowLayouts, getTotalResourceHeight } from './chunk-XMU4WSAX.mjs';
3
+
4
+ // src/timeline/view-model.ts
5
+ var TIMELINE_VIEWS_WITH_RESOURCES = /* @__PURE__ */ new Set(["timelineDay", "timelineWeek", "timelineMonth", "resourceTimelineDay", "resourceTimelineWeek", "resourceTimelineMonth"]);
6
+ function getEffectiveViewStart(cells, fallback) {
7
+ return cells[0]?.startDate ?? fallback;
8
+ }
9
+ function getEffectiveViewEnd(cells, fallback) {
10
+ return cells[cells.length - 1]?.endDate ?? fallback;
11
+ }
12
+ function buildDescendantIdMap(resources) {
13
+ const map = /* @__PURE__ */ new Map();
14
+ const collect = (resource) => {
15
+ const ids = /* @__PURE__ */ new Set([resource.id]);
16
+ for (const child of resource.children ?? []) {
17
+ const childIds = collect(child);
18
+ childIds.forEach((id) => ids.add(id));
19
+ }
20
+ map.set(resource.id, ids);
21
+ return ids;
22
+ };
23
+ for (const resource of resources) {
24
+ collect(resource);
25
+ }
26
+ return map;
27
+ }
28
+ function buildVisibleHeaderTiers(input) {
29
+ const { headerTiers, visibleCells, virtualRange } = input;
30
+ if (!virtualRange) return headerTiers;
31
+ const visibleWidth = visibleCells.reduce((sum, cell) => sum + cell.width, 0);
32
+ const windowStart = virtualRange.startOffset;
33
+ const windowEnd = windowStart + visibleWidth;
34
+ return headerTiers.map((tier) => {
35
+ let offset = 0;
36
+ return {
37
+ cells: tier.cells.flatMap((cell) => {
38
+ const cellStart = Number.isFinite(cell.left) ? cell.left : offset;
39
+ const cellEnd = cellStart + cell.width;
40
+ offset = cellEnd;
41
+ if (cellEnd <= windowStart || cellStart >= windowEnd) {
42
+ return [];
43
+ }
44
+ return [
45
+ {
46
+ ...cell,
47
+ left: Math.max(cellStart, windowStart),
48
+ width: Math.max(0, Math.min(cellEnd, windowEnd) - Math.max(cellStart, windowStart))
49
+ }
50
+ ];
51
+ })
52
+ };
53
+ });
54
+ }
55
+ function eventIntersectsRange(event, viewStart, viewEnd) {
56
+ const eventStart = event.start instanceof Date ? event.start : new Date(event.start);
57
+ const eventEnd = event.end ? event.end instanceof Date ? event.end : new Date(event.end) : eventStart;
58
+ return eventStart < viewEnd && eventEnd > viewStart;
59
+ }
60
+ function computeVisualLaneAssignment(events, getRect, stackingMode) {
61
+ if (stackingMode === "collapse" || stackingMode === "expand") {
62
+ return computeTimelineLaneAssignment(events, stackingMode);
63
+ }
64
+ const sorted = [...events].map((event) => ({ event, rect: getRect(event) })).sort((a, b) => {
65
+ if (a.rect.left !== b.rect.left) return a.rect.left - b.rect.left;
66
+ return b.rect.width - a.rect.width;
67
+ });
68
+ const assignment = /* @__PURE__ */ new Map();
69
+ const lanes = [];
70
+ for (const item of sorted) {
71
+ const start = item.rect.left;
72
+ const end = item.rect.left + item.rect.width;
73
+ let laneIndex = -1;
74
+ for (let index = 0; index < lanes.length; index++) {
75
+ const overlaps = lanes[index].some((occupant) => !(occupant.end <= start || occupant.start >= end));
76
+ if (!overlaps) {
77
+ laneIndex = index;
78
+ break;
79
+ }
80
+ }
81
+ if (laneIndex < 0) {
82
+ laneIndex = lanes.length;
83
+ lanes.push([]);
84
+ }
85
+ lanes[laneIndex].push({ start, end });
86
+ if (item.event.id != null) {
87
+ assignment.set(item.event.id, laneIndex);
88
+ }
89
+ }
90
+ return { assignment, laneCount: Math.max(1, lanes.length) };
91
+ }
92
+ function buildTimelineViewModel(input) {
93
+ const monthGranularity = isTimelineMonthGranularityView(input.view);
94
+ const slotsPerDay = monthGranularity ? 1 : Math.max(1, Math.ceil((input.maxTimeMin - input.minTimeMin) / input.slotDurationMin));
95
+ const slotWidth = Math.max(20, input.slotWidth);
96
+ const dayWidth = monthGranularity ? slotWidth : slotsPerDay * slotWidth;
97
+ const cells = buildTimelineCells({
98
+ view: input.view,
99
+ start: input.viewStart,
100
+ end: input.viewEnd,
101
+ now: input.now,
102
+ slotsPerDay,
103
+ slotDurationMin: input.slotDurationMin,
104
+ slotWidth,
105
+ minTimeMin: input.minTimeMin,
106
+ dayWidth,
107
+ timezone: input.timezone,
108
+ locale: input.locale,
109
+ calendar: input.calendar,
110
+ labels: input.labels
111
+ });
112
+ const visibleDayStarts = getTimelineVisibleDayStarts(input.view, input.viewStart, input.viewEnd);
113
+ const effectiveViewStart = getEffectiveViewStart(cells, input.viewStart);
114
+ const effectiveViewEnd = getEffectiveViewEnd(cells, input.viewEnd);
115
+ const totalWidth = cells.reduce((sum, cell) => sum + cell.width, 0);
116
+ const visibleMinutesPerDay = Math.max(1, input.maxTimeMin - input.minTimeMin);
117
+ const resources = TIMELINE_VIEWS_WITH_RESOURCES.has(input.view) ? input.resources ?? [] : [];
118
+ const visibleResources = resources.length > 0 ? input.visibleResources ?? [] : [];
119
+ const descendantIdMap = buildDescendantIdMap(resources);
120
+ const timelineEventMinHeight = resolveTimelineEventMinHeight(input.timelineEventMinHeight);
121
+ const rowAutoHeight = input.rowAutoHeight ?? input.view.startsWith("resourceTimeline");
122
+ const rowHeightMode = rowAutoHeight ? "auto" : "fixed";
123
+ const headerTiers = buildTimelineHeaderTiers({
124
+ view: input.view,
125
+ cells,
126
+ visibleDayStarts,
127
+ dayWidth,
128
+ labels: {
129
+ day: input.labels.day,
130
+ monthYear: input.labels.monthYear,
131
+ quarter: input.labels.quarter
132
+ },
133
+ locale: input.locale,
134
+ calendar: input.calendar
135
+ });
136
+ const positionInput = {
137
+ view: input.view,
138
+ cells,
139
+ visibleDayStarts,
140
+ dayWidth,
141
+ minTimeMin: input.minTimeMin,
142
+ visibleMinutesPerDay,
143
+ totalWidth
144
+ };
145
+ const getEventsForLane = (resourceId) => filterTimelineLaneEvents(input.events, {
146
+ resourceId,
147
+ matchIds: null,
148
+ viewStart: effectiveViewStart,
149
+ viewEnd: effectiveViewEnd
150
+ });
151
+ const isAggregatedRow = (resourceId) => {
152
+ if (resourceId === void 0 || !input.showAggregatedEvents) return false;
153
+ const descendants = descendantIdMap.get(resourceId);
154
+ if (!descendants || descendants.size <= 1) return false;
155
+ return !(input.isResourceExpanded?.(resourceId) ?? true);
156
+ };
157
+ const getAggregateEvents = (resourceId) => {
158
+ if (resourceId === void 0 || !isAggregatedRow(resourceId)) return [];
159
+ return filterTimelineLaneEvents(input.events, {
160
+ resourceId,
161
+ matchIds: descendantIdMap.get(resourceId) ?? /* @__PURE__ */ new Set([resourceId]),
162
+ viewStart: effectiveViewStart,
163
+ viewEnd: effectiveViewEnd
164
+ });
165
+ };
166
+ const getTimelineEventPosition = (event) => getTimelineEventRect(event, {
167
+ ...positionInput,
168
+ fallbackDurationMinutes: input.slotDurationMin
169
+ });
170
+ const laneModels = /* @__PURE__ */ new Map();
171
+ const laneResourceIds = visibleResources.length > 0 ? visibleResources.map((resource) => resource.id) : [void 0];
172
+ for (const resourceId of laneResourceIds) {
173
+ const events = getEventsForLane(resourceId);
174
+ const { assignment, laneCount } = monthGranularity ? computeVisualLaneAssignment(events, getTimelineEventPosition, input.stackingMode) : computeTimelineLaneAssignment(events, input.stackingMode);
175
+ const aggregateEvents = getAggregateEvents(resourceId);
176
+ laneModels.set(resourceId, {
177
+ resourceId,
178
+ events,
179
+ assignment,
180
+ laneCount,
181
+ aggregateEvents,
182
+ aggregateCount: aggregateEvents.length,
183
+ isAggregated: isAggregatedRow(resourceId)
184
+ });
185
+ }
186
+ const laneCounts = /* @__PURE__ */ new Map();
187
+ const expandedRowHeights = /* @__PURE__ */ new Map();
188
+ const baseRowHeight = resolveTimelineResourceRowHeight({
189
+ laneCount: 1,
190
+ eventHeight: timelineEventMinHeight,
191
+ minRowHeight: input.resourceRowHeight,
192
+ mode: rowHeightMode
193
+ });
194
+ for (const resource of visibleResources) {
195
+ const laneCount = laneModels.get(resource.id)?.laneCount ?? 1;
196
+ laneCounts.set(resource.id, laneCount);
197
+ expandedRowHeights.set(
198
+ resource.id,
199
+ resolveTimelineResourceRowHeight({
200
+ laneCount,
201
+ eventHeight: timelineEventMinHeight,
202
+ minRowHeight: input.resourceRowHeight,
203
+ mode: rowHeightMode
204
+ })
205
+ );
206
+ }
207
+ const resourceLayouts = visibleResources.length > 0 ? calculateResourceRowLayouts(visibleResources, baseRowHeight, expandedRowHeights, laneCounts) : [];
208
+ const totalResourceHeight = getTotalResourceHeight(resourceLayouts);
209
+ const virtualScrollCells = cells.map((cell, index) => ({
210
+ date: cell.startDate,
211
+ startTime: cell.startDate,
212
+ endTime: cell.endDate,
213
+ isToday: cell.isToday,
214
+ isWeekend: cell.isWeekend,
215
+ isBusinessHour: false,
216
+ width: cell.width,
217
+ index
218
+ }));
219
+ const virtualScrollEvents = input.events.filter((event) => eventIntersectsRange(event, input.viewStart, input.viewEnd)).map((event) => {
220
+ const rect = getTimelineEventPosition(event);
221
+ return {
222
+ left: rect.left,
223
+ width: rect.width,
224
+ row: 0,
225
+ event,
226
+ continuesBefore: false,
227
+ continuesAfter: false
228
+ };
229
+ });
230
+ const visibleCells = input.virtualRange ? cells.slice(input.virtualRange.startIndex, input.virtualRange.endIndex + 1) : cells;
231
+ const visibleHeaderTiers = buildVisibleHeaderTiers({
232
+ headerTiers,
233
+ visibleCells,
234
+ virtualRange: input.virtualRange
235
+ });
236
+ return {
237
+ cells,
238
+ visibleDayStarts,
239
+ effectiveViewStart,
240
+ effectiveViewEnd,
241
+ totalWidth,
242
+ visibleMinutesPerDay,
243
+ resources,
244
+ visibleResources,
245
+ headerTiers,
246
+ visibleCells,
247
+ visibleHeaderTiers,
248
+ laneModels,
249
+ resourceLayouts,
250
+ totalResourceHeight,
251
+ virtualScrollCells,
252
+ virtualScrollEvents,
253
+ getEventsForLane,
254
+ getAggregateEvents,
255
+ getAggregateCount: (resourceId) => getAggregateEvents(resourceId).length,
256
+ getEventLeft: (event) => getTimelineEventPosition(event).left,
257
+ getEventWidth: (event) => getTimelineEventPosition(event).width,
258
+ getEventLane: (event, resourceId) => {
259
+ const entry = laneModels.get(resourceId);
260
+ if (!entry || event.id == null) return 0;
261
+ return entry.assignment.get(event.id) ?? 0;
262
+ },
263
+ getLaneCount: (resourceId) => laneModels.get(resourceId)?.laneCount ?? 1,
264
+ isAggregatedRow,
265
+ timeToPixels: (date) => timeToTimelinePixels({ ...positionInput, date })
266
+ };
267
+ }
268
+
269
+ export { buildTimelineViewModel };
@@ -1,6 +1,6 @@
1
- import { parseRRule } from './chunk-FIBAZFC4.mjs';
2
- import { timeStringToMinutes } from './chunk-WFUJWDST.mjs';
3
- import { createSchedulerDateFormatter, formatTimeRange } from './chunk-TNKJPFGI.mjs';
1
+ import { parseRRule } from './chunk-6Q5FR4PN.mjs';
2
+ import { timeStringToMinutes } from './chunk-XQAYO7CQ.mjs';
3
+ import { createSchedulerDateFormatter, formatTimeRange } from './chunk-F2LYNUXG.mjs';
4
4
 
5
5
  // src/utils/blocked-intervals.ts
6
6
  function parseDate(date) {
@@ -1,6 +1,6 @@
1
- import { getLocalTimezone, convertEventsToTimezone } from './chunk-QDMZBJDV.mjs';
2
- import { formatGregorianYear, formatGregorianMonthTitle, formatGregorianWeekday, formatGregorianDayNumber, toDateString } from './chunk-WFUJWDST.mjs';
3
- import { getSchedulerCalendarAdapter } from './chunk-DYW6WUHE.mjs';
1
+ import { getLocalTimezone, convertEventsToTimezone } from './chunk-P7CIUMQZ.mjs';
2
+ import { formatGregorianYear, formatGregorianMonthTitle, formatGregorianWeekday, formatGregorianDayNumber, toDateString } from './chunk-XQAYO7CQ.mjs';
3
+ import { getSchedulerCalendarAdapter } from './chunk-6OTDPEJM.mjs';
4
4
 
5
5
  // src/year/view-model.ts
6
6
  function toDate(value) {
@@ -1,10 +1,82 @@
1
- import { positionEventsForDay, getAllDayEventsForDay, positionAllDayEventsForWeek } from './chunk-6VYWVIGM.mjs';
2
- import { parseEvents, getTimedEventsForDayAndResource, eventMatchesResource } from './chunk-2B3YLWHA.mjs';
3
- import { getTimedBusinessHoursOverlays, getTimedBlockedIntervalsOverlays } from './chunk-AAVM7UCG.mjs';
4
- import { getAppointmentSlotIndicators, getAppointmentSlotOverlays } from './chunk-NZGJN7HG.mjs';
5
- import { getDatePartsInTimezone } from './chunk-QDMZBJDV.mjs';
6
- import { timeStringToMinutes, startOfDay, toDateString } from './chunk-WFUJWDST.mjs';
7
- import { resolveSchedulerCalendarModeForView, getSchedulerCalendarAdapter } from './chunk-DYW6WUHE.mjs';
1
+ import { positionEventsForDay, getAllDayEventsForDay, positionAllDayEventsForWeek } from './chunk-QBTFRSZM.mjs';
2
+ import { parseEvents, getTimedEventsForDayAndResource, eventMatchesResource } from './chunk-UKD2NVDC.mjs';
3
+ import { getAppointmentSlotIndicators, getAppointmentSlotOverlays } from './chunk-RM6OQCEO.mjs';
4
+ import { normalizeBusinessHours, getBlockedIntervalsForDay } from './chunk-JCNXNPGM.mjs';
5
+ import { getDatePartsInTimezone } from './chunk-P7CIUMQZ.mjs';
6
+ import { timeStringToMinutes, startOfDay, toDateString, minutesToPixels } from './chunk-XQAYO7CQ.mjs';
7
+ import { resolveSchedulerCalendarModeForView, getSchedulerCalendarAdapter } from './chunk-6OTDPEJM.mjs';
8
+
9
+ // src/utils/overlay.ts
10
+ function getTimedBusinessHoursOverlays(date, businessHours, slotMinTime, slotMaxTime, slotDuration, slotHeight) {
11
+ const configs = normalizeBusinessHours(businessHours);
12
+ if (configs.length === 0) return [];
13
+ const dayOfWeek = date.getDay();
14
+ const config = configs.find((c) => c.daysOfWeek.includes(dayOfWeek));
15
+ const overlays = [];
16
+ const slotMinMinutes = timeStringToMinutes(slotMinTime);
17
+ const slotMaxMinutes = timeStringToMinutes(slotMaxTime);
18
+ const pushOverlay = (startMinutes, endMinutes) => {
19
+ const clampedStart = Math.max(startMinutes, slotMinMinutes);
20
+ const clampedEnd = Math.min(endMinutes, slotMaxMinutes);
21
+ if (clampedStart >= clampedEnd) return;
22
+ const top = minutesToPixels(clampedStart - slotMinMinutes, slotDuration, slotHeight);
23
+ const height = minutesToPixels(clampedEnd - clampedStart, slotDuration, slotHeight);
24
+ overlays.push({
25
+ position: "absolute",
26
+ top: top === 0 ? "0" : `${top}px`,
27
+ left: "0",
28
+ right: "0",
29
+ height: `${height}px`,
30
+ pointerEvents: "none",
31
+ zIndex: "0"
32
+ });
33
+ };
34
+ if (!config) {
35
+ pushOverlay(slotMinMinutes, slotMaxMinutes);
36
+ return overlays;
37
+ }
38
+ const businessStartMinutes = timeStringToMinutes(config.startTime);
39
+ const businessEndMinutes = timeStringToMinutes(config.endTime);
40
+ pushOverlay(slotMinMinutes, businessStartMinutes);
41
+ pushOverlay(businessEndMinutes, slotMaxMinutes);
42
+ return overlays;
43
+ }
44
+ function getTimedBlockedIntervalsOverlays(date, blockedIntervals, slotMinTime, slotMaxTime, slotDuration, slotHeight, resourceId) {
45
+ if (!blockedIntervals) return [];
46
+ const intervals = getBlockedIntervalsForDay(blockedIntervals, date, resourceId);
47
+ if (intervals.length === 0) return [];
48
+ const overlays = [];
49
+ const slotMinMinutes = timeStringToMinutes(slotMinTime);
50
+ const slotMaxMinutes = timeStringToMinutes(slotMaxTime);
51
+ for (const interval of intervals) {
52
+ const intervalStartMinutes = interval.start.getHours() * 60 + interval.start.getMinutes();
53
+ const intervalEndMinutes = interval.end.getHours() * 60 + interval.end.getMinutes();
54
+ const clampedStart = Math.max(intervalStartMinutes, slotMinMinutes);
55
+ const clampedEnd = Math.min(intervalEndMinutes, slotMaxMinutes);
56
+ if (clampedStart >= clampedEnd) continue;
57
+ const top = minutesToPixels(clampedStart - slotMinMinutes, slotDuration, slotHeight);
58
+ const height = minutesToPixels(clampedEnd - clampedStart, slotDuration, slotHeight);
59
+ const style = {
60
+ position: "absolute",
61
+ top: `${top}px`,
62
+ left: "0",
63
+ right: "0",
64
+ height: `${height}px`,
65
+ pointerEvents: "none",
66
+ zIndex: "2"
67
+ };
68
+ if (interval.background) {
69
+ style.background = interval.background;
70
+ }
71
+ overlays.push({
72
+ style,
73
+ title: interval.title,
74
+ className: interval.className,
75
+ interval
76
+ });
77
+ }
78
+ return overlays;
79
+ }
8
80
 
9
81
  // src/time-grid/view-model.ts
10
82
  var RESOURCE_VIEWS = ["resourceDay", "resourceWeek"];