histropediajs 1.5.0 → 1.6.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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- HistropediaJS v1.5.0 | Histropedia Ltd. (c) 2026 | https://js.histropedia.com
2
+ HistropediaJS v1.6.0 | Histropedia Ltd. (c) 2026 | https://js.histropedia.com
3
3
  Use of this software is subject to our End User Licence Agreement: https://js.histropedia.com/licence.html
4
4
  */
5
5
  (function(global, factory) {
@@ -202,8 +202,17 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
202
202
  8: "decade",
203
203
  9: "year",
204
204
  10: "month",
205
- 11: "day"
206
- };
205
+ 11: "day",
206
+ 12: "hour",
207
+ 13: "minute",
208
+ 14: "second",
209
+ 15: "millisecond"
210
+ };
211
+ const DMY_STRING_PATTERN = /^(-?\d+)(?:-(\d{1,2}))?(?:-(\d{1,2}))?(?:[T ](\d{1,2})(?::(\d{1,2}))?(?::(\d{1,2})(?:\.(\d{1,3}))?)?)?$/;
212
+ const MILLISECONDS_PER_SECOND = 1e3;
213
+ const MILLISECONDS_PER_MINUTE = 60 * MILLISECONDS_PER_SECOND;
214
+ const MILLISECONDS_PER_HOUR = 60 * MILLISECONDS_PER_MINUTE;
215
+ const MILLISECONDS_PER_DAY = 24 * MILLISECONDS_PER_HOUR;
207
216
  function normalizePrecision(precision) {
208
217
  return Object.prototype.hasOwnProperty.call(LEGACY_PRECISIONS, precision) ? LEGACY_PRECISIONS[precision] : precision || "day";
209
218
  }
@@ -216,16 +225,60 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
216
225
  };
217
226
  }
218
227
  __name(getHistoricalPeriodBounds, "getHistoricalPeriodBounds");
219
- function Dmy(year, month, day) {
228
+ function clampInteger(value, fallback, minimum, maximum) {
229
+ const parsed = Number(value);
230
+ if (!Number.isFinite(parsed)) {
231
+ return fallback;
232
+ }
233
+ return Math.min(maximum, Math.max(minimum, Math.trunc(parsed)));
234
+ }
235
+ __name(clampInteger, "clampInteger");
236
+ function setTimeParts(target, hour, minute, second, millisecond) {
237
+ const values = {
238
+ hour: clampInteger(hour, 0, 0, 23),
239
+ minute: clampInteger(minute, 0, 0, 59),
240
+ second: clampInteger(second, 0, 0, 59),
241
+ millisecond: clampInteger(millisecond, 0, 0, 999)
242
+ };
243
+ for (const [key, value] of Object.entries(values)) {
244
+ Object.defineProperty(target, key, {
245
+ value,
246
+ enumerable: value !== 0,
247
+ configurable: true,
248
+ writable: true
249
+ });
250
+ }
251
+ }
252
+ __name(setTimeParts, "setTimeParts");
253
+ function setPrecision(target, precision) {
254
+ if (precision === void 0) {
255
+ return;
256
+ }
257
+ Object.defineProperty(target, "precision", {
258
+ value: precision,
259
+ enumerable: false,
260
+ configurable: true,
261
+ writable: true
262
+ });
263
+ }
264
+ __name(setPrecision, "setPrecision");
265
+ function createAdjustedDmy(source, values) {
266
+ return new Dmy(__spreadProps(__spreadValues({}, values), { precision: source.precision }));
267
+ }
268
+ __name(createAdjustedDmy, "createAdjustedDmy");
269
+ function Dmy(year, month, day, hour, minute, second, millisecond) {
220
270
  if (typeof year === "object") {
221
271
  const options = year;
222
272
  this.year = options.year;
223
273
  this.month = options.month;
224
274
  this.day = getCorrectDay(options.year, options.month, options.day);
275
+ setTimeParts(this, options.hour, options.minute, options.second, options.millisecond);
276
+ setPrecision(this, options.precision);
225
277
  } else {
226
278
  this.year = year;
227
279
  this.month = month;
228
280
  this.day = getCorrectDay(year, month, day);
281
+ setTimeParts(this, hour, minute, second, millisecond);
229
282
  }
230
283
  }
231
284
  __name(Dmy, "Dmy");
@@ -252,14 +305,19 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
252
305
  }
253
306
  __name(digitGroupedNumber, "digitGroupedNumber");
254
307
  Dmy.prototype.getDaysTo = function(other) {
255
- return other.getDaysSinceYearZero() - this.getDaysSinceYearZero();
308
+ const dayDifference = other.getDaysSinceYearZero() - this.getDaysSinceYearZero();
309
+ const timeDifference = other.getMillisecondsOfDay() - this.getMillisecondsOfDay();
310
+ return dayDifference + timeDifference / MILLISECONDS_PER_DAY;
311
+ };
312
+ Dmy.prototype.getMillisecondsOfDay = function() {
313
+ return this.hour * MILLISECONDS_PER_HOUR + this.minute * MILLISECONDS_PER_MINUTE + this.second * MILLISECONDS_PER_SECOND + this.millisecond;
256
314
  };
257
315
  Dmy.prototype.getMonthsTo = function(other) {
258
316
  return this.getYearsTo(other) * 12;
259
317
  };
260
318
  Dmy.prototype.getYearsTo = function(other) {
261
319
  let yearDiff = other.year - this.year;
262
- yearDiff += (other.month - this.month) / 12 + (other.day - this.day) / 365.2422;
320
+ yearDiff += (other.month - this.month) / 12 + (other.day - this.day) / 365.2422 + (other.getMillisecondsOfDay() - this.getMillisecondsOfDay()) / (MILLISECONDS_PER_DAY * 365.2422);
263
321
  return yearDiff;
264
322
  };
265
323
  Dmy.prototype.getLeapYearsSinceYearZero = function() {
@@ -279,14 +337,11 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
279
337
  return days;
280
338
  };
281
339
  Dmy.prototype.getDayOfYear = function() {
282
- if (isUndefined(this._dayOfYear)) {
283
- this._dayOfYear = 0;
284
- for (let m = 1; m < this.month; m++) {
285
- this._dayOfYear += daysInMonth(this.year, m);
286
- }
287
- this._dayOfYear += this.day;
340
+ let dayOfYear = this.day;
341
+ for (let m = 1; m < this.month; m++) {
342
+ dayOfYear += daysInMonth(this.year, m);
288
343
  }
289
- return this._dayOfYear;
344
+ return dayOfYear;
290
345
  };
291
346
  Dmy.getByDayOfYear = function(year, dayOfYear) {
292
347
  const dmy = new Dmy(year, 1, 1);
@@ -312,18 +367,77 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
312
367
  let day = this.day;
313
368
  let month = this.month;
314
369
  let year = this.year;
315
- for (let i = 0; i < amount; i++) {
316
- day++;
317
- if (day > daysInMonth(year, month)) {
318
- day = 1;
319
- month++;
320
- if (month > 12) {
321
- month = 1;
322
- year++;
370
+ const direction = amount < 0 ? -1 : 1;
371
+ let remaining = Math.abs(Math.trunc(amount));
372
+ while (remaining > 0) {
373
+ if (direction > 0) {
374
+ day++;
375
+ if (day > daysInMonth(year, month)) {
376
+ day = 1;
377
+ month++;
378
+ if (month > 12) {
379
+ month = 1;
380
+ year++;
381
+ }
382
+ }
383
+ } else {
384
+ day--;
385
+ if (day < 1) {
386
+ month--;
387
+ if (month < 1) {
388
+ month = 12;
389
+ year--;
390
+ }
391
+ day = daysInMonth(year, month);
323
392
  }
324
393
  }
394
+ remaining--;
325
395
  }
326
- return new Dmy(year, month, day);
396
+ return createAdjustedDmy(this, {
397
+ year,
398
+ month,
399
+ day,
400
+ hour: this.hour,
401
+ minute: this.minute,
402
+ second: this.second,
403
+ millisecond: this.millisecond
404
+ });
405
+ };
406
+ Dmy.prototype.addMilliseconds = function(amount) {
407
+ let date = this;
408
+ let milliseconds = this.getMillisecondsOfDay() + Math.trunc(amount);
409
+ while (milliseconds < 0) {
410
+ date = date.addDays(-1);
411
+ milliseconds += MILLISECONDS_PER_DAY;
412
+ }
413
+ while (milliseconds >= MILLISECONDS_PER_DAY) {
414
+ date = date.addDays(1);
415
+ milliseconds -= MILLISECONDS_PER_DAY;
416
+ }
417
+ const hour = Math.floor(milliseconds / MILLISECONDS_PER_HOUR);
418
+ milliseconds -= hour * MILLISECONDS_PER_HOUR;
419
+ const minute = Math.floor(milliseconds / MILLISECONDS_PER_MINUTE);
420
+ milliseconds -= minute * MILLISECONDS_PER_MINUTE;
421
+ const second = Math.floor(milliseconds / MILLISECONDS_PER_SECOND);
422
+ const millisecond = milliseconds - second * MILLISECONDS_PER_SECOND;
423
+ return createAdjustedDmy(this, {
424
+ year: date.year,
425
+ month: date.month,
426
+ day: date.day,
427
+ hour,
428
+ minute,
429
+ second,
430
+ millisecond
431
+ });
432
+ };
433
+ Dmy.prototype.addSeconds = function(amount) {
434
+ return this.addMilliseconds(amount * MILLISECONDS_PER_SECOND);
435
+ };
436
+ Dmy.prototype.addMinutes = function(amount) {
437
+ return this.addMilliseconds(amount * MILLISECONDS_PER_MINUTE);
438
+ };
439
+ Dmy.prototype.addHours = function(amount) {
440
+ return this.addMilliseconds(amount * MILLISECONDS_PER_HOUR);
327
441
  };
328
442
  Dmy.prototype.addMonths = function(amount) {
329
443
  let month = this.month;
@@ -335,22 +449,10 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
335
449
  year++;
336
450
  }
337
451
  }
338
- return new Dmy(year, month, 1);
452
+ return createAdjustedDmy(this, { year, month, day: 1 });
339
453
  };
340
454
  Dmy.prototype.getPreviousDay = function() {
341
- let day = this.day;
342
- let month = this.month;
343
- let year = this.year;
344
- day--;
345
- if (day < 1) {
346
- month--;
347
- if (month < 1) {
348
- month = 12;
349
- year--;
350
- }
351
- day = daysInMonth(year, month);
352
- }
353
- return new Dmy(year, month, day);
455
+ return this.addDays(-1);
354
456
  };
355
457
  Dmy.prototype.getNextMonth = function() {
356
458
  let month = this.month;
@@ -360,7 +462,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
360
462
  month = 1;
361
463
  year++;
362
464
  }
363
- return new Dmy(year, month, 1);
465
+ return createAdjustedDmy(this, { year, month, day: 1 });
364
466
  };
365
467
  Dmy.prototype.getPreviousMonth = function() {
366
468
  let month = this.month;
@@ -370,11 +472,15 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
370
472
  month = 12;
371
473
  year--;
372
474
  }
373
- return new Dmy(year, month, 1);
475
+ return createAdjustedDmy(this, { year, month, day: 1 });
374
476
  };
375
477
  Dmy.prototype.addYears = function(amount) {
376
- return new Dmy(this.year + amount, 1, 1);
478
+ return createAdjustedDmy(this, { year: this.year + amount, month: 1, day: 1 });
377
479
  };
480
+ function pad(value, length) {
481
+ return String(value).padStart(length, "0");
482
+ }
483
+ __name(pad, "pad");
378
484
  Dmy.prototype.format = function(format, options) {
379
485
  options = options || {};
380
486
  format = format || "D MMM YYYY";
@@ -397,24 +503,26 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
397
503
  return format.replace(
398
504
  "YYYY",
399
505
  isBc ? digitGroupedNumber(-this.year + 1, thousandsSeparator) + bceText : digitGroupedNumber(this.year, thousandsSeparator)
400
- ).replace("D", this.day).replace("MMM", MONTH_NAMES[this.month - 1]);
506
+ ).replace("D", this.day).replace("MMM", MONTH_NAMES[this.month - 1]).replace("HH", pad(this.hour, 2)).replace("mm", pad(this.minute, 2)).replace("ss", pad(this.second, 2)).replace("SSS", pad(this.millisecond, 3));
401
507
  };
402
508
  Dmy.prototype.isSame = function(other) {
403
- return other.year === this.year && other.month === this.month && other.day === this.day;
509
+ return other.year === this.year && other.month === this.month && other.day === this.day && (other.hour || 0) === this.hour && (other.minute || 0) === this.minute && (other.second || 0) === this.second && (other.millisecond || 0) === this.millisecond;
404
510
  };
405
511
  Dmy.prototype.toKeyString = function() {
406
- return `${this.year}|${this.month}|${this.day}`;
512
+ const dateKey = `${this.year}|${this.month}|${this.day}`;
513
+ if (this.getMillisecondsOfDay() === 0) {
514
+ return dateKey;
515
+ }
516
+ return `${dateKey}|${this.hour}|${this.minute}|${this.second}|${this.millisecond}`;
407
517
  };
408
518
  Dmy.prototype.isAfter = function(other) {
409
- if (this.year > other.year) {
410
- return true;
411
- }
412
- if (this.year === other.year) {
413
- if (this.month > other.month) {
414
- return true;
415
- }
416
- if (this.month === other.month) {
417
- return this.day > other.day;
519
+ const fields = ["year", "month", "day", "hour", "minute", "second", "millisecond"];
520
+ for (let i = 0; i < fields.length; i++) {
521
+ const field = fields[i];
522
+ const thisValue = this[field] || 0;
523
+ const otherValue = other[field] || 0;
524
+ if (thisValue !== otherValue) {
525
+ return thisValue > otherValue;
418
526
  }
419
527
  }
420
528
  return false;
@@ -434,15 +542,24 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
434
542
  Dmy.prototype.asFloat = function() {
435
543
  const m = this.month - 1;
436
544
  const d = this.day - 1;
437
- if (m === 0 && d === 0) {
545
+ const dayFraction = this.getMillisecondsOfDay() / MILLISECONDS_PER_DAY;
546
+ if (m === 0 && d === 0 && dayFraction === 0) {
438
547
  return this.year;
439
548
  }
440
- return Math.round((this.year + (m * 31 + d) / 371) * 100) / 100;
549
+ return Math.round((this.year + (m * 31 + d + dayFraction) / 371) * 100) / 100;
441
550
  };
442
551
  Dmy.prototype.isInFuture = function() {
443
552
  const date = /* @__PURE__ */ new Date();
444
- const today = new Dmy(date.getFullYear(), date.getMonth() + 1, date.getDate());
445
- return this.isAfter(today);
553
+ const now = new Dmy(
554
+ date.getFullYear(),
555
+ date.getMonth() + 1,
556
+ date.getDate(),
557
+ date.getHours(),
558
+ date.getMinutes(),
559
+ date.getSeconds(),
560
+ date.getMilliseconds()
561
+ );
562
+ return this.isAfter(now);
446
563
  };
447
564
  Dmy.prototype.convertToIso = function() {
448
565
  if (this.year < 0) {
@@ -455,6 +572,18 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
455
572
  const month = isoDmy.month || 1;
456
573
  const day = isoDmy.day || 1;
457
574
  precision = normalizePrecision(precision);
575
+ if (precision === "millisecond") {
576
+ return new Dmy(isoDmy);
577
+ }
578
+ if (precision === "second") {
579
+ return new Dmy(isoYear, month, day, isoDmy.hour, isoDmy.minute, isoDmy.second, 0);
580
+ }
581
+ if (precision === "minute") {
582
+ return new Dmy(isoYear, month, day, isoDmy.hour, isoDmy.minute, 0, 0);
583
+ }
584
+ if (precision === "hour") {
585
+ return new Dmy(isoYear, month, day, isoDmy.hour, 0, 0, 0);
586
+ }
458
587
  if (precision === "day") {
459
588
  return new Dmy(isoYear, month, day);
460
589
  }
@@ -480,6 +609,18 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
480
609
  const month = isoDmy.month || 1;
481
610
  const day = isoDmy.day || 1;
482
611
  precision = normalizePrecision(precision);
612
+ if (precision === "millisecond") {
613
+ return new Dmy(isoDmy);
614
+ }
615
+ if (precision === "second") {
616
+ return new Dmy(isoYear, month, day, isoDmy.hour, isoDmy.minute, isoDmy.second, 999);
617
+ }
618
+ if (precision === "minute") {
619
+ return new Dmy(isoYear, month, day, isoDmy.hour, isoDmy.minute, 59, 999);
620
+ }
621
+ if (precision === "hour") {
622
+ return new Dmy(isoYear, month, day, isoDmy.hour, 59, 59, 999);
623
+ }
483
624
  if (precision === "day") {
484
625
  return new Dmy(isoYear, month, day);
485
626
  }
@@ -507,6 +648,26 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
507
648
  Logger.error("precision is not implemented");
508
649
  return new Dmy(isoYear, month, day);
509
650
  };
651
+ Dmy.CreateAsExclusiveEndOfPeriod = function(isoDmy, precision) {
652
+ precision = normalizePrecision(precision);
653
+ const start = Dmy.CreateAsStartOfPeriod(isoDmy, precision);
654
+ if (precision === "millisecond") {
655
+ return start.addMilliseconds(1);
656
+ }
657
+ if (precision === "second") {
658
+ return start.addSeconds(1);
659
+ }
660
+ if (precision === "minute") {
661
+ return start.addMinutes(1);
662
+ }
663
+ if (precision === "hour") {
664
+ return start.addHours(1);
665
+ }
666
+ if (precision === "day") {
667
+ return start.addDays(1);
668
+ }
669
+ return Dmy.CreateAsEndOfPeriod(isoDmy, precision).addDays(1);
670
+ };
510
671
  Dmy.now = function() {
511
672
  const now = /* @__PURE__ */ new Date();
512
673
  return new Dmy({
@@ -515,21 +676,37 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
515
676
  day: now.getDate()
516
677
  });
517
678
  };
679
+ function parseDmyString(dateString) {
680
+ const match = String(dateString).match(DMY_STRING_PATTERN);
681
+ if (!match) {
682
+ return null;
683
+ }
684
+ const year = parseInt(match[1], 10);
685
+ const month = match[2] == null ? 1 : parseInt(match[2], 10);
686
+ const day = match[3] == null ? 1 : parseInt(match[3], 10);
687
+ const hour = match[4] == null ? 0 : parseInt(match[4], 10);
688
+ const minute = match[5] == null ? 0 : parseInt(match[5], 10);
689
+ const second = match[6] == null ? 0 : parseInt(match[6], 10);
690
+ const millisecond = match[7] ? parseInt(match[7].padEnd(3, "0"), 10) : 0;
691
+ return {
692
+ date: new Dmy({
693
+ year,
694
+ month,
695
+ day,
696
+ hour,
697
+ minute,
698
+ second,
699
+ millisecond
700
+ }),
701
+ hasMonth: match[2] != null,
702
+ hasDay: match[3] != null,
703
+ hasTime: match[4] != null
704
+ };
705
+ }
706
+ __name(parseDmyString, "parseDmyString");
518
707
  Dmy.fromString = function(dateString) {
519
- const dateParts = dateString.split("-");
520
- const isBc = dateParts[0] === "";
521
- if (isBc) {
522
- dateParts.shift();
523
- dateParts[0] = `-${dateParts[0]}`;
524
- }
525
- const year = parseInt(dateParts[0]);
526
- const month = parseInt(dateParts[1]) || 1;
527
- const day = parseInt(dateParts[2]) || 1;
528
- return new Dmy({
529
- year: parseInt(year),
530
- month: parseInt(month),
531
- day: parseInt(day)
532
- });
708
+ const parsed = parseDmyString(dateString);
709
+ return parsed ? parsed.date : new Dmy(NaN, 1, 1);
533
710
  };
534
711
  function merge(target, ...sources) {
535
712
  return Object.assign(target, ...sources);
@@ -617,10 +794,10 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
617
794
  });
618
795
  }
619
796
  __name(defineValueOrFunctionProperty, "defineValueOrFunctionProperty");
620
- function isUndefined$1(value) {
797
+ function isUndefined(value) {
621
798
  return typeof value === "undefined";
622
799
  }
623
- __name(isUndefined$1, "isUndefined$1");
800
+ __name(isUndefined, "isUndefined");
624
801
  const propertyAbbreviations = {
625
802
  id: "i",
626
803
  title: "t",
@@ -629,10 +806,18 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
629
806
  "from.year": "fy",
630
807
  "from.month": "fm",
631
808
  "from.day": "fd",
809
+ "from.hour": "fhr",
810
+ "from.minute": "fmi",
811
+ "from.second": "fs",
812
+ "from.millisecond": "fms",
632
813
  "from.precision": "fp",
633
814
  "to.year": "ty",
634
815
  "to.month": "tm",
635
816
  "to.day": "td",
817
+ "to.hour": "thr",
818
+ "to.minute": "tmi",
819
+ "to.second": "ts",
820
+ "to.millisecond": "tms",
636
821
  "to.precision": "tp",
637
822
  isToPresent: "p",
638
823
  isStarred: "v",
@@ -651,7 +836,8 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
651
836
  __name(extractProperty, "extractProperty");
652
837
  function extractPropertyFromPath(data, path) {
653
838
  const pathParts = path.split(".");
654
- return pathParts.reduce((curr, next) => curr ? curr[next] : void 0, data);
839
+ const value = pathParts.reduce((curr, next) => curr ? curr[next] : void 0, data);
840
+ return isUndefined(value) ? data[propertyAbbreviations[path]] : value;
655
841
  }
656
842
  __name(extractPropertyFromPath, "extractPropertyFromPath");
657
843
  function isPath(property) {
@@ -667,9 +853,9 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
667
853
  __name(getPropertyFromData, "getPropertyFromData");
668
854
  function existsInData(data, property) {
669
855
  if (isPath(property)) {
670
- return !isUndefined$1(extractPropertyFromPath(data, property));
856
+ return !isUndefined(extractPropertyFromPath(data, property));
671
857
  }
672
- return !isUndefined$1(extractProperty(data, property));
858
+ return !isUndefined(extractProperty(data, property));
673
859
  }
674
860
  __name(existsInData, "existsInData");
675
861
  defineValueOrFunctionProperty(Article.prototype, "hidePeriodLine");
@@ -745,12 +931,16 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
745
931
  this.isImageInfoLoaded = false;
746
932
  };
747
933
  Article.prototype._setupArticlePeriod = function(data) {
748
- const fromDmy = new Dmy(
934
+ let fromDmy = new Dmy(
749
935
  parseInt(getPropertyFromData(data, "from.year")),
750
936
  parseInt(getPropertyFromData(data, "from.month")),
751
- parseInt(getPropertyFromData(data, "from.day"))
937
+ parseInt(getPropertyFromData(data, "from.day")),
938
+ parseInt(getPropertyFromData(data, "from.hour")),
939
+ parseInt(getPropertyFromData(data, "from.minute")),
940
+ parseInt(getPropertyFromData(data, "from.second")),
941
+ parseInt(getPropertyFromData(data, "from.millisecond"))
752
942
  );
753
- this.owner.getDmyFromInput(fromDmy);
943
+ fromDmy = this.owner.getDmyFromInput(fromDmy);
754
944
  const fromPrecision = getPropertyFromData(data, "from.precision");
755
945
  const isToPresentProp = getPropertyFromData(data, "isToPresent");
756
946
  const isToPresent = isToPresentProp === true || isToPresentProp === 1;
@@ -761,17 +951,21 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
761
951
  toDmy = new Dmy(
762
952
  parseInt(getPropertyFromData(data, "to.year")),
763
953
  parseInt(getPropertyFromData(data, "to.month")),
764
- parseInt(getPropertyFromData(data, "to.day"))
954
+ parseInt(getPropertyFromData(data, "to.day")),
955
+ parseInt(getPropertyFromData(data, "to.hour")),
956
+ parseInt(getPropertyFromData(data, "to.minute")),
957
+ parseInt(getPropertyFromData(data, "to.second")),
958
+ parseInt(getPropertyFromData(data, "to.millisecond"))
765
959
  );
766
- this.owner.getDmyFromInput(toDmy);
960
+ toDmy = this.owner.getDmyFromInput(toDmy);
767
961
  toPrecision = getPropertyFromData(data, "to.precision");
768
962
  } else {
769
963
  toDmy = fromDmy;
770
964
  toPrecision = fromPrecision;
771
965
  }
772
966
  const from = Dmy.CreateAsStartOfPeriod(fromDmy, fromPrecision);
773
- const to = Dmy.CreateAsEndOfPeriod(toDmy, toPrecision);
774
- this.period = { from, to: to.getNextDay(), isToPresent };
967
+ const to = Dmy.CreateAsExclusiveEndOfPeriod(toDmy, toPrecision);
968
+ this.period = { from, to, isToPresent };
775
969
  this.period.years = this.period.to.asFloat() - this.period.from.asFloat();
776
970
  };
777
971
  Article.prototype.setImage = function() {
@@ -886,7 +1080,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
886
1080
  return otherRight >= thisLeft && thisRight >= otherLeft;
887
1081
  };
888
1082
  Article.prototype._getWidth = function() {
889
- return this._getCurrentStyle().width;
1083
+ return this.getCurrentStyle().width;
890
1084
  };
891
1085
  Article.prototype.getWidth = function() {
892
1086
  this._ensureSizeCache();
@@ -947,29 +1141,10 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
947
1141
  const styleChanged = existsInData(option, "style");
948
1142
  const activeStyleChanged = existsInData(option, "activeStyle");
949
1143
  const hoverStyleChanged = existsInData(option, "hoverStyle");
950
- let activeHoverStyleUpdated = false;
951
- if (styleChanged) {
1144
+ if (styleChanged || hoverStyleChanged || activeStyleChanged) {
952
1145
  this.initialiseStyles(this.data);
953
- this.invalidateCaches();
954
- } else {
955
- if (hoverStyleChanged) {
956
- deepMerge(this.hoverStyle, option.hoverStyle);
957
- this.activeHoverStyle = deepMerge(
958
- {},
959
- this.hoverStyle,
960
- this.owner._getResolvedArticleOptions(this).defaultActiveStyle,
961
- this.data.activeStyle
962
- );
963
- activeHoverStyleUpdated = true;
964
- }
965
- if (activeStyleChanged) {
966
- this.activeStyle = deepMerge(this.activeStyle, option.activeStyle);
967
- if (!activeHoverStyleUpdated) {
968
- deepMerge(this.activeHoverStyle, option.activeStyle);
969
- }
970
- }
971
- this.invalidateCaches();
972
1146
  }
1147
+ this.invalidateCaches();
973
1148
  const cardLayoutChanged = existsInData(option, "cardLayout");
974
1149
  if (cardLayoutChanged) {
975
1150
  this.setCardLayout(option.cardLayout);
@@ -984,35 +1159,27 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
984
1159
  }
985
1160
  };
986
1161
  Article.prototype.initialiseStyles = function(data = this.data) {
987
- const articleOptions = this.owner._getResolvedArticleOptions(this);
988
1162
  const resolvedDefaultCardLayout = this.owner._resolveDefaultCardLayoutName(this);
989
1163
  const explicitCardLayout = this.owner._getExplicitArticleCardLayout(this);
990
1164
  const cardLayout = explicitCardLayout || resolvedDefaultCardLayout;
991
1165
  this._resolvedDefaultCardLayout = resolvedDefaultCardLayout;
992
1166
  this._resolvedCardLayoutName = cardLayout;
993
- const layoutStyles = articleOptions.layoutStyles[cardLayout] || {};
994
- const style = deepMerge(
995
- {},
996
- articleOptions.defaultStyle,
997
- layoutStyles.style || {},
998
- getPropertyFromData(data, "style") || {}
999
- );
1167
+ const styleOverrides = this.owner._getResolvedArticleStyleOverrides(this, cardLayout);
1168
+ const style = deepMerge({}, styleOverrides.style, getPropertyFromData(data, "style") || {});
1000
1169
  const activeStyle = deepMerge(
1001
1170
  {},
1002
- articleOptions.defaultActiveStyle,
1003
- layoutStyles.activeStyle || {},
1171
+ styleOverrides.activeStyle,
1004
1172
  getPropertyFromData(data, "activeStyle") || {}
1005
1173
  );
1006
1174
  const hoverStyle = deepMerge(
1007
1175
  {},
1008
- articleOptions.defaultHoverStyle,
1009
- layoutStyles.hoverStyle || {},
1176
+ styleOverrides.hoverStyle,
1010
1177
  getPropertyFromData(data, "hoverStyle") || {}
1011
1178
  );
1012
1179
  this.style = style;
1013
1180
  this.activeStyle = deepMerge({}, style, activeStyle);
1014
1181
  this.hoverStyle = deepMerge({}, style, hoverStyle);
1015
- this.activeHoverStyle = deepMerge({}, this.hoverStyle, activeStyle);
1182
+ this.activeHoverStyle = deepMerge({}, style, hoverStyle, activeStyle);
1016
1183
  };
1017
1184
  Article.prototype.setStyle = function(option, value) {
1018
1185
  if (typeof option === "string") {
@@ -1034,13 +1201,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
1034
1201
  option = buildObjectFromPath(option, value);
1035
1202
  }
1036
1203
  this.data.hoverStyle = deepMerge(this.data.hoverStyle || {}, option);
1037
- deepMerge(this.hoverStyle, option);
1038
- this.activeHoverStyle = deepMerge(
1039
- {},
1040
- this.hoverStyle,
1041
- this.owner._getResolvedArticleOptions(this).defaultActiveStyle,
1042
- this.data.activeStyle
1043
- );
1204
+ this.initialiseStyles(this.data);
1044
1205
  this.owner.requestRedraw();
1045
1206
  };
1046
1207
  Article.prototype.setActiveStyle = function(option, value) {
@@ -1051,8 +1212,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
1051
1212
  option = buildObjectFromPath(option, value);
1052
1213
  }
1053
1214
  this.data.activeStyle = deepMerge(this.data.activeStyle || {}, option);
1054
- deepMerge(this.activeStyle, option);
1055
- deepMerge(this.activeHoverStyle, option);
1215
+ this.initialiseStyles(this.data);
1056
1216
  this.owner.requestRedraw();
1057
1217
  };
1058
1218
  Article.prototype.activated = function() {
@@ -1217,6 +1377,57 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
1217
1377
  });
1218
1378
  moveAnimation.dummyElement = moveTween;
1219
1379
  };
1380
+ function roundPixel(value) {
1381
+ return Math.round(value);
1382
+ }
1383
+ __name(roundPixel, "roundPixel");
1384
+ function snapPixel(value, dpr = 1) {
1385
+ const ratio = typeof dpr === "number" && isFinite(dpr) && dpr > 0 ? dpr : 1;
1386
+ return Math.round(value * ratio) / ratio;
1387
+ }
1388
+ __name(snapPixel, "snapPixel");
1389
+ function retainPixel(value) {
1390
+ return value;
1391
+ }
1392
+ __name(retainPixel, "retainPixel");
1393
+ function createPixelSnap(dpr = 1, mode = "device") {
1394
+ if (mode === false || mode === "none") {
1395
+ return retainPixel;
1396
+ }
1397
+ if (mode === "css") {
1398
+ return roundPixel;
1399
+ }
1400
+ return /* @__PURE__ */ __name(function snapToDevicePixel(value) {
1401
+ return snapPixel(value, dpr);
1402
+ }, "snapToDevicePixel");
1403
+ }
1404
+ __name(createPixelSnap, "createPixelSnap");
1405
+ function createStrokePixelSnap(dpr = 1, mode = "device", lineWidth = 1) {
1406
+ if (mode === false || mode === "none") {
1407
+ return retainPixel;
1408
+ }
1409
+ const deviceRatio = typeof dpr === "number" && isFinite(dpr) && dpr > 0 ? dpr : 1;
1410
+ const ratio = mode === "css" ? 1 : deviceRatio;
1411
+ const width = typeof lineWidth === "number" && isFinite(lineWidth) && lineWidth > 0 ? lineWidth : 1;
1412
+ const halfPhysicalWidth = width * ratio / 2;
1413
+ return /* @__PURE__ */ __name(function snapStrokeCentre(value) {
1414
+ return (Math.round(value * ratio - halfPhysicalWidth) + halfPhysicalWidth) / ratio;
1415
+ }, "snapStrokeCentre");
1416
+ }
1417
+ __name(createStrokePixelSnap, "createStrokePixelSnap");
1418
+ function createInnerSpace(outerSpace, borderWidth, snap) {
1419
+ if (!snap) {
1420
+ snap = roundPixel;
1421
+ }
1422
+ const halfBorder = borderWidth / 2;
1423
+ return {
1424
+ left: snap(outerSpace.left + halfBorder),
1425
+ top: snap(outerSpace.top + halfBorder),
1426
+ width: snap(outerSpace.width - borderWidth),
1427
+ height: snap(outerSpace.height - borderWidth)
1428
+ };
1429
+ }
1430
+ __name(createInnerSpace, "createInnerSpace");
1220
1431
  Article.prototype.draw = function(ctx) {
1221
1432
  if (!this.isDataLoaded || isNaN(this.position.left)) {
1222
1433
  return;
@@ -1226,12 +1437,15 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
1226
1437
  const cardLayout = this._getCurrentCardLayout();
1227
1438
  cardLayout.draw.call(this, ctx);
1228
1439
  };
1229
- Article.prototype._getCurrentStyle = function() {
1440
+ Article.prototype.getCurrentStyle = function() {
1230
1441
  if (this.isActive) {
1231
1442
  return this.isMouseover ? this.activeHoverStyle : this.activeStyle;
1232
1443
  }
1233
1444
  return this.isMouseover ? this.hoverStyle : this.style;
1234
1445
  };
1446
+ Article.prototype._getCurrentStyle = function() {
1447
+ return this.getCurrentStyle();
1448
+ };
1235
1449
  Article.prototype._getPeriodLineRenderGeometry = function(axisY) {
1236
1450
  const resolvedArticleOptions = this.owner._getResolvedArticleOptions(this);
1237
1451
  const periodLineOptions = resolvedArticleOptions.periodLine || {};
@@ -1262,8 +1476,9 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
1262
1476
  };
1263
1477
  };
1264
1478
  Article.prototype.drawPeriodLinesAndConnectors = function(ctx, axisY) {
1479
+ var _a, _b, _c, _d, _e, _f;
1265
1480
  ctx.globalAlpha = this.opacity;
1266
- const style = this._getCurrentStyle();
1481
+ const style = this.getCurrentStyle();
1267
1482
  const geometry = this._getPeriodLineRenderGeometry(axisY);
1268
1483
  const y = geometry.y;
1269
1484
  if (!this.hidePeriodLine) {
@@ -1295,16 +1510,26 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
1295
1510
  const y1 = y;
1296
1511
  const x2 = connectorEnd.left;
1297
1512
  const y2 = connectorEnd.top;
1513
+ const isVertical = Math.abs(x1 - x2) < Number.EPSILON;
1514
+ const pixelSnapMode = (_d = (_c = (_b = (_a = this.owner) == null ? void 0 : _a.options) == null ? void 0 : _b.article) == null ? void 0 : _c.rendering) == null ? void 0 : _d.pixelSnap;
1515
+ const snapStroke = createStrokePixelSnap(
1516
+ ((_f = (_e = this.owner) == null ? void 0 : _e.getCanvasDpr) == null ? void 0 : _f.call(_e)) || 1,
1517
+ pixelSnapMode,
1518
+ style.connectorLine.thickness
1519
+ );
1520
+ const connectorX = isVertical ? snapStroke(x2) : null;
1521
+ const drawX1 = connectorX != null ? connectorX : x1;
1522
+ const drawX2 = connectorX != null ? connectorX : x2;
1298
1523
  ctx.strokeStyle = ctx.fillStyle = style.color;
1299
1524
  ctx.lineWidth = style.connectorLine.thickness;
1300
1525
  ctx.beginPath();
1301
- ctx.moveTo(x1, y1);
1302
- ctx.lineTo(x2, y2);
1526
+ ctx.moveTo(drawX1, y1);
1527
+ ctx.lineTo(drawX2, y2);
1303
1528
  ctx.stroke();
1304
- const radians = Math.atan((y2 - y1) / (x2 - x1)) + (x2 >= x1 ? -90 : 90) * Math.PI / 180;
1529
+ const radians = Math.atan((y2 - y1) / (drawX2 - drawX1)) + (drawX2 >= drawX1 ? -90 : 90) * Math.PI / 180;
1305
1530
  ctx.save();
1306
1531
  ctx.beginPath();
1307
- ctx.translate(x2, y2);
1532
+ ctx.translate(drawX2, y2);
1308
1533
  ctx.rotate(radians);
1309
1534
  ctx.moveTo(-style.connectorLine.arrow.width, 0);
1310
1535
  ctx.lineTo(style.connectorLine.arrow.width, 0);
@@ -1378,7 +1603,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
1378
1603
  };
1379
1604
  Article.prototype._getSizeCacheKey = function() {
1380
1605
  var _a, _b;
1381
- const style = typeof this._getCurrentStyle === "function" ? this._getCurrentStyle() : null;
1606
+ const style = typeof this.getCurrentStyle === "function" ? this.getCurrentStyle() : null;
1382
1607
  const imageStyle = style && style.image || {};
1383
1608
  const header = style && style.header || {};
1384
1609
  const subheader = style && style.subheader || {};
@@ -1614,6 +1839,10 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
1614
1839
  const MINOR_MARKER = 0;
1615
1840
  const MAJOR_MARKER = 1;
1616
1841
  const ERA_MARKER = 2;
1842
+ const ZOOM_MILLISECOND = -4;
1843
+ const ZOOM_SECOND = -3;
1844
+ const ZOOM_MINUTE = -2;
1845
+ const ZOOM_HOUR = -1;
1617
1846
  const ZOOM_DAY = 0;
1618
1847
  const ZOOM_MONTH = 1;
1619
1848
  const ZOOM_YEAR = 2;
@@ -1626,6 +1855,10 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
1626
1855
  const ZOOM_10_MILLION_YEARS = 9;
1627
1856
  const ZOOM_100_MILLION_YEARS = 10;
1628
1857
  const ZOOM_BILLION_YEARS = 11;
1858
+ const PRECISION_MILLISECOND = "millisecond";
1859
+ const PRECISION_SECOND = "second";
1860
+ const PRECISION_MINUTE = "minute";
1861
+ const PRECISION_HOUR = "hour";
1629
1862
  const PRECISION_DAY = "day";
1630
1863
  const PRECISION_MONTH = "month";
1631
1864
  const PRECISION_YEAR = "year";
@@ -1647,6 +1880,249 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
1647
1880
  const RANGE_ALL = "all";
1648
1881
  const RANGE_SCREEN = "screen";
1649
1882
  const DENSITY_SETTINGS = [
1883
+ {
1884
+ region: -26,
1885
+ zoom: { from: Number.NEGATIVE_INFINITY, to: -80.86 },
1886
+ low: 1,
1887
+ medium: 2,
1888
+ high: 3,
1889
+ all: 25,
1890
+ step: { months: 0, days: 0, divisionsPerDay: 134217728 }
1891
+ },
1892
+ {
1893
+ region: -25,
1894
+ zoom: { from: -80.86, to: -77.75 },
1895
+ low: 1,
1896
+ medium: 2,
1897
+ high: 3,
1898
+ all: 25,
1899
+ step: { months: 0, days: 0, divisionsPerDay: 67108864 }
1900
+ },
1901
+ {
1902
+ region: -24,
1903
+ zoom: { from: -77.75, to: -74.64 },
1904
+ low: 1,
1905
+ medium: 2,
1906
+ high: 3,
1907
+ all: 25,
1908
+ step: { months: 0, days: 0, divisionsPerDay: 33554432 }
1909
+ },
1910
+ {
1911
+ region: -23,
1912
+ zoom: { from: -74.64, to: -71.53 },
1913
+ low: 1,
1914
+ medium: 2,
1915
+ high: 3,
1916
+ all: 25,
1917
+ step: { months: 0, days: 0, divisionsPerDay: 16777216 }
1918
+ },
1919
+ {
1920
+ region: -22,
1921
+ zoom: { from: -71.53, to: -68.42 },
1922
+ low: 1,
1923
+ medium: 2,
1924
+ high: 3,
1925
+ all: 25,
1926
+ step: { months: 0, days: 0, divisionsPerDay: 8388608 }
1927
+ },
1928
+ {
1929
+ region: -21,
1930
+ zoom: { from: -68.42, to: -65.31 },
1931
+ low: 1,
1932
+ medium: 2,
1933
+ high: 3,
1934
+ all: 25,
1935
+ step: { months: 0, days: 0, divisionsPerDay: 4194304 }
1936
+ },
1937
+ {
1938
+ region: -20,
1939
+ zoom: { from: -65.31, to: -62.2 },
1940
+ low: 1,
1941
+ medium: 2,
1942
+ high: 3,
1943
+ all: 25,
1944
+ step: { months: 0, days: 0, divisionsPerDay: 2097152 }
1945
+ },
1946
+ {
1947
+ region: -19,
1948
+ zoom: { from: -62.2, to: -59.09 },
1949
+ low: 1,
1950
+ medium: 2,
1951
+ high: 3,
1952
+ all: 25,
1953
+ step: { months: 0, days: 0, divisionsPerDay: 1048576 }
1954
+ },
1955
+ {
1956
+ region: -18,
1957
+ zoom: { from: -59.09, to: -55.98 },
1958
+ low: 1,
1959
+ medium: 2,
1960
+ high: 3,
1961
+ all: 25,
1962
+ step: { months: 0, days: 0, divisionsPerDay: 524288 }
1963
+ },
1964
+ {
1965
+ region: -17,
1966
+ zoom: { from: -55.98, to: -52.87 },
1967
+ low: 1,
1968
+ medium: 2,
1969
+ high: 3,
1970
+ all: 25,
1971
+ step: { months: 0, days: 0, divisionsPerDay: 262144 }
1972
+ },
1973
+ {
1974
+ region: -16,
1975
+ zoom: { from: -52.87, to: -49.76 },
1976
+ low: 1,
1977
+ medium: 2,
1978
+ high: 3,
1979
+ all: 25,
1980
+ step: { months: 0, days: 0, divisionsPerDay: 131072 }
1981
+ },
1982
+ {
1983
+ region: -15,
1984
+ zoom: { from: -49.76, to: -46.65 },
1985
+ low: 1,
1986
+ medium: 2,
1987
+ high: 3,
1988
+ all: 25,
1989
+ step: { months: 0, days: 0, divisionsPerDay: 65536 }
1990
+ },
1991
+ {
1992
+ region: -14,
1993
+ zoom: { from: -46.65, to: -43.54 },
1994
+ low: 1,
1995
+ medium: 2,
1996
+ high: 3,
1997
+ all: 25,
1998
+ step: { months: 0, days: 0, divisionsPerDay: 32768 }
1999
+ },
2000
+ {
2001
+ region: -13,
2002
+ zoom: { from: -43.54, to: -40.43 },
2003
+ low: 1,
2004
+ medium: 2,
2005
+ high: 3,
2006
+ all: 25,
2007
+ step: { months: 0, days: 0, divisionsPerDay: 16384 }
2008
+ },
2009
+ {
2010
+ region: -12,
2011
+ zoom: { from: -40.43, to: -37.32 },
2012
+ low: 1,
2013
+ medium: 2,
2014
+ high: 3,
2015
+ all: 25,
2016
+ step: { months: 0, days: 0, divisionsPerDay: 8192 }
2017
+ },
2018
+ {
2019
+ region: -11,
2020
+ zoom: { from: -37.32, to: -34.21 },
2021
+ low: 1,
2022
+ medium: 2,
2023
+ high: 3,
2024
+ all: 25,
2025
+ step: { months: 0, days: 0, divisionsPerDay: 4096 }
2026
+ },
2027
+ {
2028
+ region: -10,
2029
+ zoom: { from: -34.21, to: -31.1 },
2030
+ low: 1,
2031
+ medium: 2,
2032
+ high: 3,
2033
+ all: 25,
2034
+ step: { months: 0, days: 0, divisionsPerDay: 2048 }
2035
+ },
2036
+ {
2037
+ region: -9,
2038
+ zoom: { from: -31.1, to: -27.99 },
2039
+ low: 1,
2040
+ medium: 2,
2041
+ high: 3,
2042
+ all: 25,
2043
+ step: { months: 0, days: 0, divisionsPerDay: 1024 }
2044
+ },
2045
+ {
2046
+ region: -8,
2047
+ zoom: { from: -27.99, to: -24.88 },
2048
+ low: 1,
2049
+ medium: 2,
2050
+ high: 3,
2051
+ all: 25,
2052
+ step: { months: 0, days: 0, divisionsPerDay: 512 }
2053
+ },
2054
+ {
2055
+ region: -7,
2056
+ zoom: { from: -24.88, to: -21.77 },
2057
+ low: 1,
2058
+ medium: 2,
2059
+ high: 3,
2060
+ all: 25,
2061
+ step: { months: 0, days: 0, divisionsPerDay: 256 }
2062
+ },
2063
+ {
2064
+ region: -6,
2065
+ zoom: { from: -21.77, to: -18.66 },
2066
+ low: 1,
2067
+ medium: 2,
2068
+ high: 3,
2069
+ all: 25,
2070
+ step: { months: 0, days: 0, divisionsPerDay: 128 }
2071
+ },
2072
+ {
2073
+ region: -5,
2074
+ zoom: { from: -18.66, to: -15.55 },
2075
+ low: 1,
2076
+ medium: 2,
2077
+ high: 3,
2078
+ all: 25,
2079
+ step: { months: 0, days: 0, divisionsPerDay: 64 }
2080
+ },
2081
+ {
2082
+ region: -4,
2083
+ zoom: { from: -15.55, to: -12.44 },
2084
+ low: 1,
2085
+ medium: 2,
2086
+ high: 3,
2087
+ all: 25,
2088
+ step: { months: 0, days: 0, divisionsPerDay: 32 }
2089
+ },
2090
+ {
2091
+ region: -3,
2092
+ zoom: { from: -12.44, to: -9.33 },
2093
+ low: 1,
2094
+ medium: 2,
2095
+ high: 3,
2096
+ all: 25,
2097
+ step: { months: 0, days: 0, divisionsPerDay: 16 }
2098
+ },
2099
+ {
2100
+ region: -2,
2101
+ zoom: { from: -9.33, to: -6.22 },
2102
+ low: 1,
2103
+ medium: 2,
2104
+ high: 3,
2105
+ all: 25,
2106
+ step: { months: 0, days: 0, divisionsPerDay: 8 }
2107
+ },
2108
+ {
2109
+ region: -1,
2110
+ zoom: { from: -6.22, to: -3.11 },
2111
+ low: 1,
2112
+ medium: 2,
2113
+ high: 3,
2114
+ all: 25,
2115
+ step: { months: 0, days: 0, divisionsPerDay: 4 }
2116
+ },
2117
+ {
2118
+ region: 0,
2119
+ zoom: { from: -3.11, to: 0 },
2120
+ low: 1,
2121
+ medium: 2,
2122
+ high: 3,
2123
+ all: 25,
2124
+ step: { months: 0, days: 0, divisionsPerDay: 2 }
2125
+ },
1650
2126
  {
1651
2127
  region: 1,
1652
2128
  zoom: { from: 0, to: 3.11 },
@@ -2022,9 +2498,13 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
2022
2498
  PRECISION_CENTURY,
2023
2499
  PRECISION_DAY,
2024
2500
  PRECISION_DECADE,
2501
+ PRECISION_HOUR,
2025
2502
  PRECISION_MILLENNIUM,
2026
2503
  PRECISION_MILLION_YEARS,
2504
+ PRECISION_MILLISECOND,
2505
+ PRECISION_MINUTE,
2027
2506
  PRECISION_MONTH,
2507
+ PRECISION_SECOND,
2028
2508
  PRECISION_YEAR,
2029
2509
  RANGE_ALL,
2030
2510
  RANGE_SCREEN,
@@ -2037,9 +2517,13 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
2037
2517
  ZOOM_CENTURY,
2038
2518
  ZOOM_DAY,
2039
2519
  ZOOM_DECADE,
2520
+ ZOOM_HOUR,
2040
2521
  ZOOM_MILLENNIUM,
2041
2522
  ZOOM_MILLION_YEARS,
2523
+ ZOOM_MILLISECOND,
2524
+ ZOOM_MINUTE,
2042
2525
  ZOOM_MONTH,
2526
+ ZOOM_SECOND,
2043
2527
  ZOOM_YEAR
2044
2528
  }, Symbol.toStringTag, { value: "Module" }));
2045
2529
  const CHART_RENDERERS = /* @__PURE__ */ new Map();
@@ -2112,7 +2596,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
2112
2596
  minor: {
2113
2597
  visible: true,
2114
2598
  color: "rgba(0, 0, 0, 0.035)",
2115
- thickness: 2,
2599
+ thickness: 1,
2116
2600
  minimumSpacing: 20
2117
2601
  }
2118
2602
  },
@@ -2731,10 +3215,10 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
2731
3215
  return plot.bottom - (value - domain.min) / (domain.max - domain.min) * plot.height;
2732
3216
  }
2733
3217
  __name(getValueY, "getValueY");
2734
- function clamp$2(value, min, max) {
3218
+ function clamp$1(value, min, max) {
2735
3219
  return Math.max(min, Math.min(max, value));
2736
3220
  }
2737
- __name(clamp$2, "clamp$2");
3221
+ __name(clamp$1, "clamp$1");
2738
3222
  function getViewportRange(points, drawCycleContext) {
2739
3223
  const tokens = drawCycleContext && drawCycleContext.tokens ? drawCycleContext.tokens : null;
2740
3224
  if (!tokens || !tokens.start || !tokens.end || points.length === 0) {
@@ -2781,6 +3265,126 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
2781
3265
  ctx.clip();
2782
3266
  }
2783
3267
  __name(clipToRect, "clipToRect");
3268
+ function clipLineSegmentToRect(from, to, rect) {
3269
+ const dx = to.x - from.x;
3270
+ const dy = to.y - from.y;
3271
+ let startRatio = 0;
3272
+ let endRatio = 1;
3273
+ let startBoundary = null;
3274
+ let endBoundary = null;
3275
+ const boundaries = [
3276
+ [-dx, from.x - rect.left],
3277
+ [dx, rect.right - from.x],
3278
+ [-dy, from.y - rect.top],
3279
+ [dy, rect.bottom - from.y]
3280
+ ];
3281
+ for (let i = 0; i < boundaries.length; i++) {
3282
+ const [direction, distance] = boundaries[i];
3283
+ if (direction === 0) {
3284
+ if (distance < 0) {
3285
+ return null;
3286
+ }
3287
+ continue;
3288
+ }
3289
+ const ratio = distance / direction;
3290
+ if (direction < 0) {
3291
+ if (ratio > startRatio) {
3292
+ startRatio = ratio;
3293
+ startBoundary = i;
3294
+ }
3295
+ } else if (ratio < endRatio) {
3296
+ endRatio = ratio;
3297
+ endBoundary = i;
3298
+ }
3299
+ if (startRatio > endRatio) {
3300
+ return null;
3301
+ }
3302
+ }
3303
+ const getClippedPoint = /* @__PURE__ */ __name((ratio, boundary) => {
3304
+ if (ratio === 0) {
3305
+ return from;
3306
+ }
3307
+ if (ratio === 1) {
3308
+ return to;
3309
+ }
3310
+ const point = {
3311
+ x: clamp$1(from.x + dx * ratio, rect.left, rect.right),
3312
+ y: clamp$1(from.y + dy * ratio, rect.top, rect.bottom)
3313
+ };
3314
+ if (boundary === 0) {
3315
+ point.x = rect.left;
3316
+ } else if (boundary === 1) {
3317
+ point.x = rect.right;
3318
+ } else if (boundary === 2) {
3319
+ point.y = rect.top;
3320
+ } else if (boundary === 3) {
3321
+ point.y = rect.bottom;
3322
+ }
3323
+ return point;
3324
+ }, "getClippedPoint");
3325
+ return {
3326
+ from: getClippedPoint(startRatio, startBoundary),
3327
+ to: getClippedPoint(endRatio, endBoundary)
3328
+ };
3329
+ }
3330
+ __name(clipLineSegmentToRect, "clipLineSegmentToRect");
3331
+ function pointsEqual(left, right) {
3332
+ return left && right && left.x === right.x && left.y === right.y;
3333
+ }
3334
+ __name(pointsEqual, "pointsEqual");
3335
+ function clipPolygonAgainstBoundary(points, isInside2, getIntersection) {
3336
+ if (points.length === 0) {
3337
+ return points;
3338
+ }
3339
+ const clipped = [];
3340
+ let previous = points[points.length - 1];
3341
+ let previousInside = isInside2(previous);
3342
+ for (let i = 0; i < points.length; i++) {
3343
+ const current = points[i];
3344
+ const currentInside = isInside2(current);
3345
+ if (currentInside) {
3346
+ if (!previousInside) {
3347
+ clipped.push(getIntersection(previous, current));
3348
+ }
3349
+ clipped.push(current);
3350
+ } else if (previousInside) {
3351
+ clipped.push(getIntersection(previous, current));
3352
+ }
3353
+ previous = current;
3354
+ previousInside = currentInside;
3355
+ }
3356
+ return clipped;
3357
+ }
3358
+ __name(clipPolygonAgainstBoundary, "clipPolygonAgainstBoundary");
3359
+ function clipPolygonToRect(points, rect) {
3360
+ const clipVertical = /* @__PURE__ */ __name((polygon, boundary, keepGreater) => clipPolygonAgainstBoundary(
3361
+ polygon,
3362
+ (point) => keepGreater ? point.x >= boundary : point.x <= boundary,
3363
+ (from, to) => {
3364
+ const ratio = (boundary - from.x) / (to.x - from.x);
3365
+ return {
3366
+ x: boundary,
3367
+ y: clamp$1(from.y + (to.y - from.y) * ratio, rect.top, rect.bottom)
3368
+ };
3369
+ }
3370
+ ), "clipVertical");
3371
+ const clipHorizontal = /* @__PURE__ */ __name((polygon, boundary, keepGreater) => clipPolygonAgainstBoundary(
3372
+ polygon,
3373
+ (point) => keepGreater ? point.y >= boundary : point.y <= boundary,
3374
+ (from, to) => {
3375
+ const ratio = (boundary - from.y) / (to.y - from.y);
3376
+ return {
3377
+ x: clamp$1(from.x + (to.x - from.x) * ratio, rect.left, rect.right),
3378
+ y: boundary
3379
+ };
3380
+ }
3381
+ ), "clipHorizontal");
3382
+ let clipped = clipVertical(points, rect.left, true);
3383
+ clipped = clipVertical(clipped, rect.right, false);
3384
+ clipped = clipHorizontal(clipped, rect.top, true);
3385
+ return clipHorizontal(clipped, rect.bottom, false);
3386
+ }
3387
+ __name(clipPolygonToRect, "clipPolygonToRect");
2784
3388
  function drawBackground(ctx, geometry, style) {
2785
3389
  if (!style.backgroundColor) {
2786
3390
  return;
@@ -2852,7 +3456,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
2852
3456
  return unitSizeInPixels >= minimumSpacing;
2853
3457
  }
2854
3458
  __name(shouldDrawMinorXGridLines, "shouldDrawMinorXGridLines");
2855
- function drawXGridLineGroup(ctx, plot, markerTokens, options) {
3459
+ function drawXGridLineGroup(ctx, plot, markerTokens, options, minimumSpacing = 0) {
2856
3460
  if (!options || options.visible !== true || markerTokens.length === 0) {
2857
3461
  return;
2858
3462
  }
@@ -2861,6 +3465,9 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
2861
3465
  ctx.strokeStyle = options.color || "rgba(0, 0, 0, 0.08)";
2862
3466
  for (let i = 0; i < markerTokens.length; i++) {
2863
3467
  const token = markerTokens[i];
3468
+ if (token.adaptive && token.markerSpacingInPixels < minimumSpacing) {
3469
+ continue;
3470
+ }
2864
3471
  if (typeof token.drawX !== "number" || !Number.isFinite(token.drawX)) {
2865
3472
  continue;
2866
3473
  }
@@ -2878,10 +3485,16 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
2878
3485
  const xGrid = gridLine.x || {};
2879
3486
  const major = xGrid.major || {};
2880
3487
  const minor = xGrid.minor || {};
2881
- const minorMinimumSpacing = Math.max(0, getNumber(minor.minimumSpacing, 40));
3488
+ const minorMinimumSpacing = Math.max(0, getNumber(minor.minimumSpacing, 20));
2882
3489
  drawXGridLineGroup(ctx, plot, getMarkers(drawCycleContext, MAJOR_MARKER), major);
2883
3490
  if (shouldDrawMinorXGridLines(timeline, minorMinimumSpacing)) {
2884
- drawXGridLineGroup(ctx, plot, getMarkers(drawCycleContext, MINOR_MARKER), minor);
3491
+ drawXGridLineGroup(
3492
+ ctx,
3493
+ plot,
3494
+ getMarkers(drawCycleContext, MINOR_MARKER),
3495
+ minor,
3496
+ minorMinimumSpacing
3497
+ );
2885
3498
  }
2886
3499
  }
2887
3500
  __name(drawXGridLines, "drawXGridLines");
@@ -2942,22 +3555,32 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
2942
3555
  if (Array.isArray(style.lineDash) && typeof ctx.setLineDash === "function") {
2943
3556
  ctx.setLineDash(style.lineDash);
2944
3557
  }
2945
- let hasPath = false;
3558
+ let previousPoint = null;
3559
+ let pathEnd = null;
2946
3560
  const range = getViewportRange(points, drawCycleContext);
2947
3561
  for (let i = range.start; i <= range.end; i++) {
2948
3562
  const point = points[i];
2949
3563
  if (typeof point.value !== "number" || !Number.isFinite(point.value)) {
2950
- hasPath = false;
3564
+ previousPoint = null;
3565
+ pathEnd = null;
2951
3566
  continue;
2952
3567
  }
2953
3568
  const x = timeline.getPixel(point.date, drawCycleContext);
2954
3569
  const y = getValueY(point.value, domain, plot);
2955
- if (!hasPath) {
2956
- ctx.moveTo(x, y);
2957
- hasPath = true;
2958
- } else {
2959
- ctx.lineTo(x, y);
3570
+ const currentPoint = { x, y };
3571
+ if (previousPoint && Number.isFinite(previousPoint.x) && Number.isFinite(previousPoint.y) && Number.isFinite(currentPoint.x) && Number.isFinite(currentPoint.y)) {
3572
+ const clippedSegment = clipLineSegmentToRect(previousPoint, currentPoint, plot);
3573
+ if (clippedSegment) {
3574
+ if (!pointsEqual(pathEnd, clippedSegment.from)) {
3575
+ ctx.moveTo(clippedSegment.from.x, clippedSegment.from.y);
3576
+ }
3577
+ ctx.lineTo(clippedSegment.to.x, clippedSegment.to.y);
3578
+ pathEnd = clippedSegment.to;
3579
+ } else {
3580
+ pathEnd = null;
3581
+ }
2960
3582
  }
3583
+ previousPoint = currentPoint;
2961
3584
  }
2962
3585
  ctx.stroke();
2963
3586
  if (typeof ctx.setLineDash === "function") {
@@ -2971,7 +3594,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
2971
3594
  const points = stackedSeries.points || [];
2972
3595
  const style = series.style || {};
2973
3596
  const areaStyle = style.area || {};
2974
- const opacity = clamp$2(getNumber(areaStyle.opacity, 0.2), 0, 1);
3597
+ const opacity = clamp$1(getNumber(areaStyle.opacity, 0.2), 0, 1);
2975
3598
  ctx.save();
2976
3599
  clipToRect(ctx, plot);
2977
3600
  ctx.fillStyle = areaStyle.fillColor || style.color || "#2563eb";
@@ -2982,11 +3605,23 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
2982
3605
  if (segment.length === 0) {
2983
3606
  return;
2984
3607
  }
3608
+ const polygon = [];
3609
+ for (let i = 0; i < segment.length; i++) {
3610
+ polygon.push({ x: segment[i].x, y: segment[i].y });
3611
+ }
2985
3612
  for (let i = segment.length - 1; i >= 0; i--) {
2986
- ctx.lineTo(segment[i].x, segment[i].baseY);
3613
+ polygon.push({ x: segment[i].x, y: segment[i].baseY });
3614
+ }
3615
+ const clippedPolygon = clipPolygonToRect(polygon, plot);
3616
+ if (clippedPolygon.length >= 3) {
3617
+ ctx.beginPath();
3618
+ ctx.moveTo(clippedPolygon[0].x, clippedPolygon[0].y);
3619
+ for (let i = 1; i < clippedPolygon.length; i++) {
3620
+ ctx.lineTo(clippedPolygon[i].x, clippedPolygon[i].y);
3621
+ }
3622
+ ctx.closePath();
3623
+ ctx.fill();
2987
3624
  }
2988
- ctx.closePath();
2989
- ctx.fill();
2990
3625
  segment = [];
2991
3626
  }, "closeSegment");
2992
3627
  for (let i = range.start; i <= range.end; i++) {
@@ -2997,15 +3632,8 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
2997
3632
  }
2998
3633
  const x = timeline.getPixel(point.date, drawCycleContext);
2999
3634
  const y = getValueY(point.value, domain, plot);
3000
- const baseY = clamp$2(getValueY(point.baseValue, domain, plot), plot.top, plot.bottom);
3001
- if (segment.length === 0) {
3002
- ctx.beginPath();
3003
- ctx.moveTo(x, baseY);
3004
- ctx.lineTo(x, y);
3005
- } else {
3006
- ctx.lineTo(x, y);
3007
- }
3008
- segment.push({ x, baseY });
3635
+ const baseY = clamp$1(getValueY(point.baseValue, domain, plot), plot.top, plot.bottom);
3636
+ segment.push({ x, y, baseY });
3009
3637
  }
3010
3638
  closeSegment();
3011
3639
  ctx.restore();
@@ -3122,8 +3750,16 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3122
3750
  const month = parseFiniteInteger(input.month, 1);
3123
3751
  const day = parseFiniteInteger(input.day, 1);
3124
3752
  const precision = input.precision;
3125
- const dmy = new Dmy(year, month, day);
3126
- owner.getDmyFromInput(dmy);
3753
+ let dmy = new Dmy(
3754
+ year,
3755
+ month,
3756
+ day,
3757
+ parseFiniteInteger(input.hour, 0),
3758
+ parseFiniteInteger(input.minute, 0),
3759
+ parseFiniteInteger(input.second, 0),
3760
+ parseFiniteInteger(input.millisecond, 0)
3761
+ );
3762
+ dmy = owner.getDmyFromInput(dmy);
3127
3763
  return Dmy.CreateAsStartOfPeriod(dmy, precision);
3128
3764
  }
3129
3765
  __name(normalizeDate, "normalizeDate");
@@ -3180,11 +3816,20 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3180
3816
  chart._seriesColors.push({ id, color });
3181
3817
  }
3182
3818
  __name(setAssignedSeriesColor, "setAssignedSeriesColor");
3183
- function normalizeSeries(owner, chartStyle, seriesInput, index, assignedColor) {
3819
+ function getSeriesPalette(chartOptions) {
3820
+ const configuredColors = chartOptions && chartOptions.seriesColors;
3821
+ if (!Array.isArray(configuredColors)) {
3822
+ return CHART_DEFAULT_PALETTE;
3823
+ }
3824
+ const palette = configuredColors.filter((color) => typeof color === "string" && color.length > 0);
3825
+ return palette.length > 0 ? palette : CHART_DEFAULT_PALETTE;
3826
+ }
3827
+ __name(getSeriesPalette, "getSeriesPalette");
3828
+ function normalizeSeries(owner, chartStyle, seriesInput, index, assignedColor, palette) {
3184
3829
  const input = seriesInput || {};
3185
3830
  const baseStyle = deepMerge({}, CHART_DEFAULT_SERIES_STYLE, chartStyle.series || {});
3186
3831
  if (!baseStyle.color) {
3187
- baseStyle.color = assignedColor || CHART_DEFAULT_PALETTE[index % CHART_DEFAULT_PALETTE.length];
3832
+ baseStyle.color = assignedColor || palette[index % palette.length];
3188
3833
  }
3189
3834
  const points = Array.isArray(input.points) ? input.points.map((point) => normalizePoint(owner, point)).filter(Boolean) : [];
3190
3835
  points.sort((a, b) => a.date.compare(b.date));
@@ -3265,14 +3910,21 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3265
3910
  {},
3266
3911
  CHART_DEFAULT_STYLE,
3267
3912
  chartOptions.defaultStyle || {},
3268
- { gridLine: chartOptions.gridLine || {} },
3269
3913
  getPropertyFromData(resolvedData, "style") || {}
3270
3914
  );
3271
3915
  const seriesInput = Array.isArray(resolvedData.series) ? resolvedData.series : [];
3916
+ const seriesPalette = getSeriesPalette(chartOptions);
3272
3917
  this.series = seriesInput.map((series, index) => {
3273
3918
  const seriesId = getSeriesId(series, index);
3274
3919
  const assignedColor = getAssignedSeriesColor(this, seriesId);
3275
- const normalizedSeries = normalizeSeries(this.owner, this.style, series, index, assignedColor);
3920
+ const normalizedSeries = normalizeSeries(
3921
+ this.owner,
3922
+ this.style,
3923
+ series,
3924
+ index,
3925
+ assignedColor,
3926
+ seriesPalette
3927
+ );
3276
3928
  if (hasSeriesInputColor(series) || !hasChartSeriesColor(this.style)) {
3277
3929
  setAssignedSeriesColor(this, seriesId, normalizedSeries.style.color);
3278
3930
  }
@@ -3430,10 +4082,10 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3430
4082
  return typeof value === "number" && Number.isFinite(value);
3431
4083
  }
3432
4084
  __name(isFiniteNumber, "isFiniteNumber");
3433
- function clamp$1(value, min, max) {
4085
+ function clamp(value, min, max) {
3434
4086
  return Math.min(Math.max(value, min), max);
3435
4087
  }
3436
- __name(clamp$1, "clamp$1");
4088
+ __name(clamp, "clamp");
3437
4089
  function getLaneArticleOptionImpact(articleOption) {
3438
4090
  const styleChanged = hasLaneArticlePath(articleOption, LANE_ARTICLE_STYLE_PATHS);
3439
4091
  const cacheChanged = styleChanged || hasLaneArticlePath(articleOption, LANE_ARTICLE_CACHE_ONLY_PATHS);
@@ -3504,10 +4156,10 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3504
4156
  const rawMax = isFiniteNumber(layoutOptions.max) ? layoutOptions.max : Number.POSITIVE_INFINITY;
3505
4157
  const min = Math.max(0, Math.min(rawMin, rawMax));
3506
4158
  const max = Math.max(min, rawMax);
3507
- const boundedMin = clamp$1(min, 0, safeAvailableHeight);
3508
- const boundedMax = clamp$1(max, boundedMin, safeAvailableHeight);
4159
+ const boundedMin = clamp(min, 0, safeAvailableHeight);
4160
+ const boundedMax = clamp(max, boundedMin, safeAvailableHeight);
3509
4161
  const scaledDistance = Math.round(safeAvailableHeight * ratio);
3510
- return clamp$1(scaledDistance, boundedMin, boundedMax);
4162
+ return clamp(scaledDistance, boundedMin, boundedMax);
3511
4163
  }
3512
4164
  __name(computeResponsiveDistanceToBaseline, "computeResponsiveDistanceToBaseline");
3513
4165
  function resolveDistanceToBaselineValue(distanceToBaseline, availableHeight, laneLayoutActive, cardLayoutName) {
@@ -3537,7 +4189,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3537
4189
  };
3538
4190
  const DEFAULT_STYLE = {
3539
4191
  width: 150,
3540
- color: "#e9e9e9",
4192
+ color: "#e5e5e5",
3541
4193
  backgroundColor: "#fff",
3542
4194
  topRadius: 3,
3543
4195
  // portrait card layout only
@@ -3662,6 +4314,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3662
4314
  offsetY: 0
3663
4315
  }
3664
4316
  };
4317
+ const DEFAULT_MAIN_LINE_COLOR = "#cdd2d8";
3665
4318
  const ENGINE_DEFAULTS = {
3666
4319
  width: 1e3,
3667
4320
  height: 500,
@@ -3697,7 +4350,8 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3697
4350
  // density region size
3698
4351
  initial: 200,
3699
4352
  showMinorLabels: 48,
3700
- minimum: 8
4353
+ minimum: 8,
4354
+ minimumMajor: 120
3701
4355
  }
3702
4356
  },
3703
4357
  initialDate: {
@@ -3727,7 +4381,22 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3727
4381
  visible: true,
3728
4382
  position: "bottom",
3729
4383
  size: 8,
3730
- showDateIndicators: true
4384
+ color: DEFAULT_MAIN_LINE_COLOR,
4385
+ opacity: 0.75,
4386
+ dateIndicators: {
4387
+ visible: true,
4388
+ shape: "rectangle",
4389
+ size: 4,
4390
+ color: "#666",
4391
+ opacity: 1,
4392
+ hiddenStyle: {
4393
+ opacity: 0.25
4394
+ },
4395
+ activeStyle: {
4396
+ color: "article",
4397
+ opacity: 1
4398
+ }
4399
+ }
3731
4400
  },
3732
4401
  draggingHighlight: {
3733
4402
  visible: true,
@@ -3778,6 +4447,10 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3778
4447
  x: 4,
3779
4448
  y: 0
3780
4449
  },
4450
+ sticky: {
4451
+ enabled: "auto",
4452
+ offsetX: 4
4453
+ },
3781
4454
  bceText: " ʙᴄᴇ",
3782
4455
  thousandsSeparator: ",",
3783
4456
  yearPrefixes: {
@@ -3785,6 +4458,23 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3785
4458
  Ma: { label: "Ma", value: 1e6, minDivision: 1e6 },
3786
4459
  Ga: { label: "Ga", value: 1e9, minDivision: 1e9 }
3787
4460
  }
4461
+ },
4462
+ parent: {
4463
+ visible: false,
4464
+ levels: "all",
4465
+ height: 20,
4466
+ font: "normal 14px Calibri",
4467
+ color: "#444",
4468
+ futureColor: "#ccc",
4469
+ textAlign: "start",
4470
+ offset: {
4471
+ x: 4,
4472
+ y: 0
4473
+ },
4474
+ sticky: {
4475
+ enabled: true,
4476
+ offsetX: 4
4477
+ }
3788
4478
  }
3789
4479
  },
3790
4480
  cursor: {
@@ -3812,6 +4502,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3812
4502
  up: "edge",
3813
4503
  down: 0
3814
4504
  },
4505
+ seriesColors: [...CHART_DEFAULT_PALETTE],
3815
4506
  defaultData: {},
3816
4507
  defaultStyle: deepMerge({}, CHART_DEFAULT_STYLE),
3817
4508
  data: []
@@ -3905,7 +4596,48 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3905
4596
  function warnDeprecatedOptionPath(fromPath, toPath) {
3906
4597
  Logger.warn(`DEPRECATION WARNING: ${fromPath} is deprecated. Use ${toPath} instead.`);
3907
4598
  }
3908
- __name(warnDeprecatedOptionPath, "warnDeprecatedOptionPath");
4599
+ __name(warnDeprecatedOptionPath, "warnDeprecatedOptionPath");
4600
+ const DATE_INDICATOR_SHAPES = /* @__PURE__ */ new Set(["rectangle", "circle"]);
4601
+ function validateDateIndicatorStyle(style, optionPath, { allowVisible = false } = {}) {
4602
+ if (style === void 0) {
4603
+ return;
4604
+ }
4605
+ if (!style || typeof style !== "object" || Array.isArray(style)) {
4606
+ throw new TypeError(`${optionPath} must be an object`);
4607
+ }
4608
+ if (allowVisible && style.visible !== void 0 && typeof style.visible !== "boolean") {
4609
+ throw new TypeError(`${optionPath}.visible must be a boolean`);
4610
+ }
4611
+ if (style.shape !== void 0 && !DATE_INDICATOR_SHAPES.has(style.shape)) {
4612
+ throw new TypeError(`${optionPath}.shape must be "rectangle" or "circle"`);
4613
+ }
4614
+ if (style.size !== void 0 && (typeof style.size !== "number" || !Number.isFinite(style.size) || style.size <= 0)) {
4615
+ throw new TypeError(`${optionPath}.size must be a positive finite number`);
4616
+ }
4617
+ if (style.color !== void 0 && typeof style.color !== "string") {
4618
+ throw new TypeError(`${optionPath}.color must be a CSS colour string or "article"`);
4619
+ }
4620
+ if (style.opacity !== void 0 && (typeof style.opacity !== "number" || !Number.isFinite(style.opacity) || style.opacity < 0 || style.opacity > 1)) {
4621
+ throw new TypeError(`${optionPath}.opacity must be a finite number between 0 and 1`);
4622
+ }
4623
+ }
4624
+ __name(validateDateIndicatorStyle, "validateDateIndicatorStyle");
4625
+ function validateDateIndicatorOptions(inputOptions) {
4626
+ var _a, _b;
4627
+ const dateIndicators = (_b = (_a = inputOptions == null ? void 0 : inputOptions.style) == null ? void 0 : _a.mainLine) == null ? void 0 : _b.dateIndicators;
4628
+ validateDateIndicatorStyle(dateIndicators, "style.mainLine.dateIndicators", {
4629
+ allowVisible: true
4630
+ });
4631
+ validateDateIndicatorStyle(
4632
+ dateIndicators == null ? void 0 : dateIndicators.hiddenStyle,
4633
+ "style.mainLine.dateIndicators.hiddenStyle"
4634
+ );
4635
+ validateDateIndicatorStyle(
4636
+ dateIndicators == null ? void 0 : dateIndicators.activeStyle,
4637
+ "style.mainLine.dateIndicators.activeStyle"
4638
+ );
4639
+ }
4640
+ __name(validateDateIndicatorOptions, "validateDateIndicatorOptions");
3909
4641
  function migrateArticleDistanceToBaseline(inputArticleOptions, processedArticleOptions, optionPath) {
3910
4642
  if ((inputArticleOptions == null ? void 0 : inputArticleOptions.distanceToMainLine) === void 0) {
3911
4643
  return;
@@ -3930,10 +4662,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3930
4662
  if (typeof path !== "string") {
3931
4663
  return path;
3932
4664
  }
3933
- const normalizedPath = path.replace(
3934
- /(^article\.|\.article\.)distanceToMainLine$/,
3935
- "$1distanceToBaseline.value"
3936
- );
4665
+ const normalizedPath = path.replace(/(^article\.|\.article\.)distanceToMainLine$/, "$1distanceToBaseline.value").replace(/^chart\.gridLine(?=\.|$)/, "chart.defaultStyle.gridLine");
3937
4666
  if (normalizedPath !== path) {
3938
4667
  warnDeprecatedOptionPath(path, normalizedPath);
3939
4668
  }
@@ -3960,18 +4689,31 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3960
4689
  }
3961
4690
  __name(handleDeprecatedLaneOptions, "handleDeprecatedLaneOptions");
3962
4691
  function handleDeprecatedOptions(inputOptions) {
3963
- var _a, _b, _c, _d;
4692
+ var _a, _b, _c, _d, _e, _f;
3964
4693
  if (!inputOptions) {
3965
4694
  return inputOptions;
3966
4695
  }
4696
+ validateDateIndicatorOptions(inputOptions);
3967
4697
  const processedOptions = deepMerge({}, inputOptions);
3968
- if (((_a = inputOptions.article) == null ? void 0 : _a.distanceToMainLine) !== void 0) {
4698
+ if (((_a = inputOptions.chart) == null ? void 0 : _a.gridLine) !== void 0) {
4699
+ warnDeprecatedOptionPath("chart.gridLine", "chart.defaultStyle.gridLine");
4700
+ if (!processedOptions.chart.defaultStyle) {
4701
+ processedOptions.chart.defaultStyle = {};
4702
+ }
4703
+ processedOptions.chart.defaultStyle.gridLine = deepMerge(
4704
+ {},
4705
+ inputOptions.chart.gridLine,
4706
+ ((_b = inputOptions.chart.defaultStyle) == null ? void 0 : _b.gridLine) || {}
4707
+ );
4708
+ delete processedOptions.chart.gridLine;
4709
+ }
4710
+ if (((_c = inputOptions.article) == null ? void 0 : _c.distanceToMainLine) !== void 0) {
3969
4711
  if (!processedOptions.article) {
3970
4712
  processedOptions.article = {};
3971
4713
  }
3972
4714
  migrateArticleDistanceToBaseline(inputOptions.article, processedOptions.article, "article");
3973
4715
  }
3974
- if (Array.isArray((_b = inputOptions.lane) == null ? void 0 : _b.data)) {
4716
+ if (Array.isArray((_d = inputOptions.lane) == null ? void 0 : _d.data)) {
3975
4717
  if (!processedOptions.lane) {
3976
4718
  processedOptions.lane = {};
3977
4719
  }
@@ -3980,7 +4722,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3980
4722
  processedOptions.lane.data[i] = handleDeprecatedLaneOptions(inputOptions.lane.data[i]);
3981
4723
  }
3982
4724
  }
3983
- if (((_d = (_c = inputOptions.article) == null ? void 0 : _c.periodLine) == null ? void 0 : _d.defaultHide) !== void 0) {
4725
+ if (((_f = (_e = inputOptions.article) == null ? void 0 : _e.periodLine) == null ? void 0 : _f.defaultHide) !== void 0) {
3984
4726
  Logger.warn(
3985
4727
  "DEPRECATION WARNING: article.periodLine.defaultHide is deprecated. Use article.defaultData.hidePeriodLine instead."
3986
4728
  );
@@ -4242,12 +4984,16 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
4242
4984
  this.isDataLoaded = true;
4243
4985
  };
4244
4986
  TimeBand.prototype._setupPeriod = function(data) {
4245
- const fromDmy = new Dmy(
4987
+ let fromDmy = new Dmy(
4246
4988
  parseInt(getPropertyFromData(data, "from.year")),
4247
4989
  parseInt(getPropertyFromData(data, "from.month")),
4248
- parseInt(getPropertyFromData(data, "from.day"))
4990
+ parseInt(getPropertyFromData(data, "from.day")),
4991
+ parseInt(getPropertyFromData(data, "from.hour")),
4992
+ parseInt(getPropertyFromData(data, "from.minute")),
4993
+ parseInt(getPropertyFromData(data, "from.second")),
4994
+ parseInt(getPropertyFromData(data, "from.millisecond"))
4249
4995
  );
4250
- this.owner.getDmyFromInput(fromDmy);
4996
+ fromDmy = this.owner.getDmyFromInput(fromDmy);
4251
4997
  const fromPrecision = getPropertyFromData(data, "from.precision");
4252
4998
  const isToPresentProp = getPropertyFromData(data, "isToPresent");
4253
4999
  const isToPresent = isToPresentProp === true || isToPresentProp === 1;
@@ -4259,17 +5005,21 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
4259
5005
  toDmy = new Dmy(
4260
5006
  parseInt(getPropertyFromData(data, "to.year")),
4261
5007
  parseInt(getPropertyFromData(data, "to.month")),
4262
- parseInt(getPropertyFromData(data, "to.day"))
5008
+ parseInt(getPropertyFromData(data, "to.day")),
5009
+ parseInt(getPropertyFromData(data, "to.hour")),
5010
+ parseInt(getPropertyFromData(data, "to.minute")),
5011
+ parseInt(getPropertyFromData(data, "to.second")),
5012
+ parseInt(getPropertyFromData(data, "to.millisecond"))
4263
5013
  );
4264
- this.owner.getDmyFromInput(toDmy);
5014
+ toDmy = this.owner.getDmyFromInput(toDmy);
4265
5015
  toPrecision = getPropertyFromData(data, "to.precision");
4266
5016
  } else {
4267
5017
  toDmy = fromDmy;
4268
5018
  toPrecision = fromPrecision;
4269
5019
  }
4270
5020
  const from = Dmy.CreateAsStartOfPeriod(fromDmy, fromPrecision);
4271
- const to = Dmy.CreateAsEndOfPeriod(toDmy, toPrecision);
4272
- this.period = { from, to: to.getNextDay(), isToPresent };
5021
+ const to = Dmy.CreateAsExclusiveEndOfPeriod(toDmy, toPrecision);
5022
+ this.period = { from, to, isToPresent };
4273
5023
  };
4274
5024
  TimeBand.prototype.overlapsInclusiveWithDates = function(from, to) {
4275
5025
  return !(this.period.from.isAfter(to) || from.isAfter(this.period.to));
@@ -4366,16 +5116,6 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
4366
5116
  return minIndex;
4367
5117
  }
4368
5118
  __name(findMinIndex, "findMinIndex");
4369
- function clamp(value, min, max) {
4370
- if (value < min) {
4371
- return min;
4372
- }
4373
- if (value > max) {
4374
- return max;
4375
- }
4376
- return value;
4377
- }
4378
- __name(clamp, "clamp");
4379
5119
  function isScreenAutoStackingRange(range) {
4380
5120
  return range === "screen" || range === 1;
4381
5121
  }
@@ -5055,6 +5795,151 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5055
5795
  };
5056
5796
  __name(_ImageLoader, "ImageLoader");
5057
5797
  let ImageLoader = _ImageLoader;
5798
+ const SUBDAY_UNIT_MILLISECONDS = {
5799
+ [ZOOM_MILLISECOND]: 1,
5800
+ [ZOOM_SECOND]: MILLISECONDS_PER_SECOND,
5801
+ [ZOOM_MINUTE]: MILLISECONDS_PER_MINUTE,
5802
+ [ZOOM_HOUR]: MILLISECONDS_PER_HOUR
5803
+ };
5804
+ const ADAPTIVE_MINOR_INTERVALS = {
5805
+ [ZOOM_HOUR]: [12, 6, 3, 1],
5806
+ [ZOOM_MINUTE]: [30, 10, 5, 1],
5807
+ [ZOOM_SECOND]: [30, 10, 5, 1],
5808
+ [ZOOM_MILLISECOND]: [500, 100, 50, 10, 5, 1]
5809
+ };
5810
+ const SUBDAY_VISUAL_SCALES = [
5811
+ {
5812
+ majorUnit: ZOOM_DAY,
5813
+ majorMilliseconds: MILLISECONDS_PER_DAY,
5814
+ minorUnit: ZOOM_HOUR
5815
+ },
5816
+ {
5817
+ majorUnit: ZOOM_HOUR,
5818
+ majorMilliseconds: MILLISECONDS_PER_HOUR,
5819
+ minorUnit: ZOOM_MINUTE
5820
+ },
5821
+ {
5822
+ majorUnit: ZOOM_MINUTE,
5823
+ majorMilliseconds: MILLISECONDS_PER_MINUTE,
5824
+ minorUnit: ZOOM_SECOND
5825
+ },
5826
+ {
5827
+ majorUnit: ZOOM_SECOND,
5828
+ majorMilliseconds: MILLISECONDS_PER_SECOND,
5829
+ minorUnit: ZOOM_MILLISECOND
5830
+ }
5831
+ ];
5832
+ const PARENT_CONTEXT_MAXIMUM_LEVEL = ZOOM_CENTURY;
5833
+ function getZoomUnitLengthInDays(unit) {
5834
+ if (unit < ZOOM_DAY) {
5835
+ return SUBDAY_UNIT_MILLISECONDS[unit] / MILLISECONDS_PER_DAY;
5836
+ }
5837
+ return unit === ZOOM_DAY ? 1 : null;
5838
+ }
5839
+ __name(getZoomUnitLengthInDays, "getZoomUnitLengthInDays");
5840
+ function formatSubdayVisualMajorLabel(dmy, unit, options) {
5841
+ if (unit === ZOOM_DAY) {
5842
+ return dmy.format("D MMM YYYY", options);
5843
+ }
5844
+ if (unit === ZOOM_SECOND) {
5845
+ return dmy.format("HH:mm:ss");
5846
+ }
5847
+ return dmy.format("HH:mm");
5848
+ }
5849
+ __name(formatSubdayVisualMajorLabel, "formatSubdayVisualMajorLabel");
5850
+ function formatSubdayMinorLabel(dmy, unit) {
5851
+ if (unit === ZOOM_HOUR || unit === ZOOM_MINUTE) {
5852
+ return dmy.format("HH:mm");
5853
+ }
5854
+ if (unit === ZOOM_SECOND) {
5855
+ return `:${dmy.format("ss")}`;
5856
+ }
5857
+ return `.${dmy.format("SSS")}`;
5858
+ }
5859
+ __name(formatSubdayMinorLabel, "formatSubdayMinorLabel");
5860
+ function ordinal(value, thousandsSeparator) {
5861
+ const lastTwoDigits = value % 100;
5862
+ let suffix;
5863
+ if (lastTwoDigits >= 11 && lastTwoDigits <= 13) {
5864
+ suffix = "th";
5865
+ } else {
5866
+ switch (value % 10) {
5867
+ case 1:
5868
+ suffix = "st";
5869
+ break;
5870
+ case 2:
5871
+ suffix = "nd";
5872
+ break;
5873
+ case 3:
5874
+ suffix = "rd";
5875
+ break;
5876
+ default:
5877
+ suffix = "th";
5878
+ }
5879
+ }
5880
+ const formattedValue = new Dmy(value, 1, 1).format("YYYY", {
5881
+ thousandsSeparator,
5882
+ bceText: ""
5883
+ });
5884
+ return `${formattedValue}${suffix}`;
5885
+ }
5886
+ __name(ordinal, "ordinal");
5887
+ function getParentIntervalStart(value, unit) {
5888
+ switch (unit) {
5889
+ case ZOOM_SECOND:
5890
+ return new Dmy(value.year, value.month, value.day, value.hour, value.minute, value.second);
5891
+ case ZOOM_MINUTE:
5892
+ return new Dmy(value.year, value.month, value.day, value.hour, value.minute);
5893
+ case ZOOM_HOUR:
5894
+ return new Dmy(value.year, value.month, value.day, value.hour);
5895
+ case ZOOM_DAY:
5896
+ return new Dmy(value.year, value.month, value.day);
5897
+ case ZOOM_MONTH:
5898
+ return new Dmy(value.year, value.month, 1);
5899
+ case ZOOM_YEAR:
5900
+ return new Dmy(value.year, 1, 1);
5901
+ case ZOOM_DECADE: {
5902
+ if (value.year > 0) {
5903
+ return new Dmy(Math.floor(value.year / 10) * 10, 1, 1);
5904
+ }
5905
+ const displayedYear = 1 - value.year;
5906
+ const displayedDecade = Math.floor(displayedYear / 10) * 10;
5907
+ return new Dmy(1 - (displayedDecade + 9), 1, 1);
5908
+ }
5909
+ case ZOOM_CENTURY:
5910
+ return Dmy.CreateAsStartOfPeriod(value, "century");
5911
+ case ZOOM_MILLENNIUM:
5912
+ return Dmy.CreateAsStartOfPeriod(value, "millennium");
5913
+ default:
5914
+ return null;
5915
+ }
5916
+ }
5917
+ __name(getParentIntervalStart, "getParentIntervalStart");
5918
+ function getNextParentInterval(start, unit) {
5919
+ switch (unit) {
5920
+ case ZOOM_SECOND:
5921
+ return start.addSeconds(1);
5922
+ case ZOOM_MINUTE:
5923
+ return start.addMinutes(1);
5924
+ case ZOOM_HOUR:
5925
+ return start.addHours(1);
5926
+ case ZOOM_DAY:
5927
+ return start.getNextDay();
5928
+ case ZOOM_MONTH:
5929
+ return start.getNextMonth();
5930
+ case ZOOM_YEAR:
5931
+ return start.addYears(1);
5932
+ case ZOOM_DECADE:
5933
+ return start.addYears(10);
5934
+ case ZOOM_CENTURY:
5935
+ return Dmy.CreateAsExclusiveEndOfPeriod(start, "century");
5936
+ case ZOOM_MILLENNIUM:
5937
+ return Dmy.CreateAsExclusiveEndOfPeriod(start, "millennium");
5938
+ default:
5939
+ return null;
5940
+ }
5941
+ }
5942
+ __name(getNextParentInterval, "getNextParentInterval");
5058
5943
  const _TimescaleManager = class _TimescaleManager {
5059
5944
  constructor(owner, zoomOptions) {
5060
5945
  this.owner = owner;
@@ -5063,6 +5948,9 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5063
5948
  this.startToken = null;
5064
5949
  this.unit = ZOOM_DAY;
5065
5950
  this.unitSizeInPixels = 100;
5951
+ this.adaptiveMinorUnit = null;
5952
+ this.adaptiveMinorInterval = null;
5953
+ this.adaptiveMinorMarkerSpacingInPixels = null;
5066
5954
  this.unitLengthInYears = 1;
5067
5955
  this.zoomChangedHandlers = [];
5068
5956
  this.yearPrefix = {
@@ -5071,14 +5959,16 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5071
5959
  major: false
5072
5960
  };
5073
5961
  this.unitLevels = [];
5962
+ this.unitOrder = [];
5074
5963
  }
5075
5964
  };
5076
5965
  __name(_TimescaleManager, "TimescaleManager");
5077
5966
  let TimescaleManager = _TimescaleManager;
5078
5967
  TimescaleManager.prototype.getUnitSizeInPixelsForZoom = function(zoom) {
5968
+ var _a;
5079
5969
  const zoomRatio = this.zoomOptions.ratio;
5080
5970
  const currentUnitSettings = this.unitLevels[this.unit];
5081
- const zoomStart = currentUnitSettings.zoomStart;
5971
+ const zoomStart = (_a = currentUnitSettings.referenceZoom) != null ? _a : currentUnitSettings.zoomStart;
5082
5972
  const startUnitSize = currentUnitSettings.startUnitSize;
5083
5973
  return startUnitSize * Math.pow(zoomRatio, zoom - zoomStart);
5084
5974
  };
@@ -5086,14 +5976,290 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5086
5976
  return this.unitLevels[this.unit].zoomStart;
5087
5977
  };
5088
5978
  TimescaleManager.prototype.getUnitFromZoom = function(zoom) {
5089
- const unitLevels = this.unitLevels;
5090
- for (let i = unitLevels.length - 1; i >= 0; i--) {
5091
- if (zoom >= unitLevels[i].zoomStart) {
5092
- return i;
5979
+ for (let i = this.unitOrder.length - 1; i >= 0; i--) {
5980
+ const unit = this.unitOrder[i];
5981
+ if (zoom >= this.unitLevels[unit].zoomStart) {
5982
+ return unit;
5093
5983
  }
5094
5984
  }
5095
5985
  throw new Error(`Zoom ${zoom} is out of range`);
5096
5986
  };
5987
+ TimescaleManager.prototype.getAdaptiveMinorInterval = function(unit = this.unit, unitSizeInPixels = this.unitSizeInPixels) {
5988
+ var _a;
5989
+ const intervals = ADAPTIVE_MINOR_INTERVALS[unit];
5990
+ if (!intervals) {
5991
+ return 1;
5992
+ }
5993
+ const minimumMarkerSpacing = this.zoomOptions.unitSize.minimum;
5994
+ const minimumLabelSpacing = (_a = this.zoomOptions.unitSize.showMinorLabels) != null ? _a : minimumMarkerSpacing;
5995
+ const minimumSpacing = Math.max(minimumMarkerSpacing, minimumLabelSpacing);
5996
+ for (let i = intervals.length - 1; i >= 0; i--) {
5997
+ if (unitSizeInPixels * intervals[i] >= minimumSpacing) {
5998
+ return intervals[i];
5999
+ }
6000
+ }
6001
+ return null;
6002
+ };
6003
+ TimescaleManager.prototype.getSubdayVisualMarkerLayout = function() {
6004
+ var _a;
6005
+ if (this.zoomOptions.minimum >= ZOOM_DAY || this.zoom > ZOOM_DAY || this.unit > ZOOM_DAY) {
6006
+ return null;
6007
+ }
6008
+ const unitMilliseconds = this.unit === ZOOM_DAY ? MILLISECONDS_PER_DAY : SUBDAY_UNIT_MILLISECONDS[this.unit];
6009
+ const pixelsPerMillisecond = this.unitSizeInPixels / unitMilliseconds;
6010
+ const minimumMajorSpacing = (_a = this.zoomOptions.unitSize.minimumMajor) != null ? _a : 120;
6011
+ let scale = null;
6012
+ for (let i = SUBDAY_VISUAL_SCALES.length - 1; i >= 0; i--) {
6013
+ const candidate = SUBDAY_VISUAL_SCALES[i];
6014
+ if (candidate.majorMilliseconds * pixelsPerMillisecond >= minimumMajorSpacing) {
6015
+ scale = candidate;
6016
+ break;
6017
+ }
6018
+ }
6019
+ if (!scale) {
6020
+ return null;
6021
+ }
6022
+ const minorUnitSizeInPixels = SUBDAY_UNIT_MILLISECONDS[scale.minorUnit] * pixelsPerMillisecond;
6023
+ const minorInterval = this.getAdaptiveMinorInterval(scale.minorUnit, minorUnitSizeInPixels);
6024
+ return __spreadProps(__spreadValues({}, scale), {
6025
+ majorMarkerSpacingInPixels: scale.majorMilliseconds * pixelsPerMillisecond,
6026
+ minorInterval,
6027
+ minorMarkerSpacingInPixels: minorInterval ? minorUnitSizeInPixels * minorInterval : null,
6028
+ minorMilliseconds: minorInterval ? SUBDAY_UNIT_MILLISECONDS[scale.minorUnit] * minorInterval : null,
6029
+ pixelsPerMillisecond
6030
+ });
6031
+ };
6032
+ TimescaleManager.prototype.getParentContextScale = function() {
6033
+ const visualLayout = this.getSubdayVisualMarkerLayout();
6034
+ const levelUnit = visualLayout ? visualLayout.majorUnit : this.unit + 1;
6035
+ if (levelUnit < ZOOM_MILLISECOND || levelUnit > PARENT_CONTEXT_MAXIMUM_LEVEL) {
6036
+ return null;
6037
+ }
6038
+ return {
6039
+ level: this.zoomUnitToString(levelUnit),
6040
+ levelUnit,
6041
+ parentUnit: levelUnit <= ZOOM_HOUR ? ZOOM_DAY : levelUnit + 1
6042
+ };
6043
+ };
6044
+ TimescaleManager.prototype.isParentContextTextVisible = function(options) {
6045
+ if ((options == null ? void 0 : options.visible) !== true) {
6046
+ return false;
6047
+ }
6048
+ const scale = this.getParentContextScale();
6049
+ if (!scale) {
6050
+ return false;
6051
+ }
6052
+ if (options.levels === "all") {
6053
+ return true;
6054
+ }
6055
+ return Array.isArray(options.levels) && options.levels.includes(scale.level);
6056
+ };
6057
+ TimescaleManager.prototype.formatParentContextLabel = function(value, unit) {
6058
+ const options = this.getDateLabelFormatOptions(MAJOR_MARKER);
6059
+ switch (unit) {
6060
+ case ZOOM_SECOND:
6061
+ case ZOOM_MINUTE:
6062
+ case ZOOM_HOUR:
6063
+ case ZOOM_DAY:
6064
+ return value.format("D MMM YYYY", options);
6065
+ case ZOOM_MONTH:
6066
+ return value.format("MMM YYYY", options);
6067
+ case ZOOM_YEAR:
6068
+ return value.format("YYYY", options);
6069
+ case ZOOM_DECADE: {
6070
+ const displayedYear = value.year <= 0 ? 1 - value.year : value.year;
6071
+ const decade = Math.floor(displayedYear / 10) * 10;
6072
+ const formattedDecade = new Dmy(decade, 1, 1).format("YYYY", {
6073
+ thousandsSeparator: options.thousandsSeparator,
6074
+ bceText: ""
6075
+ });
6076
+ return `${formattedDecade}s${value.year <= 0 ? options.bceText : ""}`;
6077
+ }
6078
+ case ZOOM_CENTURY:
6079
+ case ZOOM_MILLENNIUM: {
6080
+ const displayedYear = value.year <= 0 ? 1 - value.year : value.year;
6081
+ const periodSize = unit === ZOOM_CENTURY ? 100 : 1e3;
6082
+ const period = Math.ceil(displayedYear / periodSize);
6083
+ const periodName = unit === ZOOM_CENTURY ? "century" : "millennium";
6084
+ return `${ordinal(period, options.thousandsSeparator)} ${periodName}${value.year <= 0 ? options.bceText : ""}`;
6085
+ }
6086
+ default:
6087
+ return "";
6088
+ }
6089
+ };
6090
+ TimescaleManager.prototype.createParentContextTokens = function(visibleStart, width, repositionWindow) {
6091
+ const scale = this.getParentContextScale();
6092
+ if (!scale || !visibleStart || !this.startToken) {
6093
+ return [];
6094
+ }
6095
+ const tokens = [];
6096
+ let value = getParentIntervalStart(visibleStart, scale.parentUnit);
6097
+ let drawX = repositionWindow + this.getPixelsBetween(this.startToken.value, value);
6098
+ do {
6099
+ const nextValue = getNextParentInterval(value, scale.parentUnit);
6100
+ if (!nextValue) {
6101
+ break;
6102
+ }
6103
+ const nextDrawX = repositionWindow + this.getPixelsBetween(this.startToken.value, nextValue);
6104
+ tokens.push({
6105
+ drawX,
6106
+ label: this.formatParentContextLabel(value, scale.parentUnit),
6107
+ length: nextDrawX - drawX,
6108
+ unit: scale.parentUnit,
6109
+ value
6110
+ });
6111
+ value = nextValue;
6112
+ drawX = nextDrawX;
6113
+ } while (tokens.length < 1e3 && tokens[tokens.length - 1].drawX <= width);
6114
+ return tokens;
6115
+ };
6116
+ TimescaleManager.prototype.setAdaptiveMinorInterval = function() {
6117
+ const layout = this.getSubdayVisualMarkerLayout();
6118
+ if (!layout) {
6119
+ this.adaptiveMinorUnit = null;
6120
+ this.adaptiveMinorInterval = null;
6121
+ this.adaptiveMinorMarkerSpacingInPixels = null;
6122
+ return;
6123
+ }
6124
+ this.adaptiveMinorUnit = layout.minorUnit;
6125
+ this.adaptiveMinorInterval = layout.minorInterval;
6126
+ this.adaptiveMinorMarkerSpacingInPixels = layout.minorMarkerSpacingInPixels;
6127
+ };
6128
+ TimescaleManager.prototype.createSubdayVisualMarkers = function(width, repositionWindow, layout = this.getSubdayVisualMarkerLayout()) {
6129
+ const markers = {
6130
+ [MAJOR_MARKER]: [],
6131
+ [MINOR_MARKER]: []
6132
+ };
6133
+ if (!layout || !this.startToken) {
6134
+ return markers;
6135
+ }
6136
+ const buffer = 150;
6137
+ const stepMilliseconds = layout.minorMilliseconds || layout.majorMilliseconds;
6138
+ const millisecondsToLeftEdge = Math.floor(
6139
+ (-buffer - repositionWindow) / layout.pixelsPerMillisecond
6140
+ );
6141
+ const approximateStart = this.startToken.value.addMilliseconds(millisecondsToLeftEdge);
6142
+ const dayStart = new Dmy(approximateStart.year, approximateStart.month, approximateStart.day);
6143
+ const firstOffset = Math.floor(approximateStart.getMillisecondsOfDay() / stepMilliseconds) * stepMilliseconds;
6144
+ let value = dayStart.addMilliseconds(firstOffset);
6145
+ const showMinorLabels = layout.minorMarkerSpacingInPixels >= this.zoomOptions.unitSize.showMinorLabels;
6146
+ const createMajorMarker = /* @__PURE__ */ __name((majorValue) => ({
6147
+ drawX: repositionWindow + this.getPixelsBetween(this.startToken.value, majorValue),
6148
+ label: formatSubdayVisualMajorLabel(
6149
+ majorValue,
6150
+ layout.majorUnit,
6151
+ this.getDateLabelFormatOptions(MAJOR_MARKER)
6152
+ ),
6153
+ length: layout.majorMarkerSpacingInPixels,
6154
+ markerSpacingInPixels: layout.majorMarkerSpacingInPixels,
6155
+ type: MAJOR_MARKER,
6156
+ unit: layout.majorUnit,
6157
+ value: majorValue,
6158
+ visual: true
6159
+ }), "createMajorMarker");
6160
+ const owningMajorOffset = Math.floor(approximateStart.getMillisecondsOfDay() / layout.majorMilliseconds) * layout.majorMilliseconds;
6161
+ const owningMajorValue = dayStart.addMilliseconds(owningMajorOffset);
6162
+ if (owningMajorValue.isAfter(value) === false && !owningMajorValue.isSame(value)) {
6163
+ markers[MAJOR_MARKER].push(createMajorMarker(owningMajorValue));
6164
+ }
6165
+ while (true) {
6166
+ const drawX = repositionWindow + this.getPixelsBetween(this.startToken.value, value);
6167
+ if (drawX > width + buffer) {
6168
+ break;
6169
+ }
6170
+ const millisecondsOfDay = value.getMillisecondsOfDay();
6171
+ const isMajor = millisecondsOfDay % layout.majorMilliseconds === 0;
6172
+ if (isMajor) {
6173
+ markers[MAJOR_MARKER].push(createMajorMarker(value));
6174
+ } else if (layout.minorMilliseconds) {
6175
+ markers[MINOR_MARKER].push({
6176
+ adaptive: layout.minorInterval !== 1,
6177
+ drawX,
6178
+ label: showMinorLabels ? formatSubdayMinorLabel(value, layout.minorUnit) : void 0,
6179
+ length: layout.minorMarkerSpacingInPixels,
6180
+ markerSpacingInPixels: layout.minorMarkerSpacingInPixels,
6181
+ type: MINOR_MARKER,
6182
+ unit: layout.minorUnit,
6183
+ value,
6184
+ visual: true
6185
+ });
6186
+ }
6187
+ value = value.addMilliseconds(stepMilliseconds);
6188
+ }
6189
+ return markers;
6190
+ };
6191
+ TimescaleManager.prototype.createHourToken = function(dmy) {
6192
+ const token = {
6193
+ unit: ZOOM_HOUR,
6194
+ value: dmy,
6195
+ length: this.unitSizeInPixels
6196
+ };
6197
+ const unitSettings = this.unitLevels[ZOOM_HOUR];
6198
+ if (dmy.hour === 0) {
6199
+ token.label = dmy.format("D MMM YYYY", this.getDateLabelFormatOptions(MAJOR_MARKER));
6200
+ token.type = MAJOR_MARKER;
6201
+ } else {
6202
+ token.type = MINOR_MARKER;
6203
+ if (this.zoom < unitSettings.zoomHideMinorLabels) {
6204
+ token.label = formatSubdayMinorLabel(dmy, ZOOM_HOUR);
6205
+ }
6206
+ }
6207
+ return token;
6208
+ };
6209
+ TimescaleManager.prototype.createMinuteToken = function(dmy) {
6210
+ const token = {
6211
+ unit: ZOOM_MINUTE,
6212
+ value: dmy,
6213
+ length: this.unitSizeInPixels
6214
+ };
6215
+ const unitSettings = this.unitLevels[ZOOM_MINUTE];
6216
+ if (dmy.minute === 0) {
6217
+ token.label = dmy.format("HH:mm");
6218
+ token.type = MAJOR_MARKER;
6219
+ } else {
6220
+ token.type = MINOR_MARKER;
6221
+ if (this.zoom < unitSettings.zoomHideMinorLabels) {
6222
+ token.label = formatSubdayMinorLabel(dmy, ZOOM_MINUTE);
6223
+ }
6224
+ }
6225
+ return token;
6226
+ };
6227
+ TimescaleManager.prototype.createSecondToken = function(dmy) {
6228
+ const token = {
6229
+ unit: ZOOM_SECOND,
6230
+ value: dmy,
6231
+ length: this.unitSizeInPixels
6232
+ };
6233
+ const unitSettings = this.unitLevels[ZOOM_SECOND];
6234
+ if (dmy.second === 0) {
6235
+ token.label = dmy.format("HH:mm:ss");
6236
+ token.type = MAJOR_MARKER;
6237
+ } else {
6238
+ token.type = MINOR_MARKER;
6239
+ if (this.zoom < unitSettings.zoomHideMinorLabels) {
6240
+ token.label = formatSubdayMinorLabel(dmy, ZOOM_SECOND);
6241
+ }
6242
+ }
6243
+ return token;
6244
+ };
6245
+ TimescaleManager.prototype.createMillisecondToken = function(dmy) {
6246
+ const token = {
6247
+ unit: ZOOM_MILLISECOND,
6248
+ value: dmy,
6249
+ length: this.unitSizeInPixels
6250
+ };
6251
+ const unitSettings = this.unitLevels[ZOOM_MILLISECOND];
6252
+ if (dmy.millisecond === 0) {
6253
+ token.label = dmy.format("HH:mm:ss.SSS");
6254
+ token.type = MAJOR_MARKER;
6255
+ } else {
6256
+ token.type = MINOR_MARKER;
6257
+ if (this.zoom < unitSettings.zoomHideMinorLabels) {
6258
+ token.label = formatSubdayMinorLabel(dmy, ZOOM_MILLISECOND);
6259
+ }
6260
+ }
6261
+ return token;
6262
+ };
5097
6263
  TimescaleManager.prototype.getDateLabelFormatOptions = function(tokenType) {
5098
6264
  tokenType = tokenType === MAJOR_MARKER ? "major" : "minor";
5099
6265
  const dateLabelFormatOptions = this.owner.options.style.dateLabel[tokenType];
@@ -5184,6 +6350,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5184
6350
  this.zoom = nextZoom;
5185
6351
  this.unit = this.getUnitFromZoom(this.zoom);
5186
6352
  this.unitSizeInPixels = this.getUnitSizeInPixelsForZoom(this.zoom);
6353
+ this.setAdaptiveMinorInterval();
5187
6354
  let unitLengthInYears = 0;
5188
6355
  if (this.unit >= ZOOM_YEAR) {
5189
6356
  const unitYearPowerOfTen = this.unit - ZOOM_YEAR;
@@ -5202,7 +6369,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5202
6369
  TimescaleManager.prototype.getPixelsBetween = function(a, b) {
5203
6370
  const unit = this.unit;
5204
6371
  if (unit <= ZOOM_DAY) {
5205
- return a.getDaysTo(b) * this.unitSizeInPixels;
6372
+ return a.getDaysTo(b) * this.unitSizeInPixels / getZoomUnitLengthInDays(unit);
5206
6373
  }
5207
6374
  if (unit === ZOOM_MONTH) {
5208
6375
  return a.getMonthsTo(b) * this.unitSizeInPixels;
@@ -5219,9 +6386,27 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5219
6386
  bcMove = 1;
5220
6387
  }
5221
6388
  switch (this.unit) {
5222
- case ZOOM_DAY:
5223
- this.startToken = this.createDayToken(from);
6389
+ case ZOOM_MILLISECOND:
6390
+ this.startToken = this.createMillisecondToken(new Dmy(from));
5224
6391
  return 0;
6392
+ case ZOOM_SECOND: {
6393
+ const start = new Dmy(from.year, from.month, from.day, from.hour, from.minute, from.second);
6394
+ this.startToken = this.createSecondToken(start);
6395
+ return -this.getPixelsBetween(start, from);
6396
+ }
6397
+ case ZOOM_MINUTE: {
6398
+ const start = new Dmy(from.year, from.month, from.day, from.hour, from.minute);
6399
+ this.startToken = this.createMinuteToken(start);
6400
+ return -this.getPixelsBetween(start, from);
6401
+ }
6402
+ case ZOOM_HOUR: {
6403
+ const start = new Dmy(from.year, from.month, from.day, from.hour);
6404
+ this.startToken = this.createHourToken(start);
6405
+ return -this.getPixelsBetween(start, from);
6406
+ }
6407
+ case ZOOM_DAY:
6408
+ this.startToken = this.createDayToken(new Dmy(from.year, from.month, from.day));
6409
+ return -this.getPixelsBetween(this.startToken.value, from);
5225
6410
  case ZOOM_MONTH: {
5226
6411
  this.startToken = this.createMonthToken(new Dmy(from.year, from.month, 1));
5227
6412
  const unitSizeForDays = this.unitSizeInPixels / 30.44;
@@ -5244,6 +6429,14 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5244
6429
  };
5245
6430
  TimescaleManager.prototype.getStartTokenCloned = function() {
5246
6431
  switch (this.startToken.unit) {
6432
+ case ZOOM_MILLISECOND:
6433
+ return this.createMillisecondToken(this.startToken.value);
6434
+ case ZOOM_SECOND:
6435
+ return this.createSecondToken(this.startToken.value);
6436
+ case ZOOM_MINUTE:
6437
+ return this.createMinuteToken(this.startToken.value);
6438
+ case ZOOM_HOUR:
6439
+ return this.createHourToken(this.startToken.value);
5247
6440
  case ZOOM_DAY:
5248
6441
  return this.createDayToken(this.startToken.value);
5249
6442
  case ZOOM_MONTH:
@@ -5254,6 +6447,14 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5254
6447
  };
5255
6448
  TimescaleManager.prototype.getNext = function(token) {
5256
6449
  switch (token.unit) {
6450
+ case ZOOM_MILLISECOND:
6451
+ return this.createMillisecondToken(token.value.addMilliseconds(1));
6452
+ case ZOOM_SECOND:
6453
+ return this.createSecondToken(token.value.addSeconds(1));
6454
+ case ZOOM_MINUTE:
6455
+ return this.createMinuteToken(token.value.addMinutes(1));
6456
+ case ZOOM_HOUR:
6457
+ return this.createHourToken(token.value.addHours(1));
5257
6458
  case ZOOM_DAY:
5258
6459
  return this.createDayToken(token.value.getNextDay());
5259
6460
  case ZOOM_MONTH:
@@ -5272,6 +6473,14 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5272
6473
  };
5273
6474
  TimescaleManager.prototype.getPrevious = function(token) {
5274
6475
  switch (token.unit) {
6476
+ case ZOOM_MILLISECOND:
6477
+ return this.createMillisecondToken(token.value.addMilliseconds(-1));
6478
+ case ZOOM_SECOND:
6479
+ return this.createSecondToken(token.value.addSeconds(-1));
6480
+ case ZOOM_MINUTE:
6481
+ return this.createMinuteToken(token.value.addMinutes(-1));
6482
+ case ZOOM_HOUR:
6483
+ return this.createHourToken(token.value.addHours(-1));
5275
6484
  case ZOOM_DAY:
5276
6485
  return this.createDayToken(token.value.getPreviousDay());
5277
6486
  case ZOOM_MONTH:
@@ -5294,6 +6503,14 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5294
6503
  };
5295
6504
  TimescaleManager.prototype.zoomUnitToString = function(unit) {
5296
6505
  switch (unit) {
6506
+ case ZOOM_MILLISECOND:
6507
+ return "millisecond";
6508
+ case ZOOM_SECOND:
6509
+ return "second";
6510
+ case ZOOM_MINUTE:
6511
+ return "minute";
6512
+ case ZOOM_HOUR:
6513
+ return "hour";
5297
6514
  case ZOOM_DAY:
5298
6515
  return "day";
5299
6516
  case ZOOM_MONTH:
@@ -5324,9 +6541,14 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5324
6541
  };
5325
6542
  TimescaleManager.prototype.setUnitLevels = function() {
5326
6543
  this.unitLevels = [];
6544
+ this.unitOrder = [];
5327
6545
  const minUnitSize = this.zoomOptions.unitSize.minimum;
5328
6546
  const showMinorLabelUnitSize = this.zoomOptions.unitSize.showMinorLabels;
5329
6547
  const dayZoomStart = 0;
6548
+ const addUnit = /* @__PURE__ */ __name((unit, settings) => {
6549
+ this.unitLevels[unit] = settings;
6550
+ this.unitOrder.push(unit);
6551
+ }, "addUnit");
5330
6552
  const hideLabelsZoomChangeFromEnd = this.getZoomChangeByDistance(
5331
6553
  showMinorLabelUnitSize,
5332
6554
  minUnitSize
@@ -5341,12 +6563,41 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5341
6563
  zoomHideMinorLabels: dayZoomHideMinorLabels,
5342
6564
  zoomEnd: dayZoomEnd
5343
6565
  };
5344
- this.unitLevels.push(daySettings);
6566
+ addUnit(ZOOM_DAY, daySettings);
6567
+ const hourSizeAtDayBoundary = dayStartUnitSize / 24;
6568
+ const hourZoomStart = this.getZoomChangeByDistance(hourSizeAtDayBoundary, minUnitSize * 60);
6569
+ addUnit(ZOOM_HOUR, {
6570
+ startUnitSize: minUnitSize * 60,
6571
+ zoomStart: hourZoomStart,
6572
+ zoomEnd: dayZoomStart,
6573
+ zoomHideMinorLabels: hourZoomStart + this.getZoomChangeByDistance(minUnitSize * 60, showMinorLabelUnitSize)
6574
+ });
6575
+ const minuteZoomStart = hourZoomStart + this.getZoomChangeByDistance(minUnitSize, minUnitSize * 60);
6576
+ addUnit(ZOOM_MINUTE, {
6577
+ startUnitSize: minUnitSize * 60,
6578
+ zoomStart: minuteZoomStart,
6579
+ zoomEnd: hourZoomStart,
6580
+ zoomHideMinorLabels: minuteZoomStart + this.getZoomChangeByDistance(minUnitSize * 60, showMinorLabelUnitSize)
6581
+ });
6582
+ const secondZoomStart = minuteZoomStart + this.getZoomChangeByDistance(minUnitSize, minUnitSize * 1e3);
6583
+ addUnit(ZOOM_SECOND, {
6584
+ startUnitSize: minUnitSize * 1e3,
6585
+ zoomStart: secondZoomStart,
6586
+ zoomEnd: minuteZoomStart,
6587
+ zoomHideMinorLabels: secondZoomStart + this.getZoomChangeByDistance(minUnitSize * 1e3, showMinorLabelUnitSize)
6588
+ });
6589
+ addUnit(ZOOM_MILLISECOND, {
6590
+ startUnitSize: minUnitSize,
6591
+ referenceZoom: secondZoomStart,
6592
+ zoomStart: Number.NEGATIVE_INFINITY,
6593
+ zoomEnd: secondZoomStart,
6594
+ zoomHideMinorLabels: secondZoomStart + this.getZoomChangeByDistance(minUnitSize, showMinorLabelUnitSize)
6595
+ });
5345
6596
  const monthStartUnitSize = minUnitSize * 31;
5346
6597
  const monthZoomSpan = this.getZoomChangeByDistance(monthStartUnitSize, minUnitSize);
5347
6598
  const monthZoomEnd = dayZoomEnd + monthZoomSpan;
5348
6599
  const monthZoomHideMinorLabels = monthZoomEnd - hideLabelsZoomChangeFromEnd;
5349
- this.unitLevels.push({
6600
+ addUnit(ZOOM_MONTH, {
5350
6601
  startUnitSize: monthStartUnitSize,
5351
6602
  zoomStart: dayZoomEnd,
5352
6603
  zoomHideMinorLabels: monthZoomHideMinorLabels,
@@ -5356,7 +6607,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5356
6607
  const yearZoomSpan = this.getZoomChangeByDistance(yearStartUnitSize, minUnitSize);
5357
6608
  const yearZoomEnd = monthZoomEnd + yearZoomSpan;
5358
6609
  const yearZoomHideMinorLabels = yearZoomEnd - hideLabelsZoomChangeFromEnd;
5359
- this.unitLevels.push({
6610
+ addUnit(ZOOM_YEAR, {
5360
6611
  startUnitSize: yearStartUnitSize,
5361
6612
  zoomStart: monthZoomEnd,
5362
6613
  zoomHideMinorLabels: yearZoomHideMinorLabels,
@@ -5373,7 +6624,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5373
6624
  zoomSpan = this.getZoomChangeByDistance(startUnitSize, minUnitSize);
5374
6625
  zoomEnd = zoomStart + zoomSpan;
5375
6626
  zoomHideMinorLabels = zoomEnd - hideLabelsZoomChangeFromEnd;
5376
- this.unitLevels.push({
6627
+ addUnit(ZOOM_YEAR + i, {
5377
6628
  startUnitSize,
5378
6629
  zoomStart,
5379
6630
  zoomHideMinorLabels,
@@ -5384,6 +6635,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5384
6635
  this.zoomOptions.maximum = Math.min(this.zoomOptions.maximum, zoomEnd);
5385
6636
  }
5386
6637
  }
6638
+ this.unitOrder.sort((a, b) => a - b);
5387
6639
  };
5388
6640
  TimescaleManager.prototype.getZoomChangeByDistance = function(startDistance, endDistance) {
5389
6641
  const zoomRatio = this.zoomOptions.ratio;
@@ -5830,6 +7082,8 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5830
7082
  function Timeline(container, inputOptions) {
5831
7083
  var _a;
5832
7084
  const processedInputOptions = handleDeprecatedOptions(inputOptions);
7085
+ this._registeredArticleLayoutStyles = deepMerge({}, DEFAULT_OPTIONS.article.layoutStyles || {});
7086
+ this._explicitArticleOptions = deepMerge({}, (processedInputOptions == null ? void 0 : processedInputOptions.article) || {});
5833
7087
  this.options = deepMerge({}, DEFAULT_OPTIONS, processedInputOptions);
5834
7088
  if (isCanvas(container)) {
5835
7089
  this.canvas = container;
@@ -5908,7 +7162,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5908
7162
  }
5909
7163
  this._isInitialized = false;
5910
7164
  this._hasPendingTimelineStateChange = false;
5911
- const zoom = this.options.zoom, startDate = this.getDmyFromInput(new Dmy(this.options.initialDate));
7165
+ const zoom = this.options.zoom, startDate = this.getDmyFromInput(this.options.initialDate);
5912
7166
  this.timescaleManager = new TimescaleManager(this, zoom);
5913
7167
  this.timescaleManager.setUnitLevels();
5914
7168
  this.timescaleManager.addZoomChangedHandler(this.zoomChanged, this);
@@ -5960,7 +7214,9 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5960
7214
  return vicinityParameters;
5961
7215
  }
5962
7216
  const pos = relativePosition || this.getRelativePosition(event);
5963
- return pos.top > this.top - vicinityParameters.up && pos.top < this.top + vicinityParameters.down;
7217
+ const isWithinUpperBound = vicinityParameters.up === void 0 || pos.top > this.top - vicinityParameters.up;
7218
+ const isWithinLowerBound = vicinityParameters.down === void 0 || pos.top < this.top + vicinityParameters.down;
7219
+ return isWithinUpperBound && isWithinLowerBound;
5964
7220
  };
5965
7221
  Timeline.prototype.getPixel = function(dmy, drawCycleContext) {
5966
7222
  let cache;
@@ -6198,7 +7454,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6198
7454
  };
6199
7455
  Timeline.prototype._getArticleImageTargetSpec = function(article) {
6200
7456
  const layout = article._getCurrentCardLayoutName();
6201
- const style = article._getCurrentStyle();
7457
+ const style = article.getCurrentStyle();
6202
7458
  const imageStyle = style && style.image ? style.image : {};
6203
7459
  const shape = imageStyle.shape || (layout === "portrait" ? "square" : "square");
6204
7460
  let cssTargetW = null, cssTargetH = null;
@@ -6244,6 +7500,9 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6244
7500
  option = buildObjectFromPath(normalizedOptionPath, value);
6245
7501
  }
6246
7502
  option = handleDeprecatedOptions(option);
7503
+ if (existsInData(option, "article")) {
7504
+ deepMerge(this._explicitArticleOptions, option.article || {});
7505
+ }
6247
7506
  deepMerge(this.options, option);
6248
7507
  const sizeChanged = option.width || option.height;
6249
7508
  if (sizeChanged) {
@@ -6266,6 +7525,10 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6266
7525
  if (timeBandsSpaceChanged) {
6267
7526
  this.top = this.options.height - this._getEffectiveVerticalOffset();
6268
7527
  }
7528
+ const parentContextSpaceChanged = existsInData(option, "style.dateLabel.parent.visible") || existsInData(option, "style.dateLabel.parent.height");
7529
+ if (parentContextSpaceChanged) {
7530
+ this.top = this.options.height - this._getEffectiveVerticalOffset();
7531
+ }
6269
7532
  const articleImpact = getLaneArticleOptionImpact(getPropertyFromData(option, "article"));
6270
7533
  const timeBandsDefaultStyleChanged = existsInData(option, "timeBand.defaultStyle");
6271
7534
  if (timeBandsDefaultStyleChanged && Array.isArray(this.timeBands) && this.timeBands.length > 0) {
@@ -6280,11 +7543,15 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6280
7543
  if (Array.isArray(chartData) && typeof this.addCharts === "function") {
6281
7544
  this.addCharts(chartData);
6282
7545
  }
6283
- const chartDefaultsChanged = existsInData(option, "chart.defaultData") || existsInData(option, "chart.defaultStyle");
7546
+ const chartSeriesColorsChanged = existsInData(option, "chart.seriesColors");
7547
+ const chartDefaultsChanged = chartSeriesColorsChanged || existsInData(option, "chart.defaultData") || existsInData(option, "chart.defaultStyle");
6284
7548
  if (chartDefaultsChanged && Array.isArray(this.charts) && this.charts.length > 0) {
6285
7549
  let chartLaneChanged = false;
6286
7550
  for (let i = 0; i < this.charts.length; i++) {
6287
7551
  const previousLaneId = this.charts[i].laneId;
7552
+ if (chartSeriesColorsChanged) {
7553
+ this.charts[i]._seriesColors = [];
7554
+ }
6288
7555
  this.charts[i]._resolveFromData();
6289
7556
  if (existsInData(option, "chart.defaultData") && this.charts[i].laneId != null) {
6290
7557
  this._ensureChartLane(this.charts[i].laneId);
@@ -6337,22 +7604,43 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6337
7604
  this.requestRedraw();
6338
7605
  };
6339
7606
  Timeline.prototype._getEffectiveVerticalOffset = function() {
7607
+ var _a, _b;
6340
7608
  const base = this.options.verticalOffset || 0;
6341
7609
  const tb = this.options.timeBand || {};
6342
7610
  const hasLoadedBands = Array.isArray(this.timeBands) && this.timeBands.length > 0;
6343
7611
  const reserve = !!tb.reserveSpace;
6344
- const extra = reserve && tb.visible && hasLoadedBands ? tb.reserveSpacePixels || 0 : 0;
6345
- return base + extra;
7612
+ const timeBandExtra = reserve && tb.visible && hasLoadedBands ? tb.reserveSpacePixels || 0 : 0;
7613
+ const parent = ((_b = (_a = this.options.style) == null ? void 0 : _a.dateLabel) == null ? void 0 : _b.parent) || {};
7614
+ const parentExtra = parent.visible === true ? parent.height || 0 : 0;
7615
+ return base + timeBandExtra + parentExtra;
6346
7616
  };
6347
7617
  Timeline.prototype.generateDensitySettings = function() {
6348
7618
  const zoomRatio = this.timescaleManager.zoomOptions.ratio;
6349
- Logger.log(this.timescaleManager);
6350
7619
  const newSettings = [];
6351
- const halfZoom = Math.round(Math.log(0.5) / Math.log(zoomRatio) * 100) / 100;
6352
- for (let i = 0; i < 19; i++) {
7620
+ const roundZoom = /* @__PURE__ */ __name((value) => Math.round(value * 100) / 100, "roundZoom");
7621
+ const halfZoom = roundZoom(Math.log(0.5) / Math.log(zoomRatio));
7622
+ const finestSubdayPower = Math.ceil(Math.log2(MILLISECONDS_PER_DAY));
7623
+ for (let power = finestSubdayPower; power >= 1; power--) {
7624
+ newSettings.push({
7625
+ region: 1 - power,
7626
+ zoom: {
7627
+ from: power === finestSubdayPower ? Number.NEGATIVE_INFINITY : roundZoom(-power * halfZoom),
7628
+ to: roundZoom(-(power - 1) * halfZoom)
7629
+ },
7630
+ low: 1,
7631
+ medium: 2,
7632
+ high: 3,
7633
+ all: 25,
7634
+ step: { months: 0, days: 0, divisionsPerDay: Math.pow(2, power) }
7635
+ });
7636
+ }
7637
+ const positiveRegionCount = Math.ceil(this.timescaleManager.zoomOptions.maximum / halfZoom);
7638
+ for (let i = 0; i < positiveRegionCount; i++) {
7639
+ const from = roundZoom(i * halfZoom);
7640
+ const to = roundZoom((i + 1) * halfZoom);
6353
7641
  const nextRegion = {
6354
7642
  region: i + 1,
6355
- zoom: { from: i * halfZoom, to: (i + 1) * halfZoom },
7643
+ zoom: { from, to },
6356
7644
  low: 1,
6357
7645
  medium: 2,
6358
7646
  high: 3,
@@ -6361,12 +7649,109 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6361
7649
  };
6362
7650
  newSettings.push(nextRegion);
6363
7651
  }
6364
- Logger.log(JSON.stringify(newSettings));
7652
+ const output = JSON.stringify(
7653
+ newSettings,
7654
+ (_key, value) => value === Number.NEGATIVE_INFINITY ? "__DENSITY_NEGATIVE_INFINITY__" : value,
7655
+ 2
7656
+ ).replace('"__DENSITY_NEGATIVE_INFINITY__"', "Number.NEGATIVE_INFINITY");
7657
+ Logger.log(output);
6365
7658
  };
7659
+ function isSubdayDensityGroupIndex(index) {
7660
+ return index != null && typeof index === "object";
7661
+ }
7662
+ __name(isSubdayDensityGroupIndex, "isSubdayDensityGroupIndex");
7663
+ function createSubdayDensityGroupIndex(date, divisionsPerDay) {
7664
+ return {
7665
+ day: date.getDaysSinceYearZero(),
7666
+ division: Math.floor(date.getMillisecondsOfDay() * divisionsPerDay / MILLISECONDS_PER_DAY),
7667
+ divisionsPerDay
7668
+ };
7669
+ }
7670
+ __name(createSubdayDensityGroupIndex, "createSubdayDensityGroupIndex");
7671
+ function compareDensityGroupIndexes(left, right) {
7672
+ if (!isSubdayDensityGroupIndex(left) && !isSubdayDensityGroupIndex(right)) {
7673
+ return left === right ? 0 : left < right ? -1 : 1;
7674
+ }
7675
+ if (left.day !== right.day) {
7676
+ return left.day < right.day ? -1 : 1;
7677
+ }
7678
+ if (left.division !== right.division) {
7679
+ return left.division < right.division ? -1 : 1;
7680
+ }
7681
+ return 0;
7682
+ }
7683
+ __name(compareDensityGroupIndexes, "compareDensityGroupIndexes");
7684
+ function shiftDensityGroupIndex(index, offset) {
7685
+ if (!isSubdayDensityGroupIndex(index)) {
7686
+ return index + offset;
7687
+ }
7688
+ const unnormalisedDivision = index.division + offset;
7689
+ const dayOffset = Math.floor(unnormalisedDivision / index.divisionsPerDay);
7690
+ return {
7691
+ day: index.day + dayOffset,
7692
+ division: unnormalisedDivision - dayOffset * index.divisionsPerDay,
7693
+ divisionsPerDay: index.divisionsPerDay
7694
+ };
7695
+ }
7696
+ __name(shiftDensityGroupIndex, "shiftDensityGroupIndex");
7697
+ function clampDensityGroupIndex(index, minimum, maximum) {
7698
+ if (compareDensityGroupIndexes(index, minimum) < 0) {
7699
+ return minimum;
7700
+ }
7701
+ if (compareDensityGroupIndexes(index, maximum) > 0) {
7702
+ return maximum;
7703
+ }
7704
+ return index;
7705
+ }
7706
+ __name(clampDensityGroupIndex, "clampDensityGroupIndex");
7707
+ function getDensityGroupKey(index) {
7708
+ if (!isSubdayDensityGroupIndex(index)) {
7709
+ return String(index);
7710
+ }
7711
+ return `${index.day}:${index.division}`;
7712
+ }
7713
+ __name(getDensityGroupKey, "getDensityGroupKey");
7714
+ function getSubdayDensityGroupBoundary(index) {
7715
+ return {
7716
+ dayNumber: index.day,
7717
+ dayFraction: index.division / index.divisionsPerDay
7718
+ };
7719
+ }
7720
+ __name(getSubdayDensityGroupBoundary, "getSubdayDensityGroupBoundary");
6366
7721
  function getLaneGroupKey(laneId, groupIndex) {
6367
- return `${laneId}::${groupIndex}`;
7722
+ return `${laneId}::${getDensityGroupKey(groupIndex)}`;
6368
7723
  }
6369
7724
  __name(getLaneGroupKey, "getLaneGroupKey");
7725
+ const STARRED_INCREASE_CONSTANT = 1e7;
7726
+ const ACTIVE_INCREASE_CONSTANT = 2e7;
7727
+ function getArticleEffectiveRank(article) {
7728
+ if (article.isActive) {
7729
+ return article.rank + ACTIVE_INCREASE_CONSTANT;
7730
+ }
7731
+ return article.rank + (article.isStarred ? STARRED_INCREASE_CONSTANT : 0);
7732
+ }
7733
+ __name(getArticleEffectiveRank, "getArticleEffectiveRank");
7734
+ function selectRankedArticles(articles, pick) {
7735
+ const topArticles = [];
7736
+ let minRankIndex = 0;
7737
+ for (let i = 0; i < articles.length; i++) {
7738
+ const article = articles[i];
7739
+ article.effectiveRank = getArticleEffectiveRank(article);
7740
+ if (topArticles.length < pick) {
7741
+ topArticles.push(article);
7742
+ if (article.effectiveRank < topArticles[minRankIndex].effectiveRank) {
7743
+ minRankIndex = topArticles.length - 1;
7744
+ }
7745
+ continue;
7746
+ }
7747
+ if (article.effectiveRank > topArticles[minRankIndex].effectiveRank) {
7748
+ topArticles[minRankIndex] = article;
7749
+ minRankIndex = findMinIndex(topArticles, "effectiveRank");
7750
+ }
7751
+ }
7752
+ return topArticles;
7753
+ }
7754
+ __name(selectRankedArticles, "selectRankedArticles");
6370
7755
  Timeline.prototype.updateArticlesGroupIndex = function() {
6371
7756
  this.forLoadedArticles(function(article) {
6372
7757
  article.groupIndex = this.calculateGroupIndex(article.period.from);
@@ -6376,15 +7761,21 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6376
7761
  if (this._isLaneLayoutActive()) {
6377
7762
  this.groups = {};
6378
7763
  const groupIndexExtension2 = isScreenAutoStackingRange(this.options.article.autoStacking.range) ? 1 : 20;
6379
- const leftmostGroupIndex2 = this.calculateGroupIndex(drawCycleContext.tokens.start) - groupIndexExtension2;
6380
- const rightmostGroupIndex2 = this.calculateGroupIndex(drawCycleContext.tokens.end) + groupIndexExtension2;
7764
+ const leftmostGroupIndex2 = shiftDensityGroupIndex(
7765
+ this.calculateGroupIndex(drawCycleContext.tokens.start),
7766
+ -groupIndexExtension2
7767
+ );
7768
+ const rightmostGroupIndex2 = shiftDensityGroupIndex(
7769
+ this.calculateGroupIndex(drawCycleContext.tokens.end),
7770
+ groupIndexExtension2
7771
+ );
6381
7772
  const activeLanes = this._getActiveLanesForLayout();
6382
7773
  this.forLoadedArticles(function(article) {
6383
7774
  article.isVisibleInGroup = false;
6384
7775
  });
6385
7776
  for (let l = 0; l < activeLanes.length; l++) {
6386
7777
  const lane = activeLanes[l];
6387
- for (let index = leftmostGroupIndex2; index <= rightmostGroupIndex2; index++) {
7778
+ for (let index = leftmostGroupIndex2; compareDensityGroupIndexes(index, rightmostGroupIndex2) <= 0; index = shiftDensityGroupIndex(index, 1)) {
6388
7779
  const key = getLaneGroupKey(lane.id, index);
6389
7780
  this.groups[key] = this.getArticlesInGroup(
6390
7781
  index,
@@ -6401,42 +7792,33 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6401
7792
  }
6402
7793
  this.groups = {};
6403
7794
  const groupIndexExtension = isScreenAutoStackingRange(this.options.article.autoStacking.range) ? 1 : 20;
6404
- const leftmostGroupIndex = this.calculateGroupIndex(drawCycleContext.tokens.start) - groupIndexExtension;
6405
- const rightmostGroupIndex = this.calculateGroupIndex(drawCycleContext.tokens.end) + groupIndexExtension;
7795
+ const leftmostGroupIndex = shiftDensityGroupIndex(
7796
+ this.calculateGroupIndex(drawCycleContext.tokens.start),
7797
+ -groupIndexExtension
7798
+ );
7799
+ const rightmostGroupIndex = shiftDensityGroupIndex(
7800
+ this.calculateGroupIndex(drawCycleContext.tokens.end),
7801
+ groupIndexExtension
7802
+ );
6406
7803
  this.forLoadedArticles(function(article) {
6407
7804
  article.isVisibleInGroup = false;
6408
7805
  });
6409
- for (let index = leftmostGroupIndex; index <= rightmostGroupIndex; index++) {
6410
- this.groups[index] = this.getArticlesInGroup(
7806
+ for (let index = leftmostGroupIndex; compareDensityGroupIndexes(index, rightmostGroupIndex) <= 0; index = shiftDensityGroupIndex(index, 1)) {
7807
+ this.groups[getDensityGroupKey(index)] = this.getArticlesInGroup(
6411
7808
  index,
6412
7809
  leftmostGroupIndex,
6413
7810
  rightmostGroupIndex
6414
7811
  ).map(function(a) {
6415
- a.isVisibleInGroup = true;
6416
- return a.id;
6417
- });
6418
- }
6419
- };
6420
- const STARRED_INCREASE_CONSTANT = 1e7;
6421
- const ACTIVE_INCREASE_CONSTANT = 2e7;
6422
- Timeline.prototype.getArticlesInGroup = function(index, leftmostGroupIndex, rightmostGroupIndex, laneId) {
6423
- function getArticleEffectiveRank(article) {
6424
- let effectiveRank = article.rank;
6425
- if (article.isActive) {
6426
- effectiveRank += ACTIVE_INCREASE_CONSTANT;
6427
- } else {
6428
- if (article.isStarred) {
6429
- effectiveRank += STARRED_INCREASE_CONSTANT;
6430
- }
6431
- }
6432
- return effectiveRank;
7812
+ a.isVisibleInGroup = true;
7813
+ return a.id;
7814
+ });
6433
7815
  }
6434
- __name(getArticleEffectiveRank, "getArticleEffectiveRank");
7816
+ };
7817
+ Timeline.prototype.getArticlesInGroup = function(index, leftmostGroupIndex, rightmostGroupIndex, laneId) {
6435
7818
  const lane = typeof laneId !== "undefined" ? this.getLaneById(laneId) : null;
6436
7819
  const density = lane && lane.resolvedArticleOptions ? lane.resolvedArticleOptions.density : this.options.article.density;
6437
7820
  const pick = this.getDensityPick(density);
6438
- const topArticles = [];
6439
- let minRankIndex = 0;
7821
+ const articlesInGroup = [];
6440
7822
  for (let i = 0; i < this.articles.length; i++) {
6441
7823
  const article = this.articles[i];
6442
7824
  if (!article.isDataLoaded || article.isHiddenByFilter) {
@@ -6445,26 +7827,21 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6445
7827
  if (typeof laneId !== "undefined" && article.laneId !== laneId) {
6446
7828
  continue;
6447
7829
  }
6448
- const belongsToThisGroup = clamp(article.groupIndex, leftmostGroupIndex, rightmostGroupIndex) === index;
7830
+ const belongsToThisGroup = compareDensityGroupIndexes(
7831
+ clampDensityGroupIndex(article.groupIndex, leftmostGroupIndex, rightmostGroupIndex),
7832
+ index
7833
+ ) === 0;
6449
7834
  if (!belongsToThisGroup) {
6450
7835
  continue;
6451
7836
  }
6452
- article.effectiveRank = getArticleEffectiveRank(article);
6453
- if (topArticles.length < pick) {
6454
- topArticles.push(article);
6455
- if (article.effectiveRank < topArticles[minRankIndex].effectiveRank) {
6456
- minRankIndex = topArticles.length - 1;
6457
- }
6458
- continue;
6459
- }
6460
- if (article.effectiveRank > topArticles[minRankIndex].effectiveRank) {
6461
- topArticles[minRankIndex] = article;
6462
- minRankIndex = findMinIndex(topArticles, "effectiveRank");
6463
- }
7837
+ articlesInGroup.push(article);
6464
7838
  }
6465
- return topArticles;
7839
+ return selectRankedArticles(articlesInGroup, pick);
6466
7840
  };
6467
7841
  Timeline.prototype.calculateGroupIndex = function(date) {
7842
+ if (this.currentDensitySetting.step.divisionsPerDay) {
7843
+ return createSubdayDensityGroupIndex(date, this.currentDensitySetting.step.divisionsPerDay);
7844
+ }
6468
7845
  if (this.timescaleManager.unit >= ZOOM_MONTH && this.currentDensitySetting.step.months !== 0) {
6469
7846
  const g2 = date.year * 12 + (date.month - 1);
6470
7847
  return Math.floor(g2 / this.currentDensitySetting.step.months);
@@ -6481,17 +7858,18 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6481
7858
  }
6482
7859
  startToken = startToken || this.timescaleManager.startToken;
6483
7860
  endToken = endToken || this.calculateEndToken();
6484
- const leftmostGroupIndex = this.calculateGroupIndex(startToken.value) - 1;
6485
- const rightmostGroupIndex = this.calculateGroupIndex(endToken.value) + 1;
6486
- const effectiveArticleGroupIndex = clamp(
7861
+ const leftmostGroupIndex = shiftDensityGroupIndex(this.calculateGroupIndex(startToken.value), -1);
7862
+ const rightmostGroupIndex = shiftDensityGroupIndex(this.calculateGroupIndex(endToken.value), 1);
7863
+ const effectiveArticleGroupIndex = clampDensityGroupIndex(
6487
7864
  article.groupIndex,
6488
7865
  leftmostGroupIndex,
6489
7866
  rightmostGroupIndex
6490
7867
  );
6491
- if (!Object.prototype.hasOwnProperty.call(this.groups, effectiveArticleGroupIndex)) {
7868
+ const effectiveGroupKey = getDensityGroupKey(effectiveArticleGroupIndex);
7869
+ if (!Object.prototype.hasOwnProperty.call(this.groups, effectiveGroupKey)) {
6492
7870
  return false;
6493
7871
  }
6494
- return this.groups[effectiveArticleGroupIndex].indexOf(article.id) >= 0;
7872
+ return this.groups[effectiveGroupKey].indexOf(article.id) >= 0;
6495
7873
  };
6496
7874
  const DEFAULT_MAX_FRAME_DELTA = 64;
6497
7875
  function startInertia({
@@ -6569,17 +7947,77 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6569
7947
  }
6570
7948
  __name(normalisePadding, "normalisePadding");
6571
7949
  function normaliseDateInput(date) {
6572
- var _a, _b;
6573
- if (!date || !Number.isFinite(date.year)) {
6574
- throw new Error("fitDateRange requires start and end dates with a numeric year");
7950
+ var _a, _b, _c, _d, _e, _f, _g;
7951
+ const parsed = typeof date === "string" ? (_a = parseDmyString(date)) == null ? void 0 : _a.date : date;
7952
+ if (!parsed || !Number.isFinite(parsed.year)) {
7953
+ throw new Error("Date input requires a numeric year or canonical Histropedia date string");
6575
7954
  }
6576
7955
  return new Dmy({
6577
- year: date.year,
6578
- month: (_a = date.month) != null ? _a : 1,
6579
- day: (_b = date.day) != null ? _b : 1
7956
+ year: parsed.year,
7957
+ month: (_b = parsed.month) != null ? _b : 1,
7958
+ day: (_c = parsed.day) != null ? _c : 1,
7959
+ hour: (_d = parsed.hour) != null ? _d : 0,
7960
+ minute: (_e = parsed.minute) != null ? _e : 0,
7961
+ second: (_f = parsed.second) != null ? _f : 0,
7962
+ millisecond: (_g = parsed.millisecond) != null ? _g : 0
6580
7963
  });
6581
7964
  }
6582
7965
  __name(normaliseDateInput, "normaliseDateInput");
7966
+ function normaliseDayPoint(point) {
7967
+ const dayOffset = Math.floor(point.millisecond / MILLISECONDS_PER_DAY);
7968
+ return {
7969
+ dayNumber: point.dayNumber + dayOffset,
7970
+ millisecond: point.millisecond - dayOffset * MILLISECONDS_PER_DAY
7971
+ };
7972
+ }
7973
+ __name(normaliseDayPoint, "normaliseDayPoint");
7974
+ function getDayPoint(dmy) {
7975
+ return {
7976
+ dayNumber: dmy.getDaysSinceYearZero(),
7977
+ millisecond: dmy.getMillisecondsOfDay()
7978
+ };
7979
+ }
7980
+ __name(getDayPoint, "getDayPoint");
7981
+ function compareDayPoints(left, right) {
7982
+ if (left.dayNumber !== right.dayNumber) {
7983
+ return left.dayNumber < right.dayNumber ? -1 : 1;
7984
+ }
7985
+ if (left.millisecond !== right.millisecond) {
7986
+ return left.millisecond < right.millisecond ? -1 : 1;
7987
+ }
7988
+ return 0;
7989
+ }
7990
+ __name(compareDayPoints, "compareDayPoints");
7991
+ function getDayPointDifference(start, end) {
7992
+ const wholeDays = end.dayNumber - start.dayNumber;
7993
+ const milliseconds = end.millisecond - start.millisecond;
7994
+ return wholeDays + milliseconds / MILLISECONDS_PER_DAY;
7995
+ }
7996
+ __name(getDayPointDifference, "getDayPointDifference");
7997
+ function addDaysToDayPoint(point, days) {
7998
+ const wholeDays = Math.floor(days);
7999
+ return normaliseDayPoint({
8000
+ dayNumber: point.dayNumber + wholeDays,
8001
+ millisecond: point.millisecond + (days - wholeDays) * MILLISECONDS_PER_DAY
8002
+ });
8003
+ }
8004
+ __name(addDaysToDayPoint, "addDaysToDayPoint");
8005
+ function interpolateDayPoints(start, end, progress) {
8006
+ if (progress <= 0) {
8007
+ return __spreadValues({}, start);
8008
+ }
8009
+ if (progress >= 1) {
8010
+ return __spreadValues({}, end);
8011
+ }
8012
+ const scaledWholeDayDifference = (end.dayNumber - start.dayNumber) * progress;
8013
+ const wholeDays = Math.floor(scaledWholeDayDifference);
8014
+ const milliseconds = start.millisecond + (scaledWholeDayDifference - wholeDays) * MILLISECONDS_PER_DAY + (end.millisecond - start.millisecond) * progress;
8015
+ return normaliseDayPoint({
8016
+ dayNumber: start.dayNumber + wholeDays,
8017
+ millisecond: milliseconds
8018
+ });
8019
+ }
8020
+ __name(interpolateDayPoints, "interpolateDayPoints");
6583
8021
  function getNextYearStart(year) {
6584
8022
  return new Dmy(year === -1 ? 1 : year + 1, 1, 1);
6585
8023
  }
@@ -6593,18 +8031,20 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6593
8031
  __name(getNextMonthStart, "getNextMonthStart");
6594
8032
  function normaliseDateRangeInput(date) {
6595
8033
  const start = normaliseDateInput(date);
6596
- const hasMonth = date.month != null;
6597
- const hasDay = date.day != null;
6598
- if (!hasMonth) {
8034
+ const parsedString = typeof date === "string" ? parseDmyString(date) : null;
8035
+ const hasMonth = parsedString ? parsedString.hasMonth : date.month != null;
8036
+ const hasDay = parsedString ? parsedString.hasDay : date.day != null;
8037
+ const hasTime = parsedString ? parsedString.hasTime : date.hour != null || date.minute != null || date.second != null || date.millisecond != null;
8038
+ if (!hasMonth && !hasTime) {
6599
8039
  return {
6600
8040
  start,
6601
- end: getNextYearStart(date.year)
8041
+ end: getNextYearStart(start.year)
6602
8042
  };
6603
8043
  }
6604
- if (!hasDay) {
8044
+ if (!hasDay && !hasTime) {
6605
8045
  return {
6606
8046
  start,
6607
- end: getNextMonthStart(date.year, date.month)
8047
+ end: getNextMonthStart(start.year, start.month)
6608
8048
  };
6609
8049
  }
6610
8050
  return {
@@ -6639,24 +8079,29 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6639
8079
  }
6640
8080
  __name(normaliseZoomForManager, "normaliseZoomForManager");
6641
8081
  function getUnitFromZoom(manager, zoom) {
8082
+ if (typeof manager.getUnitFromZoom === "function") {
8083
+ return manager.getUnitFromZoom(zoom);
8084
+ }
6642
8085
  const unitLevels = manager.unitLevels;
6643
8086
  if (!Array.isArray(unitLevels) || unitLevels.length === 0) {
6644
8087
  return manager.unit;
6645
8088
  }
6646
- for (let i = unitLevels.length - 1; i >= 0; i--) {
6647
- if (zoom >= unitLevels[i].zoomStart) {
6648
- return i;
8089
+ const unitOrder = manager.unitOrder || unitLevels.map((_settings, unit) => unit);
8090
+ for (let i = unitOrder.length - 1; i >= 0; i--) {
8091
+ const unit = unitOrder[i];
8092
+ if (zoom >= unitLevels[unit].zoomStart) {
8093
+ return unit;
6649
8094
  }
6650
8095
  }
6651
8096
  return manager.unit;
6652
8097
  }
6653
8098
  __name(getUnitFromZoom, "getUnitFromZoom");
6654
8099
  function getUnitSizeInPixelsForZoom(manager, unit, zoom) {
6655
- var _a, _b;
8100
+ var _a, _b, _c, _d;
6656
8101
  const unitSettings = (_a = manager.unitLevels) == null ? void 0 : _a[unit];
6657
8102
  const zoomRatio = (_b = manager.zoomOptions) == null ? void 0 : _b.ratio;
6658
- if (unitSettings && Number.isFinite(unitSettings.startUnitSize) && Number.isFinite(unitSettings.zoomStart) && Number.isFinite(zoomRatio) && zoomRatio > 0) {
6659
- return unitSettings.startUnitSize * Math.pow(zoomRatio, zoom - unitSettings.zoomStart);
8103
+ if (unitSettings && Number.isFinite(unitSettings.startUnitSize) && Number.isFinite((_c = unitSettings.referenceZoom) != null ? _c : unitSettings.zoomStart) && Number.isFinite(zoomRatio) && zoomRatio > 0) {
8104
+ return unitSettings.startUnitSize * Math.pow(zoomRatio, zoom - ((_d = unitSettings.referenceZoom) != null ? _d : unitSettings.zoomStart));
6660
8105
  }
6661
8106
  if (!Number.isFinite(manager.unitSizeInPixels)) {
6662
8107
  return NaN;
@@ -6677,7 +8122,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6677
8122
  return NaN;
6678
8123
  }
6679
8124
  if (unit <= ZOOM_DAY) {
6680
- return startDate.getDaysTo(endDate) * unitSizeInPixels;
8125
+ return startDate.getDaysTo(endDate) * unitSizeInPixels / getZoomUnitLengthInDays(unit);
6681
8126
  }
6682
8127
  if (unit === ZOOM_MONTH) {
6683
8128
  return startDate.getMonthsTo(endDate) * unitSizeInPixels;
@@ -6685,23 +8130,23 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6685
8130
  return startDate.getYearsTo(endDate) * unitSizeInPixels / getUnitLengthInYears(unit);
6686
8131
  }
6687
8132
  __name(getPixelsBetweenAtZoom, "getPixelsBetweenAtZoom");
6688
- function getPixelsBetweenDayNumbersAtZoom(manager, startDayNumber, endDayNumber, zoom) {
8133
+ function getPixelsBetweenDayPointsAtZoom(manager, startPoint, endPoint, zoom) {
6689
8134
  const normalisedZoom = normaliseZoomForManager(manager, zoom);
6690
8135
  const unit = getUnitFromZoom(manager, normalisedZoom);
6691
8136
  const unitSizeInPixels = getUnitSizeInPixelsForZoom(manager, unit, normalisedZoom);
6692
8137
  if (!Number.isFinite(unitSizeInPixels) || unitSizeInPixels <= 0) {
6693
8138
  return NaN;
6694
8139
  }
6695
- const daySpan = endDayNumber - startDayNumber;
8140
+ const daySpan = getDayPointDifference(startPoint, endPoint);
6696
8141
  if (unit <= ZOOM_DAY) {
6697
- return daySpan * unitSizeInPixels;
8142
+ return daySpan * unitSizeInPixels / getZoomUnitLengthInDays(unit);
6698
8143
  }
6699
8144
  if (unit === ZOOM_MONTH) {
6700
8145
  return daySpan * unitSizeInPixels / 30.44;
6701
8146
  }
6702
8147
  return daySpan * unitSizeInPixels / (365.2422 * getUnitLengthInYears(unit));
6703
8148
  }
6704
- __name(getPixelsBetweenDayNumbersAtZoom, "getPixelsBetweenDayNumbersAtZoom");
8149
+ __name(getPixelsBetweenDayPointsAtZoom, "getPixelsBetweenDayPointsAtZoom");
6705
8150
  function getFitZoomForInternalDates(timeline, internalStart, internalEnd, padding) {
6706
8151
  const manager = timeline.timescaleManager;
6707
8152
  const currentPixelSpan = manager.getPixelsBetween(internalStart, internalEnd);
@@ -6749,14 +8194,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6749
8194
  if (date == null) {
6750
8195
  return null;
6751
8196
  }
6752
- const normalised = normaliseDateInput(typeof date === "string" ? Dmy.fromString(date) : date);
6753
- return timeline.getDmyFromInput(
6754
- new Dmy({
6755
- year: normalised.year,
6756
- month: normalised.month,
6757
- day: normalised.day
6758
- })
6759
- );
8197
+ return timeline.getDmyFromInput(normaliseDateInput(date));
6760
8198
  }
6761
8199
  __name(normaliseBoundDate, "normaliseBoundDate");
6762
8200
  function getTimelineDateBounds(timeline) {
@@ -6776,24 +8214,27 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6776
8214
  return {
6777
8215
  minDate,
6778
8216
  maxDate,
8217
+ minPoint: minDate ? getDayPoint(minDate) : null,
8218
+ maxPoint: maxDate ? getDayPoint(maxDate) : null,
6779
8219
  minDay: minDate ? getDayNumber(minDate) : null,
6780
8220
  maxDay: maxDate ? getDayNumber(maxDate) : null,
6781
8221
  overflow: bounds.overflow === "clamp" ? "clamp" : "elastic"
6782
8222
  };
6783
8223
  }
6784
8224
  __name(getTimelineDateBounds, "getTimelineDateBounds");
6785
- function getViewportDayRange(timeline) {
6786
- const start = getDayNumberAtPixel(timeline, 0);
6787
- const end = getDayNumberAtPixel(timeline, timeline.getWidth());
6788
- return start <= end ? { start, end } : { start: end, end: start };
8225
+ function getViewportDayPointRange(timeline) {
8226
+ const start = getDayPointAtPixel(timeline, 0);
8227
+ const end = getDayPointAtPixel(timeline, timeline.getWidth());
8228
+ return compareDayPoints(start, end) <= 0 ? { start, end } : { start: end, end: start };
6789
8229
  }
6790
- __name(getViewportDayRange, "getViewportDayRange");
8230
+ __name(getViewportDayPointRange, "getViewportDayPointRange");
6791
8231
  function getDateBoundSideCorrection(bounds, viewport, width) {
6792
- const minOverflow = bounds.minDay != null ? bounds.minDay - viewport.start : 0;
6793
- const maxOverflow = bounds.maxDay != null ? viewport.end - bounds.maxDay : 0;
8232
+ const minOverflow = bounds.minPoint ? getDayPointDifference(viewport.start, bounds.minPoint) : 0;
8233
+ const maxOverflow = bounds.maxPoint ? getDayPointDifference(bounds.maxPoint, viewport.end) : 0;
6794
8234
  if (minOverflow > 0 && minOverflow >= maxOverflow) {
6795
8235
  return {
6796
8236
  type: "min",
8237
+ dayPoint: bounds.minPoint,
6797
8238
  dayNumber: bounds.minDay,
6798
8239
  pixelOffset: 0,
6799
8240
  overflowDays: minOverflow
@@ -6802,6 +8243,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6802
8243
  if (maxOverflow > 0) {
6803
8244
  return {
6804
8245
  type: "max",
8246
+ dayPoint: bounds.maxPoint,
6805
8247
  dayNumber: bounds.maxDay,
6806
8248
  pixelOffset: width,
6807
8249
  overflowDays: maxOverflow
@@ -6814,22 +8256,23 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6814
8256
  if (!bounds) {
6815
8257
  return null;
6816
8258
  }
6817
- const viewport = getViewportDayRange(timeline);
8259
+ const viewport = getViewportDayPointRange(timeline);
6818
8260
  const width = timeline.getWidth();
6819
8261
  const sideCorrection = getDateBoundSideCorrection(bounds, viewport, width);
6820
8262
  if (options.mode === "elastic" && bounds.overflow === "elastic" && sideCorrection) {
6821
8263
  return sideCorrection;
6822
8264
  }
6823
- if (bounds.minDay != null && bounds.maxDay != null && viewport.end - viewport.start > bounds.maxDay - bounds.minDay) {
8265
+ if (bounds.minPoint && bounds.maxPoint && getDayPointDifference(viewport.start, viewport.end) > getDayPointDifference(bounds.minPoint, bounds.maxPoint)) {
6824
8266
  return {
6825
8267
  type: "range",
6826
- zoom: getFitZoomForDayNumbers(
8268
+ zoom: getFitZoomForDayPoints(
6827
8269
  timeline,
6828
- bounds.minDay,
6829
- bounds.maxDay,
8270
+ bounds.minPoint,
8271
+ bounds.maxPoint,
6830
8272
  { left: 0, right: 0 },
6831
8273
  timeline.timescaleManager.zoom
6832
8274
  ),
8275
+ dayPoint: bounds.minPoint,
6833
8276
  dayNumber: bounds.minDay,
6834
8277
  pixelOffset: 0
6835
8278
  };
@@ -6849,22 +8292,44 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6849
8292
  return resistedPixels / pixelsPerDay;
6850
8293
  }
6851
8294
  __name(getElasticOverflowDays, "getElasticOverflowDays");
6852
- function setElasticBoundedViewportStartDay(timeline, targetStartDayNumber, viewportSpanDays) {
8295
+ function getUnresistedElasticOverflowDays(timeline, overflowDays) {
8296
+ const pixelsPerDay = getPixelsPerDay(timeline);
8297
+ if (!pixelsPerDay || !Number.isFinite(overflowDays) || overflowDays <= 0) {
8298
+ return 0;
8299
+ }
8300
+ const width = Math.max(1, timeline.getWidth());
8301
+ const maxElasticPixels = Math.max(32, width * 0.22);
8302
+ const resistedPixels = overflowDays * pixelsPerDay;
8303
+ if (resistedPixels >= maxElasticPixels) {
8304
+ return Number.MAX_SAFE_INTEGER / pixelsPerDay;
8305
+ }
8306
+ return maxElasticPixels * resistedPixels / (maxElasticPixels - resistedPixels) / pixelsPerDay;
8307
+ }
8308
+ __name(getUnresistedElasticOverflowDays, "getUnresistedElasticOverflowDays");
8309
+ function setElasticBoundedViewportStartPoint(timeline, targetStartPoint, viewportSpanDays) {
6853
8310
  const bounds = getTimelineDateBounds(timeline);
6854
- let nextStartDayNumber = targetStartDayNumber;
8311
+ let nextStartPoint = targetStartPoint;
6855
8312
  if ((bounds == null ? void 0 : bounds.overflow) === "elastic" && Number.isFinite(viewportSpanDays)) {
6856
- const targetEndDayNumber = targetStartDayNumber + viewportSpanDays;
6857
- if (bounds.minDay != null && targetStartDayNumber < bounds.minDay) {
6858
- nextStartDayNumber = bounds.minDay - getElasticOverflowDays(timeline, bounds.minDay - targetStartDayNumber);
6859
- } else if (bounds.maxDay != null && targetEndDayNumber > bounds.maxDay) {
6860
- nextStartDayNumber = bounds.maxDay + getElasticOverflowDays(timeline, targetEndDayNumber - bounds.maxDay) - viewportSpanDays;
8313
+ const targetEndPoint = addDaysToDayPoint(targetStartPoint, viewportSpanDays);
8314
+ if (bounds.minPoint && compareDayPoints(targetStartPoint, bounds.minPoint) < 0) {
8315
+ const overflow = getDayPointDifference(targetStartPoint, bounds.minPoint);
8316
+ nextStartPoint = addDaysToDayPoint(
8317
+ bounds.minPoint,
8318
+ -getElasticOverflowDays(timeline, overflow)
8319
+ );
8320
+ } else if (bounds.maxPoint && compareDayPoints(targetEndPoint, bounds.maxPoint) > 0) {
8321
+ const overflow = getDayPointDifference(bounds.maxPoint, targetEndPoint);
8322
+ nextStartPoint = addDaysToDayPoint(
8323
+ bounds.maxPoint,
8324
+ getElasticOverflowDays(timeline, overflow) - viewportSpanDays
8325
+ );
6861
8326
  }
6862
8327
  }
6863
- setInternalStartDayNumber(timeline, nextStartDayNumber, 0, false, {
8328
+ setInternalStartDayPoint(timeline, nextStartPoint, 0, false, {
6864
8329
  skipDateBounds: true
6865
8330
  });
6866
8331
  }
6867
- __name(setElasticBoundedViewportStartDay, "setElasticBoundedViewportStartDay");
8332
+ __name(setElasticBoundedViewportStartPoint, "setElasticBoundedViewportStartPoint");
6868
8333
  function applyTimelineDateBounds(timeline, options = {}) {
6869
8334
  const bounds = getTimelineDateBounds(timeline);
6870
8335
  if (!bounds) {
@@ -6879,7 +8344,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6879
8344
  if (correction.zoom !== timeline.timescaleManager.zoom) {
6880
8345
  timeline.timescaleManager.setZoom(correction.zoom);
6881
8346
  }
6882
- setInternalStartDayNumber(timeline, correction.dayNumber, correction.pixelOffset, false, {
8347
+ setInternalStartDayPoint(timeline, correction.dayPoint, correction.pixelOffset, false, {
6883
8348
  skipDateBounds: true
6884
8349
  });
6885
8350
  return true;
@@ -6887,13 +8352,17 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6887
8352
  if (mode === "elastic" && bounds.overflow === "elastic") {
6888
8353
  const elasticOverflowDays = getElasticOverflowDays(timeline, correction.overflowDays);
6889
8354
  if (correction.type === "min") {
6890
- setInternalStartDayNumber(timeline, correction.dayNumber - elasticOverflowDays, 0, false, {
6891
- skipDateBounds: true
6892
- });
8355
+ setInternalStartDayPoint(
8356
+ timeline,
8357
+ addDaysToDayPoint(correction.dayPoint, -elasticOverflowDays),
8358
+ 0,
8359
+ false,
8360
+ { skipDateBounds: true }
8361
+ );
6893
8362
  } else {
6894
- setInternalStartDayNumber(
8363
+ setInternalStartDayPoint(
6895
8364
  timeline,
6896
- correction.dayNumber + elasticOverflowDays,
8365
+ addDaysToDayPoint(correction.dayPoint, elasticOverflowDays),
6897
8366
  correction.pixelOffset,
6898
8367
  false,
6899
8368
  { skipDateBounds: true }
@@ -6901,7 +8370,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6901
8370
  }
6902
8371
  return true;
6903
8372
  }
6904
- setInternalStartDayNumber(timeline, correction.dayNumber, correction.pixelOffset, false, {
8373
+ setInternalStartDayPoint(timeline, correction.dayPoint, correction.pixelOffset, false, {
6905
8374
  skipDateBounds: true
6906
8375
  });
6907
8376
  return true;
@@ -6912,13 +8381,14 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6912
8381
  }
6913
8382
  __name(isViewportOutsideDateBounds, "isViewportOutsideDateBounds");
6914
8383
  function getPixelsPerDay(timeline) {
8384
+ var _a;
6915
8385
  const manager = timeline.timescaleManager;
6916
8386
  const unitSize = manager.unitSizeInPixels;
6917
8387
  if (!Number.isFinite(unitSize) || unitSize <= 0) {
6918
8388
  return 0;
6919
8389
  }
6920
8390
  if (manager.unit == null || manager.unit <= ZOOM_DAY) {
6921
- return unitSize;
8391
+ return unitSize / getZoomUnitLengthInDays((_a = manager.unit) != null ? _a : ZOOM_DAY);
6922
8392
  }
6923
8393
  if (manager.unit === ZOOM_MONTH) {
6924
8394
  return unitSize / 30.44;
@@ -6927,11 +8397,13 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6927
8397
  return unitSize / (365.2422 * unitLengthInYears);
6928
8398
  }
6929
8399
  __name(getPixelsPerDay, "getPixelsPerDay");
6930
- function setInternalStartDayNumber(timeline, dayNumber, pixelOffset, emitStateChange = false, options = {}) {
8400
+ function setInternalStartDayPoint(timeline, dayPoint, pixelOffset, emitStateChange = false, options = {}) {
6931
8401
  var _a;
6932
- const startDayNumber = Math.floor(dayNumber);
6933
- const startDmy = getDmyFromDayNumber(startDayNumber);
6934
- const partialDayPixels = (dayNumber - startDayNumber) * getPixelsPerDay(timeline);
8402
+ const normalisedPoint = normaliseDayPoint(dayPoint);
8403
+ const milliseconds = Math.floor(normalisedPoint.millisecond);
8404
+ const millisecondFraction = normalisedPoint.millisecond - milliseconds;
8405
+ const startDmy = getDmyFromDayNumber(normalisedPoint.dayNumber).addMilliseconds(milliseconds);
8406
+ const partialDayPixels = millisecondFraction * getPixelsPerDay(timeline) / MILLISECONDS_PER_DAY;
6935
8407
  const dateFraction = timeline.timescaleManager.setStartDate(startDmy);
6936
8408
  timeline.repositionWindow = dateFraction - partialDayPixels;
6937
8409
  if (pixelOffset) {
@@ -6946,26 +8418,26 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6946
8418
  timeline._emitTimelineStateChange();
6947
8419
  }
6948
8420
  }
6949
- __name(setInternalStartDayNumber, "setInternalStartDayNumber");
8421
+ __name(setInternalStartDayPoint, "setInternalStartDayPoint");
6950
8422
  function setInternalStartDate(timeline, dmy, pixelOffset, emitStateChange = false, options = {}) {
6951
- const dayNumber = getDayNumber(dmy);
6952
- setInternalStartDayNumber(timeline, dayNumber, pixelOffset, emitStateChange, options);
8423
+ setInternalStartDayPoint(timeline, getDayPoint(dmy), pixelOffset, emitStateChange, options);
6953
8424
  }
6954
8425
  __name(setInternalStartDate, "setInternalStartDate");
6955
- function getDayNumberFromPivotPoint(timeline, pivotPoint) {
8426
+ function getDayPointFromPivotPoint(timeline, pivotPoint) {
6956
8427
  const pixelsPerDay = getPixelsPerDay(timeline);
8428
+ const point = getDayPoint(pivotPoint.date);
6957
8429
  if (!pixelsPerDay) {
6958
- return getDayNumber(pivotPoint.date);
8430
+ return point;
6959
8431
  }
6960
- return getDayNumber(pivotPoint.date) + pivotPoint.fraction / pixelsPerDay;
8432
+ return addDaysToDayPoint(point, pivotPoint.fraction / pixelsPerDay);
6961
8433
  }
6962
- __name(getDayNumberFromPivotPoint, "getDayNumberFromPivotPoint");
6963
- function getDayNumberAtPixel(timeline, pixel) {
6964
- return getDayNumberFromPivotPoint(timeline, timeline.getPivotPoint(pixel));
8434
+ __name(getDayPointFromPivotPoint, "getDayPointFromPivotPoint");
8435
+ function getDayPointAtPixel(timeline, pixel) {
8436
+ return getDayPointFromPivotPoint(timeline, timeline.getPivotPoint(pixel));
6965
8437
  }
6966
- __name(getDayNumberAtPixel, "getDayNumberAtPixel");
8438
+ __name(getDayPointAtPixel, "getDayPointAtPixel");
6967
8439
  function getDayNumber(dmy) {
6968
- return dmy.getDaysSinceYearZero();
8440
+ return dmy.getDaysSinceYearZero() + dmy.getMillisecondsOfDay() / MILLISECONDS_PER_DAY;
6969
8441
  }
6970
8442
  __name(getDayNumber, "getDayNumber");
6971
8443
  function getDmyFromDayNumber(dayNumber) {
@@ -6990,12 +8462,12 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6990
8462
  return start + (end - start) * progress;
6991
8463
  }
6992
8464
  __name(interpolate, "interpolate");
6993
- function getFitZoomForDayNumbers(timeline, startDayNumber, endDayNumber, padding, fallbackZoom) {
6994
- if (endDayNumber <= startDayNumber) {
8465
+ function getFitZoomForDayPoints(timeline, startPoint, endPoint, padding, fallbackZoom) {
8466
+ if (compareDayPoints(endPoint, startPoint) <= 0) {
6995
8467
  return fallbackZoom;
6996
8468
  }
6997
8469
  const manager = timeline.timescaleManager;
6998
- const currentPixelSpan = (endDayNumber - startDayNumber) * getPixelsPerDay(timeline);
8470
+ const currentPixelSpan = getDayPointDifference(startPoint, endPoint) * getPixelsPerDay(timeline);
6999
8471
  if (!Number.isFinite(currentPixelSpan) || currentPixelSpan <= 0) {
7000
8472
  return fallbackZoom;
7001
8473
  }
@@ -7006,10 +8478,10 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7006
8478
  }
7007
8479
  let targetZoom = manager.zoom + zoomChange;
7008
8480
  for (let i = 0; i < 4; i++) {
7009
- const predictedPixelSpan = getPixelsBetweenDayNumbersAtZoom(
8481
+ const predictedPixelSpan = getPixelsBetweenDayPointsAtZoom(
7010
8482
  manager,
7011
- startDayNumber,
7012
- endDayNumber,
8483
+ startPoint,
8484
+ endPoint,
7013
8485
  targetZoom
7014
8486
  );
7015
8487
  if (!Number.isFinite(predictedPixelSpan) || predictedPixelSpan <= 0) {
@@ -7026,7 +8498,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7026
8498
  }
7027
8499
  return normaliseZoomForManager(manager, targetZoom);
7028
8500
  }
7029
- __name(getFitZoomForDayNumbers, "getFitZoomForDayNumbers");
8501
+ __name(getFitZoomForDayPoints, "getFitZoomForDayPoints");
7030
8502
  function stopNavigationAnimations(timeline) {
7031
8503
  var _a, _b, _c, _d, _e;
7032
8504
  if (typeof timeline.stopPanAnimation === "function") {
@@ -7065,13 +8537,13 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7065
8537
  timeline.startAnimation();
7066
8538
  const startZoom = timeline.timescaleManager.zoom;
7067
8539
  const fitPixelSpan = getFitPixelSpan(timeline, padding);
7068
- const startDayNumberAtPadding = getDayNumberAtPixel(timeline, padding.left);
7069
- const startEndDayNumberAtPadding = getDayNumberAtPixel(timeline, padding.left + fitPixelSpan);
8540
+ const startPointAtPadding = getDayPointAtPixel(timeline, padding.left);
8541
+ const startEndPointAtPadding = getDayPointAtPixel(timeline, padding.left + fitPixelSpan);
7070
8542
  const targetInternalStart = timeline.getDmyFromInput(normaliseDateInput(targetStartDate));
7071
8543
  const targetInternalEnd = timeline.getDmyFromInput(normaliseDateInput(targetEndDate));
7072
- const targetDayNumber = getDayNumber(targetInternalStart);
7073
- const targetEndDayNumber = getDayNumber(targetInternalEnd);
7074
- const canInterpolateBoundaries = startEndDayNumberAtPadding > startDayNumberAtPadding && targetEndDayNumber > targetDayNumber;
8544
+ const targetPoint = getDayPoint(targetInternalStart);
8545
+ const targetEndPoint = getDayPoint(targetInternalEnd);
8546
+ const canInterpolateBoundaries = compareDayPoints(startEndPointAtPadding, startPointAtPadding) > 0 && compareDayPoints(targetEndPoint, targetPoint) > 0;
7075
8547
  const rangeTween = tween({
7076
8548
  from: 0,
7077
8549
  to: 1,
@@ -7083,13 +8555,13 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7083
8555
  rangeTween.stop();
7084
8556
  return;
7085
8557
  }
7086
- const nextDayNumber = interpolate(startDayNumberAtPadding, targetDayNumber, progress);
8558
+ const nextPoint = interpolateDayPoints(startPointAtPadding, targetPoint, progress);
7087
8559
  let nextZoom = startZoom;
7088
8560
  if (progress > 0) {
7089
- nextZoom = canInterpolateBoundaries ? getFitZoomForDayNumbers(
8561
+ nextZoom = canInterpolateBoundaries ? getFitZoomForDayPoints(
7090
8562
  timeline,
7091
- nextDayNumber,
7092
- interpolate(startEndDayNumberAtPadding, targetEndDayNumber, progress),
8563
+ nextPoint,
8564
+ interpolateDayPoints(startEndPointAtPadding, targetEndPoint, progress),
7093
8565
  padding,
7094
8566
  timeline.timescaleManager.zoom
7095
8567
  ) : interpolate(startZoom, targetZoom, progress);
@@ -7097,7 +8569,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7097
8569
  if (nextZoom !== timeline.timescaleManager.zoom) {
7098
8570
  timeline.timescaleManager.setZoom(nextZoom);
7099
8571
  }
7100
- setInternalStartDayNumber(timeline, nextDayNumber, padding.left);
8572
+ setInternalStartDayPoint(timeline, nextPoint, padding.left);
7101
8573
  },
7102
8574
  onComplete() {
7103
8575
  if (targetZoom !== timeline.timescaleManager.zoom) {
@@ -7129,7 +8601,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7129
8601
  if (!latest || from.compare(latest) > 0) {
7130
8602
  latest = from;
7131
8603
  }
7132
- const style = article._getCurrentStyle();
8604
+ const style = article.getCurrentStyle();
7133
8605
  const connectorOffset = (_c = (_b = style.connectorLine) == null ? void 0 : _b.offsetX) != null ? _c : 0;
7134
8606
  const width = (_d = style.width) != null ? _d : 0;
7135
8607
  maxCardLeftOffset = Math.max(maxCardLeftOffset, connectorOffset);
@@ -7488,10 +8960,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7488
8960
  function onPointerEnd(evt, tracker) {
7489
8961
  var _a, _b, _c;
7490
8962
  if (me.isPinching && tracker.list.length < 2) {
7491
- if (tracker.list.length === 1) {
7492
- const primary = getPrimary(tracker);
7493
- me.dragStartX = primary.x;
7494
- }
8963
+ const remainingPointer = tracker.list.length === 1 ? getPrimary(tracker) : null;
7495
8964
  const endScale = pinch.scale || 1;
7496
8965
  const actualEndZoom = me.timescaleManager.zoom;
7497
8966
  const endTotalZoomDelta = actualEndZoom - pinch.initial.zoom;
@@ -7513,9 +8982,18 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7513
8982
  }),
7514
8983
  evt
7515
8984
  );
7516
- (_a = me.settleDateBounds) == null ? void 0 : _a.call(me);
7517
- if (!me.isPanning) {
7518
- (_b = me._flushTimelineStateChange) == null ? void 0 : _b.call(me);
8985
+ if (remainingPointer) {
8986
+ if (me.isDragging) {
8987
+ me.resetDragTracking(remainingPointer);
8988
+ }
8989
+ } else if (me.isDragging) {
8990
+ me.resetDragTracking(getPoint(evt));
8991
+ me.endDragging(evt);
8992
+ } else {
8993
+ (_a = me.settleDateBounds) == null ? void 0 : _a.call(me);
8994
+ if (!me.isPanning) {
8995
+ (_b = me._flushTimelineStateChange) == null ? void 0 : _b.call(me);
8996
+ }
7519
8997
  }
7520
8998
  return;
7521
8999
  }
@@ -7578,31 +9056,51 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7578
9056
  (_b = this.stopZoomAnimation) == null ? void 0 : _b.call(this);
7579
9057
  this.isDragging = true;
7580
9058
  const page = getPoint(evt);
9059
+ Timeline.prototype.resetDragTracking.call(this, page);
9060
+ this.trigger(
9061
+ "viewport-drag-start",
9062
+ makeViewportDragPayload({
9063
+ startToken: this.timescaleManager.startToken,
9064
+ offsetX: this.repositionWindow
9065
+ }),
9066
+ evt
9067
+ );
9068
+ }, "startDragging");
9069
+ Timeline.prototype.resetDragTracking = /* @__PURE__ */ __name(function resetDragTracking(page) {
7581
9070
  this.dragOrigin = { left: page.x, top: page.y };
7582
9071
  this.dragStartX = page.x;
7583
9072
  this.dragStartY = page.y;
7584
9073
  this.dragMomentumSamples = [{ time: Date.now(), x: page.x }];
7585
9074
  this.dragDateBoundsState = null;
7586
9075
  const bounds = getTimelineDateBounds(this);
7587
- const pixelsPerDay = getPixelsPerDay(this);
7588
- if ((bounds == null ? void 0 : bounds.overflow) === "elastic" && pixelsPerDay) {
7589
- const leftDayNumber = getDayNumberAtPixel(this, 0);
7590
- const rightDayNumber = getDayNumberAtPixel(this, this.getWidth());
9076
+ if ((bounds == null ? void 0 : bounds.overflow) === "elastic") {
9077
+ const pixelsPerDay = getPixelsPerDay(this);
9078
+ if (!pixelsPerDay) {
9079
+ return;
9080
+ }
9081
+ const viewport = getViewportDayPointRange(this);
9082
+ const viewportSpanDays = getDayPointDifference(viewport.start, viewport.end);
9083
+ let leftDayPoint = viewport.start;
9084
+ if (bounds.minPoint && compareDayPoints(viewport.start, bounds.minPoint) < 0) {
9085
+ const overflow = getDayPointDifference(viewport.start, bounds.minPoint);
9086
+ leftDayPoint = addDaysToDayPoint(
9087
+ bounds.minPoint,
9088
+ -getUnresistedElasticOverflowDays(this, overflow)
9089
+ );
9090
+ } else if (bounds.maxPoint && compareDayPoints(viewport.end, bounds.maxPoint) > 0) {
9091
+ const overflow = getDayPointDifference(bounds.maxPoint, viewport.end);
9092
+ leftDayPoint = addDaysToDayPoint(
9093
+ bounds.maxPoint,
9094
+ getUnresistedElasticOverflowDays(this, overflow) - viewportSpanDays
9095
+ );
9096
+ }
7591
9097
  this.dragDateBoundsState = {
7592
- leftDayNumber,
9098
+ leftDayPoint,
7593
9099
  pixelsPerDay,
7594
- viewportSpanDays: rightDayNumber - leftDayNumber
9100
+ viewportSpanDays
7595
9101
  };
7596
9102
  }
7597
- this.trigger(
7598
- "viewport-drag-start",
7599
- makeViewportDragPayload({
7600
- startToken: this.timescaleManager.startToken,
7601
- offsetX: this.repositionWindow
7602
- }),
7603
- evt
7604
- );
7605
- }, "startDragging");
9103
+ }, "resetDragTracking");
7606
9104
  Timeline.prototype.endDragging = /* @__PURE__ */ __name(function endDragging(evt) {
7607
9105
  var _a, _b, _c;
7608
9106
  this.isDragging = false;
@@ -7649,10 +9147,13 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7649
9147
  this.animation.dragRedrawFunction = this.defaultRedraw;
7650
9148
  }
7651
9149
  if (this.dragDateBoundsState) {
7652
- const targetLeftDayNumber = this.dragDateBoundsState.leftDayNumber + cumulativeMovePixelsX / this.dragDateBoundsState.pixelsPerDay;
7653
- setElasticBoundedViewportStartDay(
9150
+ const targetLeftDayPoint = addDaysToDayPoint(
9151
+ this.dragDateBoundsState.leftDayPoint,
9152
+ cumulativeMovePixelsX / this.dragDateBoundsState.pixelsPerDay
9153
+ );
9154
+ setElasticBoundedViewportStartPoint(
7654
9155
  this,
7655
- targetLeftDayNumber,
9156
+ targetLeftDayPoint,
7656
9157
  this.dragDateBoundsState.viewportSpanDays
7657
9158
  );
7658
9159
  } else {
@@ -7841,20 +9342,27 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7841
9342
  }
7842
9343
  };
7843
9344
  Timeline.prototype.getDmyFromInput = function(dmy) {
7844
- var _a, _b, _c;
9345
+ var _a, _b, _c, _d, _e, _f, _g;
7845
9346
  let normalised;
7846
9347
  if (typeof dmy === "string") {
7847
9348
  normalised = Dmy.fromString(dmy);
9349
+ if (!Number.isFinite(normalised.year)) {
9350
+ throw new Error(`Invalid Histropedia date string: ${dmy}`);
9351
+ }
7848
9352
  } else if (dmy instanceof Dmy) {
7849
9353
  normalised = new Dmy(dmy);
7850
9354
  } else {
7851
9355
  normalised = new Dmy({
7852
9356
  year: dmy.year,
7853
9357
  month: (_a = dmy.month) != null ? _a : 1,
7854
- day: (_b = dmy.day) != null ? _b : 1
9358
+ day: (_b = dmy.day) != null ? _b : 1,
9359
+ hour: (_c = dmy.hour) != null ? _c : 0,
9360
+ minute: (_d = dmy.minute) != null ? _d : 0,
9361
+ second: (_e = dmy.second) != null ? _e : 0,
9362
+ millisecond: (_f = dmy.millisecond) != null ? _f : 0
7855
9363
  });
7856
9364
  }
7857
- if (!((_c = this.options) == null ? void 0 : _c.shiftBceDates)) {
9365
+ if (!((_g = this.options) == null ? void 0 : _g.shiftBceDates)) {
7858
9366
  return normalised;
7859
9367
  }
7860
9368
  if (normalised.year < 0) {
@@ -7925,7 +9433,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7925
9433
  article = this.articles[i];
7926
9434
  }
7927
9435
  }
7928
- return !isUndefined$1(article);
9436
+ return !isUndefined(article);
7929
9437
  };
7930
9438
  Timeline.prototype.reposition = function(article, drawCycleContext) {
7931
9439
  if (article.isDragging) {
@@ -7969,7 +9477,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7969
9477
  from = 0;
7970
9478
  }
7971
9479
  }
7972
- const style = article._getCurrentStyle();
9480
+ const style = article.getCurrentStyle();
7973
9481
  const lane = this.getLaneById(article.laneId);
7974
9482
  if (this._isLaneLayoutActive() && lane && lane.geometry) {
7975
9483
  return {
@@ -8338,6 +9846,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8338
9846
  };
8339
9847
  }
8340
9848
  __name(resolveAreaExtents, "resolveAreaExtents");
9849
+ const MAIN_RANGE_RIGHT_BUFFER = 150;
8341
9850
  Timeline.prototype.defaultRedraw = function() {
8342
9851
  this.redraw({
8343
9852
  // 1. update isVisibleInGroup and after articles IsInRange is decided
@@ -8443,7 +9952,6 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8443
9952
  });
8444
9953
  };
8445
9954
  Timeline.prototype.render = function(ctx, top, width, markers, drawCycleContext) {
8446
- const halfMainlineSize = this.options.style.mainLine.size >> 1;
8447
9955
  const effectiveVerticalOffset = this._getEffectiveVerticalOffset ? this._getEffectiveVerticalOffset() : this.options.verticalOffset;
8448
9956
  if (!this.owner) {
8449
9957
  ctx.clearRect(0, 0, width, this.top + effectiveVerticalOffset);
@@ -8455,19 +9963,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8455
9963
  this.drawDraggingHighlight(ctx, top, width);
8456
9964
  const mainLineTop = this.options.style.mainLine.position === "top" ? -effectiveVerticalOffset : top;
8457
9965
  this.drawMainline(ctx, mainLineTop, width, markers);
8458
- if (this.options.style.mainLine.showDateIndicators) {
8459
- ctx.beginPath();
8460
- this.forInRangeArticles(/* @__PURE__ */ __name(function redraw_articles_drawIndicators(article) {
8461
- if (!article.isHiddenByFilter && article.isInView) {
8462
- ctx.moveTo(article.indicator.fromX, top - halfMainlineSize);
8463
- ctx.lineTo(article.indicator.fromX, top + halfMainlineSize);
8464
- }
8465
- }, "redraw_articles_drawIndicators"));
8466
- ctx.lineWidth = 3;
8467
- ctx.globalAlpha = 0.75;
8468
- ctx.strokeStyle = "#303030";
8469
- ctx.stroke();
8470
- }
9966
+ this.drawDateIndicators(ctx, mainLineTop);
8471
9967
  ctx.globalAlpha = 1;
8472
9968
  for (let i = 0; i < this.articles.length; i++) {
8473
9969
  const article = this.articles[i];
@@ -8498,7 +9994,55 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8498
9994
  this.drawDensityRegionBoundaries(ctx, width, drawCycleContext);
8499
9995
  }
8500
9996
  };
9997
+ function resolveDateIndicatorColor(timeline, article, color, useActiveArticleColor) {
9998
+ var _a, _b, _c;
9999
+ if (color !== "article") {
10000
+ return color;
10001
+ }
10002
+ if (useActiveArticleColor) {
10003
+ return ((_a = article.activeStyle) == null ? void 0 : _a.color) || ((_b = article.style) == null ? void 0 : _b.color) || timeline.options.article.defaultStyle.color;
10004
+ }
10005
+ return ((_c = article.style) == null ? void 0 : _c.color) || timeline.options.article.defaultStyle.color;
10006
+ }
10007
+ __name(resolveDateIndicatorColor, "resolveDateIndicatorColor");
10008
+ Timeline.prototype.drawDateIndicators = function(ctx, top) {
10009
+ const dateIndicators = this.options.style.mainLine.dateIndicators;
10010
+ if (!dateIndicators.visible) {
10011
+ return;
10012
+ }
10013
+ const mainLineSize = this.options.style.mainLine.size;
10014
+ const halfMainLineSize = mainLineSize / 2;
10015
+ ctx.save();
10016
+ ctx.globalAlpha = 1;
10017
+ this.forInRangeArticles(/* @__PURE__ */ __name(function redraw_articles_drawIndicators(article) {
10018
+ var _a;
10019
+ if (article.isHiddenByFilter || !article.isInView) {
10020
+ return;
10021
+ }
10022
+ const isActive = article.isActive === true;
10023
+ const isDensityHidden = !isActive && article.isVisibleInLane !== false && article.isVisibleInGroup === false;
10024
+ const stateStyle = isActive ? dateIndicators.activeStyle : isDensityHidden ? dateIndicators.hiddenStyle : null;
10025
+ const style = stateStyle ? __spreadValues(__spreadValues({}, dateIndicators), stateStyle) : dateIndicators;
10026
+ const size = style.size;
10027
+ const halfSize = size / 2;
10028
+ const x = article.indicator.fromX;
10029
+ const useActiveArticleColor = isActive && (stateStyle == null ? void 0 : stateStyle.color) === "article";
10030
+ ctx.globalAlpha = (_a = style.opacity) != null ? _a : 1;
10031
+ ctx.fillStyle = resolveDateIndicatorColor(this, article, style.color, useActiveArticleColor);
10032
+ if (style.shape === "circle") {
10033
+ ctx.beginPath();
10034
+ ctx.arc(x, top, halfSize, 0, Math.PI * 2);
10035
+ ctx.fill();
10036
+ return;
10037
+ }
10038
+ ctx.fillRect(x - halfSize, top - halfMainLineSize, size, mainLineSize);
10039
+ }, "redraw_articles_drawIndicators"));
10040
+ ctx.restore();
10041
+ };
8501
10042
  Timeline.prototype.getDensityRegionBoundaryDate = function(groupIndex) {
10043
+ if (isSubdayDensityGroupIndex(groupIndex)) {
10044
+ return getDmyFromDayNumber(groupIndex.day);
10045
+ }
8502
10046
  const step = this.currentDensitySetting.step;
8503
10047
  if (this.timescaleManager.unit >= ZOOM_MONTH && step.months !== 0) {
8504
10048
  const monthIndex = groupIndex * step.months;
@@ -8523,15 +10067,29 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8523
10067
  }
8524
10068
  return boundary;
8525
10069
  };
10070
+ Timeline.prototype.getDensityRegionBoundaryPoint = function(groupIndex) {
10071
+ if (isSubdayDensityGroupIndex(groupIndex)) {
10072
+ const boundary = getSubdayDensityGroupBoundary(groupIndex);
10073
+ return {
10074
+ date: getDmyFromDayNumber(boundary.dayNumber),
10075
+ dayFraction: boundary.dayFraction
10076
+ };
10077
+ }
10078
+ return {
10079
+ date: this.getDensityRegionBoundaryDate(groupIndex),
10080
+ dayFraction: 0
10081
+ };
10082
+ };
8526
10083
  Timeline.prototype.drawDensityRegionBoundaries = function(ctx, width, drawCycleContext) {
8527
10084
  var _a;
8528
10085
  const tokens = drawCycleContext == null ? void 0 : drawCycleContext.tokens;
8529
10086
  if (!(tokens == null ? void 0 : tokens.start) || !(tokens == null ? void 0 : tokens.end) || !((_a = this.currentDensitySetting) == null ? void 0 : _a.step)) {
8530
10087
  return;
8531
10088
  }
8532
- const firstGroup = this.calculateGroupIndex(tokens.start) - 1;
8533
- const lastGroup = this.calculateGroupIndex(tokens.end) + 1;
10089
+ const firstGroup = shiftDensityGroupIndex(this.calculateGroupIndex(tokens.start), -1);
10090
+ const lastGroup = shiftDensityGroupIndex(this.calculateGroupIndex(tokens.end), 1);
8534
10091
  const startDate = this.timescaleManager.startToken.value;
10092
+ const pixelsPerDay = getPixelsPerDay(this);
8535
10093
  const height = this.options.height;
8536
10094
  let previousX = null;
8537
10095
  ctx.save();
@@ -8540,9 +10098,9 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8540
10098
  ctx.lineWidth = 1;
8541
10099
  ctx.strokeStyle = "rgba(204, 0, 153, 0.8)";
8542
10100
  ctx.setLineDash([4, 4]);
8543
- for (let groupIndex = firstGroup; groupIndex <= lastGroup; groupIndex++) {
8544
- const boundary = this.getDensityRegionBoundaryDate(groupIndex);
8545
- const rawX = this.timescaleManager.getPixelsBetween(startDate, boundary) + this.repositionWindow;
10101
+ for (let groupIndex = firstGroup; compareDensityGroupIndexes(groupIndex, lastGroup) <= 0; groupIndex = shiftDensityGroupIndex(groupIndex, 1)) {
10102
+ const boundary = this.getDensityRegionBoundaryPoint(groupIndex);
10103
+ const rawX = this.timescaleManager.getPixelsBetween(startDate, boundary.date) + boundary.dayFraction * pixelsPerDay + this.repositionWindow;
8546
10104
  const x = Math.round(rawX) + 0.5;
8547
10105
  if (x < 0 || x > width || x === previousX) {
8548
10106
  continue;
@@ -8558,23 +10116,26 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8558
10116
  if (this.options.style.mainLine.visible) {
8559
10117
  ctx.globalAlpha = 1;
8560
10118
  const halfMainlineSize = this.options.style.mainLine.size >> 1;
8561
- const mainLineGradient = ctx.createLinearGradient(
8562
- 0,
8563
- top - halfMainlineSize,
8564
- 0,
8565
- top + halfMainlineSize
8566
- );
8567
- mainLineGradient.addColorStop(0, "#808080");
8568
- mainLineGradient.addColorStop(1, "#ccc");
10119
+ const color = this.options.style.mainLine.color;
10120
+ let fillStyle = typeof color === "string" ? color : DEFAULT_MAIN_LINE_COLOR;
10121
+ if ((color == null ? void 0 : color.type) === "gradient" && typeof color.topColor === "string" && typeof color.bottomColor === "string") {
10122
+ fillStyle = ctx.createLinearGradient(0, top - halfMainlineSize, 0, top + halfMainlineSize);
10123
+ fillStyle.addColorStop(0, color.topColor);
10124
+ fillStyle.addColorStop(1, color.bottomColor);
10125
+ }
8569
10126
  ctx.beginPath();
8570
10127
  ctx.lineWidth = this.options.style.mainLine.size;
8571
- ctx.strokeStyle = ctx.fillStyle = mainLineGradient;
10128
+ ctx.strokeStyle = ctx.fillStyle = fillStyle;
8572
10129
  ctx.moveTo(0, top);
8573
10130
  ctx.lineTo(width, top);
8574
10131
  ctx.stroke();
8575
10132
  for (const type in markers) {
8576
- this.drawMarkersAndLabels(ctx, markers[type], type, top + halfMainlineSize);
10133
+ this.drawMarkersAndLabels(ctx, markers[type], type, top + halfMainlineSize, {
10134
+ minorTokens: markers[MINOR_MARKER],
10135
+ viewportWidth: width
10136
+ });
8577
10137
  }
10138
+ this.drawParentDateLabels(ctx, top + halfMainlineSize, width);
8578
10139
  }
8579
10140
  };
8580
10141
  Timeline.prototype.drawDraggingHighlight = function(ctx, top, width) {
@@ -8644,28 +10205,204 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8644
10205
  ctx.restore();
8645
10206
  };
8646
10207
  Timeline.prototype.getTokensAndMarkers = function(width) {
10208
+ var _a, _b;
8647
10209
  const tokens = {};
8648
10210
  const markers = {};
8649
10211
  markers[MAJOR_MARKER] = [];
8650
10212
  markers[MINOR_MARKER] = [];
10213
+ const visualMarkerLayout = (_b = (_a = this.timescaleManager).getSubdayVisualMarkerLayout) == null ? void 0 : _b.call(_a);
8651
10214
  let x = this.repositionWindow;
8652
10215
  let token = this.timescaleManager.startToken;
8653
10216
  tokens.start = token.value;
8654
- let endToken = token;
8655
- const leftBufferNumberOfTokens = 9;
8656
- token = this.timescaleManager.getPreviousNth(token, leftBufferNumberOfTokens);
8657
- x -= token.length * leftBufferNumberOfTokens;
10217
+ const minimumLeftBufferTokens = 9;
10218
+ let bufferedTokenCount = 0;
10219
+ let hasMajorBeforeViewport = token.type === MAJOR_MARKER && x <= 0;
10220
+ while (bufferedTokenCount < minimumLeftBufferTokens || !hasMajorBeforeViewport) {
10221
+ token = this.timescaleManager.getPrevious(token);
10222
+ x -= token.length;
10223
+ bufferedTokenCount++;
10224
+ if (token.type === MAJOR_MARKER && x <= 0) {
10225
+ hasMajorBeforeViewport = true;
10226
+ }
10227
+ }
8658
10228
  do {
8659
- markers[token.type].push(token);
8660
- tokens[token.value.toKeyString()] = token.drawX = x;
10229
+ token.drawX = x;
10230
+ tokens[token.value.toKeyString()] = x;
10231
+ if (!visualMarkerLayout) {
10232
+ markers[token.type].push(token);
10233
+ }
8661
10234
  x += token.length;
8662
- endToken = token;
8663
10235
  token = this.timescaleManager.getNext(token);
8664
- } while (x < width + 150);
8665
- tokens.end = endToken.value;
10236
+ } while (x < width + MAIN_RANGE_RIGHT_BUFFER);
10237
+ if (visualMarkerLayout) {
10238
+ const visualMarkers = this.timescaleManager.createSubdayVisualMarkers(
10239
+ width,
10240
+ this.repositionWindow,
10241
+ visualMarkerLayout
10242
+ );
10243
+ markers[MAJOR_MARKER] = visualMarkers[MAJOR_MARKER];
10244
+ markers[MINOR_MARKER] = visualMarkers[MINOR_MARKER];
10245
+ }
10246
+ tokens.end = this.getPivotPoint(width + MAIN_RANGE_RIGHT_BUFFER).date;
8666
10247
  return { tokens, markers };
8667
10248
  };
8668
- Timeline.prototype.drawMarkersAndLabels = function(ctx, tokens, tokenType, markerTop) {
10249
+ function getLabelMetrics(ctx, token, labelStyle) {
10250
+ var _a;
10251
+ const width = ctx.measureText(token.label).width;
10252
+ const offsetX = Number.isFinite((_a = labelStyle.offset) == null ? void 0 : _a.x) ? labelStyle.offset.x : 0;
10253
+ const anchorX = Math.round(token.drawX) + offsetX;
10254
+ let left = anchorX;
10255
+ if (labelStyle.textAlign === "center") {
10256
+ left -= width / 2;
10257
+ } else if (labelStyle.textAlign === "right" || labelStyle.textAlign === "end") {
10258
+ left -= width;
10259
+ }
10260
+ return { left, width };
10261
+ }
10262
+ __name(getLabelMetrics, "getLabelMetrics");
10263
+ function getTextAnchorForLeft(left, width, textAlign) {
10264
+ if (textAlign === "center") {
10265
+ return left + width / 2;
10266
+ }
10267
+ if (textAlign === "right" || textAlign === "end") {
10268
+ return left + width;
10269
+ }
10270
+ return left;
10271
+ }
10272
+ __name(getTextAnchorForLeft, "getTextAnchorForLeft");
10273
+ function isStickyMajorLabelEnabled(stickyStyle, tokens) {
10274
+ var _a;
10275
+ if ((stickyStyle == null ? void 0 : stickyStyle.enabled) === true) {
10276
+ return true;
10277
+ }
10278
+ if ((stickyStyle == null ? void 0 : stickyStyle.enabled) !== "auto") {
10279
+ return false;
10280
+ }
10281
+ return Number.isFinite((_a = tokens[0]) == null ? void 0 : _a.unit) && tokens[0].unit <= ZOOM_MONTH;
10282
+ }
10283
+ __name(isStickyMajorLabelEnabled, "isStickyMajorLabelEnabled");
10284
+ const MAJOR_LABEL_MINIMUM_GAP = 8;
10285
+ function getStickyTextLabel(ctx, tokens, labelStyle, viewportWidth) {
10286
+ var _a;
10287
+ if (((_a = labelStyle.sticky) == null ? void 0 : _a.enabled) !== true || !Number.isFinite(viewportWidth)) {
10288
+ return null;
10289
+ }
10290
+ const stickyLeft = Number.isFinite(labelStyle.sticky.offsetX) ? labelStyle.sticky.offsetX : 0;
10291
+ let candidateIndex = -1;
10292
+ let candidateMetrics;
10293
+ for (let i = 0; i < tokens.length; i++) {
10294
+ const metrics = getLabelMetrics(ctx, tokens[i], labelStyle);
10295
+ if (metrics.left <= stickyLeft) {
10296
+ candidateIndex = i;
10297
+ candidateMetrics = metrics;
10298
+ }
10299
+ }
10300
+ if (candidateIndex < 0) {
10301
+ return null;
10302
+ }
10303
+ const token = tokens[candidateIndex];
10304
+ const nextToken = tokens[candidateIndex + 1];
10305
+ if (token.drawX > viewportWidth || !nextToken && token.drawX + token.length < 0) {
10306
+ return null;
10307
+ }
10308
+ let labelLeft = stickyLeft;
10309
+ if (nextToken) {
10310
+ const nextMetrics = getLabelMetrics(ctx, nextToken, labelStyle);
10311
+ labelLeft = Math.min(
10312
+ labelLeft,
10313
+ nextMetrics.left - candidateMetrics.width - MAJOR_LABEL_MINIMUM_GAP
10314
+ );
10315
+ }
10316
+ return {
10317
+ token,
10318
+ labelX: getTextAnchorForLeft(labelLeft, candidateMetrics.width, labelStyle.textAlign)
10319
+ };
10320
+ }
10321
+ __name(getStickyTextLabel, "getStickyTextLabel");
10322
+ function getStickyMajorLabel(ctx, tokens, labelStyle, drawOptions) {
10323
+ const stickyStyle = labelStyle.sticky;
10324
+ const minorTokens = drawOptions.minorTokens || [];
10325
+ const viewportWidth = drawOptions.viewportWidth;
10326
+ if (!isStickyMajorLabelEnabled(stickyStyle, tokens) || !Number.isFinite(viewportWidth)) {
10327
+ return null;
10328
+ }
10329
+ const stickyLeft = Number.isFinite(stickyStyle.offsetX) ? stickyStyle.offsetX : 0;
10330
+ let candidateIndex = -1;
10331
+ let candidateMetrics;
10332
+ for (let i = 0; i < tokens.length; i++) {
10333
+ const metrics = getLabelMetrics(ctx, tokens[i], labelStyle);
10334
+ if (metrics.left <= stickyLeft) {
10335
+ candidateIndex = i;
10336
+ candidateMetrics = metrics;
10337
+ }
10338
+ }
10339
+ if (candidateIndex < 0) {
10340
+ return null;
10341
+ }
10342
+ const token = tokens[candidateIndex];
10343
+ const nextToken = tokens[candidateIndex + 1];
10344
+ const hasVisibleInterval = token.drawX <= viewportWidth && (nextToken ? nextToken.drawX >= 0 : token.visual === true && token.drawX + token.length >= 0 || minorTokens.some(
10345
+ (minorToken) => minorToken.drawX >= 0 && minorToken.drawX <= viewportWidth && minorToken.drawX > token.drawX
10346
+ ));
10347
+ if (!hasVisibleInterval) {
10348
+ return null;
10349
+ }
10350
+ let labelLeft = stickyLeft;
10351
+ if (nextToken) {
10352
+ const nextMetrics = getLabelMetrics(ctx, nextToken, labelStyle);
10353
+ labelLeft = Math.min(
10354
+ labelLeft,
10355
+ nextMetrics.left - candidateMetrics.width - MAJOR_LABEL_MINIMUM_GAP
10356
+ );
10357
+ }
10358
+ return {
10359
+ token,
10360
+ labelX: getTextAnchorForLeft(labelLeft, candidateMetrics.width, labelStyle.textAlign)
10361
+ };
10362
+ }
10363
+ __name(getStickyMajorLabel, "getStickyMajorLabel");
10364
+ Timeline.prototype.drawParentDateLabels = function(ctx, markerTop, viewportWidth) {
10365
+ const labelStyle = this.options.style.dateLabel.parent;
10366
+ if (!this.timescaleManager.isParentContextTextVisible(labelStyle)) {
10367
+ return;
10368
+ }
10369
+ const visibleStart = this.getPivotPoint(0).date;
10370
+ const tokens = this.timescaleManager.createParentContextTokens(
10371
+ visibleStart,
10372
+ viewportWidth,
10373
+ this.repositionWindow
10374
+ );
10375
+ if (tokens.length === 0) {
10376
+ return;
10377
+ }
10378
+ const markerDirection = this.options.style.mainLine.position === "top" ? -1 : 1;
10379
+ const majorStyle = this.options.style.dateLabel.major;
10380
+ const majorMarkerHeight = this.options.style.marker.major.height;
10381
+ const labelY = markerTop + majorMarkerHeight * markerDirection + majorStyle.offset.y + labelStyle.height * markerDirection + labelStyle.offset.y;
10382
+ ctx.font = labelStyle.font;
10383
+ ctx.textAlign = labelStyle.textAlign;
10384
+ ctx.textBaseline = markerDirection === 1 ? "alphabetic" : "top";
10385
+ const stickyLabel = getStickyTextLabel(ctx, tokens, labelStyle, viewportWidth);
10386
+ let previousLabelRight = Number.NEGATIVE_INFINITY;
10387
+ for (let i = 0; i < tokens.length; i++) {
10388
+ const token = tokens[i];
10389
+ const labelX = (stickyLabel == null ? void 0 : stickyLabel.token) === token ? stickyLabel.labelX : Math.round(token.drawX) + labelStyle.offset.x;
10390
+ const labelWidth = ctx.measureText(token.label).width;
10391
+ let labelLeft = labelX;
10392
+ if (labelStyle.textAlign === "center") {
10393
+ labelLeft -= labelWidth / 2;
10394
+ } else if (labelStyle.textAlign === "right" || labelStyle.textAlign === "end") {
10395
+ labelLeft -= labelWidth;
10396
+ }
10397
+ if ((stickyLabel == null ? void 0 : stickyLabel.token) !== token && labelLeft < previousLabelRight + MAJOR_LABEL_MINIMUM_GAP) {
10398
+ continue;
10399
+ }
10400
+ ctx.fillStyle = token.value.isInFuture() ? labelStyle.futureColor : labelStyle.color;
10401
+ ctx.fillText(token.label, labelX, labelY);
10402
+ previousLabelRight = labelLeft + labelWidth;
10403
+ }
10404
+ };
10405
+ Timeline.prototype.drawMarkersAndLabels = function(ctx, tokens, tokenType, markerTop, drawOptions = {}) {
8669
10406
  if (tokens.length === 0) {
8670
10407
  return;
8671
10408
  }
@@ -8683,7 +10420,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8683
10420
  const isExtended = markerStyle.extend;
8684
10421
  const markerDirection = this.options.style.mainLine.position === "top" ? -1 : 1;
8685
10422
  const markerHeight = markerStyle.height;
8686
- const withLabel = !!tokens[0].label;
10423
+ const withLabel = tokens.some((token) => token.label);
8687
10424
  let isInFuture = tokens[0].value.isInFuture();
8688
10425
  let wasInPast = !isInFuture;
8689
10426
  let labelStyle;
@@ -8698,6 +10435,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8698
10435
  ctx.textBaseline = markerDirection === 1 ? "alphabetic" : "top";
8699
10436
  labelY = markerTop + markerHeight * markerDirection + labelStyle.offset.y;
8700
10437
  }
10438
+ const stickyLabel = withLabel && tokenType === "major" ? getStickyMajorLabel(ctx, tokens, labelStyle, drawOptions) : null;
8701
10439
  ctx.beginPath();
8702
10440
  for (let i = 0; i < tokens.length; i++) {
8703
10441
  const token = tokens[i];
@@ -8714,7 +10452,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8714
10452
  const markerEndY = isExtended ? markerTop + -1 * markerDirection * this.top : markerTop;
8715
10453
  ctx.lineTo(drawX, markerEndY);
8716
10454
  if (withLabel && token.label) {
8717
- const labelX = drawX + labelStyle.offset.x;
10455
+ const labelX = (stickyLabel == null ? void 0 : stickyLabel.token) === token ? stickyLabel.labelX : drawX + labelStyle.offset.x;
8718
10456
  ctx.fillStyle = isInFuture ? labelStyle.futureColor : labelStyle.color;
8719
10457
  ctx.fillText(token.label, labelX, labelY);
8720
10458
  }
@@ -8770,6 +10508,46 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8770
10508
  const lane = this.getLaneById(laneId);
8771
10509
  return getResolvedLaneArticleOptions(this, lane);
8772
10510
  };
10511
+ Timeline.prototype._getResolvedArticleStyleOverrides = function(articleOrData, cardLayout) {
10512
+ var _a, _b, _c;
10513
+ const laneId = articleOrData && articleOrData.laneId != null ? articleOrData.laneId : this._resolveLaneIdFromArticleData(articleOrData);
10514
+ const lane = this.getLaneById(laneId);
10515
+ const baseOptions = ENGINE_DEFAULTS.article || {};
10516
+ const layoutDefaults = ((_a = this._registeredArticleLayoutStyles) == null ? void 0 : _a[cardLayout]) || {};
10517
+ const timelineOptions = this._explicitArticleOptions || {};
10518
+ const timelineLayoutStyles = ((_b = timelineOptions.layoutStyles) == null ? void 0 : _b[cardLayout]) || {};
10519
+ const laneOptions = (lane == null ? void 0 : lane.articleOptions) || {};
10520
+ const laneLayoutStyles = ((_c = laneOptions.layoutStyles) == null ? void 0 : _c[cardLayout]) || {};
10521
+ return {
10522
+ style: deepMerge(
10523
+ {},
10524
+ baseOptions.defaultStyle || {},
10525
+ layoutDefaults.style || {},
10526
+ timelineOptions.defaultStyle || {},
10527
+ timelineLayoutStyles.style || {},
10528
+ laneOptions.defaultStyle || {},
10529
+ laneLayoutStyles.style || {}
10530
+ ),
10531
+ hoverStyle: deepMerge(
10532
+ {},
10533
+ baseOptions.defaultHoverStyle || {},
10534
+ layoutDefaults.hoverStyle || {},
10535
+ timelineOptions.defaultHoverStyle || {},
10536
+ timelineLayoutStyles.hoverStyle || {},
10537
+ laneOptions.defaultHoverStyle || {},
10538
+ laneLayoutStyles.hoverStyle || {}
10539
+ ),
10540
+ activeStyle: deepMerge(
10541
+ {},
10542
+ baseOptions.defaultActiveStyle || {},
10543
+ layoutDefaults.activeStyle || {},
10544
+ timelineOptions.defaultActiveStyle || {},
10545
+ timelineLayoutStyles.activeStyle || {},
10546
+ laneOptions.defaultActiveStyle || {},
10547
+ laneLayoutStyles.activeStyle || {}
10548
+ )
10549
+ };
10550
+ };
8773
10551
  Timeline.prototype._getExplicitArticleCardLayout = function(articleOrData) {
8774
10552
  if (!articleOrData) {
8775
10553
  return null;
@@ -10124,6 +11902,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
10124
11902
  const FRAME_MS = 1e3 / 60;
10125
11903
  const STANDARD_WHEEL_NOTCH_DELTA = 120;
10126
11904
  const MIN_BROWSER_ZOOM_SCALED_NOTCH_DELTA = 24;
11905
+ const MILLISECOND_BOUNDARY_EPSILON = 1e-7;
10127
11906
  const BROWSER_ZOOM_SCALE_FACTORS = [
10128
11907
  0.25,
10129
11908
  1 / 3,
@@ -10399,7 +12178,8 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
10399
12178
  Timeline.prototype.setZoomByPivotPoint = /* @__PURE__ */ __name(function setZoomByPivotPoint(newZoom, pivotPoint, pivotPixel, offsetX = 0) {
10400
12179
  this.timescaleManager.setZoom(newZoom);
10401
12180
  const compensation = this.timescaleManager.setStartDate(pivotPoint.date);
10402
- this.repositionWindow = compensation - pivotPoint.fraction;
12181
+ const residualPixels = Number.isFinite(pivotPoint.millisecondFraction) ? pivotPoint.millisecondFraction * getPixelsPerDay(this) / MILLISECONDS_PER_DAY : pivotPoint.fraction;
12182
+ this.repositionWindow = compensation - residualPixels;
10403
12183
  this.updateFromByPixels(-pivotPixel + offsetX);
10404
12184
  applyTimelineDateBounds(this, {
10405
12185
  mode: this.isDragging || this.isPinching ? "elastic" : "clamp"
@@ -10423,7 +12203,23 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
10423
12203
  let fraction = pixel - (x - token.length);
10424
12204
  const dmy = prevToken.value;
10425
12205
  let { year, month, day } = dmy;
10426
- if (unit === ZOOM_MONTH) {
12206
+ if (unit <= ZOOM_DAY) {
12207
+ const pixelsPerMillisecond = getPixelsPerDay(this) / MILLISECONDS_PER_DAY;
12208
+ let millisecondsFromToken = pixelsPerMillisecond > 0 ? fraction / pixelsPerMillisecond : 0;
12209
+ const nearestMillisecond = Math.round(millisecondsFromToken);
12210
+ if (Math.abs(millisecondsFromToken - nearestMillisecond) < MILLISECOND_BOUNDARY_EPSILON) {
12211
+ millisecondsFromToken = nearestMillisecond;
12212
+ }
12213
+ const wholeMilliseconds = Math.floor(millisecondsFromToken);
12214
+ const millisecondFraction = millisecondsFromToken - wholeMilliseconds;
12215
+ prevToken.value = prevToken.value.addMilliseconds(wholeMilliseconds);
12216
+ fraction -= wholeMilliseconds * pixelsPerMillisecond;
12217
+ return {
12218
+ date: prevToken.value,
12219
+ fraction,
12220
+ millisecondFraction
12221
+ };
12222
+ } else if (unit === ZOOM_MONTH) {
10427
12223
  day = Math.floor(fraction / len * 30.44) + 1;
10428
12224
  fraction -= (day - 1) * len / 30.44;
10429
12225
  prevToken.value = new Dmy(year, month, day);
@@ -10706,10 +12502,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
10706
12502
  var _a;
10707
12503
  const settings = normaliseSetStartDateOptions(options);
10708
12504
  const padding = settings.padding || 0;
10709
- if (typeof dmy === "string") {
10710
- dmy = Dmy.fromString(dmy);
10711
- }
10712
- dmy = this.getDmyFromInput(dmy);
12505
+ dmy = this.getDmyFromInput(normaliseDateInput(dmy));
10713
12506
  if ((_a = settings.animation) == null ? void 0 : _a.active) {
10714
12507
  animateStartDate(this, dmy, padding, settings.animation);
10715
12508
  return;
@@ -10869,44 +12662,6 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
10869
12662
  this.off(event, handlers[event]);
10870
12663
  }
10871
12664
  };
10872
- function roundPixel(value) {
10873
- return Math.round(value);
10874
- }
10875
- __name(roundPixel, "roundPixel");
10876
- function snapPixel(value, dpr = 1) {
10877
- const ratio = typeof dpr === "number" && isFinite(dpr) && dpr > 0 ? dpr : 1;
10878
- return Math.round(value * ratio) / ratio;
10879
- }
10880
- __name(snapPixel, "snapPixel");
10881
- function retainPixel(value) {
10882
- return value;
10883
- }
10884
- __name(retainPixel, "retainPixel");
10885
- function createPixelSnap(dpr = 1, mode = "device") {
10886
- if (mode === false || mode === "none") {
10887
- return retainPixel;
10888
- }
10889
- if (mode === "css") {
10890
- return roundPixel;
10891
- }
10892
- return /* @__PURE__ */ __name(function snapToDevicePixel(value) {
10893
- return snapPixel(value, dpr);
10894
- }, "snapToDevicePixel");
10895
- }
10896
- __name(createPixelSnap, "createPixelSnap");
10897
- function createInnerSpace(outerSpace, borderWidth, snap) {
10898
- if (!snap) {
10899
- snap = roundPixel;
10900
- }
10901
- const halfBorder = borderWidth / 2;
10902
- return {
10903
- left: snap(outerSpace.left + halfBorder),
10904
- top: snap(outerSpace.top + halfBorder),
10905
- width: snap(outerSpace.width - borderWidth),
10906
- height: snap(outerSpace.height - borderWidth)
10907
- };
10908
- }
10909
- __name(createInnerSpace, "createInnerSpace");
10910
12665
  function getPixelSnap$1(article) {
10911
12666
  var _a, _b, _c, _d, _e, _f;
10912
12667
  const dpr = ((_b = (_a = article.owner) == null ? void 0 : _a.getCanvasDpr) == null ? void 0 : _b.call(_a)) || 1;
@@ -10929,7 +12684,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
10929
12684
  if (!this.isDataLoaded || isNaN(this.position.left)) {
10930
12685
  return;
10931
12686
  }
10932
- const style = this._getCurrentStyle();
12687
+ const style = this.getCurrentStyle();
10933
12688
  const snap = getPixelSnap$1(this);
10934
12689
  const articleOrigin = getSnappedArticleOrigin$1(this);
10935
12690
  const top = articleOrigin.top;
@@ -11105,7 +12860,11 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11105
12860
  }
11106
12861
  }
11107
12862
  if (showStar) {
11108
- const star = this.getIconBox();
12863
+ const box = this.getIconBox();
12864
+ const centreX = snap(box.left + box.width / 2);
12865
+ const centreY = snap(box.top + box.height / 2);
12866
+ const outerRadius = snap(Math.min(box.width, box.height) / 2);
12867
+ const innerRadius = snap(outerRadius / 2);
11109
12868
  let starStroke, starFill;
11110
12869
  if (!this.isStarred) {
11111
12870
  if (this.isMouseOverStar) {
@@ -11124,26 +12883,17 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11124
12883
  starFill = "#fff800";
11125
12884
  }
11126
12885
  }
11127
- drawStar(
11128
- ctx,
11129
- star.centreX,
11130
- star.centreY,
11131
- 5,
11132
- star.innerRadius,
11133
- star.outerRadius,
11134
- starFill,
11135
- starStroke
11136
- );
12886
+ drawStar(ctx, centreX, centreY, 5, innerRadius, outerRadius, starFill, starStroke);
11137
12887
  }
11138
12888
  },
11139
12889
  getWidth() {
11140
- return this._getCurrentStyle().width;
12890
+ return this.getCurrentStyle().width;
11141
12891
  },
11142
12892
  getHeight() {
11143
- return this._getCurrentStyle().height;
12893
+ return this.getCurrentStyle().height;
11144
12894
  },
11145
12895
  getConnectorEnd() {
11146
- const style = this._getCurrentStyle();
12896
+ const style = this.getCurrentStyle();
11147
12897
  const articleOrigin = getSnappedArticleOrigin$1(this);
11148
12898
  return {
11149
12899
  left: articleOrigin.left + style.connectorLine.offsetX,
@@ -11155,7 +12905,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11155
12905
  if (((_d = (_c = (_b = (_a = this.owner) == null ? void 0 : _a.options) == null ? void 0 : _b.article) == null ? void 0 : _c.star) == null ? void 0 : _d.visible) === false) {
11156
12906
  return false;
11157
12907
  }
11158
- const style = this._getCurrentStyle();
12908
+ const style = this.getCurrentStyle();
11159
12909
  const snap = getPixelSnap$1(this);
11160
12910
  const sideLength = style.star.width;
11161
12911
  const box = {
@@ -11166,10 +12916,6 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11166
12916
  const articleOrigin = getSnappedArticleOrigin$1(this);
11167
12917
  box.left = snap(articleOrigin.left - br / 4 + this._getWidth() - box.width - style.star.margin);
11168
12918
  box.top = snap(articleOrigin.top + br / 4 + style.star.margin);
11169
- box.centreX = snap(box.left + box.width / 2);
11170
- box.centreY = snap(box.top + box.height / 2);
11171
- box.outerRadius = snap(box.width / 2);
11172
- box.innerRadius = snap(box.outerRadius / 2);
11173
12919
  return box;
11174
12920
  },
11175
12921
  defaultStyle: {
@@ -11233,7 +12979,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11233
12979
  name: "portrait",
11234
12980
  draw(ctx) {
11235
12981
  var _a, _b, _c, _d, _e, _f, _g, _h;
11236
- const style = this._getCurrentStyle();
12982
+ const style = this.getCurrentStyle();
11237
12983
  const snap = getPixelSnap(this);
11238
12984
  const borderWidth = style.border.width;
11239
12985
  const maxBorderWidth = Math.max(
@@ -11472,7 +13218,11 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11472
13218
  ctx.stroke();
11473
13219
  }
11474
13220
  if (((_h = (_g = (_f = (_e = this.owner) == null ? void 0 : _e.options) == null ? void 0 : _f.article) == null ? void 0 : _g.star) == null ? void 0 : _h.visible) !== false && (this.isActive || this.isStarred)) {
11475
- const star = getStarBox(this);
13221
+ const box = this.getIconBox();
13222
+ const centreX = snap(box.left + box.width / 2);
13223
+ const centreY = snap(box.top + box.height / 2);
13224
+ const outerRadius = snap(Math.min(box.width, box.height) / 2);
13225
+ const innerRadius = snap(outerRadius / 2);
11476
13226
  let starStroke, starFill;
11477
13227
  if (!this.isStarred) {
11478
13228
  if (this.isMouseOverStar) {
@@ -11491,23 +13241,14 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11491
13241
  starFill = "#fff800";
11492
13242
  }
11493
13243
  }
11494
- drawStar(
11495
- ctx,
11496
- star.centreX,
11497
- star.centreY,
11498
- 5,
11499
- star.innerRadius,
11500
- star.outerRadius,
11501
- starFill,
11502
- starStroke
11503
- );
13244
+ drawStar(ctx, centreX, centreY, 5, innerRadius, outerRadius, starFill, starStroke);
11504
13245
  }
11505
13246
  },
11506
13247
  getWidth() {
11507
- return this._getCurrentStyle().width;
13248
+ return this.getCurrentStyle().width;
11508
13249
  },
11509
13250
  getHeight() {
11510
- const style = this._getCurrentStyle();
13251
+ const style = this.getCurrentStyle();
11511
13252
  const snap = getPixelSnap(this);
11512
13253
  let imageHeight = 0;
11513
13254
  if (this.imageLoaded) {
@@ -11533,7 +13274,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11533
13274
  return imageHeight + articleTopHeight + style.border.width;
11534
13275
  },
11535
13276
  getConnectorEnd() {
11536
- const style = this._getCurrentStyle();
13277
+ const style = this.getCurrentStyle();
11537
13278
  const articleOrigin = getSnappedArticleOrigin(this);
11538
13279
  return {
11539
13280
  left: articleOrigin.left + style.connectorLine.offsetX,
@@ -11545,7 +13286,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11545
13286
  if (((_d = (_c = (_b = (_a = this.owner) == null ? void 0 : _a.options) == null ? void 0 : _b.article) == null ? void 0 : _c.star) == null ? void 0 : _d.visible) === false) {
11546
13287
  return false;
11547
13288
  }
11548
- const style = this._getCurrentStyle();
13289
+ const style = this.getCurrentStyle();
11549
13290
  const snap = getPixelSnap(this);
11550
13291
  const articleOrigin = getSnappedArticleOrigin(this);
11551
13292
  const sideLength = style.star.width;
@@ -11560,36 +13301,16 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11560
13301
  return box;
11561
13302
  }
11562
13303
  };
11563
- function getStarBox(article) {
11564
- const style = article._getCurrentStyle();
11565
- const snap = getPixelSnap(article);
11566
- const articleOrigin = getSnappedArticleOrigin(article);
11567
- const sideLength = style.star.width;
11568
- const box = {
11569
- width: sideLength,
11570
- height: sideLength
11571
- };
11572
- box.left = snap(
11573
- articleOrigin.left - style.topRadius / 4 + article._getWidth() - box.width - style.star.margin
11574
- );
11575
- box.top = snap(articleOrigin.top + style.topRadius / 4 + style.star.margin);
11576
- box.centreX = snap(box.left + box.width / 2);
11577
- box.centreY = snap(box.top + box.height / 2);
11578
- box.outerRadius = snap(box.width / 2);
11579
- box.innerRadius = snap(box.outerRadius / 2);
11580
- return box;
11581
- }
11582
- __name(getStarBox, "getStarBox");
11583
13304
  const _cardLayouts = /* @__PURE__ */ new Map();
11584
13305
  function _injectDimensionFallbacks(layout) {
11585
13306
  if (typeof layout.getWidth !== "function") {
11586
13307
  layout.getWidth = function() {
11587
- return this._getCurrentStyle().width;
13308
+ return this.getCurrentStyle().width;
11588
13309
  };
11589
13310
  }
11590
13311
  if (typeof layout.getHeight !== "function") {
11591
13312
  layout.getHeight = function() {
11592
- return this._getCurrentStyle().height;
13313
+ return this.getCurrentStyle().height;
11593
13314
  };
11594
13315
  }
11595
13316
  if (typeof layout.getIconBox !== "function") {
@@ -11651,10 +13372,23 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11651
13372
  Timeline.prototype.getStatusForSave = function() {
11652
13373
  const from = this.timescaleManager.startToken.value;
11653
13374
  const articleSaveInfo = [];
13375
+ const fromTime = {};
13376
+ if (from.hour) {
13377
+ fromTime.fhr = from.hour;
13378
+ }
13379
+ if (from.minute) {
13380
+ fromTime.fmi = from.minute;
13381
+ }
13382
+ if (from.second) {
13383
+ fromTime.fs = from.second;
13384
+ }
13385
+ if (from.millisecond) {
13386
+ fromTime.fms = from.millisecond;
13387
+ }
11654
13388
  for (let i = 0; i < this.articles.length; i++) {
11655
13389
  articleSaveInfo.push(this.articles[i].getStatusForSave());
11656
13390
  }
11657
- return JSON.stringify({
13391
+ return JSON.stringify(__spreadProps(__spreadValues({
11658
13392
  t: this.title,
11659
13393
  o: this.ownerId,
11660
13394
  // set by host app if needed
@@ -11662,10 +13396,11 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11662
13396
  // d: event spacing removed in current implementation
11663
13397
  fy: from.year,
11664
13398
  fm: from.month,
11665
- fd: from.day,
13399
+ fd: from.day
13400
+ }, fromTime), {
11666
13401
  w: this.repositionWindow,
11667
13402
  a: articleSaveInfo
11668
- });
13403
+ }));
11669
13404
  };
11670
13405
  Timeline.prototype._emitTimelineStateChange = function() {
11671
13406
  if (this && this._isInitialized === true) {