histropediajs 1.5.1 → 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.1 | 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: []
@@ -3906,6 +4597,47 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3906
4597
  Logger.warn(`DEPRECATION WARNING: ${fromPath} is deprecated. Use ${toPath} instead.`);
3907
4598
  }
3908
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));
6365
- };
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);
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,13 +7792,19 @@ 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
@@ -6417,26 +7814,11 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6417
7814
  });
6418
7815
  }
6419
7816
  };
6420
- const STARRED_INCREASE_CONSTANT = 1e7;
6421
- const ACTIVE_INCREASE_CONSTANT = 2e7;
6422
7817
  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;
6433
- }
6434
- __name(getArticleEffectiveRank, "getArticleEffectiveRank");
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
  };
@@ -6863,22 +8306,30 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6863
8306
  return maxElasticPixels * resistedPixels / (maxElasticPixels - resistedPixels) / pixelsPerDay;
6864
8307
  }
6865
8308
  __name(getUnresistedElasticOverflowDays, "getUnresistedElasticOverflowDays");
6866
- function setElasticBoundedViewportStartDay(timeline, targetStartDayNumber, viewportSpanDays) {
8309
+ function setElasticBoundedViewportStartPoint(timeline, targetStartPoint, viewportSpanDays) {
6867
8310
  const bounds = getTimelineDateBounds(timeline);
6868
- let nextStartDayNumber = targetStartDayNumber;
8311
+ let nextStartPoint = targetStartPoint;
6869
8312
  if ((bounds == null ? void 0 : bounds.overflow) === "elastic" && Number.isFinite(viewportSpanDays)) {
6870
- const targetEndDayNumber = targetStartDayNumber + viewportSpanDays;
6871
- if (bounds.minDay != null && targetStartDayNumber < bounds.minDay) {
6872
- nextStartDayNumber = bounds.minDay - getElasticOverflowDays(timeline, bounds.minDay - targetStartDayNumber);
6873
- } else if (bounds.maxDay != null && targetEndDayNumber > bounds.maxDay) {
6874
- 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
+ );
6875
8326
  }
6876
8327
  }
6877
- setInternalStartDayNumber(timeline, nextStartDayNumber, 0, false, {
8328
+ setInternalStartDayPoint(timeline, nextStartPoint, 0, false, {
6878
8329
  skipDateBounds: true
6879
8330
  });
6880
8331
  }
6881
- __name(setElasticBoundedViewportStartDay, "setElasticBoundedViewportStartDay");
8332
+ __name(setElasticBoundedViewportStartPoint, "setElasticBoundedViewportStartPoint");
6882
8333
  function applyTimelineDateBounds(timeline, options = {}) {
6883
8334
  const bounds = getTimelineDateBounds(timeline);
6884
8335
  if (!bounds) {
@@ -6893,7 +8344,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6893
8344
  if (correction.zoom !== timeline.timescaleManager.zoom) {
6894
8345
  timeline.timescaleManager.setZoom(correction.zoom);
6895
8346
  }
6896
- setInternalStartDayNumber(timeline, correction.dayNumber, correction.pixelOffset, false, {
8347
+ setInternalStartDayPoint(timeline, correction.dayPoint, correction.pixelOffset, false, {
6897
8348
  skipDateBounds: true
6898
8349
  });
6899
8350
  return true;
@@ -6901,13 +8352,17 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6901
8352
  if (mode === "elastic" && bounds.overflow === "elastic") {
6902
8353
  const elasticOverflowDays = getElasticOverflowDays(timeline, correction.overflowDays);
6903
8354
  if (correction.type === "min") {
6904
- setInternalStartDayNumber(timeline, correction.dayNumber - elasticOverflowDays, 0, false, {
6905
- skipDateBounds: true
6906
- });
8355
+ setInternalStartDayPoint(
8356
+ timeline,
8357
+ addDaysToDayPoint(correction.dayPoint, -elasticOverflowDays),
8358
+ 0,
8359
+ false,
8360
+ { skipDateBounds: true }
8361
+ );
6907
8362
  } else {
6908
- setInternalStartDayNumber(
8363
+ setInternalStartDayPoint(
6909
8364
  timeline,
6910
- correction.dayNumber + elasticOverflowDays,
8365
+ addDaysToDayPoint(correction.dayPoint, elasticOverflowDays),
6911
8366
  correction.pixelOffset,
6912
8367
  false,
6913
8368
  { skipDateBounds: true }
@@ -6915,7 +8370,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6915
8370
  }
6916
8371
  return true;
6917
8372
  }
6918
- setInternalStartDayNumber(timeline, correction.dayNumber, correction.pixelOffset, false, {
8373
+ setInternalStartDayPoint(timeline, correction.dayPoint, correction.pixelOffset, false, {
6919
8374
  skipDateBounds: true
6920
8375
  });
6921
8376
  return true;
@@ -6926,13 +8381,14 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6926
8381
  }
6927
8382
  __name(isViewportOutsideDateBounds, "isViewportOutsideDateBounds");
6928
8383
  function getPixelsPerDay(timeline) {
8384
+ var _a;
6929
8385
  const manager = timeline.timescaleManager;
6930
8386
  const unitSize = manager.unitSizeInPixels;
6931
8387
  if (!Number.isFinite(unitSize) || unitSize <= 0) {
6932
8388
  return 0;
6933
8389
  }
6934
8390
  if (manager.unit == null || manager.unit <= ZOOM_DAY) {
6935
- return unitSize;
8391
+ return unitSize / getZoomUnitLengthInDays((_a = manager.unit) != null ? _a : ZOOM_DAY);
6936
8392
  }
6937
8393
  if (manager.unit === ZOOM_MONTH) {
6938
8394
  return unitSize / 30.44;
@@ -6941,11 +8397,13 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6941
8397
  return unitSize / (365.2422 * unitLengthInYears);
6942
8398
  }
6943
8399
  __name(getPixelsPerDay, "getPixelsPerDay");
6944
- function setInternalStartDayNumber(timeline, dayNumber, pixelOffset, emitStateChange = false, options = {}) {
8400
+ function setInternalStartDayPoint(timeline, dayPoint, pixelOffset, emitStateChange = false, options = {}) {
6945
8401
  var _a;
6946
- const startDayNumber = Math.floor(dayNumber);
6947
- const startDmy = getDmyFromDayNumber(startDayNumber);
6948
- 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;
6949
8407
  const dateFraction = timeline.timescaleManager.setStartDate(startDmy);
6950
8408
  timeline.repositionWindow = dateFraction - partialDayPixels;
6951
8409
  if (pixelOffset) {
@@ -6960,26 +8418,26 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
6960
8418
  timeline._emitTimelineStateChange();
6961
8419
  }
6962
8420
  }
6963
- __name(setInternalStartDayNumber, "setInternalStartDayNumber");
8421
+ __name(setInternalStartDayPoint, "setInternalStartDayPoint");
6964
8422
  function setInternalStartDate(timeline, dmy, pixelOffset, emitStateChange = false, options = {}) {
6965
- const dayNumber = getDayNumber(dmy);
6966
- setInternalStartDayNumber(timeline, dayNumber, pixelOffset, emitStateChange, options);
8423
+ setInternalStartDayPoint(timeline, getDayPoint(dmy), pixelOffset, emitStateChange, options);
6967
8424
  }
6968
8425
  __name(setInternalStartDate, "setInternalStartDate");
6969
- function getDayNumberFromPivotPoint(timeline, pivotPoint) {
8426
+ function getDayPointFromPivotPoint(timeline, pivotPoint) {
6970
8427
  const pixelsPerDay = getPixelsPerDay(timeline);
8428
+ const point = getDayPoint(pivotPoint.date);
6971
8429
  if (!pixelsPerDay) {
6972
- return getDayNumber(pivotPoint.date);
8430
+ return point;
6973
8431
  }
6974
- return getDayNumber(pivotPoint.date) + pivotPoint.fraction / pixelsPerDay;
8432
+ return addDaysToDayPoint(point, pivotPoint.fraction / pixelsPerDay);
6975
8433
  }
6976
- __name(getDayNumberFromPivotPoint, "getDayNumberFromPivotPoint");
6977
- function getDayNumberAtPixel(timeline, pixel) {
6978
- return getDayNumberFromPivotPoint(timeline, timeline.getPivotPoint(pixel));
8434
+ __name(getDayPointFromPivotPoint, "getDayPointFromPivotPoint");
8435
+ function getDayPointAtPixel(timeline, pixel) {
8436
+ return getDayPointFromPivotPoint(timeline, timeline.getPivotPoint(pixel));
6979
8437
  }
6980
- __name(getDayNumberAtPixel, "getDayNumberAtPixel");
8438
+ __name(getDayPointAtPixel, "getDayPointAtPixel");
6981
8439
  function getDayNumber(dmy) {
6982
- return dmy.getDaysSinceYearZero();
8440
+ return dmy.getDaysSinceYearZero() + dmy.getMillisecondsOfDay() / MILLISECONDS_PER_DAY;
6983
8441
  }
6984
8442
  __name(getDayNumber, "getDayNumber");
6985
8443
  function getDmyFromDayNumber(dayNumber) {
@@ -7004,12 +8462,12 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7004
8462
  return start + (end - start) * progress;
7005
8463
  }
7006
8464
  __name(interpolate, "interpolate");
7007
- function getFitZoomForDayNumbers(timeline, startDayNumber, endDayNumber, padding, fallbackZoom) {
7008
- if (endDayNumber <= startDayNumber) {
8465
+ function getFitZoomForDayPoints(timeline, startPoint, endPoint, padding, fallbackZoom) {
8466
+ if (compareDayPoints(endPoint, startPoint) <= 0) {
7009
8467
  return fallbackZoom;
7010
8468
  }
7011
8469
  const manager = timeline.timescaleManager;
7012
- const currentPixelSpan = (endDayNumber - startDayNumber) * getPixelsPerDay(timeline);
8470
+ const currentPixelSpan = getDayPointDifference(startPoint, endPoint) * getPixelsPerDay(timeline);
7013
8471
  if (!Number.isFinite(currentPixelSpan) || currentPixelSpan <= 0) {
7014
8472
  return fallbackZoom;
7015
8473
  }
@@ -7020,10 +8478,10 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7020
8478
  }
7021
8479
  let targetZoom = manager.zoom + zoomChange;
7022
8480
  for (let i = 0; i < 4; i++) {
7023
- const predictedPixelSpan = getPixelsBetweenDayNumbersAtZoom(
8481
+ const predictedPixelSpan = getPixelsBetweenDayPointsAtZoom(
7024
8482
  manager,
7025
- startDayNumber,
7026
- endDayNumber,
8483
+ startPoint,
8484
+ endPoint,
7027
8485
  targetZoom
7028
8486
  );
7029
8487
  if (!Number.isFinite(predictedPixelSpan) || predictedPixelSpan <= 0) {
@@ -7040,7 +8498,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7040
8498
  }
7041
8499
  return normaliseZoomForManager(manager, targetZoom);
7042
8500
  }
7043
- __name(getFitZoomForDayNumbers, "getFitZoomForDayNumbers");
8501
+ __name(getFitZoomForDayPoints, "getFitZoomForDayPoints");
7044
8502
  function stopNavigationAnimations(timeline) {
7045
8503
  var _a, _b, _c, _d, _e;
7046
8504
  if (typeof timeline.stopPanAnimation === "function") {
@@ -7079,13 +8537,13 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7079
8537
  timeline.startAnimation();
7080
8538
  const startZoom = timeline.timescaleManager.zoom;
7081
8539
  const fitPixelSpan = getFitPixelSpan(timeline, padding);
7082
- const startDayNumberAtPadding = getDayNumberAtPixel(timeline, padding.left);
7083
- const startEndDayNumberAtPadding = getDayNumberAtPixel(timeline, padding.left + fitPixelSpan);
8540
+ const startPointAtPadding = getDayPointAtPixel(timeline, padding.left);
8541
+ const startEndPointAtPadding = getDayPointAtPixel(timeline, padding.left + fitPixelSpan);
7084
8542
  const targetInternalStart = timeline.getDmyFromInput(normaliseDateInput(targetStartDate));
7085
8543
  const targetInternalEnd = timeline.getDmyFromInput(normaliseDateInput(targetEndDate));
7086
- const targetDayNumber = getDayNumber(targetInternalStart);
7087
- const targetEndDayNumber = getDayNumber(targetInternalEnd);
7088
- 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;
7089
8547
  const rangeTween = tween({
7090
8548
  from: 0,
7091
8549
  to: 1,
@@ -7097,13 +8555,13 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7097
8555
  rangeTween.stop();
7098
8556
  return;
7099
8557
  }
7100
- const nextDayNumber = interpolate(startDayNumberAtPadding, targetDayNumber, progress);
8558
+ const nextPoint = interpolateDayPoints(startPointAtPadding, targetPoint, progress);
7101
8559
  let nextZoom = startZoom;
7102
8560
  if (progress > 0) {
7103
- nextZoom = canInterpolateBoundaries ? getFitZoomForDayNumbers(
8561
+ nextZoom = canInterpolateBoundaries ? getFitZoomForDayPoints(
7104
8562
  timeline,
7105
- nextDayNumber,
7106
- interpolate(startEndDayNumberAtPadding, targetEndDayNumber, progress),
8563
+ nextPoint,
8564
+ interpolateDayPoints(startEndPointAtPadding, targetEndPoint, progress),
7107
8565
  padding,
7108
8566
  timeline.timescaleManager.zoom
7109
8567
  ) : interpolate(startZoom, targetZoom, progress);
@@ -7111,7 +8569,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7111
8569
  if (nextZoom !== timeline.timescaleManager.zoom) {
7112
8570
  timeline.timescaleManager.setZoom(nextZoom);
7113
8571
  }
7114
- setInternalStartDayNumber(timeline, nextDayNumber, padding.left);
8572
+ setInternalStartDayPoint(timeline, nextPoint, padding.left);
7115
8573
  },
7116
8574
  onComplete() {
7117
8575
  if (targetZoom !== timeline.timescaleManager.zoom) {
@@ -7143,7 +8601,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7143
8601
  if (!latest || from.compare(latest) > 0) {
7144
8602
  latest = from;
7145
8603
  }
7146
- const style = article._getCurrentStyle();
8604
+ const style = article.getCurrentStyle();
7147
8605
  const connectorOffset = (_c = (_b = style.connectorLine) == null ? void 0 : _b.offsetX) != null ? _c : 0;
7148
8606
  const width = (_d = style.width) != null ? _d : 0;
7149
8607
  maxCardLeftOffset = Math.max(maxCardLeftOffset, connectorOffset);
@@ -7620,16 +9078,24 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7620
9078
  if (!pixelsPerDay) {
7621
9079
  return;
7622
9080
  }
7623
- const viewport = getViewportDayRange(this);
7624
- const viewportSpanDays = viewport.end - viewport.start;
7625
- let leftDayNumber = viewport.start;
7626
- if (bounds.minDay != null && viewport.start < bounds.minDay) {
7627
- leftDayNumber = bounds.minDay - getUnresistedElasticOverflowDays(this, bounds.minDay - viewport.start);
7628
- } else if (bounds.maxDay != null && viewport.end > bounds.maxDay) {
7629
- leftDayNumber = bounds.maxDay + getUnresistedElasticOverflowDays(this, viewport.end - bounds.maxDay) - viewportSpanDays;
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
+ );
7630
9096
  }
7631
9097
  this.dragDateBoundsState = {
7632
- leftDayNumber,
9098
+ leftDayPoint,
7633
9099
  pixelsPerDay,
7634
9100
  viewportSpanDays
7635
9101
  };
@@ -7681,10 +9147,13 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7681
9147
  this.animation.dragRedrawFunction = this.defaultRedraw;
7682
9148
  }
7683
9149
  if (this.dragDateBoundsState) {
7684
- const targetLeftDayNumber = this.dragDateBoundsState.leftDayNumber + cumulativeMovePixelsX / this.dragDateBoundsState.pixelsPerDay;
7685
- setElasticBoundedViewportStartDay(
9150
+ const targetLeftDayPoint = addDaysToDayPoint(
9151
+ this.dragDateBoundsState.leftDayPoint,
9152
+ cumulativeMovePixelsX / this.dragDateBoundsState.pixelsPerDay
9153
+ );
9154
+ setElasticBoundedViewportStartPoint(
7686
9155
  this,
7687
- targetLeftDayNumber,
9156
+ targetLeftDayPoint,
7688
9157
  this.dragDateBoundsState.viewportSpanDays
7689
9158
  );
7690
9159
  } else {
@@ -7873,20 +9342,27 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7873
9342
  }
7874
9343
  };
7875
9344
  Timeline.prototype.getDmyFromInput = function(dmy) {
7876
- var _a, _b, _c;
9345
+ var _a, _b, _c, _d, _e, _f, _g;
7877
9346
  let normalised;
7878
9347
  if (typeof dmy === "string") {
7879
9348
  normalised = Dmy.fromString(dmy);
9349
+ if (!Number.isFinite(normalised.year)) {
9350
+ throw new Error(`Invalid Histropedia date string: ${dmy}`);
9351
+ }
7880
9352
  } else if (dmy instanceof Dmy) {
7881
9353
  normalised = new Dmy(dmy);
7882
9354
  } else {
7883
9355
  normalised = new Dmy({
7884
9356
  year: dmy.year,
7885
9357
  month: (_a = dmy.month) != null ? _a : 1,
7886
- 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
7887
9363
  });
7888
9364
  }
7889
- if (!((_c = this.options) == null ? void 0 : _c.shiftBceDates)) {
9365
+ if (!((_g = this.options) == null ? void 0 : _g.shiftBceDates)) {
7890
9366
  return normalised;
7891
9367
  }
7892
9368
  if (normalised.year < 0) {
@@ -7957,7 +9433,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
7957
9433
  article = this.articles[i];
7958
9434
  }
7959
9435
  }
7960
- return !isUndefined$1(article);
9436
+ return !isUndefined(article);
7961
9437
  };
7962
9438
  Timeline.prototype.reposition = function(article, drawCycleContext) {
7963
9439
  if (article.isDragging) {
@@ -8001,7 +9477,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8001
9477
  from = 0;
8002
9478
  }
8003
9479
  }
8004
- const style = article._getCurrentStyle();
9480
+ const style = article.getCurrentStyle();
8005
9481
  const lane = this.getLaneById(article.laneId);
8006
9482
  if (this._isLaneLayoutActive() && lane && lane.geometry) {
8007
9483
  return {
@@ -8370,6 +9846,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8370
9846
  };
8371
9847
  }
8372
9848
  __name(resolveAreaExtents, "resolveAreaExtents");
9849
+ const MAIN_RANGE_RIGHT_BUFFER = 150;
8373
9850
  Timeline.prototype.defaultRedraw = function() {
8374
9851
  this.redraw({
8375
9852
  // 1. update isVisibleInGroup and after articles IsInRange is decided
@@ -8475,7 +9952,6 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8475
9952
  });
8476
9953
  };
8477
9954
  Timeline.prototype.render = function(ctx, top, width, markers, drawCycleContext) {
8478
- const halfMainlineSize = this.options.style.mainLine.size >> 1;
8479
9955
  const effectiveVerticalOffset = this._getEffectiveVerticalOffset ? this._getEffectiveVerticalOffset() : this.options.verticalOffset;
8480
9956
  if (!this.owner) {
8481
9957
  ctx.clearRect(0, 0, width, this.top + effectiveVerticalOffset);
@@ -8487,19 +9963,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8487
9963
  this.drawDraggingHighlight(ctx, top, width);
8488
9964
  const mainLineTop = this.options.style.mainLine.position === "top" ? -effectiveVerticalOffset : top;
8489
9965
  this.drawMainline(ctx, mainLineTop, width, markers);
8490
- if (this.options.style.mainLine.showDateIndicators) {
8491
- ctx.beginPath();
8492
- this.forInRangeArticles(/* @__PURE__ */ __name(function redraw_articles_drawIndicators(article) {
8493
- if (!article.isHiddenByFilter && article.isInView) {
8494
- ctx.moveTo(article.indicator.fromX, top - halfMainlineSize);
8495
- ctx.lineTo(article.indicator.fromX, top + halfMainlineSize);
8496
- }
8497
- }, "redraw_articles_drawIndicators"));
8498
- ctx.lineWidth = 3;
8499
- ctx.globalAlpha = 0.75;
8500
- ctx.strokeStyle = "#303030";
8501
- ctx.stroke();
8502
- }
9966
+ this.drawDateIndicators(ctx, mainLineTop);
8503
9967
  ctx.globalAlpha = 1;
8504
9968
  for (let i = 0; i < this.articles.length; i++) {
8505
9969
  const article = this.articles[i];
@@ -8530,7 +9994,55 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8530
9994
  this.drawDensityRegionBoundaries(ctx, width, drawCycleContext);
8531
9995
  }
8532
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
+ };
8533
10042
  Timeline.prototype.getDensityRegionBoundaryDate = function(groupIndex) {
10043
+ if (isSubdayDensityGroupIndex(groupIndex)) {
10044
+ return getDmyFromDayNumber(groupIndex.day);
10045
+ }
8534
10046
  const step = this.currentDensitySetting.step;
8535
10047
  if (this.timescaleManager.unit >= ZOOM_MONTH && step.months !== 0) {
8536
10048
  const monthIndex = groupIndex * step.months;
@@ -8555,15 +10067,29 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8555
10067
  }
8556
10068
  return boundary;
8557
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
+ };
8558
10083
  Timeline.prototype.drawDensityRegionBoundaries = function(ctx, width, drawCycleContext) {
8559
10084
  var _a;
8560
10085
  const tokens = drawCycleContext == null ? void 0 : drawCycleContext.tokens;
8561
10086
  if (!(tokens == null ? void 0 : tokens.start) || !(tokens == null ? void 0 : tokens.end) || !((_a = this.currentDensitySetting) == null ? void 0 : _a.step)) {
8562
10087
  return;
8563
10088
  }
8564
- const firstGroup = this.calculateGroupIndex(tokens.start) - 1;
8565
- 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);
8566
10091
  const startDate = this.timescaleManager.startToken.value;
10092
+ const pixelsPerDay = getPixelsPerDay(this);
8567
10093
  const height = this.options.height;
8568
10094
  let previousX = null;
8569
10095
  ctx.save();
@@ -8572,9 +10098,9 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8572
10098
  ctx.lineWidth = 1;
8573
10099
  ctx.strokeStyle = "rgba(204, 0, 153, 0.8)";
8574
10100
  ctx.setLineDash([4, 4]);
8575
- for (let groupIndex = firstGroup; groupIndex <= lastGroup; groupIndex++) {
8576
- const boundary = this.getDensityRegionBoundaryDate(groupIndex);
8577
- 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;
8578
10104
  const x = Math.round(rawX) + 0.5;
8579
10105
  if (x < 0 || x > width || x === previousX) {
8580
10106
  continue;
@@ -8590,23 +10116,26 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8590
10116
  if (this.options.style.mainLine.visible) {
8591
10117
  ctx.globalAlpha = 1;
8592
10118
  const halfMainlineSize = this.options.style.mainLine.size >> 1;
8593
- const mainLineGradient = ctx.createLinearGradient(
8594
- 0,
8595
- top - halfMainlineSize,
8596
- 0,
8597
- top + halfMainlineSize
8598
- );
8599
- mainLineGradient.addColorStop(0, "#808080");
8600
- 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
+ }
8601
10126
  ctx.beginPath();
8602
10127
  ctx.lineWidth = this.options.style.mainLine.size;
8603
- ctx.strokeStyle = ctx.fillStyle = mainLineGradient;
10128
+ ctx.strokeStyle = ctx.fillStyle = fillStyle;
8604
10129
  ctx.moveTo(0, top);
8605
10130
  ctx.lineTo(width, top);
8606
10131
  ctx.stroke();
8607
10132
  for (const type in markers) {
8608
- 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
+ });
8609
10137
  }
10138
+ this.drawParentDateLabels(ctx, top + halfMainlineSize, width);
8610
10139
  }
8611
10140
  };
8612
10141
  Timeline.prototype.drawDraggingHighlight = function(ctx, top, width) {
@@ -8676,28 +10205,204 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8676
10205
  ctx.restore();
8677
10206
  };
8678
10207
  Timeline.prototype.getTokensAndMarkers = function(width) {
10208
+ var _a, _b;
8679
10209
  const tokens = {};
8680
10210
  const markers = {};
8681
10211
  markers[MAJOR_MARKER] = [];
8682
10212
  markers[MINOR_MARKER] = [];
10213
+ const visualMarkerLayout = (_b = (_a = this.timescaleManager).getSubdayVisualMarkerLayout) == null ? void 0 : _b.call(_a);
8683
10214
  let x = this.repositionWindow;
8684
10215
  let token = this.timescaleManager.startToken;
8685
10216
  tokens.start = token.value;
8686
- let endToken = token;
8687
- const leftBufferNumberOfTokens = 9;
8688
- token = this.timescaleManager.getPreviousNth(token, leftBufferNumberOfTokens);
8689
- 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
+ }
8690
10228
  do {
8691
- markers[token.type].push(token);
8692
- 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
+ }
8693
10234
  x += token.length;
8694
- endToken = token;
8695
10235
  token = this.timescaleManager.getNext(token);
8696
- } while (x < width + 150);
8697
- 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;
8698
10247
  return { tokens, markers };
8699
10248
  };
8700
- 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 = {}) {
8701
10406
  if (tokens.length === 0) {
8702
10407
  return;
8703
10408
  }
@@ -8715,7 +10420,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8715
10420
  const isExtended = markerStyle.extend;
8716
10421
  const markerDirection = this.options.style.mainLine.position === "top" ? -1 : 1;
8717
10422
  const markerHeight = markerStyle.height;
8718
- const withLabel = !!tokens[0].label;
10423
+ const withLabel = tokens.some((token) => token.label);
8719
10424
  let isInFuture = tokens[0].value.isInFuture();
8720
10425
  let wasInPast = !isInFuture;
8721
10426
  let labelStyle;
@@ -8730,6 +10435,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8730
10435
  ctx.textBaseline = markerDirection === 1 ? "alphabetic" : "top";
8731
10436
  labelY = markerTop + markerHeight * markerDirection + labelStyle.offset.y;
8732
10437
  }
10438
+ const stickyLabel = withLabel && tokenType === "major" ? getStickyMajorLabel(ctx, tokens, labelStyle, drawOptions) : null;
8733
10439
  ctx.beginPath();
8734
10440
  for (let i = 0; i < tokens.length; i++) {
8735
10441
  const token = tokens[i];
@@ -8746,7 +10452,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8746
10452
  const markerEndY = isExtended ? markerTop + -1 * markerDirection * this.top : markerTop;
8747
10453
  ctx.lineTo(drawX, markerEndY);
8748
10454
  if (withLabel && token.label) {
8749
- const labelX = drawX + labelStyle.offset.x;
10455
+ const labelX = (stickyLabel == null ? void 0 : stickyLabel.token) === token ? stickyLabel.labelX : drawX + labelStyle.offset.x;
8750
10456
  ctx.fillStyle = isInFuture ? labelStyle.futureColor : labelStyle.color;
8751
10457
  ctx.fillText(token.label, labelX, labelY);
8752
10458
  }
@@ -8802,6 +10508,46 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8802
10508
  const lane = this.getLaneById(laneId);
8803
10509
  return getResolvedLaneArticleOptions(this, lane);
8804
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
+ };
8805
10551
  Timeline.prototype._getExplicitArticleCardLayout = function(articleOrData) {
8806
10552
  if (!articleOrData) {
8807
10553
  return null;
@@ -10156,6 +11902,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
10156
11902
  const FRAME_MS = 1e3 / 60;
10157
11903
  const STANDARD_WHEEL_NOTCH_DELTA = 120;
10158
11904
  const MIN_BROWSER_ZOOM_SCALED_NOTCH_DELTA = 24;
11905
+ const MILLISECOND_BOUNDARY_EPSILON = 1e-7;
10159
11906
  const BROWSER_ZOOM_SCALE_FACTORS = [
10160
11907
  0.25,
10161
11908
  1 / 3,
@@ -10431,7 +12178,8 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
10431
12178
  Timeline.prototype.setZoomByPivotPoint = /* @__PURE__ */ __name(function setZoomByPivotPoint(newZoom, pivotPoint, pivotPixel, offsetX = 0) {
10432
12179
  this.timescaleManager.setZoom(newZoom);
10433
12180
  const compensation = this.timescaleManager.setStartDate(pivotPoint.date);
10434
- 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;
10435
12183
  this.updateFromByPixels(-pivotPixel + offsetX);
10436
12184
  applyTimelineDateBounds(this, {
10437
12185
  mode: this.isDragging || this.isPinching ? "elastic" : "clamp"
@@ -10455,7 +12203,23 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
10455
12203
  let fraction = pixel - (x - token.length);
10456
12204
  const dmy = prevToken.value;
10457
12205
  let { year, month, day } = dmy;
10458
- 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) {
10459
12223
  day = Math.floor(fraction / len * 30.44) + 1;
10460
12224
  fraction -= (day - 1) * len / 30.44;
10461
12225
  prevToken.value = new Dmy(year, month, day);
@@ -10738,10 +12502,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
10738
12502
  var _a;
10739
12503
  const settings = normaliseSetStartDateOptions(options);
10740
12504
  const padding = settings.padding || 0;
10741
- if (typeof dmy === "string") {
10742
- dmy = Dmy.fromString(dmy);
10743
- }
10744
- dmy = this.getDmyFromInput(dmy);
12505
+ dmy = this.getDmyFromInput(normaliseDateInput(dmy));
10745
12506
  if ((_a = settings.animation) == null ? void 0 : _a.active) {
10746
12507
  animateStartDate(this, dmy, padding, settings.animation);
10747
12508
  return;
@@ -10901,44 +12662,6 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
10901
12662
  this.off(event, handlers[event]);
10902
12663
  }
10903
12664
  };
10904
- function roundPixel(value) {
10905
- return Math.round(value);
10906
- }
10907
- __name(roundPixel, "roundPixel");
10908
- function snapPixel(value, dpr = 1) {
10909
- const ratio = typeof dpr === "number" && isFinite(dpr) && dpr > 0 ? dpr : 1;
10910
- return Math.round(value * ratio) / ratio;
10911
- }
10912
- __name(snapPixel, "snapPixel");
10913
- function retainPixel(value) {
10914
- return value;
10915
- }
10916
- __name(retainPixel, "retainPixel");
10917
- function createPixelSnap(dpr = 1, mode = "device") {
10918
- if (mode === false || mode === "none") {
10919
- return retainPixel;
10920
- }
10921
- if (mode === "css") {
10922
- return roundPixel;
10923
- }
10924
- return /* @__PURE__ */ __name(function snapToDevicePixel(value) {
10925
- return snapPixel(value, dpr);
10926
- }, "snapToDevicePixel");
10927
- }
10928
- __name(createPixelSnap, "createPixelSnap");
10929
- function createInnerSpace(outerSpace, borderWidth, snap) {
10930
- if (!snap) {
10931
- snap = roundPixel;
10932
- }
10933
- const halfBorder = borderWidth / 2;
10934
- return {
10935
- left: snap(outerSpace.left + halfBorder),
10936
- top: snap(outerSpace.top + halfBorder),
10937
- width: snap(outerSpace.width - borderWidth),
10938
- height: snap(outerSpace.height - borderWidth)
10939
- };
10940
- }
10941
- __name(createInnerSpace, "createInnerSpace");
10942
12665
  function getPixelSnap$1(article) {
10943
12666
  var _a, _b, _c, _d, _e, _f;
10944
12667
  const dpr = ((_b = (_a = article.owner) == null ? void 0 : _a.getCanvasDpr) == null ? void 0 : _b.call(_a)) || 1;
@@ -10961,7 +12684,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
10961
12684
  if (!this.isDataLoaded || isNaN(this.position.left)) {
10962
12685
  return;
10963
12686
  }
10964
- const style = this._getCurrentStyle();
12687
+ const style = this.getCurrentStyle();
10965
12688
  const snap = getPixelSnap$1(this);
10966
12689
  const articleOrigin = getSnappedArticleOrigin$1(this);
10967
12690
  const top = articleOrigin.top;
@@ -11137,7 +12860,11 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11137
12860
  }
11138
12861
  }
11139
12862
  if (showStar) {
11140
- 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);
11141
12868
  let starStroke, starFill;
11142
12869
  if (!this.isStarred) {
11143
12870
  if (this.isMouseOverStar) {
@@ -11156,26 +12883,17 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11156
12883
  starFill = "#fff800";
11157
12884
  }
11158
12885
  }
11159
- drawStar(
11160
- ctx,
11161
- star.centreX,
11162
- star.centreY,
11163
- 5,
11164
- star.innerRadius,
11165
- star.outerRadius,
11166
- starFill,
11167
- starStroke
11168
- );
12886
+ drawStar(ctx, centreX, centreY, 5, innerRadius, outerRadius, starFill, starStroke);
11169
12887
  }
11170
12888
  },
11171
12889
  getWidth() {
11172
- return this._getCurrentStyle().width;
12890
+ return this.getCurrentStyle().width;
11173
12891
  },
11174
12892
  getHeight() {
11175
- return this._getCurrentStyle().height;
12893
+ return this.getCurrentStyle().height;
11176
12894
  },
11177
12895
  getConnectorEnd() {
11178
- const style = this._getCurrentStyle();
12896
+ const style = this.getCurrentStyle();
11179
12897
  const articleOrigin = getSnappedArticleOrigin$1(this);
11180
12898
  return {
11181
12899
  left: articleOrigin.left + style.connectorLine.offsetX,
@@ -11187,7 +12905,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11187
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) {
11188
12906
  return false;
11189
12907
  }
11190
- const style = this._getCurrentStyle();
12908
+ const style = this.getCurrentStyle();
11191
12909
  const snap = getPixelSnap$1(this);
11192
12910
  const sideLength = style.star.width;
11193
12911
  const box = {
@@ -11198,10 +12916,6 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11198
12916
  const articleOrigin = getSnappedArticleOrigin$1(this);
11199
12917
  box.left = snap(articleOrigin.left - br / 4 + this._getWidth() - box.width - style.star.margin);
11200
12918
  box.top = snap(articleOrigin.top + br / 4 + style.star.margin);
11201
- box.centreX = snap(box.left + box.width / 2);
11202
- box.centreY = snap(box.top + box.height / 2);
11203
- box.outerRadius = snap(box.width / 2);
11204
- box.innerRadius = snap(box.outerRadius / 2);
11205
12919
  return box;
11206
12920
  },
11207
12921
  defaultStyle: {
@@ -11265,7 +12979,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11265
12979
  name: "portrait",
11266
12980
  draw(ctx) {
11267
12981
  var _a, _b, _c, _d, _e, _f, _g, _h;
11268
- const style = this._getCurrentStyle();
12982
+ const style = this.getCurrentStyle();
11269
12983
  const snap = getPixelSnap(this);
11270
12984
  const borderWidth = style.border.width;
11271
12985
  const maxBorderWidth = Math.max(
@@ -11504,7 +13218,11 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11504
13218
  ctx.stroke();
11505
13219
  }
11506
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)) {
11507
- 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);
11508
13226
  let starStroke, starFill;
11509
13227
  if (!this.isStarred) {
11510
13228
  if (this.isMouseOverStar) {
@@ -11523,23 +13241,14 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11523
13241
  starFill = "#fff800";
11524
13242
  }
11525
13243
  }
11526
- drawStar(
11527
- ctx,
11528
- star.centreX,
11529
- star.centreY,
11530
- 5,
11531
- star.innerRadius,
11532
- star.outerRadius,
11533
- starFill,
11534
- starStroke
11535
- );
13244
+ drawStar(ctx, centreX, centreY, 5, innerRadius, outerRadius, starFill, starStroke);
11536
13245
  }
11537
13246
  },
11538
13247
  getWidth() {
11539
- return this._getCurrentStyle().width;
13248
+ return this.getCurrentStyle().width;
11540
13249
  },
11541
13250
  getHeight() {
11542
- const style = this._getCurrentStyle();
13251
+ const style = this.getCurrentStyle();
11543
13252
  const snap = getPixelSnap(this);
11544
13253
  let imageHeight = 0;
11545
13254
  if (this.imageLoaded) {
@@ -11565,7 +13274,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11565
13274
  return imageHeight + articleTopHeight + style.border.width;
11566
13275
  },
11567
13276
  getConnectorEnd() {
11568
- const style = this._getCurrentStyle();
13277
+ const style = this.getCurrentStyle();
11569
13278
  const articleOrigin = getSnappedArticleOrigin(this);
11570
13279
  return {
11571
13280
  left: articleOrigin.left + style.connectorLine.offsetX,
@@ -11577,7 +13286,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11577
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) {
11578
13287
  return false;
11579
13288
  }
11580
- const style = this._getCurrentStyle();
13289
+ const style = this.getCurrentStyle();
11581
13290
  const snap = getPixelSnap(this);
11582
13291
  const articleOrigin = getSnappedArticleOrigin(this);
11583
13292
  const sideLength = style.star.width;
@@ -11592,36 +13301,16 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11592
13301
  return box;
11593
13302
  }
11594
13303
  };
11595
- function getStarBox(article) {
11596
- const style = article._getCurrentStyle();
11597
- const snap = getPixelSnap(article);
11598
- const articleOrigin = getSnappedArticleOrigin(article);
11599
- const sideLength = style.star.width;
11600
- const box = {
11601
- width: sideLength,
11602
- height: sideLength
11603
- };
11604
- box.left = snap(
11605
- articleOrigin.left - style.topRadius / 4 + article._getWidth() - box.width - style.star.margin
11606
- );
11607
- box.top = snap(articleOrigin.top + style.topRadius / 4 + style.star.margin);
11608
- box.centreX = snap(box.left + box.width / 2);
11609
- box.centreY = snap(box.top + box.height / 2);
11610
- box.outerRadius = snap(box.width / 2);
11611
- box.innerRadius = snap(box.outerRadius / 2);
11612
- return box;
11613
- }
11614
- __name(getStarBox, "getStarBox");
11615
13304
  const _cardLayouts = /* @__PURE__ */ new Map();
11616
13305
  function _injectDimensionFallbacks(layout) {
11617
13306
  if (typeof layout.getWidth !== "function") {
11618
13307
  layout.getWidth = function() {
11619
- return this._getCurrentStyle().width;
13308
+ return this.getCurrentStyle().width;
11620
13309
  };
11621
13310
  }
11622
13311
  if (typeof layout.getHeight !== "function") {
11623
13312
  layout.getHeight = function() {
11624
- return this._getCurrentStyle().height;
13313
+ return this.getCurrentStyle().height;
11625
13314
  };
11626
13315
  }
11627
13316
  if (typeof layout.getIconBox !== "function") {
@@ -11683,10 +13372,23 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11683
13372
  Timeline.prototype.getStatusForSave = function() {
11684
13373
  const from = this.timescaleManager.startToken.value;
11685
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
+ }
11686
13388
  for (let i = 0; i < this.articles.length; i++) {
11687
13389
  articleSaveInfo.push(this.articles[i].getStatusForSave());
11688
13390
  }
11689
- return JSON.stringify({
13391
+ return JSON.stringify(__spreadProps(__spreadValues({
11690
13392
  t: this.title,
11691
13393
  o: this.ownerId,
11692
13394
  // set by host app if needed
@@ -11694,10 +13396,11 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
11694
13396
  // d: event spacing removed in current implementation
11695
13397
  fy: from.year,
11696
13398
  fm: from.month,
11697
- fd: from.day,
13399
+ fd: from.day
13400
+ }, fromTime), {
11698
13401
  w: this.repositionWindow,
11699
13402
  a: articleSaveInfo
11700
- });
13403
+ }));
11701
13404
  };
11702
13405
  Timeline.prototype._emitTimelineStateChange = function() {
11703
13406
  if (this && this._isInitialized === true) {