@open-rlb/ng-bootstrap 3.3.17 → 3.3.18
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.
|
@@ -2513,17 +2513,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
2513
2513
|
args: [{ selector: 'rlb-fab', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ButtonComponent], template: "<button rlb-button [color]=\"color()\" [disabled]=\"disabled()\" [outline]=\"outline()\"\n class=\"fab-button d-flex align-items-center justify-content-center\" [class]=\"[sizeClass(), positionClass()]\">\n <ng-content></ng-content>\n</button>", styles: [".fab-button{border-radius:50%;box-shadow:0 4px 12px #00000040;z-index:1050;transition:transform .2s ease,box-shadow .2s ease;padding:0}.fab-button:hover{transform:scale(1.08);box-shadow:0 6px 18px #00000059}.fab-button:active{transform:scale(.95)}:host{width:fit-content;display:block}.fab-xs{width:32px;height:32px;font-size:1rem}.fab-sm{width:44px;height:44px;font-size:1.2rem}.fab-md{width:56px;height:56px;font-size:1.4rem}.fab-lg{width:68px;height:68px;font-size:1.7rem}.fab-bottom-right{bottom:24px;right:24px}.fab-bottom-left{bottom:24px;left:24px}.fab-top-right{top:24px;right:24px}.fab-top-left{top:24px;left:24px}\n"] }]
|
|
2514
2514
|
}], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], outline: [{ type: i0.Input, args: [{ isSignal: true, alias: "outline", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }] } });
|
|
2515
2515
|
|
|
2516
|
+
const MS_PER_DAY = 86_400_000;
|
|
2517
|
+
/**
|
|
2518
|
+
* NOTE on date-tz: the getters (`.hour`, `.minute`, `.day`, `.dayOfWeek`, ...)
|
|
2519
|
+
* and `toString()` are timezone-aware (they add `timezoneOffset` to the raw
|
|
2520
|
+
* timestamp), but the mutators `set()`, `add()` and `stripSecMillis()` are
|
|
2521
|
+
* timezone-NAIVE — they decompose/recompose the raw timestamp as if it were
|
|
2522
|
+
* UTC. So `set(0, 'hour')` zeroes the UTC hour, not the local one.
|
|
2523
|
+
*
|
|
2524
|
+
* For calendar layout we need timezone-aware day math, so the helpers below
|
|
2525
|
+
* derive day boundaries and intra-day offsets from the tz-aware side of the
|
|
2526
|
+
* library instead of from `set()/add()`.
|
|
2527
|
+
*/
|
|
2516
2528
|
/** Returns the IANA timezone resolved from the browser/runtime. */
|
|
2517
2529
|
function getBrowserTimezone() {
|
|
2518
2530
|
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
2519
2531
|
}
|
|
2532
|
+
/** Epoch ms of local midnight (in `timezone`) of the day containing `d`. */
|
|
2533
|
+
function startOfDayTs(d, timezone) {
|
|
2534
|
+
const local = d.cloneToTimezone(timezone);
|
|
2535
|
+
const localMs = local.timestamp + local.timezoneOffset;
|
|
2536
|
+
return Math.floor(localMs / MS_PER_DAY) * MS_PER_DAY - local.timezoneOffset;
|
|
2537
|
+
}
|
|
2538
|
+
/** Minutes elapsed since local midnight (in `timezone`) for `d`. */
|
|
2539
|
+
function minutesSinceMidnight(d, timezone) {
|
|
2540
|
+
const local = d.cloneToTimezone(timezone);
|
|
2541
|
+
return local.hour * 60 + local.minute;
|
|
2542
|
+
}
|
|
2543
|
+
/** Local-midnight instance (in `timezone`) for the day at index `offsetDays` from `d`. */
|
|
2544
|
+
function dayAt(d, timezone, offsetDays = 0) {
|
|
2545
|
+
const baseMidnight = startOfDayTs(d, timezone);
|
|
2546
|
+
// Re-floor after the raw day shift so DST transitions can't drift the result.
|
|
2547
|
+
const shifted = new DateTz(baseMidnight + offsetDays * MS_PER_DAY, timezone);
|
|
2548
|
+
return new DateTz(startOfDayTs(shifted, timezone), timezone);
|
|
2549
|
+
}
|
|
2520
2550
|
function isSameDay(a, b, timezone) {
|
|
2521
2551
|
const tz = timezone ?? getBrowserTimezone();
|
|
2522
|
-
|
|
2523
|
-
const db = b.cloneToTimezone(tz);
|
|
2524
|
-
return da.year === db.year &&
|
|
2525
|
-
da.month === db.month &&
|
|
2526
|
-
da.day === db.day;
|
|
2552
|
+
return startOfDayTs(a, tz) === startOfDayTs(b, tz);
|
|
2527
2553
|
}
|
|
2528
2554
|
function addDays(date, days) {
|
|
2529
2555
|
return new DateTz(date.add(days, 'day'));
|
|
@@ -2532,17 +2558,9 @@ function startOfMonth(date) {
|
|
|
2532
2558
|
const d = new DateTz(date);
|
|
2533
2559
|
return d.set(1, 'day');
|
|
2534
2560
|
}
|
|
2535
|
-
// export function endOfMonth(date: IDateTz): DateTz {
|
|
2536
|
-
// const d = new DateTz(date.timestamp, 'UTC');
|
|
2537
|
-
// return d.add(1, 'month').set(1, 'day').add(-1, 'day');
|
|
2538
|
-
// }
|
|
2539
2561
|
function isToday(date, timezone) {
|
|
2540
2562
|
const tz = timezone ?? getBrowserTimezone();
|
|
2541
|
-
|
|
2542
|
-
const today = getToday(tz);
|
|
2543
|
-
return d.year === today.year &&
|
|
2544
|
-
d.month === today.month &&
|
|
2545
|
-
d.day === today.day;
|
|
2563
|
+
return startOfDayTs(date, tz) === startOfDayTs(getToday(tz), tz);
|
|
2546
2564
|
}
|
|
2547
2565
|
function getToday(timezone) {
|
|
2548
2566
|
return DateTz.now(timezone ?? getBrowserTimezone());
|
|
@@ -2733,13 +2751,12 @@ class CalendarWeekGridComponent {
|
|
|
2733
2751
|
const rawMinutesFromStart = (newTopPx / this.layout().rowHeight) * 60;
|
|
2734
2752
|
const snappedMinutes = Math.round(rawMinutesFromStart / this.SNAP_MINUTES) * this.SNAP_MINUTES;
|
|
2735
2753
|
const validMinutes = Math.max(0, snappedMinutes);
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
.stripSecMillis();
|
|
2754
|
+
// Local midnight of the target day + dropped offset (tz-aware).
|
|
2755
|
+
const tz = this.timezone();
|
|
2756
|
+
const newStartTs = startOfDayTs(newDay, tz) + validMinutes * 60 * 1000;
|
|
2757
|
+
const newStart = new DateTz$1(newStartTs, tz).stripSecMillis();
|
|
2741
2758
|
const durationMs = movedEvent.end.timestamp - movedEvent.start.timestamp;
|
|
2742
|
-
const newEnd = new DateTz$1(newStart.timestamp + durationMs,
|
|
2759
|
+
const newEnd = new DateTz$1(newStart.timestamp + durationMs, tz).stripSecMillis();
|
|
2743
2760
|
if (newStart.timestamp !== movedEvent.start.timestamp) {
|
|
2744
2761
|
const updatedEvent = {
|
|
2745
2762
|
...movedEvent,
|
|
@@ -2750,13 +2767,10 @@ class CalendarWeekGridComponent {
|
|
|
2750
2767
|
}
|
|
2751
2768
|
}
|
|
2752
2769
|
getEventsForDay(day) {
|
|
2753
|
-
|
|
2754
|
-
return this.processedEvents().get(dayTs) || [];
|
|
2770
|
+
return this.processedEvents().get(startOfDayTs(day, this.timezone())) || [];
|
|
2755
2771
|
}
|
|
2756
2772
|
calculateEventTop(event) {
|
|
2757
|
-
const
|
|
2758
|
-
const diffMs = event.start.timestamp - startOfDay.timestamp;
|
|
2759
|
-
const diffMinutes = diffMs / (1000 * 60);
|
|
2773
|
+
const diffMinutes = minutesSinceMidnight(event.start, this.timezone());
|
|
2760
2774
|
return (diffMinutes / 60) * this.layout().rowHeight;
|
|
2761
2775
|
}
|
|
2762
2776
|
calculateEventHeight(event) {
|
|
@@ -2803,16 +2817,13 @@ class CalendarWeekGridComponent {
|
|
|
2803
2817
|
return `var(--bs-${interval.color || 'success'})`;
|
|
2804
2818
|
}
|
|
2805
2819
|
buildWeekGrid(currentDate) {
|
|
2806
|
-
const
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
.set(0, 'hour')
|
|
2811
|
-
.set(0, 'minute')
|
|
2812
|
-
.stripSecMillis();
|
|
2820
|
+
const tz = this.timezone();
|
|
2821
|
+
const dayOfWeek = currentDate.cloneToTimezone(tz).dayOfWeek; // 0 = Sunday, 1 = Monday ...
|
|
2822
|
+
// Offset (in days) from currentDate back to the week's Monday.
|
|
2823
|
+
const mondayOffset = 1 - dayOfWeek; // Sun(0) -> +1, Mon(1) -> 0, Tue(2) -> -1 ...
|
|
2813
2824
|
const newDays = [];
|
|
2814
2825
|
for (let i = 0; i < 7; i++) {
|
|
2815
|
-
newDays.push(
|
|
2826
|
+
newDays.push(dayAt(currentDate, tz, mondayOffset + i));
|
|
2816
2827
|
}
|
|
2817
2828
|
this.days.set(newDays);
|
|
2818
2829
|
this.startNowTimer();
|
|
@@ -2833,37 +2844,32 @@ class CalendarWeekGridComponent {
|
|
|
2833
2844
|
}
|
|
2834
2845
|
processAllEvents(events) {
|
|
2835
2846
|
const eventsByDay = new Map();
|
|
2847
|
+
const tz = this.timezone();
|
|
2836
2848
|
for (const event of events) {
|
|
2837
|
-
const
|
|
2838
|
-
const
|
|
2839
|
-
let
|
|
2840
|
-
while (
|
|
2841
|
-
const
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
const chunkEndTimestamp = Math.min(originalEnd.timestamp, startOfNextDay.timestamp);
|
|
2847
|
-
const chunkEnd = new DateTz$1(chunkEndTimestamp);
|
|
2848
|
-
const currentDayStart = new DateTz$1(currentChunkStart)
|
|
2849
|
-
.set(0, 'hour')
|
|
2850
|
-
.set(0, 'minute')
|
|
2851
|
-
.stripSecMillis();
|
|
2852
|
-
const dayTimestamp = currentDayStart.timestamp;
|
|
2849
|
+
const originalStartTs = new DateTz$1(event.start).stripSecMillis().timestamp;
|
|
2850
|
+
const originalEndTs = new DateTz$1(event.end).stripSecMillis().timestamp;
|
|
2851
|
+
let chunkStartTs = originalStartTs;
|
|
2852
|
+
while (chunkStartTs < originalEndTs) {
|
|
2853
|
+
const chunkInst = new DateTz$1(chunkStartTs, tz);
|
|
2854
|
+
// tz-aware day boundaries (set()/add() would be UTC-naive here).
|
|
2855
|
+
const dayStartTs = startOfDayTs(chunkInst, tz);
|
|
2856
|
+
const startOfNextDayTs = dayAt(chunkInst, tz, 1).timestamp;
|
|
2857
|
+
const chunkEndTs = Math.min(originalEndTs, startOfNextDayTs);
|
|
2853
2858
|
const visualEvent = {
|
|
2854
2859
|
...event,
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2860
|
+
// Chunks live in the calendar timezone, so labels and positions agree.
|
|
2861
|
+
start: new DateTz$1(chunkStartTs, tz),
|
|
2862
|
+
end: new DateTz$1(chunkEndTs, tz),
|
|
2863
|
+
isContinuedBefore: chunkStartTs > originalStartTs,
|
|
2864
|
+
isContinuedAfter: chunkEndTs < originalEndTs,
|
|
2859
2865
|
left: 0,
|
|
2860
2866
|
width: 0
|
|
2861
2867
|
};
|
|
2862
|
-
if (!eventsByDay.has(
|
|
2863
|
-
eventsByDay.set(
|
|
2868
|
+
if (!eventsByDay.has(dayStartTs)) {
|
|
2869
|
+
eventsByDay.set(dayStartTs, []);
|
|
2864
2870
|
}
|
|
2865
|
-
eventsByDay.get(
|
|
2866
|
-
|
|
2871
|
+
eventsByDay.get(dayStartTs).push(visualEvent);
|
|
2872
|
+
chunkStartTs = startOfNextDayTs;
|
|
2867
2873
|
}
|
|
2868
2874
|
}
|
|
2869
2875
|
const newProcessedEvents = new Map();
|
|
@@ -3079,21 +3085,18 @@ class CalendarMonthGridComponent {
|
|
|
3079
3085
|
}
|
|
3080
3086
|
// --- Core Logic ---
|
|
3081
3087
|
buildMonthGrid() {
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3088
|
+
const tz = this.timezone();
|
|
3089
|
+
// 1. Calculate Grid Boundaries (tz-aware; set()/add() would be UTC-naive)
|
|
3090
|
+
const current = this.currentDate().cloneToTimezone(tz);
|
|
3091
|
+
// First day of the month at local midnight
|
|
3092
|
+
const firstOfMonth = dayAt(current, tz, -(current.day - 1));
|
|
3093
|
+
// Calculate offset to find the start of the grid (Monday-first)
|
|
3094
|
+
const dayOfWeek = firstOfMonth.dayOfWeek; // 0 = Sun, 1 = Mon...
|
|
3089
3095
|
const offset = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
|
|
3090
|
-
const gridStart = new DateTz(startOfMonth).add(-offset, 'day');
|
|
3091
3096
|
// 2. Generate Days
|
|
3092
3097
|
const days = [];
|
|
3093
|
-
let iter = new DateTz(gridStart);
|
|
3094
3098
|
for (let i = 0; i < DAYS_IN_GRID; i++) {
|
|
3095
|
-
days.push(
|
|
3096
|
-
iter = new DateTz(iter).add(1, 'day');
|
|
3099
|
+
days.push(dayAt(firstOfMonth, tz, i - offset));
|
|
3097
3100
|
}
|
|
3098
3101
|
// Header is just the first week
|
|
3099
3102
|
this.weekDaysHeader.set(days.slice(0, 7));
|
|
@@ -3148,6 +3151,7 @@ class CalendarMonthGridComponent {
|
|
|
3148
3151
|
* Places events into rows so that long events maintain their vertical position across days.
|
|
3149
3152
|
*/
|
|
3150
3153
|
calculateEventSlots(days, events) {
|
|
3154
|
+
const tz = this.timezone();
|
|
3151
3155
|
const dayMap = new Map();
|
|
3152
3156
|
days.forEach(d => dayMap.set(d.timestamp, []));
|
|
3153
3157
|
// Sort: Longest events first, then by start time
|
|
@@ -3161,25 +3165,18 @@ class CalendarMonthGridComponent {
|
|
|
3161
3165
|
const gridStartTs = days[0].timestamp;
|
|
3162
3166
|
const lastDay = days[days.length - 1];
|
|
3163
3167
|
// End of grid is the start of the next day after the last cell
|
|
3164
|
-
const gridEndTs =
|
|
3168
|
+
const gridEndTs = dayAt(lastDay, tz, 1).timestamp;
|
|
3165
3169
|
for (const event of sortedEvents) {
|
|
3166
|
-
//
|
|
3167
|
-
const
|
|
3168
|
-
|
|
3169
|
-
//
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
if (evtEndRaw.timestamp > evtStart.timestamp && isMidnight) {
|
|
3175
|
-
evtEnd = evtEndRaw; // Keeps it clean for comparison, effectively 00:00 of next day
|
|
3176
|
-
}
|
|
3177
|
-
else {
|
|
3178
|
-
// Round to start of next day to cover full day
|
|
3179
|
-
evtEnd = new DateTz(evtEndRaw).set(0, 'hour').set(0, 'minute').add(1, 'day').stripSecMillis();
|
|
3180
|
-
}
|
|
3170
|
+
// tz-aware day-floors (set()/add() would be UTC-naive).
|
|
3171
|
+
const evtStartTs = startOfDayTs(event.start, tz);
|
|
3172
|
+
// Normalize end. If it ends exactly at local 00:00, it visually ends on the
|
|
3173
|
+
// previous day; otherwise round up to the start of the next day.
|
|
3174
|
+
const endsAtMidnight = minutesSinceMidnight(event.end, tz) === 0;
|
|
3175
|
+
const evtEndTs = (event.end.timestamp > evtStartTs && endsAtMidnight)
|
|
3176
|
+
? startOfDayTs(event.end, tz)
|
|
3177
|
+
: dayAt(event.end, tz, 1).timestamp;
|
|
3181
3178
|
// Skip if completely outside grid
|
|
3182
|
-
if (
|
|
3179
|
+
if (evtEndTs <= gridStartTs || evtStartTs >= gridEndTs) {
|
|
3183
3180
|
continue;
|
|
3184
3181
|
}
|
|
3185
3182
|
// Find which grid indices this event occupies
|
|
@@ -3187,7 +3184,7 @@ class CalendarMonthGridComponent {
|
|
|
3187
3184
|
for (let i = 0; i < days.length; i++) {
|
|
3188
3185
|
const dTs = days[i].timestamp;
|
|
3189
3186
|
// Check intersection: [DayStart, DayEnd) overlaps [EventStart, EventEnd)
|
|
3190
|
-
if (dTs >=
|
|
3187
|
+
if (dTs >= evtStartTs && dTs < evtEndTs) {
|
|
3191
3188
|
daysIndices.push(i);
|
|
3192
3189
|
}
|
|
3193
3190
|
}
|
|
@@ -3226,10 +3223,10 @@ class CalendarMonthGridComponent {
|
|
|
3226
3223
|
const isLastRenderDay = (i === daysIndices.length - 1);
|
|
3227
3224
|
// `dayInTz` is the grid cell, already in the calendar timezone.
|
|
3228
3225
|
const dayInTz = days[idx];
|
|
3229
|
-
const currentDayEnd =
|
|
3226
|
+
const currentDayEnd = dayAt(dayInTz, tz, 1);
|
|
3230
3227
|
// Visual flags for rounding corners
|
|
3231
|
-
const isContinuedBefore = !isFirstRenderDay || (
|
|
3232
|
-
const isContinuedAfter = !isLastRenderDay || (
|
|
3228
|
+
const isContinuedBefore = !isFirstRenderDay || (evtStartTs < days[daysIndices[0]].timestamp);
|
|
3229
|
+
const isContinuedAfter = !isLastRenderDay || (evtEndTs > currentDayEnd.timestamp);
|
|
3233
3230
|
const eventView = {
|
|
3234
3231
|
...event,
|
|
3235
3232
|
// Override start/end for the specific cell (crucial for DnD to know the cell context)
|
|
@@ -3327,13 +3324,12 @@ class CalendarDayGridComponent {
|
|
|
3327
3324
|
const rawMinutesFromStart = (newTopPx / this.layout().rowHeight) * 60;
|
|
3328
3325
|
const snappedMinutes = Math.round(rawMinutesFromStart / this.SNAP_MINUTES) * this.SNAP_MINUTES;
|
|
3329
3326
|
const validMinutes = Math.max(0, snappedMinutes);
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
.stripSecMillis();
|
|
3327
|
+
// Local midnight of the target day + dropped offset (tz-aware).
|
|
3328
|
+
const tz = this.timezone();
|
|
3329
|
+
const newStartTs = startOfDayTs(newDay, tz) + validMinutes * 60 * 1000;
|
|
3330
|
+
const newStart = new DateTz$1(newStartTs, tz).stripSecMillis();
|
|
3335
3331
|
const durationMs = movedEvent.end.timestamp - movedEvent.start.timestamp;
|
|
3336
|
-
const newEnd = new DateTz$1(newStart.timestamp + durationMs,
|
|
3332
|
+
const newEnd = new DateTz$1(newStart.timestamp + durationMs, tz).stripSecMillis();
|
|
3337
3333
|
if (newStart.timestamp !== movedEvent.start.timestamp) {
|
|
3338
3334
|
const updatedEvent = {
|
|
3339
3335
|
...movedEvent,
|
|
@@ -3344,16 +3340,9 @@ class CalendarDayGridComponent {
|
|
|
3344
3340
|
}
|
|
3345
3341
|
}
|
|
3346
3342
|
calculateEventTop(event) {
|
|
3347
|
-
|
|
3348
|
-
//
|
|
3349
|
-
|
|
3350
|
-
// Logic from week grid handles "chunks", here we assume processAllEvents has given us the chunk for this day.
|
|
3351
|
-
let eventStart = new DateTz$1(event.start);
|
|
3352
|
-
if (eventStart.timestamp < startOfDay.timestamp) {
|
|
3353
|
-
eventStart = startOfDay;
|
|
3354
|
-
}
|
|
3355
|
-
const diffMs = eventStart.timestamp - startOfDay.timestamp;
|
|
3356
|
-
const diffMinutes = diffMs / (1000 * 60);
|
|
3343
|
+
// processAllEvents already clamped the event to this day, so its start is
|
|
3344
|
+
// within [00:00, 24:00) of the day. Minutes-since-local-midnight is tz-aware.
|
|
3345
|
+
const diffMinutes = minutesSinceMidnight(event.start, this.timezone());
|
|
3357
3346
|
return (diffMinutes / 60) * this.layout().rowHeight;
|
|
3358
3347
|
}
|
|
3359
3348
|
calculateEventHeight(event) {
|
|
@@ -3400,7 +3389,8 @@ class CalendarDayGridComponent {
|
|
|
3400
3389
|
return `var(--bs-${interval.color || 'success'})`;
|
|
3401
3390
|
}
|
|
3402
3391
|
buildDayGrid(currentDate) {
|
|
3403
|
-
|
|
3392
|
+
// Anchor the day to local midnight in the calendar timezone.
|
|
3393
|
+
this.day.set(dayAt(currentDate, this.timezone(), 0));
|
|
3404
3394
|
this.startNowTimer();
|
|
3405
3395
|
}
|
|
3406
3396
|
buildTimeSlots() {
|
|
@@ -3420,29 +3410,23 @@ class CalendarDayGridComponent {
|
|
|
3420
3410
|
processAllEvents(events, day) {
|
|
3421
3411
|
if (!day)
|
|
3422
3412
|
return;
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
const
|
|
3413
|
+
const tz = this.timezone();
|
|
3414
|
+
// tz-aware day boundaries (set()/add() would be UTC-naive here).
|
|
3415
|
+
const dayStartTs = startOfDayTs(day, tz);
|
|
3416
|
+
const dayEndTs = dayAt(day, tz, 1).timestamp;
|
|
3426
3417
|
const dayEvents = [];
|
|
3427
3418
|
for (const event of events) {
|
|
3428
3419
|
// Check overlap with the day
|
|
3429
|
-
if (event.end.timestamp >
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
if (visualStart.timestamp < dayStart.timestamp) {
|
|
3435
|
-
visualStart = dayStart;
|
|
3436
|
-
isContinuedBefore = true;
|
|
3437
|
-
}
|
|
3438
|
-
if (visualEnd.timestamp > dayEnd.timestamp) {
|
|
3439
|
-
visualEnd = dayEnd;
|
|
3440
|
-
isContinuedAfter = true;
|
|
3441
|
-
}
|
|
3420
|
+
if (event.end.timestamp > dayStartTs && event.start.timestamp < dayEndTs) {
|
|
3421
|
+
const isContinuedBefore = event.start.timestamp < dayStartTs;
|
|
3422
|
+
const isContinuedAfter = event.end.timestamp > dayEndTs;
|
|
3423
|
+
const visualStartTs = Math.max(event.start.timestamp, dayStartTs);
|
|
3424
|
+
const visualEndTs = Math.min(event.end.timestamp, dayEndTs);
|
|
3442
3425
|
dayEvents.push({
|
|
3443
3426
|
...event,
|
|
3444
|
-
|
|
3445
|
-
|
|
3427
|
+
// Chunks live in the calendar timezone, so labels and positions agree.
|
|
3428
|
+
start: new DateTz$1(visualStartTs, tz),
|
|
3429
|
+
end: new DateTz$1(visualEndTs, tz),
|
|
3446
3430
|
isContinuedBefore,
|
|
3447
3431
|
isContinuedAfter,
|
|
3448
3432
|
left: 0,
|