trud-calendar-core 0.4.0 → 1.0.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.
- package/dist/index.cjs +374 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +200 -4
- package/dist/index.d.ts +200 -4
- package/dist/index.js +364 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -8,6 +8,7 @@ var DEFAULT_LABELS = {
|
|
|
8
8
|
day: "Day",
|
|
9
9
|
agenda: "Agenda",
|
|
10
10
|
year: "Year",
|
|
11
|
+
timeline: "Timeline",
|
|
11
12
|
allDay: "all-day",
|
|
12
13
|
noEvents: "No events in this period",
|
|
13
14
|
more: (n) => `+${n} more`
|
|
@@ -20,7 +21,7 @@ var DEFAULT_VIEW = "month";
|
|
|
20
21
|
var HOURS_IN_DAY = 24;
|
|
21
22
|
var MINUTES_IN_HOUR = 60;
|
|
22
23
|
var MINUTES_IN_DAY = HOURS_IN_DAY * MINUTES_IN_HOUR;
|
|
23
|
-
var VIEWS = ["month", "week", "day", "agenda", "year"];
|
|
24
|
+
var VIEWS = ["month", "week", "day", "agenda", "year", "timeline"];
|
|
24
25
|
var DEFAULT_DAY_START_HOUR = 0;
|
|
25
26
|
var DEFAULT_DAY_END_HOUR = 24;
|
|
26
27
|
var DEFAULT_SNAP_DURATION = 15;
|
|
@@ -142,6 +143,8 @@ function getVisibleRange(date, view, weekStartsOn = 0) {
|
|
|
142
143
|
const yearEnd = `${d.getFullYear()}-12-31`;
|
|
143
144
|
return { start: yearStart, end: yearEnd };
|
|
144
145
|
}
|
|
146
|
+
case "timeline":
|
|
147
|
+
return { start: date, end: date };
|
|
145
148
|
}
|
|
146
149
|
}
|
|
147
150
|
function getISOWeekNumber(date) {
|
|
@@ -215,6 +218,13 @@ function formatToolbarTitle(date, view, locale = "en-US") {
|
|
|
215
218
|
return getFormatter(locale, { month: "long", year: "numeric" }).format(d);
|
|
216
219
|
case "year":
|
|
217
220
|
return getFormatter(locale, { year: "numeric" }).format(d);
|
|
221
|
+
case "timeline":
|
|
222
|
+
return getFormatter(locale, {
|
|
223
|
+
weekday: "long",
|
|
224
|
+
month: "long",
|
|
225
|
+
day: "numeric",
|
|
226
|
+
year: "numeric"
|
|
227
|
+
}).format(d);
|
|
218
228
|
}
|
|
219
229
|
}
|
|
220
230
|
function formatWeekdayShort(date, locale = "en-US") {
|
|
@@ -269,6 +279,8 @@ function navigateByView(date, view, direction) {
|
|
|
269
279
|
return addMonths(date, direction);
|
|
270
280
|
case "year":
|
|
271
281
|
return addMonths(date, 12 * direction);
|
|
282
|
+
case "timeline":
|
|
283
|
+
return addDays(date, direction);
|
|
272
284
|
}
|
|
273
285
|
}
|
|
274
286
|
function calendarReducer(state, action) {
|
|
@@ -301,6 +313,261 @@ function calendarReducer(state, action) {
|
|
|
301
313
|
}
|
|
302
314
|
}
|
|
303
315
|
|
|
316
|
+
// src/utils/timezone.ts
|
|
317
|
+
var WALL_RE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?$/;
|
|
318
|
+
var UTC_RE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?Z$/;
|
|
319
|
+
function pad2(n) {
|
|
320
|
+
return n < 10 ? `0${n}` : `${n}`;
|
|
321
|
+
}
|
|
322
|
+
function parseWall(wall) {
|
|
323
|
+
const m = WALL_RE.exec(wall);
|
|
324
|
+
if (!m) throw new RangeError(`Invalid wall-clock DateTimeString: ${wall}`);
|
|
325
|
+
return {
|
|
326
|
+
year: +m[1],
|
|
327
|
+
month: +m[2],
|
|
328
|
+
day: +m[3],
|
|
329
|
+
hour: +m[4],
|
|
330
|
+
minute: +m[5],
|
|
331
|
+
second: +m[6]
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
function formatWall(p) {
|
|
335
|
+
return `${p.year}-${pad2(p.month)}-${pad2(p.day)}T${pad2(p.hour)}:${pad2(p.minute)}:${pad2(p.second)}`;
|
|
336
|
+
}
|
|
337
|
+
function parseUtcMs(utc) {
|
|
338
|
+
if (UTC_RE.test(utc)) return Date.parse(utc);
|
|
339
|
+
if (WALL_RE.test(utc)) return Date.parse(`${utc}Z`);
|
|
340
|
+
throw new RangeError(`Invalid datetime string: ${utc}`);
|
|
341
|
+
}
|
|
342
|
+
function utcMsToIso(ms) {
|
|
343
|
+
return new Date(ms).toISOString().replace(/\.\d+Z$/, "Z");
|
|
344
|
+
}
|
|
345
|
+
var dtfCache = /* @__PURE__ */ new Map();
|
|
346
|
+
function dtfFor(timeZone) {
|
|
347
|
+
let dtf = dtfCache.get(timeZone);
|
|
348
|
+
if (!dtf) {
|
|
349
|
+
dtf = new Intl.DateTimeFormat("en-US", {
|
|
350
|
+
timeZone,
|
|
351
|
+
year: "numeric",
|
|
352
|
+
month: "2-digit",
|
|
353
|
+
day: "2-digit",
|
|
354
|
+
hour: "2-digit",
|
|
355
|
+
minute: "2-digit",
|
|
356
|
+
second: "2-digit",
|
|
357
|
+
hour12: false,
|
|
358
|
+
hourCycle: "h23"
|
|
359
|
+
});
|
|
360
|
+
dtfCache.set(timeZone, dtf);
|
|
361
|
+
}
|
|
362
|
+
return dtf;
|
|
363
|
+
}
|
|
364
|
+
function partsAt(timeZone, utcMs) {
|
|
365
|
+
const parts = dtfFor(timeZone).formatToParts(new Date(utcMs));
|
|
366
|
+
const result = {};
|
|
367
|
+
for (const part of parts) {
|
|
368
|
+
switch (part.type) {
|
|
369
|
+
case "year":
|
|
370
|
+
result.year = +part.value;
|
|
371
|
+
break;
|
|
372
|
+
case "month":
|
|
373
|
+
result.month = +part.value;
|
|
374
|
+
break;
|
|
375
|
+
case "day":
|
|
376
|
+
result.day = +part.value;
|
|
377
|
+
break;
|
|
378
|
+
case "hour":
|
|
379
|
+
result.hour = +part.value % 24;
|
|
380
|
+
break;
|
|
381
|
+
case "minute":
|
|
382
|
+
result.minute = +part.value;
|
|
383
|
+
break;
|
|
384
|
+
case "second":
|
|
385
|
+
result.second = +part.value;
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return result;
|
|
390
|
+
}
|
|
391
|
+
function getBrowserTimeZone() {
|
|
392
|
+
try {
|
|
393
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
394
|
+
if (typeof tz === "string" && tz.length > 0) return tz;
|
|
395
|
+
} catch {
|
|
396
|
+
}
|
|
397
|
+
return "UTC";
|
|
398
|
+
}
|
|
399
|
+
function eventWallToDisplay(eventWall, eventTimeZone, displayTimeZone) {
|
|
400
|
+
if (!eventTimeZone) return eventWall;
|
|
401
|
+
const target = displayTimeZone ?? getBrowserTimeZone();
|
|
402
|
+
if (eventTimeZone === target) return eventWall;
|
|
403
|
+
return convertWallTime(eventWall, eventTimeZone, target);
|
|
404
|
+
}
|
|
405
|
+
function displayWallToEvent(displayWall, eventTimeZone, displayTimeZone, options) {
|
|
406
|
+
if (!eventTimeZone) return displayWall;
|
|
407
|
+
const source = displayTimeZone ?? getBrowserTimeZone();
|
|
408
|
+
if (eventTimeZone === source) return displayWall;
|
|
409
|
+
return convertWallTime(displayWall, source, eventTimeZone, options);
|
|
410
|
+
}
|
|
411
|
+
var validTzCache = /* @__PURE__ */ new Map();
|
|
412
|
+
function isValidTimeZone(timeZone) {
|
|
413
|
+
if (typeof timeZone !== "string" || timeZone.length === 0) return false;
|
|
414
|
+
const cached = validTzCache.get(timeZone);
|
|
415
|
+
if (cached !== void 0) return cached;
|
|
416
|
+
let ok;
|
|
417
|
+
try {
|
|
418
|
+
Intl.DateTimeFormat("en-US", { timeZone });
|
|
419
|
+
ok = true;
|
|
420
|
+
} catch {
|
|
421
|
+
ok = false;
|
|
422
|
+
}
|
|
423
|
+
validTzCache.set(timeZone, ok);
|
|
424
|
+
return ok;
|
|
425
|
+
}
|
|
426
|
+
var FALLBACK_TIMEZONES = Object.freeze([
|
|
427
|
+
"UTC",
|
|
428
|
+
"Africa/Cairo",
|
|
429
|
+
"Africa/Johannesburg",
|
|
430
|
+
"Africa/Lagos",
|
|
431
|
+
"Africa/Nairobi",
|
|
432
|
+
"America/Anchorage",
|
|
433
|
+
"America/Argentina/Buenos_Aires",
|
|
434
|
+
"America/Bogota",
|
|
435
|
+
"America/Caracas",
|
|
436
|
+
"America/Chicago",
|
|
437
|
+
"America/Denver",
|
|
438
|
+
"America/Halifax",
|
|
439
|
+
"America/Lima",
|
|
440
|
+
"America/Los_Angeles",
|
|
441
|
+
"America/Mexico_City",
|
|
442
|
+
"America/Montevideo",
|
|
443
|
+
"America/New_York",
|
|
444
|
+
"America/Phoenix",
|
|
445
|
+
"America/Santiago",
|
|
446
|
+
"America/Sao_Paulo",
|
|
447
|
+
"America/St_Johns",
|
|
448
|
+
"America/Toronto",
|
|
449
|
+
"America/Vancouver",
|
|
450
|
+
"Asia/Bangkok",
|
|
451
|
+
"Asia/Dubai",
|
|
452
|
+
"Asia/Hong_Kong",
|
|
453
|
+
"Asia/Jakarta",
|
|
454
|
+
"Asia/Jerusalem",
|
|
455
|
+
"Asia/Karachi",
|
|
456
|
+
"Asia/Kathmandu",
|
|
457
|
+
"Asia/Kolkata",
|
|
458
|
+
"Asia/Kuala_Lumpur",
|
|
459
|
+
"Asia/Manila",
|
|
460
|
+
"Asia/Riyadh",
|
|
461
|
+
"Asia/Seoul",
|
|
462
|
+
"Asia/Shanghai",
|
|
463
|
+
"Asia/Singapore",
|
|
464
|
+
"Asia/Taipei",
|
|
465
|
+
"Asia/Tehran",
|
|
466
|
+
"Asia/Tokyo",
|
|
467
|
+
"Atlantic/Azores",
|
|
468
|
+
"Atlantic/Cape_Verde",
|
|
469
|
+
"Atlantic/Reykjavik",
|
|
470
|
+
"Australia/Adelaide",
|
|
471
|
+
"Australia/Brisbane",
|
|
472
|
+
"Australia/Darwin",
|
|
473
|
+
"Australia/Melbourne",
|
|
474
|
+
"Australia/Perth",
|
|
475
|
+
"Australia/Sydney",
|
|
476
|
+
"Europe/Amsterdam",
|
|
477
|
+
"Europe/Athens",
|
|
478
|
+
"Europe/Berlin",
|
|
479
|
+
"Europe/Brussels",
|
|
480
|
+
"Europe/Bucharest",
|
|
481
|
+
"Europe/Budapest",
|
|
482
|
+
"Europe/Copenhagen",
|
|
483
|
+
"Europe/Dublin",
|
|
484
|
+
"Europe/Helsinki",
|
|
485
|
+
"Europe/Istanbul",
|
|
486
|
+
"Europe/Lisbon",
|
|
487
|
+
"Europe/London",
|
|
488
|
+
"Europe/Madrid",
|
|
489
|
+
"Europe/Moscow",
|
|
490
|
+
"Europe/Oslo",
|
|
491
|
+
"Europe/Paris",
|
|
492
|
+
"Europe/Prague",
|
|
493
|
+
"Europe/Rome",
|
|
494
|
+
"Europe/Stockholm",
|
|
495
|
+
"Europe/Vienna",
|
|
496
|
+
"Europe/Warsaw",
|
|
497
|
+
"Europe/Zurich",
|
|
498
|
+
"Pacific/Auckland",
|
|
499
|
+
"Pacific/Fiji",
|
|
500
|
+
"Pacific/Guam",
|
|
501
|
+
"Pacific/Honolulu",
|
|
502
|
+
"Pacific/Midway",
|
|
503
|
+
"Pacific/Pago_Pago",
|
|
504
|
+
"Pacific/Tongatapu"
|
|
505
|
+
]);
|
|
506
|
+
function listTimeZones() {
|
|
507
|
+
const fn = Intl.supportedValuesOf;
|
|
508
|
+
if (typeof fn === "function") {
|
|
509
|
+
try {
|
|
510
|
+
const values = fn("timeZone");
|
|
511
|
+
return values.includes("UTC") ? values.slice() : ["UTC", ...values];
|
|
512
|
+
} catch {
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return FALLBACK_TIMEZONES.slice();
|
|
516
|
+
}
|
|
517
|
+
function getTimeZoneOffset(utcInstant, timeZone) {
|
|
518
|
+
const utcMs = parseUtcMs(utcInstant);
|
|
519
|
+
const wall = partsAt(timeZone, utcMs);
|
|
520
|
+
const wallAsUtcMs = Date.UTC(wall.year, wall.month - 1, wall.day, wall.hour, wall.minute, wall.second);
|
|
521
|
+
return Math.round((wallAsUtcMs - utcMs) / 6e4);
|
|
522
|
+
}
|
|
523
|
+
function wallTimeToUtc(wallTime, timeZone, options = {}) {
|
|
524
|
+
const ambiguous = options.ambiguous ?? "earlier";
|
|
525
|
+
const invalid = options.invalid ?? "shift";
|
|
526
|
+
const w = parseWall(wallTime);
|
|
527
|
+
const guessUtcMs = Date.UTC(w.year, w.month - 1, w.day, w.hour, w.minute, w.second);
|
|
528
|
+
const offsetBefore = getTimeZoneOffset(utcMsToIso(guessUtcMs - 12 * 36e5), timeZone);
|
|
529
|
+
const offsetAfter = getTimeZoneOffset(utcMsToIso(guessUtcMs + 12 * 36e5), timeZone);
|
|
530
|
+
const candidateBefore = guessUtcMs - offsetBefore * 6e4;
|
|
531
|
+
const candidateAfter = guessUtcMs - offsetAfter * 6e4;
|
|
532
|
+
const roundTripBefore = roundTripWall(candidateBefore, timeZone);
|
|
533
|
+
const roundTripAfter = roundTripWall(candidateAfter, timeZone);
|
|
534
|
+
const beforeMatches = wallEquals(roundTripBefore, w);
|
|
535
|
+
const afterMatches = wallEquals(roundTripAfter, w);
|
|
536
|
+
if (beforeMatches && afterMatches) {
|
|
537
|
+
if (candidateBefore === candidateAfter) {
|
|
538
|
+
return utcMsToIso(candidateBefore);
|
|
539
|
+
}
|
|
540
|
+
return utcMsToIso(ambiguous === "earlier" ? Math.min(candidateBefore, candidateAfter) : Math.max(candidateBefore, candidateAfter));
|
|
541
|
+
}
|
|
542
|
+
if (beforeMatches) return utcMsToIso(candidateBefore);
|
|
543
|
+
if (afterMatches) return utcMsToIso(candidateAfter);
|
|
544
|
+
if (invalid === "throw") {
|
|
545
|
+
throw new RangeError(`Wall time ${wallTime} does not exist in ${timeZone} (DST gap)`);
|
|
546
|
+
}
|
|
547
|
+
return utcMsToIso(Math.max(candidateBefore, candidateAfter));
|
|
548
|
+
}
|
|
549
|
+
function roundTripWall(utcMs, timeZone) {
|
|
550
|
+
return partsAt(timeZone, utcMs);
|
|
551
|
+
}
|
|
552
|
+
function wallEquals(a, b) {
|
|
553
|
+
return a.year === b.year && a.month === b.month && a.day === b.day && a.hour === b.hour && a.minute === b.minute && a.second === b.second;
|
|
554
|
+
}
|
|
555
|
+
function utcToWallTime(utcInstant, timeZone) {
|
|
556
|
+
return formatWall(partsAt(timeZone, parseUtcMs(utcInstant)));
|
|
557
|
+
}
|
|
558
|
+
function convertWallTime(wallTime, fromTimeZone, toTimeZone, options) {
|
|
559
|
+
if (fromTimeZone === toTimeZone) return wallTime;
|
|
560
|
+
const utc = wallTimeToUtc(wallTime, fromTimeZone, options);
|
|
561
|
+
return utcToWallTime(utc, toTimeZone);
|
|
562
|
+
}
|
|
563
|
+
function getTimeZoneAbbreviation(timeZone, atInstant) {
|
|
564
|
+
const utcMs = atInstant === void 0 ? Date.now() : parseUtcMs(atInstant);
|
|
565
|
+
const dtf = new Intl.DateTimeFormat("en-US", { timeZone, timeZoneName: "short" });
|
|
566
|
+
const parts = dtf.formatToParts(new Date(utcMs));
|
|
567
|
+
const tzPart = parts.find((p) => p.type === "timeZoneName");
|
|
568
|
+
return tzPart?.value ?? timeZone;
|
|
569
|
+
}
|
|
570
|
+
|
|
304
571
|
// src/utils/events.ts
|
|
305
572
|
function sortEvents(events) {
|
|
306
573
|
return [...events].sort((a, b) => {
|
|
@@ -431,15 +698,17 @@ function assignColumns(group) {
|
|
|
431
698
|
const totalColumns = columns.length;
|
|
432
699
|
return result.map((r) => ({ ...r, totalColumns }));
|
|
433
700
|
}
|
|
434
|
-
function computeTimePositions(events, dayStartHour = 0, dayEndHour = 24) {
|
|
701
|
+
function computeTimePositions(events, dayStartHour = 0, dayEndHour = 24, displayTimeZone) {
|
|
435
702
|
const totalHours = dayEndHour - dayStartHour;
|
|
436
703
|
const groups = buildOverlapGroups(events);
|
|
437
704
|
const positioned = [];
|
|
438
705
|
for (const group of groups) {
|
|
439
706
|
const columns = assignColumns(group);
|
|
440
707
|
for (const { event, column, totalColumns } of columns) {
|
|
441
|
-
const
|
|
442
|
-
const
|
|
708
|
+
const eventStart = displayTimeZone && event.timeZone ? eventWallToDisplay(event.start, event.timeZone, displayTimeZone) : event.start;
|
|
709
|
+
const eventEnd = displayTimeZone && event.timeZone ? eventWallToDisplay(event.end, event.timeZone, displayTimeZone) : event.end;
|
|
710
|
+
const startTime = Math.max(getTimeOfDay(eventStart), dayStartHour);
|
|
711
|
+
const endTime = Math.min(getTimeOfDay(eventEnd), dayEndHour);
|
|
443
712
|
const top = (startTime - dayStartHour) / totalHours * 100;
|
|
444
713
|
const height = Math.max((endTime - startTime) / totalHours * 100, 1);
|
|
445
714
|
positioned.push({
|
|
@@ -910,6 +1179,96 @@ function groupEventsByResource(events, resources) {
|
|
|
910
1179
|
return map;
|
|
911
1180
|
}
|
|
912
1181
|
|
|
1182
|
+
// src/utils/timeline.ts
|
|
1183
|
+
var datePart = (s) => s.slice(0, 10);
|
|
1184
|
+
function intersectDay(event, day) {
|
|
1185
|
+
const evStartDay = datePart(event.start);
|
|
1186
|
+
const evEndDay = datePart(event.end);
|
|
1187
|
+
if (day < evStartDay || day > evEndDay) return null;
|
|
1188
|
+
const startsToday = evStartDay === day;
|
|
1189
|
+
const endsToday = evEndDay === day;
|
|
1190
|
+
const start = startsToday ? getTimeOfDay(event.start) : 0;
|
|
1191
|
+
const end = endsToday ? getTimeOfDay(event.end) : 24;
|
|
1192
|
+
if (end <= start) return null;
|
|
1193
|
+
return { start, end, isStart: startsToday, isEnd: endsToday };
|
|
1194
|
+
}
|
|
1195
|
+
function computeTimelinePositions(events, resourceIds, day, dayStartHour = 0, dayEndHour = 24) {
|
|
1196
|
+
const totalHours = Math.max(1e-4, dayEndHour - dayStartHour);
|
|
1197
|
+
const result = /* @__PURE__ */ new Map();
|
|
1198
|
+
for (const id of resourceIds) result.set(id, []);
|
|
1199
|
+
const byResource = /* @__PURE__ */ new Map();
|
|
1200
|
+
for (const event of events) {
|
|
1201
|
+
if (event.allDay) continue;
|
|
1202
|
+
if (event.display === "background") continue;
|
|
1203
|
+
const rid = event.resourceId;
|
|
1204
|
+
if (!rid || !result.has(rid)) continue;
|
|
1205
|
+
let bucket = byResource.get(rid);
|
|
1206
|
+
if (!bucket) {
|
|
1207
|
+
bucket = [];
|
|
1208
|
+
byResource.set(rid, bucket);
|
|
1209
|
+
}
|
|
1210
|
+
bucket.push(event);
|
|
1211
|
+
}
|
|
1212
|
+
for (const [resourceId, bucketEvents] of byResource) {
|
|
1213
|
+
const clipped = [];
|
|
1214
|
+
for (const event of bucketEvents) {
|
|
1215
|
+
const window = intersectDay(event, day);
|
|
1216
|
+
if (!window) continue;
|
|
1217
|
+
const start = Math.max(window.start, dayStartHour);
|
|
1218
|
+
const end = Math.min(window.end, dayEndHour);
|
|
1219
|
+
if (end <= start) continue;
|
|
1220
|
+
clipped.push({
|
|
1221
|
+
original: event,
|
|
1222
|
+
clippedStart: start,
|
|
1223
|
+
clippedEnd: end,
|
|
1224
|
+
isSegmentStart: window.isStart && window.start >= dayStartHour,
|
|
1225
|
+
isSegmentEnd: window.isEnd && window.end <= dayEndHour
|
|
1226
|
+
});
|
|
1227
|
+
}
|
|
1228
|
+
if (clipped.length === 0) continue;
|
|
1229
|
+
const fakeIso = (h) => {
|
|
1230
|
+
const hours = Math.floor(h);
|
|
1231
|
+
const minutes = Math.floor((h - hours) * 60);
|
|
1232
|
+
const seconds = Math.floor(((h - hours) * 60 - minutes) * 60);
|
|
1233
|
+
const pad = (n) => n < 10 ? `0${n}` : `${n}`;
|
|
1234
|
+
return `${day}T${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
|
|
1235
|
+
};
|
|
1236
|
+
const synthetic = clipped.map((c, idx) => ({
|
|
1237
|
+
...c.original,
|
|
1238
|
+
// Keep the original id but tag the index so two clipped segments
|
|
1239
|
+
// of the same parent never collide in a Map lookup.
|
|
1240
|
+
id: `${c.original.id}::tl::${idx}`,
|
|
1241
|
+
start: fakeIso(c.clippedStart),
|
|
1242
|
+
end: fakeIso(c.clippedEnd)
|
|
1243
|
+
}));
|
|
1244
|
+
const groups = buildOverlapGroups(synthetic);
|
|
1245
|
+
const positioned = [];
|
|
1246
|
+
for (const group of groups) {
|
|
1247
|
+
const cols = assignColumns(group);
|
|
1248
|
+
for (const { event, column, totalColumns } of cols) {
|
|
1249
|
+
const idx = parseInt(event.id.split("::tl::")[1] ?? "0", 10);
|
|
1250
|
+
const meta = clipped[idx];
|
|
1251
|
+
const start = meta.clippedStart;
|
|
1252
|
+
const end = meta.clippedEnd;
|
|
1253
|
+
const leftPct = (start - dayStartHour) / totalHours * 100;
|
|
1254
|
+
const widthPct = Math.max((end - start) / totalHours * 100, 0.5);
|
|
1255
|
+
positioned.push({
|
|
1256
|
+
event: meta.original,
|
|
1257
|
+
resourceId,
|
|
1258
|
+
leftPct,
|
|
1259
|
+
widthPct,
|
|
1260
|
+
row: column,
|
|
1261
|
+
totalRows: totalColumns,
|
|
1262
|
+
isSegmentStart: meta.isSegmentStart,
|
|
1263
|
+
isSegmentEnd: meta.isSegmentEnd
|
|
1264
|
+
});
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
result.set(resourceId, positioned);
|
|
1268
|
+
}
|
|
1269
|
+
return result;
|
|
1270
|
+
}
|
|
1271
|
+
|
|
913
1272
|
// src/utils/undo.ts
|
|
914
1273
|
var DEFAULT_MAX_HISTORY = 30;
|
|
915
1274
|
function createUndoStack(initial) {
|
|
@@ -978,13 +1337,17 @@ exports.canRedo = canRedo;
|
|
|
978
1337
|
exports.canUndo = canUndo;
|
|
979
1338
|
exports.computeDropPosition = computeDropPosition;
|
|
980
1339
|
exports.computeTimePositions = computeTimePositions;
|
|
1340
|
+
exports.computeTimelinePositions = computeTimelinePositions;
|
|
1341
|
+
exports.convertWallTime = convertWallTime;
|
|
981
1342
|
exports.createInitialState = createInitialState;
|
|
982
1343
|
exports.createUndoStack = createUndoStack;
|
|
983
1344
|
exports.dateInRange = dateInRange;
|
|
984
1345
|
exports.daysBetween = daysBetween;
|
|
1346
|
+
exports.displayWallToEvent = displayWallToEvent;
|
|
985
1347
|
exports.downloadICal = downloadICal;
|
|
986
1348
|
exports.eachDayOfRange = eachDayOfRange;
|
|
987
1349
|
exports.endOfMonth = endOfMonth;
|
|
1350
|
+
exports.eventWallToDisplay = eventWallToDisplay;
|
|
988
1351
|
exports.eventsToICal = eventsToICal;
|
|
989
1352
|
exports.expandRecurringEvents = expandRecurringEvents;
|
|
990
1353
|
exports.filterEventsInRange = filterEventsInRange;
|
|
@@ -1001,6 +1364,7 @@ exports.formatWeekdayNarrow = formatWeekdayNarrow;
|
|
|
1001
1364
|
exports.formatWeekdayShort = formatWeekdayShort;
|
|
1002
1365
|
exports.fractionalHourToDateTime = fractionalHourToDateTime;
|
|
1003
1366
|
exports.generateOccurrences = generateOccurrences;
|
|
1367
|
+
exports.getBrowserTimeZone = getBrowserTimeZone;
|
|
1004
1368
|
exports.getDurationHours = getDurationHours;
|
|
1005
1369
|
exports.getEventSegments = getEventSegments;
|
|
1006
1370
|
exports.getEventsForDay = getEventsForDay;
|
|
@@ -1009,6 +1373,8 @@ exports.getHourLabels = getHourLabels;
|
|
|
1009
1373
|
exports.getISOWeekNumber = getISOWeekNumber;
|
|
1010
1374
|
exports.getMonthViewRange = getMonthViewRange;
|
|
1011
1375
|
exports.getTimeOfDay = getTimeOfDay;
|
|
1376
|
+
exports.getTimeZoneAbbreviation = getTimeZoneAbbreviation;
|
|
1377
|
+
exports.getTimeZoneOffset = getTimeZoneOffset;
|
|
1012
1378
|
exports.getVisibleRange = getVisibleRange;
|
|
1013
1379
|
exports.getWeekDays = getWeekDays;
|
|
1014
1380
|
exports.getWeekViewRange = getWeekViewRange;
|
|
@@ -1020,6 +1386,8 @@ exports.isMultiDayEvent = isMultiDayEvent;
|
|
|
1020
1386
|
exports.isSameDay = isSameDay;
|
|
1021
1387
|
exports.isSameMonth = isSameMonth;
|
|
1022
1388
|
exports.isToday = isToday;
|
|
1389
|
+
exports.isValidTimeZone = isValidTimeZone;
|
|
1390
|
+
exports.listTimeZones = listTimeZones;
|
|
1023
1391
|
exports.normalizeRange = normalizeRange;
|
|
1024
1392
|
exports.parseDate = parseDate;
|
|
1025
1393
|
exports.parseRRule = parseRRule;
|
|
@@ -1038,6 +1406,8 @@ exports.toDateString = toDateString;
|
|
|
1038
1406
|
exports.toDateTimeString = toDateTimeString;
|
|
1039
1407
|
exports.toRRuleString = toRRuleString;
|
|
1040
1408
|
exports.undo = undo;
|
|
1409
|
+
exports.utcToWallTime = utcToWallTime;
|
|
1410
|
+
exports.wallTimeToUtc = wallTimeToUtc;
|
|
1041
1411
|
exports.yPositionToFractionalHour = yPositionToFractionalHour;
|
|
1042
1412
|
//# sourceMappingURL=index.cjs.map
|
|
1043
1413
|
//# sourceMappingURL=index.cjs.map
|