histropediajs 1.6.0 → 1.6.2

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.6.0 | Histropedia Ltd. (c) 2026 | https://js.histropedia.com
2
+ HistropediaJS v1.6.2 | 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
  var __defProp = Object.defineProperty;
@@ -65,1785 +65,42 @@ function tween({
65
65
  };
66
66
  }
67
67
  __name(tween, "tween");
68
- const _LoggerImpl = class _LoggerImpl {
69
- constructor() {
70
- this._enabled = false;
71
- this._prefix = "[Histropedia]";
72
- const c = typeof console !== "undefined" ? console : null;
73
- this._console = c;
74
- this._fns = {
75
- log: c && c.log ? c.log.bind(c) : () => {
76
- },
77
- warn: c && c.warn ? c.warn.bind(c) : () => {
78
- },
79
- error: c && c.error ? c.error.bind(c) : () => {
80
- },
81
- info: c && c.info ? c.info.bind(c) : () => {
82
- },
83
- debug: c && c.debug ? c.debug.bind(c) : c && c.log ? c.log.bind(c) : () => {
84
- },
85
- group: c && c.group ? c.group.bind(c) : c && c.log ? c.log.bind(c) : () => {
86
- },
87
- groupCollapsed: c && c.groupCollapsed ? c.groupCollapsed.bind(c) : c && c.group ? c.group.bind(c) : c && c.log ? c.log.bind(c) : () => {
88
- },
89
- groupEnd: c && c.groupEnd ? c.groupEnd.bind(c) : () => {
90
- }
91
- };
92
- }
93
- setEnabled(enabled) {
94
- this._enabled = !!enabled;
95
- }
96
- isEnabled() {
97
- return !!this._enabled;
98
- }
99
- setPrefix(prefix) {
100
- this._prefix = String(prefix || "");
101
- }
102
- getPrefix() {
103
- return this._prefix;
104
- }
105
- _withPrefixedArgs(argsArray) {
106
- if (!this._prefix) {
107
- return argsArray;
108
- }
109
- if (argsArray && argsArray.length > 0 && typeof argsArray[0] === "string") {
110
- const cloned = argsArray.slice();
111
- cloned[0] = `${this._prefix} ${cloned[0]}`;
112
- return cloned;
113
- }
114
- return [this._prefix, ...argsArray];
115
- }
116
- _log(method, args) {
117
- if (!this._enabled) {
118
- return;
119
- }
120
- const fn = this._fns[method] || this._fns.log;
121
- fn(...this._withPrefixedArgs(args));
122
- }
123
- log(...args) {
124
- this._log("log", args);
125
- }
126
- warn(...args) {
127
- this._log("warn", args);
128
- }
129
- error(...args) {
130
- this._log("error", args);
131
- }
132
- info(...args) {
133
- this._log("info", args);
134
- }
135
- debug(...args) {
136
- this._log("debug", args);
137
- }
138
- group(...args) {
139
- if (!this._enabled) {
140
- return;
141
- }
142
- this._fns.group(...this._withPrefixedArgs(args));
143
- }
144
- groupCollapsed(...args) {
145
- if (!this._enabled) {
146
- return;
147
- }
148
- this._fns.groupCollapsed(...this._withPrefixedArgs(args));
149
- }
150
- groupEnd() {
151
- if (!this._enabled) {
152
- return;
153
- }
154
- this._fns.groupEnd();
155
- }
156
- };
157
- __name(_LoggerImpl, "LoggerImpl");
158
- let LoggerImpl = _LoggerImpl;
159
- const Logger = new LoggerImpl();
160
- const DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
161
- const MONTH_NAMES = [
162
- "Jan",
163
- "Feb",
164
- "Mar",
165
- "Apr",
166
- "May",
167
- "Jun",
168
- "Jul",
169
- "Aug",
170
- "Sep",
171
- "Oct",
172
- "Nov",
173
- "Dec"
174
- ];
175
- const LEGACY_PRECISIONS = {
176
- 1: "billion-years",
177
- 3: "million-years",
178
- 6: "millennium",
179
- 7: "century",
180
- 8: "decade",
181
- 9: "year",
182
- 10: "month",
183
- 11: "day",
184
- 12: "hour",
185
- 13: "minute",
186
- 14: "second",
187
- 15: "millisecond"
188
- };
189
- const DMY_STRING_PATTERN = /^(-?\d+)(?:-(\d{1,2}))?(?:-(\d{1,2}))?(?:[T ](\d{1,2})(?::(\d{1,2}))?(?::(\d{1,2})(?:\.(\d{1,3}))?)?)?$/;
190
- const MILLISECONDS_PER_SECOND = 1e3;
191
- const MILLISECONDS_PER_MINUTE = 60 * MILLISECONDS_PER_SECOND;
192
- const MILLISECONDS_PER_HOUR = 60 * MILLISECONDS_PER_MINUTE;
193
- const MILLISECONDS_PER_DAY = 24 * MILLISECONDS_PER_HOUR;
194
- function normalizePrecision(precision) {
195
- return Object.prototype.hasOwnProperty.call(LEGACY_PRECISIONS, precision) ? LEGACY_PRECISIONS[precision] : precision || "day";
196
- }
197
- __name(normalizePrecision, "normalizePrecision");
198
- function getHistoricalPeriodBounds(year, size) {
199
- const endYear = Math.ceil(year / size) * size;
200
- return {
201
- startYear: endYear - size + 1,
202
- endYear
203
- };
204
- }
205
- __name(getHistoricalPeriodBounds, "getHistoricalPeriodBounds");
206
- function clampInteger(value, fallback, minimum, maximum) {
207
- const parsed = Number(value);
208
- if (!Number.isFinite(parsed)) {
209
- return fallback;
210
- }
211
- return Math.min(maximum, Math.max(minimum, Math.trunc(parsed)));
212
- }
213
- __name(clampInteger, "clampInteger");
214
- function setTimeParts(target, hour, minute, second, millisecond) {
215
- const values = {
216
- hour: clampInteger(hour, 0, 0, 23),
217
- minute: clampInteger(minute, 0, 0, 59),
218
- second: clampInteger(second, 0, 0, 59),
219
- millisecond: clampInteger(millisecond, 0, 0, 999)
220
- };
221
- for (const [key, value] of Object.entries(values)) {
222
- Object.defineProperty(target, key, {
223
- value,
224
- enumerable: value !== 0,
225
- configurable: true,
226
- writable: true
227
- });
228
- }
229
- }
230
- __name(setTimeParts, "setTimeParts");
231
- function setPrecision(target, precision) {
232
- if (precision === void 0) {
233
- return;
234
- }
235
- Object.defineProperty(target, "precision", {
236
- value: precision,
237
- enumerable: false,
238
- configurable: true,
239
- writable: true
240
- });
241
- }
242
- __name(setPrecision, "setPrecision");
243
- function createAdjustedDmy(source, values) {
244
- return new Dmy({ ...values, precision: source.precision });
245
- }
246
- __name(createAdjustedDmy, "createAdjustedDmy");
247
- function Dmy(year, month, day, hour, minute, second, millisecond) {
248
- if (typeof year === "object") {
249
- const options = year;
250
- this.year = options.year;
251
- this.month = options.month;
252
- this.day = getCorrectDay(options.year, options.month, options.day);
253
- setTimeParts(this, options.hour, options.minute, options.second, options.millisecond);
254
- setPrecision(this, options.precision);
255
- } else {
256
- this.year = year;
257
- this.month = month;
258
- this.day = getCorrectDay(year, month, day);
259
- setTimeParts(this, hour, minute, second, millisecond);
260
- }
261
- }
262
- __name(Dmy, "Dmy");
263
- function getCorrectDay(year, month, day) {
264
- return day > 28 ? Math.min(day, daysInMonth(year, month)) : day;
265
- }
266
- __name(getCorrectDay, "getCorrectDay");
267
- function daysInMonth(year, month) {
268
- if (month === 2) {
269
- if (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0) {
270
- return 29;
271
- }
272
- }
273
- return DAYS_IN_MONTH[month - 1];
274
- }
275
- __name(daysInMonth, "daysInMonth");
276
- function digitGroupedNumber(number, separator) {
277
- number = number.toString();
278
- separator = typeof separator === "string" ? separator : ",";
279
- if (number.length <= 4) {
280
- return number;
281
- }
282
- return number.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
283
- }
284
- __name(digitGroupedNumber, "digitGroupedNumber");
285
- Dmy.prototype.getDaysTo = function(other) {
286
- const dayDifference = other.getDaysSinceYearZero() - this.getDaysSinceYearZero();
287
- const timeDifference = other.getMillisecondsOfDay() - this.getMillisecondsOfDay();
288
- return dayDifference + timeDifference / MILLISECONDS_PER_DAY;
289
- };
290
- Dmy.prototype.getMillisecondsOfDay = function() {
291
- return this.hour * MILLISECONDS_PER_HOUR + this.minute * MILLISECONDS_PER_MINUTE + this.second * MILLISECONDS_PER_SECOND + this.millisecond;
292
- };
293
- Dmy.prototype.getMonthsTo = function(other) {
294
- return this.getYearsTo(other) * 12;
295
- };
296
- Dmy.prototype.getYearsTo = function(other) {
297
- let yearDiff = other.year - this.year;
298
- yearDiff += (other.month - this.month) / 12 + (other.day - this.day) / 365.2422 + (other.getMillisecondsOfDay() - this.getMillisecondsOfDay()) / (MILLISECONDS_PER_DAY * 365.2422);
299
- return yearDiff;
300
- };
301
- Dmy.prototype.getLeapYearsSinceYearZero = function() {
302
- let year = this.year;
303
- if (this.month < 3) {
304
- year--;
305
- }
306
- return Math.floor(year / 4) - Math.floor(year / 100) + Math.floor(year / 400);
307
- };
308
- Dmy.prototype.getDaysSinceYearZero = function() {
309
- const year = this.year;
310
- let days = year * 365 + this.day;
311
- for (let i = 0; i < this.month - 1; i++) {
312
- days += DAYS_IN_MONTH[i];
313
- }
314
- days += this.getLeapYearsSinceYearZero();
315
- return days;
316
- };
317
- Dmy.prototype.getDayOfYear = function() {
318
- let dayOfYear = this.day;
319
- for (let m = 1; m < this.month; m++) {
320
- dayOfYear += daysInMonth(this.year, m);
321
- }
322
- return dayOfYear;
323
- };
324
- Dmy.getByDayOfYear = function(year, dayOfYear) {
325
- const dmy = new Dmy(year, 1, 1);
326
- let dim = DAYS_IN_MONTH[0];
327
- for (let i = 0; i < dayOfYear - 1; i++) {
328
- dmy.day++;
329
- if (dmy.day > dim) {
330
- dmy.day = 1;
331
- dmy.month++;
332
- if (dmy.month > 12) {
333
- dmy.month = 1;
334
- dmy.year++;
335
- }
336
- dim = dmy.month === 2 ? daysInMonth(dmy.year, dmy.month) : DAYS_IN_MONTH[dmy.month - 1];
337
- }
338
- }
339
- return dmy;
340
- };
341
- Dmy.prototype.getNextDay = function() {
342
- return this.addDays(1);
343
- };
344
- Dmy.prototype.addDays = function(amount) {
345
- let day = this.day;
346
- let month = this.month;
347
- let year = this.year;
348
- const direction = amount < 0 ? -1 : 1;
349
- let remaining = Math.abs(Math.trunc(amount));
350
- while (remaining > 0) {
351
- if (direction > 0) {
352
- day++;
353
- if (day > daysInMonth(year, month)) {
354
- day = 1;
355
- month++;
356
- if (month > 12) {
357
- month = 1;
358
- year++;
359
- }
360
- }
361
- } else {
362
- day--;
363
- if (day < 1) {
364
- month--;
365
- if (month < 1) {
366
- month = 12;
367
- year--;
368
- }
369
- day = daysInMonth(year, month);
370
- }
371
- }
372
- remaining--;
373
- }
374
- return createAdjustedDmy(this, {
375
- year,
376
- month,
377
- day,
378
- hour: this.hour,
379
- minute: this.minute,
380
- second: this.second,
381
- millisecond: this.millisecond
382
- });
383
- };
384
- Dmy.prototype.addMilliseconds = function(amount) {
385
- let date = this;
386
- let milliseconds = this.getMillisecondsOfDay() + Math.trunc(amount);
387
- while (milliseconds < 0) {
388
- date = date.addDays(-1);
389
- milliseconds += MILLISECONDS_PER_DAY;
390
- }
391
- while (milliseconds >= MILLISECONDS_PER_DAY) {
392
- date = date.addDays(1);
393
- milliseconds -= MILLISECONDS_PER_DAY;
394
- }
395
- const hour = Math.floor(milliseconds / MILLISECONDS_PER_HOUR);
396
- milliseconds -= hour * MILLISECONDS_PER_HOUR;
397
- const minute = Math.floor(milliseconds / MILLISECONDS_PER_MINUTE);
398
- milliseconds -= minute * MILLISECONDS_PER_MINUTE;
399
- const second = Math.floor(milliseconds / MILLISECONDS_PER_SECOND);
400
- const millisecond = milliseconds - second * MILLISECONDS_PER_SECOND;
401
- return createAdjustedDmy(this, {
402
- year: date.year,
403
- month: date.month,
404
- day: date.day,
405
- hour,
406
- minute,
407
- second,
408
- millisecond
409
- });
410
- };
411
- Dmy.prototype.addSeconds = function(amount) {
412
- return this.addMilliseconds(amount * MILLISECONDS_PER_SECOND);
413
- };
414
- Dmy.prototype.addMinutes = function(amount) {
415
- return this.addMilliseconds(amount * MILLISECONDS_PER_MINUTE);
416
- };
417
- Dmy.prototype.addHours = function(amount) {
418
- return this.addMilliseconds(amount * MILLISECONDS_PER_HOUR);
419
- };
420
- Dmy.prototype.addMonths = function(amount) {
421
- let month = this.month;
422
- let year = this.year;
423
- for (let i = 0; i < amount; i++) {
424
- month++;
425
- if (month > 12) {
426
- month = 1;
427
- year++;
428
- }
429
- }
430
- return createAdjustedDmy(this, { year, month, day: 1 });
431
- };
432
- Dmy.prototype.getPreviousDay = function() {
433
- return this.addDays(-1);
434
- };
435
- Dmy.prototype.getNextMonth = function() {
436
- let month = this.month;
437
- let year = this.year;
438
- month++;
439
- if (month > 12) {
440
- month = 1;
441
- year++;
442
- }
443
- return createAdjustedDmy(this, { year, month, day: 1 });
444
- };
445
- Dmy.prototype.getPreviousMonth = function() {
446
- let month = this.month;
447
- let year = this.year;
448
- month--;
449
- if (month < 1) {
450
- month = 12;
451
- year--;
452
- }
453
- return createAdjustedDmy(this, { year, month, day: 1 });
454
- };
455
- Dmy.prototype.addYears = function(amount) {
456
- return createAdjustedDmy(this, { year: this.year + amount, month: 1, day: 1 });
457
- };
458
- function pad(value, length) {
459
- return String(value).padStart(length, "0");
460
- }
461
- __name(pad, "pad");
462
- Dmy.prototype.format = function(format, options) {
463
- options = options || {};
464
- format = format || "D MMM YYYY";
465
- const prefixSettings = options.yearPrefix;
466
- const bceText = typeof options.bceText === "string" ? options.bceText : " ʙᴄᴇ";
467
- const isBc = this.year <= 0;
468
- const is1Bc = this.year === 0;
469
- const thousandsSeparator = options.thousandsSeparator;
470
- if (prefixSettings && !is1Bc) {
471
- const prefixValue = prefixSettings.value || 1;
472
- const prefixLabel = prefixSettings.label || "";
473
- let formattedYear;
474
- if (isBc) {
475
- formattedYear = digitGroupedNumber((-this.year + 1) / prefixValue, thousandsSeparator) + prefixLabel + bceText;
476
- } else {
477
- formattedYear = digitGroupedNumber(this.year / prefixValue, thousandsSeparator) + prefixLabel;
478
- }
479
- return formattedYear;
480
- }
481
- return format.replace(
482
- "YYYY",
483
- isBc ? digitGroupedNumber(-this.year + 1, thousandsSeparator) + bceText : digitGroupedNumber(this.year, thousandsSeparator)
484
- ).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));
485
- };
486
- Dmy.prototype.isSame = function(other) {
487
- 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;
488
- };
489
- Dmy.prototype.toKeyString = function() {
490
- const dateKey = `${this.year}|${this.month}|${this.day}`;
491
- if (this.getMillisecondsOfDay() === 0) {
492
- return dateKey;
493
- }
494
- return `${dateKey}|${this.hour}|${this.minute}|${this.second}|${this.millisecond}`;
495
- };
496
- Dmy.prototype.isAfter = function(other) {
497
- const fields = ["year", "month", "day", "hour", "minute", "second", "millisecond"];
498
- for (let i = 0; i < fields.length; i++) {
499
- const field = fields[i];
500
- const thisValue = this[field] || 0;
501
- const otherValue = other[field] || 0;
502
- if (thisValue !== otherValue) {
503
- return thisValue > otherValue;
504
- }
505
- }
506
- return false;
507
- };
508
- Dmy.prototype.isBetween = function(from, to) {
509
- return this.isAfter(from) && to.isAfter(this);
510
- };
511
- Dmy.prototype.compare = function(other) {
512
- if (this.isSame(other)) {
513
- return 0;
514
- }
515
- if (this.isAfter(other)) {
516
- return 1;
517
- }
518
- return -1;
519
- };
520
- Dmy.prototype.asFloat = function() {
521
- const m = this.month - 1;
522
- const d = this.day - 1;
523
- const dayFraction = this.getMillisecondsOfDay() / MILLISECONDS_PER_DAY;
524
- if (m === 0 && d === 0 && dayFraction === 0) {
525
- return this.year;
526
- }
527
- return Math.round((this.year + (m * 31 + d + dayFraction) / 371) * 100) / 100;
528
- };
529
- Dmy.prototype.isInFuture = function() {
530
- const date = /* @__PURE__ */ new Date();
531
- const now = new Dmy(
532
- date.getFullYear(),
533
- date.getMonth() + 1,
534
- date.getDate(),
535
- date.getHours(),
536
- date.getMinutes(),
537
- date.getSeconds(),
538
- date.getMilliseconds()
539
- );
540
- return this.isAfter(now);
541
- };
542
- Dmy.prototype.convertToIso = function() {
543
- if (this.year < 0) {
544
- this.year += 1;
545
- }
546
- return this;
547
- };
548
- Dmy.CreateAsStartOfPeriod = function(isoDmy, precision) {
549
- const isoYear = isoDmy.year;
550
- const month = isoDmy.month || 1;
551
- const day = isoDmy.day || 1;
552
- precision = normalizePrecision(precision);
553
- if (precision === "millisecond") {
554
- return new Dmy(isoDmy);
555
- }
556
- if (precision === "second") {
557
- return new Dmy(isoYear, month, day, isoDmy.hour, isoDmy.minute, isoDmy.second, 0);
558
- }
559
- if (precision === "minute") {
560
- return new Dmy(isoYear, month, day, isoDmy.hour, isoDmy.minute, 0, 0);
561
- }
562
- if (precision === "hour") {
563
- return new Dmy(isoYear, month, day, isoDmy.hour, 0, 0, 0);
564
- }
565
- if (precision === "day") {
566
- return new Dmy(isoYear, month, day);
567
- }
568
- if (precision === "month") {
569
- return new Dmy(isoYear, month, 1);
570
- }
571
- if (precision === "year" || precision === "million-years" || precision === "billion-years") {
572
- return new Dmy(isoYear, 1, 1);
573
- }
574
- if (precision === "decade") {
575
- return new Dmy(Math.floor(isoYear / 10) * 10, 1, 1);
576
- }
577
- if (precision === "century") {
578
- return new Dmy(getHistoricalPeriodBounds(isoYear, 100).startYear, 1, 1);
579
- }
580
- if (precision === "millennium") {
581
- return new Dmy(getHistoricalPeriodBounds(isoYear, 1e3).startYear, 1, 1);
582
- }
583
- return new Dmy(isoYear, month, day);
584
- };
585
- Dmy.CreateAsEndOfPeriod = function(isoDmy, precision) {
586
- const isoYear = isoDmy.year;
587
- const month = isoDmy.month || 1;
588
- const day = isoDmy.day || 1;
589
- precision = normalizePrecision(precision);
590
- if (precision === "millisecond") {
591
- return new Dmy(isoDmy);
592
- }
593
- if (precision === "second") {
594
- return new Dmy(isoYear, month, day, isoDmy.hour, isoDmy.minute, isoDmy.second, 999);
595
- }
596
- if (precision === "minute") {
597
- return new Dmy(isoYear, month, day, isoDmy.hour, isoDmy.minute, 59, 999);
598
- }
599
- if (precision === "hour") {
600
- return new Dmy(isoYear, month, day, isoDmy.hour, 59, 59, 999);
601
- }
602
- if (precision === "day") {
603
- return new Dmy(isoYear, month, day);
604
- }
605
- if (precision === "month") {
606
- return new Dmy(isoYear, month, daysInMonth(isoYear, month));
607
- }
608
- if (precision === "year") {
609
- return new Dmy(isoYear, 12, 31);
610
- }
611
- if (precision === "decade") {
612
- return new Dmy(Math.floor(isoYear / 10) * 10 + 9, 12, 31);
613
- }
614
- if (precision === "century") {
615
- return new Dmy(getHistoricalPeriodBounds(isoYear, 100).endYear, 12, 31);
616
- }
617
- if (precision === "millennium") {
618
- return new Dmy(getHistoricalPeriodBounds(isoYear, 1e3).endYear, 12, 31);
619
- }
620
- if (precision === "million-years") {
621
- return new Dmy(isoYear + 999999, 12, 31);
622
- }
623
- if (precision === "billion-years") {
624
- return new Dmy(isoYear + 999999999, 12, 31);
625
- }
626
- Logger.error("precision is not implemented");
627
- return new Dmy(isoYear, month, day);
628
- };
629
- Dmy.CreateAsExclusiveEndOfPeriod = function(isoDmy, precision) {
630
- precision = normalizePrecision(precision);
631
- const start = Dmy.CreateAsStartOfPeriod(isoDmy, precision);
632
- if (precision === "millisecond") {
633
- return start.addMilliseconds(1);
634
- }
635
- if (precision === "second") {
636
- return start.addSeconds(1);
637
- }
638
- if (precision === "minute") {
639
- return start.addMinutes(1);
640
- }
641
- if (precision === "hour") {
642
- return start.addHours(1);
643
- }
644
- if (precision === "day") {
645
- return start.addDays(1);
646
- }
647
- return Dmy.CreateAsEndOfPeriod(isoDmy, precision).addDays(1);
648
- };
649
- Dmy.now = function() {
650
- const now = /* @__PURE__ */ new Date();
651
- return new Dmy({
652
- year: now.getYear() + 1900,
653
- month: now.getMonth() + 1,
654
- day: now.getDate()
655
- });
656
- };
657
- function parseDmyString(dateString) {
658
- const match = String(dateString).match(DMY_STRING_PATTERN);
659
- if (!match) {
660
- return null;
661
- }
662
- const year = parseInt(match[1], 10);
663
- const month = match[2] == null ? 1 : parseInt(match[2], 10);
664
- const day = match[3] == null ? 1 : parseInt(match[3], 10);
665
- const hour = match[4] == null ? 0 : parseInt(match[4], 10);
666
- const minute = match[5] == null ? 0 : parseInt(match[5], 10);
667
- const second = match[6] == null ? 0 : parseInt(match[6], 10);
668
- const millisecond = match[7] ? parseInt(match[7].padEnd(3, "0"), 10) : 0;
669
- return {
670
- date: new Dmy({
671
- year,
672
- month,
673
- day,
674
- hour,
675
- minute,
676
- second,
677
- millisecond
678
- }),
679
- hasMonth: match[2] != null,
680
- hasDay: match[3] != null,
681
- hasTime: match[4] != null
682
- };
683
- }
684
- __name(parseDmyString, "parseDmyString");
685
- Dmy.fromString = function(dateString) {
686
- const parsed = parseDmyString(dateString);
687
- return parsed ? parsed.date : new Dmy(NaN, 1, 1);
688
- };
689
- function merge(target, ...sources) {
690
- return Object.assign(target, ...sources);
691
- }
692
- __name(merge, "merge");
693
- function deepMerge(target, ...sources) {
694
- const ensureSafeProto = /* @__PURE__ */ __name((obj) => {
695
- if (obj && typeof obj === "object" && !Object.prototype.hasOwnProperty.call(obj, "__proto__")) {
696
- try {
697
- Object.defineProperty(obj, "__proto__", {
698
- value: void 0,
699
- writable: true,
700
- enumerable: false,
701
- configurable: true
702
- });
703
- } catch {
704
- }
705
- }
706
- }, "ensureSafeProto");
707
- ensureSafeProto(target);
708
- const isUnsafeKey = /* @__PURE__ */ __name((key) => key === "__proto__" || key === "constructor" || key === "prototype", "isUnsafeKey");
709
- const isPlainObject = /* @__PURE__ */ __name((obj) => {
710
- if (obj === null || typeof obj !== "object") {
711
- return false;
712
- }
713
- const proto = Object.getPrototypeOf(obj);
714
- return proto === Object.prototype || proto === null;
715
- }, "isPlainObject");
716
- for (const src of sources) {
717
- if (!src || typeof src !== "object") {
718
- continue;
719
- }
720
- for (const k of Object.keys(src)) {
721
- if (isUnsafeKey(k)) {
722
- continue;
723
- }
724
- const v = src[k];
725
- if (Array.isArray(v)) {
726
- target[k] = v.slice();
727
- continue;
728
- }
729
- if (isPlainObject(v)) {
730
- const base = isPlainObject(target[k]) ? target[k] : {};
731
- ensureSafeProto(base);
732
- target[k] = deepMerge(base, v);
733
- continue;
734
- }
735
- target[k] = v;
736
- }
737
- }
738
- ensureSafeProto(target);
739
- return target;
740
- }
741
- __name(deepMerge, "deepMerge");
742
- function buildObjectFromPath(path, value) {
743
- const pathParts = path.split(".");
744
- const pathEnd = pathParts[pathParts.length - 1];
745
- let obj = {};
746
- obj[pathEnd] = value;
747
- for (let i = pathParts.length - 2; i >= 0; i--) {
748
- const previousPathPart = pathParts[i];
749
- const objClone = deepMerge({}, obj);
750
- obj = {};
751
- obj[previousPathPart] = objClone;
752
- }
753
- return obj;
754
- }
755
- __name(buildObjectFromPath, "buildObjectFromPath");
756
- function defineValueOrFunctionProperty(obj, propName) {
757
- const privatePropertyName = `_${propName}`;
758
- obj[privatePropertyName] = void 0;
759
- Object.defineProperty(obj, propName, {
760
- get() {
761
- const value = this[privatePropertyName];
762
- if (typeof value === "function") {
763
- return value(this);
764
- }
765
- return value;
766
- },
767
- set(value) {
768
- this[privatePropertyName] = value;
769
- },
770
- enumerable: true,
771
- configurable: false
772
- });
773
- }
774
- __name(defineValueOrFunctionProperty, "defineValueOrFunctionProperty");
775
- function isUndefined(value) {
776
- return typeof value === "undefined";
777
- }
778
- __name(isUndefined, "isUndefined");
779
- const propertyAbbreviations = {
780
- id: "i",
781
- title: "t",
782
- rank: "r",
783
- subtitle: "s",
784
- "from.year": "fy",
785
- "from.month": "fm",
786
- "from.day": "fd",
787
- "from.hour": "fhr",
788
- "from.minute": "fmi",
789
- "from.second": "fs",
790
- "from.millisecond": "fms",
791
- "from.precision": "fp",
792
- "to.year": "ty",
793
- "to.month": "tm",
794
- "to.day": "td",
795
- "to.hour": "thr",
796
- "to.minute": "tmi",
797
- "to.second": "ts",
798
- "to.millisecond": "tms",
799
- "to.precision": "tp",
800
- isToPresent: "p",
801
- isStarred: "v",
802
- "offset.left": "ol",
803
- "offset.top": "ot",
804
- imageUrl: "m",
805
- lane: "ln",
806
- style: "st",
807
- activeStyle: "ast",
808
- hiddenByFilter: "h",
809
- hidePeriodLine: "hp"
810
- };
811
- function extractProperty(data, property) {
812
- return Object.prototype.hasOwnProperty.call(data, property) ? data[property] : data[propertyAbbreviations[property]];
813
- }
814
- __name(extractProperty, "extractProperty");
815
- function extractPropertyFromPath(data, path) {
816
- const pathParts = path.split(".");
817
- const value = pathParts.reduce((curr, next) => curr ? curr[next] : void 0, data);
818
- return isUndefined(value) ? data[propertyAbbreviations[path]] : value;
819
- }
820
- __name(extractPropertyFromPath, "extractPropertyFromPath");
821
- function isPath(property) {
822
- return property.indexOf(".") > -1;
823
- }
824
- __name(isPath, "isPath");
825
- function getPropertyFromData(data, property) {
826
- if (isPath(property)) {
827
- return extractPropertyFromPath(data, property);
828
- }
829
- return extractProperty(data, property);
830
- }
831
- __name(getPropertyFromData, "getPropertyFromData");
832
- function existsInData(data, property) {
833
- if (isPath(property)) {
834
- return !isUndefined(extractPropertyFromPath(data, property));
835
- }
836
- return !isUndefined(extractProperty(data, property));
837
- }
838
- __name(existsInData, "existsInData");
839
- defineValueOrFunctionProperty(Article.prototype, "hidePeriodLine");
840
- defineValueOrFunctionProperty(Article.prototype, "hiddenByFilter");
841
- function Article(owner, id) {
842
- this.id = id;
843
- this.owner = owner;
844
- this.isDataLoaded = false;
845
- this.imageLoaded = false;
846
- this.stacking = 0;
847
- this.groupIndex = 0;
848
- this.isActive = false;
849
- this.isVisible = false;
850
- this.isVisibleInLane = true;
851
- this.isInRange = false;
852
- this.isInView = false;
853
- this.isVisibleInGroup = false;
854
- this.isVisibleInRows = true;
855
- this.isStarred = false;
856
- this.isMouseOverStar = false;
857
- this.isMouseover = false;
858
- this.isDragging = false;
859
- this.registeredPosition = { left: 0, top: 0 };
860
- this.position = { left: 0, top: 0 };
861
- this.dragStartOffset = { left: 0, top: 0 };
862
- this.indicator = { fromX: 0, toX: 0 };
863
- this.offset = { left: 0, top: 0 };
864
- this.finalOffset = { left: 0, top: 0 };
865
- this.isVisibleAfterFade = false;
866
- this.opacity = 0;
867
- this.fadeAnimation = {
868
- finalOpacity: 0,
869
- dummyElement: null
870
- };
871
- this.moveAnimation = {
872
- finalOffset: { left: 0, top: 0 },
873
- dummyElement: void 0
874
- };
875
- this.row = 0;
876
- this.laneId = null;
877
- this.laneOrder = 0;
878
- this.isFading = false;
879
- this.isMoving = false;
880
- this._cachedHeight = 0;
881
- this._cachedWidth = 0;
882
- this._sizeValid = false;
883
- this._sizeCacheKey = null;
884
- this._layoutCaches = null;
885
- this._resolvedDefaultCardLayout = null;
886
- this._resolvedCardLayoutName = null;
887
- }
888
- __name(Article, "Article");
889
- Article.prototype.setupByReceivedData = function(receivedData) {
890
- this.owner._assignArticleToLane(this, this.owner._resolveLaneIdFromArticleData(receivedData));
891
- const articleDefaultData = this.owner._getResolvedArticleOptions(this).defaultData;
892
- const data = deepMerge({}, articleDefaultData, receivedData);
893
- if (!existsInData(receivedData, "to")) {
894
- delete data.to;
895
- }
896
- this.data = deepMerge({}, receivedData);
897
- this.title = getPropertyFromData(data, "title") || "";
898
- this.rank = getPropertyFromData(data, "rank") || 0;
899
- this.subtitle = getPropertyFromData(data, "subtitle") || "";
900
- this._setupArticlePeriod(data);
901
- this.offset.left = this.finalOffset.left = this.moveAnimation.finalOffset.left = data.offsetLeft || 0;
902
- this.offset.top = this.finalOffset.top = this.moveAnimation.finalOffset.top = data.offsetTop || 0;
903
- this.isStarred = !!data.starred;
904
- this.cardLayout = getPropertyFromData(data, "cardLayout") || null;
905
- this.initialiseStyles(data);
906
- this.hiddenByFilter = getPropertyFromData(data, "hiddenByFilter");
907
- this.hidePeriodLine = existsInData(data, "hidePeriodLine") ? getPropertyFromData(data, "hidePeriodLine") : this.owner.options.article.periodLine.defaultHide;
908
- this.isDataLoaded = true;
909
- this.isImageInfoLoaded = false;
910
- };
911
- Article.prototype._setupArticlePeriod = function(data) {
912
- let fromDmy = new Dmy(
913
- parseInt(getPropertyFromData(data, "from.year")),
914
- parseInt(getPropertyFromData(data, "from.month")),
915
- parseInt(getPropertyFromData(data, "from.day")),
916
- parseInt(getPropertyFromData(data, "from.hour")),
917
- parseInt(getPropertyFromData(data, "from.minute")),
918
- parseInt(getPropertyFromData(data, "from.second")),
919
- parseInt(getPropertyFromData(data, "from.millisecond"))
920
- );
921
- fromDmy = this.owner.getDmyFromInput(fromDmy);
922
- const fromPrecision = getPropertyFromData(data, "from.precision");
923
- const isToPresentProp = getPropertyFromData(data, "isToPresent");
924
- const isToPresent = isToPresentProp === true || isToPresentProp === 1;
925
- let toDmy, toPrecision;
926
- if (isToPresent) {
927
- toDmy = Dmy.now();
928
- } else if (existsInData(data, "to")) {
929
- toDmy = new Dmy(
930
- parseInt(getPropertyFromData(data, "to.year")),
931
- parseInt(getPropertyFromData(data, "to.month")),
932
- parseInt(getPropertyFromData(data, "to.day")),
933
- parseInt(getPropertyFromData(data, "to.hour")),
934
- parseInt(getPropertyFromData(data, "to.minute")),
935
- parseInt(getPropertyFromData(data, "to.second")),
936
- parseInt(getPropertyFromData(data, "to.millisecond"))
937
- );
938
- toDmy = this.owner.getDmyFromInput(toDmy);
939
- toPrecision = getPropertyFromData(data, "to.precision");
940
- } else {
941
- toDmy = fromDmy;
942
- toPrecision = fromPrecision;
943
- }
944
- const from = Dmy.CreateAsStartOfPeriod(fromDmy, fromPrecision);
945
- const to = Dmy.CreateAsExclusiveEndOfPeriod(toDmy, toPrecision);
946
- this.period = { from, to, isToPresent };
947
- this.period.years = this.period.to.asFloat() - this.period.from.asFloat();
948
- };
949
- Article.prototype.setImage = function() {
950
- this.isImageInfoLoaded = true;
951
- if (getPropertyFromData(this.data, "imageUrl")) {
952
- this.owner.enqueueImageLoad(this);
953
- } else {
954
- this._releaseImageResource();
955
- this.image = null;
956
- this.imageLoaded = false;
957
- }
958
- };
959
- Article.prototype._releaseImageResource = function(options = {}) {
960
- const releaser = typeof this._closeImage === "function" ? this._closeImage : null;
961
- if (releaser) {
962
- this._closeImage = null;
963
- try {
964
- releaser(options);
965
- } catch {
966
- }
967
- return;
968
- }
969
- if (!options.keepState) {
970
- this.image = null;
971
- this.imageLoaded = false;
972
- this._loadedImageKey = null;
973
- }
974
- };
975
- Article.prototype.registerPosition = function(pos) {
976
- this.registeredPosition = this.position = pos;
977
- };
978
- Article.prototype.overlaps = function(other) {
979
- return other.period.from.isSame(this.period.from) && other.period.to.isSame(this.period.to) || other.period.from.isBetween(this.period.from, this.period.to) || other.period.to.isBetween(this.period.from, this.period.to) || this.period.from.isBetween(other.period.from, other.period.to) || this.period.to.isBetween(other.period.from, other.period.to);
980
- };
981
- Article.prototype.overlapsInclusiveWithDates = function(from, to) {
982
- return !(this.period.from.isAfter(to) || from.isAfter(this.period.to));
983
- };
984
- Article.prototype.overlapsInclusive = function(other) {
985
- return this.overlapsInclusiveWithDates(other.period.from, other.period.to);
986
- };
987
- Article.prototype.isInside = function(pos) {
988
- if (!this.isVisible) {
989
- return false;
990
- }
991
- this._ensureSizeCache();
992
- const left = this.position.left;
993
- const top = this.position.top;
994
- const width = this._cachedWidth;
995
- const height = this._cachedHeight;
996
- return pos.left >= left && pos.left <= left + width && pos.top >= top && pos.top <= top + height;
997
- };
998
- Article.prototype.pointerEnter = function(event) {
999
- this.isMouseover = true;
1000
- this.owner.trigger("article-pointerenter", this, event);
1001
- };
1002
- Article.prototype.pointerLeave = function(event) {
1003
- this.isMouseover = false;
1004
- this.owner.trigger("article-pointerleave", this, event);
1005
- };
1006
- Article.prototype.updateIsMouseOverStar = function(pos) {
1007
- const star = this.getIconBox();
1008
- if (!star) {
1009
- return false;
1010
- }
1011
- const oldState = this.isMouseOverStar;
1012
- this.isMouseOverStar = pos.left >= star.left && pos.left <= star.left + star.width && pos.top >= star.top && pos.top <= star.top + star.height;
1013
- if (this.isMouseOverStar !== oldState && !this.owner.isAnimating) {
1014
- this.owner.redraw();
1015
- }
1016
- return this.isMouseOverStar;
1017
- };
1018
- Article.prototype.getCursor = function(pos) {
1019
- const cursor = this.owner.options.style.cursor;
1020
- if (this.isDragging) {
1021
- return cursor.article.dragging;
1022
- }
1023
- this.updateIsMouseOverStar(pos);
1024
- if (!this.owner.options.article.draggable) {
1025
- return cursor.clickable;
1026
- }
1027
- if (this.isActive) {
1028
- return this.isMouseOverStar ? cursor.clickable : cursor.article.hoverDraggable;
1029
- }
1030
- return cursor.clickable;
1031
- };
1032
- Article.prototype.clicked = function(pos) {
1033
- this.updateIsMouseOverStar(pos);
1034
- if (this.isMouseOverStar) {
1035
- this.isStarred = !this.isStarred;
1036
- return true;
1037
- }
1038
- return false;
1039
- };
1040
- Article.prototype.getStatusForSave = function() {
1041
- const state = { i: this.id };
1042
- if (this.offset.left !== 0) {
1043
- state.l = this.offset.left;
1044
- }
1045
- if (this.offset.top !== 0) {
1046
- state.t = this.offset.top;
1047
- }
1048
- if (this.isStarred) {
1049
- state.v = true;
1050
- }
1051
- return state;
1052
- };
1053
- Article.prototype.headerOverlapsWith = function(other) {
1054
- const thisLeft = this.registeredPosition.left;
1055
- const otherLeft = other.registeredPosition.left;
1056
- const thisRight = thisLeft + this.getWidth();
1057
- const otherRight = otherLeft + other.getWidth();
1058
- return otherRight >= thisLeft && thisRight >= otherLeft;
1059
- };
1060
- Article.prototype._getWidth = function() {
1061
- return this.getCurrentStyle().width;
1062
- };
1063
- Article.prototype.getWidth = function() {
1064
- this._ensureSizeCache();
1065
- return this._cachedWidth;
1066
- };
1067
- Article.prototype.getHeight = function() {
1068
- this._ensureSizeCache();
1069
- return this._cachedHeight;
1070
- };
1071
- Article.prototype.setOption = function(option, value) {
1072
- let needsDefaultRedraw = false;
1073
- if (typeof option === "string") {
1074
- if (typeof value === "undefined") {
1075
- const selectedOption = getPropertyFromData(this.data, option);
1076
- return selectedOption;
1077
- }
1078
- option = buildObjectFromPath(option, value);
1079
- }
1080
- deepMerge(this.data, option);
1081
- if (existsInData(option, "id")) {
1082
- this.id = option.id;
1083
- }
1084
- if (existsInData(option, "title")) {
1085
- this.title = option.title;
1086
- this.titleLines = void 0;
1087
- }
1088
- if (existsInData(option, "subtitle")) {
1089
- this.subtitle = option.subtitle;
1090
- this.summarisedSubtitle = void 0;
1091
- }
1092
- if (existsInData(option, "from") || existsInData(option, "to") || existsInData(option, "isToPresent")) {
1093
- this._setupArticlePeriod(this.data);
1094
- needsDefaultRedraw = true;
1095
- }
1096
- if (existsInData(option, "imageUrl")) {
1097
- this.setImage();
1098
- }
1099
- if (existsInData(option, "rank")) {
1100
- this.rank = option.rank;
1101
- needsDefaultRedraw = true;
1102
- }
1103
- if (existsInData(option, "starred")) {
1104
- this.isStarred = option.starred;
1105
- }
1106
- if (existsInData(option, "hiddenByFilter")) {
1107
- this.hiddenByFilter = option.hiddenByFilter;
1108
- }
1109
- if (existsInData(option, "hidePeriodLine")) {
1110
- this.hidePeriodLine = option.hidePeriodLine;
1111
- }
1112
- const laneChanged = existsInData(option, "lane");
1113
- if (laneChanged) {
1114
- this.owner._assignArticleToLane(this, option.lane);
1115
- this.initialiseStyles(this.data);
1116
- this.invalidateCaches();
1117
- needsDefaultRedraw = true;
1118
- }
1119
- const styleChanged = existsInData(option, "style");
1120
- const activeStyleChanged = existsInData(option, "activeStyle");
1121
- const hoverStyleChanged = existsInData(option, "hoverStyle");
1122
- if (styleChanged || hoverStyleChanged || activeStyleChanged) {
1123
- this.initialiseStyles(this.data);
1124
- }
1125
- this.invalidateCaches();
1126
- const cardLayoutChanged = existsInData(option, "cardLayout");
1127
- if (cardLayoutChanged) {
1128
- this.setCardLayout(option.cardLayout);
1129
- }
1130
- if (laneChanged) {
1131
- this.owner.updateArticlesGroupIndex();
1132
- }
1133
- if (needsDefaultRedraw) {
1134
- this.owner.requestRedraw();
1135
- } else {
1136
- this.owner.requestRedraw(this.redraw);
1137
- }
1138
- };
1139
- Article.prototype.initialiseStyles = function(data = this.data) {
1140
- const resolvedDefaultCardLayout = this.owner._resolveDefaultCardLayoutName(this);
1141
- const explicitCardLayout = this.owner._getExplicitArticleCardLayout(this);
1142
- const cardLayout = explicitCardLayout || resolvedDefaultCardLayout;
1143
- this._resolvedDefaultCardLayout = resolvedDefaultCardLayout;
1144
- this._resolvedCardLayoutName = cardLayout;
1145
- const styleOverrides = this.owner._getResolvedArticleStyleOverrides(this, cardLayout);
1146
- const style = deepMerge({}, styleOverrides.style, getPropertyFromData(data, "style") || {});
1147
- const activeStyle = deepMerge(
1148
- {},
1149
- styleOverrides.activeStyle,
1150
- getPropertyFromData(data, "activeStyle") || {}
1151
- );
1152
- const hoverStyle = deepMerge(
1153
- {},
1154
- styleOverrides.hoverStyle,
1155
- getPropertyFromData(data, "hoverStyle") || {}
1156
- );
1157
- this.style = style;
1158
- this.activeStyle = deepMerge({}, style, activeStyle);
1159
- this.hoverStyle = deepMerge({}, style, hoverStyle);
1160
- this.activeHoverStyle = deepMerge({}, style, hoverStyle, activeStyle);
1161
- };
1162
- Article.prototype.setStyle = function(option, value) {
1163
- if (typeof option === "string") {
1164
- if (typeof value === "undefined") {
1165
- return getPropertyFromData(this.style, option);
1166
- }
1167
- option = buildObjectFromPath(option, value);
1168
- }
1169
- this.data.style = deepMerge(this.data.style || {}, option);
1170
- this.initialiseStyles(this.data);
1171
- this.invalidateCaches();
1172
- this.owner.requestRedraw();
1173
- };
1174
- Article.prototype.setHoverStyle = function(option, value) {
1175
- if (typeof option === "string") {
1176
- if (typeof value === "undefined") {
1177
- return getPropertyFromData(this.activeStyle, option);
1178
- }
1179
- option = buildObjectFromPath(option, value);
1180
- }
1181
- this.data.hoverStyle = deepMerge(this.data.hoverStyle || {}, option);
1182
- this.initialiseStyles(this.data);
1183
- this.owner.requestRedraw();
1184
- };
1185
- Article.prototype.setActiveStyle = function(option, value) {
1186
- if (typeof option === "string") {
1187
- if (typeof value === "undefined") {
1188
- return getPropertyFromData(this.activeStyle, option);
1189
- }
1190
- option = buildObjectFromPath(option, value);
1191
- }
1192
- this.data.activeStyle = deepMerge(this.data.activeStyle || {}, option);
1193
- this.initialiseStyles(this.data);
1194
- this.owner.requestRedraw();
1195
- };
1196
- Article.prototype.activated = function() {
1197
- Logger.warn(
1198
- 'DEPRECATION WARNING: article.activated() was deprecated in v1.3.0. Use timeline.select(article.id) and handle selection with options.on["article-select"] instead.'
1199
- );
1200
- this.owner.trigger("article-click", this);
1201
- };
1202
- Article.prototype.updateVisibility = function() {
1203
- const oldVisibility = this.isVisibleAfterFade;
1204
- const newVisibility = this.isInRange && this.isVisibleInLane && this.isVisibleInGroup && this.isVisibleInRows && !this.isHiddenByFilter;
1205
- if (!this.isVisibleInLane) {
1206
- this.setVisibility(false);
1207
- return;
1208
- }
1209
- if (oldVisibility === newVisibility) {
1210
- return;
1211
- }
1212
- if (newVisibility && !this.isImageInfoLoaded) {
1213
- this.setImage();
1214
- }
1215
- if (!this.owner.options.article.animation.fade.active) {
1216
- this.setVisibility(newVisibility);
1217
- return;
1218
- }
1219
- this.setVisibilityWithFade(newVisibility);
1220
- };
1221
- Article.prototype.setVisibility = function(visibility) {
1222
- if (this.isFading && this.fadeAnimation?.dummyElement?.stop) {
1223
- this.fadeAnimation.dummyElement.stop();
1224
- this.isFading = false;
1225
- if (this.owner?.lastAnimatingArticle?.id === this.id && this.owner.lastAnimatingArticle.animationType === "fade") {
1226
- this.owner.isAnimatingArticles = false;
1227
- }
1228
- }
1229
- this.isVisible = visibility;
1230
- this.isVisibleAfterFade = visibility;
1231
- this.opacity = visibility ? 1 : 0;
1232
- if (!visibility) {
1233
- this._releaseImageResource({ skipRedraw: true });
1234
- }
1235
- };
1236
- Article.prototype.setVisibilityWithFade = function(visibility) {
1237
- const me = this;
1238
- if (visibility === me.isVisibleAfterFade) {
1239
- return;
1240
- }
1241
- if (me.isFading && me.fadeAnimation?.dummyElement?.stop) {
1242
- me.fadeAnimation.dummyElement.stop();
1243
- }
1244
- me.isFading = true;
1245
- me.isVisibleAfterFade = visibility;
1246
- me.fadeAnimation = me.fadeAnimation || {};
1247
- me.fadeAnimation.finalOpacity = visibility;
1248
- if (visibility) {
1249
- me.isVisible = true;
1250
- }
1251
- me.owner.notifyArticleAnimating("fade", me.id);
1252
- const settings = me.owner.options.article.animation.fade;
1253
- const duration = settings.duration ?? 400;
1254
- const easingName = settings.easing ?? "swing";
1255
- const easingFn = EASINGS[easingName] || EASINGS.swing;
1256
- const startOpacity = me.opacity;
1257
- const endOpacity = visibility ? 1 : 0;
1258
- const fadeTween = tween({
1259
- from: startOpacity,
1260
- to: endOpacity,
1261
- duration,
1262
- easing: easingFn,
1263
- /** Fired every animation frame */
1264
- onUpdate(value) {
1265
- me.opacity = value;
1266
- me.owner.requestRedraw();
1267
- },
1268
- /** Finalise */
1269
- onComplete() {
1270
- me.isFading = false;
1271
- if (!visibility) {
1272
- me.isVisible = false;
1273
- me._releaseImageResource({ skipRedraw: true });
1274
- }
1275
- const last = me.owner.lastAnimatingArticle;
1276
- if (me.id === last.id && last.animationType === "fade") {
1277
- me.owner.isAnimatingArticles = false;
1278
- }
1279
- if (typeof settings.complete === "function") {
1280
- settings.complete.call(me);
1281
- }
1282
- }
1283
- });
1284
- me.fadeAnimation.dummyElement = fadeTween;
1285
- };
1286
- Article.prototype.moveToOffset = function(destination) {
1287
- this.finalOffset.top = this.offset.top = destination.top || this.offset.top;
1288
- this.finalOffset.left = this.offset.left = destination.left || this.offset.left;
1289
- this.position.top = this.registeredPosition.top + this.offset.top;
1290
- this.position.left = this.registeredPosition.left + this.offset.left;
1291
- };
1292
- Article.prototype.moveTo = function(destination) {
1293
- const finalOffset = {
1294
- left: destination.left - this.registeredPosition.left,
1295
- top: destination.top - this.registeredPosition.top
1296
- };
1297
- this.moveToOffset(finalOffset);
1298
- };
1299
- Article.prototype.moveToWithAnim = function(destination) {
1300
- const finalOffset = {
1301
- left: destination.left - this.registeredPosition.left,
1302
- top: destination.top - this.registeredPosition.top
1303
- };
1304
- this.moveToOffsetWithAnim(finalOffset);
1305
- };
1306
- Article.prototype.moveToOffsetWithAnim = function(destination) {
1307
- const me = this;
1308
- const moveAnimation = me.moveAnimation;
1309
- if (destination.top === moveAnimation.finalOffset.top && destination.left === moveAnimation.finalOffset.left) {
1310
- return;
1311
- }
1312
- if (me.isMoving && moveAnimation?.dummyElement?.stop) {
1313
- moveAnimation.dummyElement.stop();
1314
- }
1315
- moveAnimation.finalOffset = this.finalOffset = {
1316
- left: destination.left,
1317
- top: destination.top
1318
- };
1319
- me.isMoving = true;
1320
- me.owner.notifyArticleAnimating("move", me.id);
1321
- const settings = me.owner.options.article.animation.move;
1322
- const duration = settings.duration ?? 400;
1323
- const easingName = settings.easing ?? "swing";
1324
- const easingFn = EASINGS[easingName] || EASINGS.swing;
1325
- const startTop = me.offset.top;
1326
- const startLeft = me.offset.left;
1327
- const deltaTop = destination.top - startTop;
1328
- const deltaLeft = destination.left - startLeft;
1329
- const moveTween = tween({
1330
- from: 0,
1331
- to: 1,
1332
- duration,
1333
- easing: easingFn,
1334
- onUpdate(progress) {
1335
- me.offset.top = startTop + deltaTop * progress;
1336
- me.offset.left = startLeft + deltaLeft * progress;
1337
- me.position.top = me.registeredPosition.top + me.offset.top;
1338
- me.position.left = me.registeredPosition.left + me.offset.left;
1339
- me.owner.requestRedraw();
1340
- },
1341
- onComplete() {
1342
- me.offset.top = destination.top;
1343
- me.offset.left = destination.left;
1344
- me.position.top = me.registeredPosition.top + destination.top;
1345
- me.position.left = me.registeredPosition.left + destination.left;
1346
- me.isMoving = false;
1347
- const last = me.owner.lastAnimatingArticle;
1348
- if (me.id === last.id && last.animationType === "move") {
1349
- me.owner.isAnimatingArticles = false;
1350
- }
1351
- }
1352
- });
1353
- moveAnimation.dummyElement = moveTween;
1354
- };
1355
- function roundPixel(value) {
1356
- return Math.round(value);
1357
- }
1358
- __name(roundPixel, "roundPixel");
1359
- function snapPixel(value, dpr = 1) {
1360
- const ratio = typeof dpr === "number" && isFinite(dpr) && dpr > 0 ? dpr : 1;
1361
- return Math.round(value * ratio) / ratio;
1362
- }
1363
- __name(snapPixel, "snapPixel");
1364
- function retainPixel(value) {
1365
- return value;
1366
- }
1367
- __name(retainPixel, "retainPixel");
1368
- function createPixelSnap(dpr = 1, mode = "device") {
1369
- if (mode === false || mode === "none") {
1370
- return retainPixel;
1371
- }
1372
- if (mode === "css") {
1373
- return roundPixel;
1374
- }
1375
- return /* @__PURE__ */ __name(function snapToDevicePixel(value) {
1376
- return snapPixel(value, dpr);
1377
- }, "snapToDevicePixel");
1378
- }
1379
- __name(createPixelSnap, "createPixelSnap");
1380
- function createStrokePixelSnap(dpr = 1, mode = "device", lineWidth = 1) {
1381
- if (mode === false || mode === "none") {
1382
- return retainPixel;
1383
- }
1384
- const deviceRatio = typeof dpr === "number" && isFinite(dpr) && dpr > 0 ? dpr : 1;
1385
- const ratio = mode === "css" ? 1 : deviceRatio;
1386
- const width = typeof lineWidth === "number" && isFinite(lineWidth) && lineWidth > 0 ? lineWidth : 1;
1387
- const halfPhysicalWidth = width * ratio / 2;
1388
- return /* @__PURE__ */ __name(function snapStrokeCentre(value) {
1389
- return (Math.round(value * ratio - halfPhysicalWidth) + halfPhysicalWidth) / ratio;
1390
- }, "snapStrokeCentre");
1391
- }
1392
- __name(createStrokePixelSnap, "createStrokePixelSnap");
1393
- function createInnerSpace(outerSpace, borderWidth, snap) {
1394
- if (!snap) {
1395
- snap = roundPixel;
1396
- }
1397
- const halfBorder = borderWidth / 2;
1398
- return {
1399
- left: snap(outerSpace.left + halfBorder),
1400
- top: snap(outerSpace.top + halfBorder),
1401
- width: snap(outerSpace.width - borderWidth),
1402
- height: snap(outerSpace.height - borderWidth)
1403
- };
1404
- }
1405
- __name(createInnerSpace, "createInnerSpace");
1406
- Article.prototype.draw = function(ctx) {
1407
- if (!this.isDataLoaded || isNaN(this.position.left)) {
1408
- return;
1409
- }
1410
- this._ensureSizeCache();
1411
- ctx.globalAlpha = this.opacity;
1412
- const cardLayout = this._getCurrentCardLayout();
1413
- cardLayout.draw.call(this, ctx);
1414
- };
1415
- Article.prototype.getCurrentStyle = function() {
1416
- if (this.isActive) {
1417
- return this.isMouseover ? this.activeHoverStyle : this.activeStyle;
1418
- }
1419
- return this.isMouseover ? this.hoverStyle : this.style;
1420
- };
1421
- Article.prototype._getCurrentStyle = function() {
1422
- return this.getCurrentStyle();
1423
- };
1424
- Article.prototype._getPeriodLineRenderGeometry = function(axisY) {
1425
- const resolvedArticleOptions = this.owner._getResolvedArticleOptions(this);
1426
- const periodLineOptions = resolvedArticleOptions.periodLine || {};
1427
- const globalPeriodLineOptions = this.owner.options.article.periodLine || {};
1428
- const position = globalPeriodLineOptions.position || "axis";
1429
- const baselineGap = Number.isFinite(periodLineOptions.baselineGap) ? periodLineOptions.baselineGap : 0;
1430
- const spacing = this.hidePeriodLine ? 0 : periodLineOptions.spacing || 0;
1431
- const thickness = this.hidePeriodLine ? 0 : periodLineOptions.thickness || 0;
1432
- const offset = (spacing + thickness) * this.stacking;
1433
- let anchorY = axisY;
1434
- let anchorOffset = this.owner.options.style.mainLine.size / 2;
1435
- if (position === "lane" && this.owner._isLaneLayoutActive()) {
1436
- const lane = this.owner.getLaneById(this.laneId);
1437
- if (lane && lane.geometry) {
1438
- anchorY = Math.floor(lane.geometry.bottom);
1439
- anchorOffset = 0;
1440
- }
1441
- }
1442
- const y = anchorY - baselineGap - offset - anchorOffset - thickness / 2;
1443
- return {
1444
- position,
1445
- baselineGap,
1446
- spacing,
1447
- thickness,
1448
- anchorY,
1449
- anchorOffset,
1450
- y
1451
- };
1452
- };
1453
- Article.prototype.drawPeriodLinesAndConnectors = function(ctx, axisY) {
1454
- ctx.globalAlpha = this.opacity;
1455
- const style = this.getCurrentStyle();
1456
- const geometry = this._getPeriodLineRenderGeometry(axisY);
1457
- const y = geometry.y;
1458
- if (!this.hidePeriodLine) {
1459
- const fromX = this.indicator.fromX, toX = this.indicator.toX;
1460
- ctx.beginPath();
1461
- ctx.lineWidth = geometry.thickness;
1462
- ctx.moveTo(fromX, y);
1463
- ctx.lineTo(toX, y);
1464
- if (this.period.isToPresent) {
1465
- const periodLength = toX - fromX, maxFadeLength = 15, fadeStartColorStop = Math.max(1 - maxFadeLength / periodLength, 0.7), grad = ctx.createLinearGradient(fromX, y, toX, y);
1466
- grad.addColorStop(0, style.color);
1467
- grad.addColorStop(fadeStartColorStop, style.color);
1468
- grad.addColorStop(1, "rgba(255,255,255,0)");
1469
- ctx.strokeStyle = grad;
1470
- } else {
1471
- ctx.strokeStyle = style.color;
1472
- }
1473
- ctx.stroke();
1474
- }
1475
- if (!style.connectorLine.visible) {
1476
- return;
1477
- }
1478
- const cardLayout = this._getCurrentCardLayout();
1479
- const connectorEnd = typeof cardLayout.getConnectorEnd === "function" ? cardLayout.getConnectorEnd.call(this) : {
1480
- left: this.position.left + style.connectorLine.offsetX,
1481
- top: this.position.top + this.getHeight() + style.connectorLine.offsetY
1482
- };
1483
- const x1 = Math.max(0, this.indicator.fromX);
1484
- const y1 = y;
1485
- const x2 = connectorEnd.left;
1486
- const y2 = connectorEnd.top;
1487
- const isVertical = Math.abs(x1 - x2) < Number.EPSILON;
1488
- const pixelSnapMode = this.owner?.options?.article?.rendering?.pixelSnap;
1489
- const snapStroke = createStrokePixelSnap(
1490
- this.owner?.getCanvasDpr?.() || 1,
1491
- pixelSnapMode,
1492
- style.connectorLine.thickness
1493
- );
1494
- const connectorX = isVertical ? snapStroke(x2) : null;
1495
- const drawX1 = connectorX ?? x1;
1496
- const drawX2 = connectorX ?? x2;
1497
- ctx.strokeStyle = ctx.fillStyle = style.color;
1498
- ctx.lineWidth = style.connectorLine.thickness;
1499
- ctx.beginPath();
1500
- ctx.moveTo(drawX1, y1);
1501
- ctx.lineTo(drawX2, y2);
1502
- ctx.stroke();
1503
- const radians = Math.atan((y2 - y1) / (drawX2 - drawX1)) + (drawX2 >= drawX1 ? -90 : 90) * Math.PI / 180;
1504
- ctx.save();
1505
- ctx.beginPath();
1506
- ctx.translate(drawX2, y2);
1507
- ctx.rotate(radians);
1508
- ctx.moveTo(-style.connectorLine.arrow.width, 0);
1509
- ctx.lineTo(style.connectorLine.arrow.width, 0);
1510
- ctx.lineTo(0, -style.connectorLine.arrow.height);
1511
- ctx.closePath();
1512
- ctx.restore();
1513
- ctx.fill();
1514
- };
1515
- Article.prototype.getIconBox = function() {
1516
- const cardLayout = this._getCurrentCardLayout();
1517
- return cardLayout.getIconBox.call(this);
1518
- };
1519
- Article.prototype.startDragging = function(pos, evt) {
1520
- if (this.isMoving) {
1521
- this.moveAnimation.dummyElement.stop();
1522
- }
1523
- this.isDragging = true;
1524
- this.dragInitialPosition = { left: this.position.left, top: this.position.top };
1525
- this.lastDragPosition = { left: this.position.left, top: this.position.top };
1526
- this.dragStartOffset = {
1527
- left: pos.left - this.position.left,
1528
- top: pos.top - this.position.top
1529
- };
1530
- this.owner.startAnimation();
1531
- if (this.owner && typeof this.owner.trigger === "function") {
1532
- this.owner.trigger("article-drag-start", this, evt);
1533
- }
1534
- };
1535
- Article.prototype.stopDragging = function(evt) {
1536
- this.offset = this.finalOffset = this.moveAnimation.finalOffset = {
1537
- left: this.position.left - this.registeredPosition.left,
1538
- top: this.position.top - this.registeredPosition.top
1539
- };
1540
- this.isDragging = false;
1541
- this.owner?._markTimelineStateChanged?.();
1542
- if (this.owner && typeof this.owner.trigger === "function") {
1543
- this.owner.trigger("article-drag-end", this, evt);
1544
- }
1545
- };
1546
- Article.prototype.dragging = function(pos, evt) {
1547
- const newPosition = {
1548
- left: pos.left - this.dragStartOffset.left,
1549
- top: pos.top - this.dragStartOffset.top
1550
- };
1551
- const previousPosition = this.lastDragPosition || {
1552
- left: this.position.left,
1553
- top: this.position.top
1554
- };
1555
- const initialPosition = this.dragInitialPosition || previousPosition;
1556
- const dx = newPosition.left - previousPosition.left;
1557
- const dy = newPosition.top - previousPosition.top;
1558
- const totalDx = newPosition.left - initialPosition.left;
1559
- const totalDy = newPosition.top - initialPosition.top;
1560
- this.position = newPosition;
1561
- this.lastDragPosition = newPosition;
1562
- if (this.owner && typeof this.owner.trigger === "function") {
1563
- this.owner.trigger("article-drag", this, { dx, dy, totalDx, totalDy }, evt);
1564
- }
1565
- };
1566
- Article.prototype._cacheBucket = function() {
1567
- const name = this._getCurrentCardLayoutName();
1568
- if (!this._layoutCaches) {
1569
- this._layoutCaches = /* @__PURE__ */ Object.create(null);
1570
- }
1571
- return this._layoutCaches[name] || (this._layoutCaches[name] = /* @__PURE__ */ Object.create(null));
1572
- };
1573
- Article.prototype.memo = function(key, factory) {
1574
- const bucket = this._cacheBucket();
1575
- return key in bucket ? bucket[key] : bucket[key] = factory.call(this);
1576
- };
1577
- Article.prototype._getSizeCacheKey = function() {
1578
- const style = typeof this.getCurrentStyle === "function" ? this.getCurrentStyle() : null;
1579
- const imageStyle = style && style.image || {};
1580
- const header = style && style.header || {};
1581
- const subheader = style && style.subheader || {};
1582
- const border = style && style.border || {};
1583
- const layout = typeof this._getCurrentCardLayoutName === "function" ? this._getCurrentCardLayoutName() : "";
1584
- const hasImage = this.imageLoaded && this.image;
1585
- const keyParts = [
1586
- layout,
1587
- style && style.width,
1588
- style && style.height,
1589
- header.height,
1590
- subheader.height,
1591
- border.width,
1592
- imageStyle.margin ?? 0,
1593
- imageStyle.shape || "",
1594
- imageStyle.maxHeight ?? "",
1595
- style && style.maxImageHeight !== void 0 ? style.maxImageHeight : "",
1596
- hasImage ? this.image.width : "noimg",
1597
- hasImage ? this.image.height : ""
1598
- ];
1599
- return keyParts.join("|");
1600
- };
1601
- Article.prototype.updateCachedSize = function() {
1602
- const cardLayout = this._getCurrentCardLayout();
1603
- this._cachedWidth = cardLayout.getWidth.call(this);
1604
- this._cachedHeight = cardLayout.getHeight.call(this);
1605
- this.height = this._cachedHeight;
1606
- this._sizeValid = true;
1607
- this._sizeCacheKey = this._getSizeCacheKey();
1608
- };
1609
- Article.prototype._ensureSizeCache = function() {
1610
- const cacheKey = this._getSizeCacheKey();
1611
- if (!this._sizeValid || cacheKey !== this._sizeCacheKey) {
1612
- this.updateCachedSize();
1613
- }
1614
- };
1615
- Article.prototype.invalidateCaches = function() {
1616
- this._sizeValid = false;
1617
- this._sizeCacheKey = null;
1618
- if (this._layoutCaches) {
1619
- const buckets = this._layoutCaches;
1620
- for (const layoutName in buckets) {
1621
- const bucket = buckets[layoutName];
1622
- if (!bucket) {
1623
- continue;
1624
- }
1625
- for (const k in bucket) {
1626
- const v = bucket[k];
1627
- if (v && typeof v.close === "function") {
1628
- try {
1629
- v.close();
1630
- } catch {
1631
- }
1632
- }
1633
- }
1634
- }
1635
- }
1636
- this._layoutCaches = null;
1637
- };
1638
- Article.prototype._getCurrentCardLayoutName = function() {
1639
- return this._resolvedCardLayoutName || this.cardLayout || this._resolvedDefaultCardLayout || this.owner._resolveArticleCardLayoutName(this);
1640
- };
1641
- Article.prototype._getCurrentCardLayout = function() {
1642
- return this.owner.getCardLayout(this._getCurrentCardLayoutName());
1643
- };
1644
- Article.prototype.setCardLayout = function(cardLayout) {
1645
- const layout = this.owner.getCardLayout(cardLayout);
1646
- if (!layout) {
1647
- throw new Error(`Card layout "${cardLayout}" not found`);
1648
- }
1649
- this.cardLayout = cardLayout;
1650
- this._resolvedCardLayoutName = cardLayout;
1651
- this.initialiseStyles();
1652
- this.invalidateCaches();
1653
- this.owner.requestRedraw(this.redraw);
1654
- };
1655
- function compareArticleIds(idA, idB) {
1656
- const numA = Number(idA);
1657
- const numB = Number(idB);
1658
- const idsAreNumeric = Number.isFinite(numA) && Number.isFinite(numB);
1659
- if (idsAreNumeric) {
1660
- return numA - numB;
1661
- }
1662
- const strA = String(idA);
1663
- const strB = String(idB);
1664
- if (strA === strB) {
1665
- return 0;
1666
- }
1667
- return strA < strB ? -1 : 1;
1668
- }
1669
- __name(compareArticleIds, "compareArticleIds");
1670
- function ARTICLE_DURATION_SORTER(articleA, articleB) {
1671
- const a = articleA.period.from.getDaysTo(articleA.period.to);
1672
- const b = articleB.period.from.getDaysTo(articleB.period.to);
1673
- if (a < b) {
1674
- return 1;
1675
- }
1676
- if (a > b) {
1677
- return -1;
1678
- }
1679
- return compareArticleIds(articleA.id, articleB.id);
1680
- }
1681
- __name(ARTICLE_DURATION_SORTER, "ARTICLE_DURATION_SORTER");
1682
- function ARTICLE_DURATION_YEARS_SORTER(articleA, articleB) {
1683
- const a = articleA.period.years;
1684
- const b = articleB.period.years;
1685
- if (a < b) {
1686
- return 1;
1687
- }
1688
- if (a > b) {
1689
- return -1;
1690
- }
1691
- return compareArticleIds(articleA.id, articleB.id);
1692
- }
1693
- __name(ARTICLE_DURATION_YEARS_SORTER, "ARTICLE_DURATION_YEARS_SORTER");
1694
- function ARTICLE_IMAGE_QUEUE_SORTER(articleA, articleB) {
1695
- const a = articleA.isInView && articleA.isVisible;
1696
- const b = articleB.isInView && articleB.isVisible;
1697
- if (!a && b) {
1698
- return -1;
1699
- }
1700
- if (a && !b) {
1701
- return 1;
1702
- }
1703
- return articleA.position.top - articleB.position.top;
1704
- }
1705
- __name(ARTICLE_IMAGE_QUEUE_SORTER, "ARTICLE_IMAGE_QUEUE_SORTER");
1706
- function ARTICLE_FROM_SORTER(articleA, articleB) {
1707
- const a = articleA.period.from;
1708
- const b = articleB.period.from;
1709
- let result = a.compare(b);
1710
- if (result === 0) {
1711
- result = compareArticleIds(articleB.id, articleA.id);
1712
- }
1713
- return result;
1714
- }
1715
- __name(ARTICLE_FROM_SORTER, "ARTICLE_FROM_SORTER");
1716
- function ARTICLE_TO_SORTER(articleA, articleB) {
1717
- const a = articleA.period.to;
1718
- const b = articleB.period.to;
1719
- let result = b.compare(a);
1720
- if (result === 0) {
1721
- result = compareArticleIds(articleB.id, articleA.id);
1722
- }
1723
- return result;
1724
- }
1725
- __name(ARTICLE_TO_SORTER, "ARTICLE_TO_SORTER");
1726
- function ARTICLE_TOP_SORTER(articleA, articleB) {
1727
- const a = articleA.position.top;
1728
- const b = articleB.position.top;
1729
- if (a < b) {
1730
- return -1;
1731
- }
1732
- if (a > b) {
1733
- return 1;
1734
- }
1735
- return compareArticleIds(articleB.id, articleA.id);
1736
- }
1737
- __name(ARTICLE_TOP_SORTER, "ARTICLE_TOP_SORTER");
1738
- function ARTICLE_ROW_SORTER(articleA, articleB) {
1739
- const laneOrderA = articleA.laneOrder || 0;
1740
- const laneOrderB = articleB.laneOrder || 0;
1741
- if (laneOrderA > laneOrderB) {
1742
- return -1;
1743
- }
1744
- if (laneOrderA < laneOrderB) {
1745
- return 1;
1746
- }
1747
- const a = articleA.row;
1748
- const b = articleB.row;
1749
- if (a < b) {
1750
- return 1;
1751
- }
1752
- if (a > b) {
1753
- return -1;
1754
- }
1755
- return compareArticleIds(articleB.id, articleA.id);
1756
- }
1757
- __name(ARTICLE_ROW_SORTER, "ARTICLE_ROW_SORTER");
1758
- function ARTICLE_RANK_SORTER(articleA, articleB) {
1759
- const a = articleA.rank;
1760
- const b = articleB.rank;
1761
- if (a < b) {
1762
- return 1;
1763
- }
1764
- if (a > b) {
1765
- return -1;
1766
- }
1767
- return compareArticleIds(articleB.id, articleA.id);
1768
- }
1769
- __name(ARTICLE_RANK_SORTER, "ARTICLE_RANK_SORTER");
1770
- function ARTICLE_EFFECTIVE_RANK_SORTER(articleA, articleB) {
1771
- const a = articleA.effectiveRank;
1772
- const b = articleB.effectiveRank;
1773
- if (a < b) {
1774
- return 1;
1775
- }
1776
- if (a > b) {
1777
- return -1;
1778
- }
1779
- return compareArticleIds(articleB.id, articleA.id);
1780
- }
1781
- __name(ARTICLE_EFFECTIVE_RANK_SORTER, "ARTICLE_EFFECTIVE_RANK_SORTER");
1782
- function ARTICLE_POSITION_SORTER(articleA, articleB) {
1783
- const a = articleA.position.left;
1784
- const b = articleB.position.left;
1785
- let result = a < b ? 1 : a > b ? -1 : 0;
1786
- if (result === 0) {
1787
- result = articleA.position.top - articleB.position.top;
1788
- if (result === 0) {
1789
- result = articleA.period.from.compare(articleB.period.from);
1790
- if (result === 0) {
1791
- result = compareArticleIds(articleA.id, articleB.id);
1792
- }
1793
- }
1794
- }
1795
- return result;
1796
- }
1797
- __name(ARTICLE_POSITION_SORTER, "ARTICLE_POSITION_SORTER");
1798
- const sorters = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1799
- __proto__: null,
1800
- ARTICLE_DURATION_SORTER,
1801
- ARTICLE_DURATION_YEARS_SORTER,
1802
- ARTICLE_EFFECTIVE_RANK_SORTER,
1803
- ARTICLE_FROM_SORTER,
1804
- ARTICLE_IMAGE_QUEUE_SORTER,
1805
- ARTICLE_POSITION_SORTER,
1806
- ARTICLE_RANK_SORTER,
1807
- ARTICLE_ROW_SORTER,
1808
- ARTICLE_TOP_SORTER,
1809
- ARTICLE_TO_SORTER
1810
- }, Symbol.toStringTag, { value: "Module" }));
1811
- const MINOR_MARKER = 0;
1812
- const MAJOR_MARKER = 1;
1813
- const ERA_MARKER = 2;
1814
- const ZOOM_MILLISECOND = -4;
1815
- const ZOOM_SECOND = -3;
1816
- const ZOOM_MINUTE = -2;
1817
- const ZOOM_HOUR = -1;
1818
- const ZOOM_DAY = 0;
1819
- const ZOOM_MONTH = 1;
1820
- const ZOOM_YEAR = 2;
1821
- const ZOOM_DECADE = 3;
1822
- const ZOOM_CENTURY = 4;
1823
- const ZOOM_MILLENNIUM = 5;
1824
- const ZOOM_10_THOUSAND_YEARS = 6;
1825
- const ZOOM_100_THOUSAND_YEARS = 7;
1826
- const ZOOM_MILLION_YEARS = 8;
1827
- const ZOOM_10_MILLION_YEARS = 9;
1828
- const ZOOM_100_MILLION_YEARS = 10;
1829
- const ZOOM_BILLION_YEARS = 11;
1830
- const PRECISION_MILLISECOND = "millisecond";
1831
- const PRECISION_SECOND = "second";
1832
- const PRECISION_MINUTE = "minute";
1833
- const PRECISION_HOUR = "hour";
1834
- const PRECISION_DAY = "day";
1835
- const PRECISION_MONTH = "month";
1836
- const PRECISION_YEAR = "year";
1837
- const PRECISION_DECADE = "decade";
1838
- const PRECISION_CENTURY = "century";
1839
- const PRECISION_MILLENNIUM = "millennium";
1840
- const PRECISION_MILLION_YEARS = "million-years";
1841
- const PRECISION_BILLION_YEARS = "billion-years";
1842
- const YEAR_PREFIXES = {
1843
- //uses power of ten of prefix as key to access it's settings
1844
- 3: { label: " ka", value: 1e3 },
1845
- 6: { label: " Ma", value: 1e6 },
1846
- 9: { label: " Ga", value: 1e9 }
68
+ const MINOR_MARKER = 0;
69
+ const MAJOR_MARKER = 1;
70
+ const ERA_MARKER = 2;
71
+ const ZOOM_MILLISECOND = -4;
72
+ const ZOOM_SECOND = -3;
73
+ const ZOOM_MINUTE = -2;
74
+ const ZOOM_HOUR = -1;
75
+ const ZOOM_DAY = 0;
76
+ const ZOOM_MONTH = 1;
77
+ const ZOOM_YEAR = 2;
78
+ const ZOOM_DECADE = 3;
79
+ const ZOOM_CENTURY = 4;
80
+ const ZOOM_MILLENNIUM = 5;
81
+ const ZOOM_10_THOUSAND_YEARS = 6;
82
+ const ZOOM_100_THOUSAND_YEARS = 7;
83
+ const ZOOM_MILLION_YEARS = 8;
84
+ const ZOOM_10_MILLION_YEARS = 9;
85
+ const ZOOM_100_MILLION_YEARS = 10;
86
+ const ZOOM_BILLION_YEARS = 11;
87
+ const PRECISION_MILLISECOND = "millisecond";
88
+ const PRECISION_SECOND = "second";
89
+ const PRECISION_MINUTE = "minute";
90
+ const PRECISION_HOUR = "hour";
91
+ const PRECISION_DAY = "day";
92
+ const PRECISION_MONTH = "month";
93
+ const PRECISION_YEAR = "year";
94
+ const PRECISION_DECADE = "decade";
95
+ const PRECISION_CENTURY = "century";
96
+ const PRECISION_MILLENNIUM = "millennium";
97
+ const PRECISION_MILLION_YEARS = "million-years";
98
+ const PRECISION_BILLION_YEARS = "billion-years";
99
+ const YEAR_PREFIXES = {
100
+ //uses power of ten of prefix as key to access it's settings
101
+ 3: { label: " ka", value: 1e3 },
102
+ 6: { label: " Ma", value: 1e6 },
103
+ 9: { label: " Ga", value: 1e9 }
1847
104
  };
1848
105
  const DENSITY_LOW = "low";
1849
106
  const DENSITY_MEDIUM = "medium";
@@ -2455,48 +712,1829 @@ const DENSITY_SETTINGS = [
2455
712
  all: 25,
2456
713
  step: { months: 0, days: 549755813888 }
2457
714
  }
2458
- ];
2459
- const constants = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
715
+ ];
716
+ const constants = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
717
+ __proto__: null,
718
+ DENSITY_ALL,
719
+ DENSITY_HIGH,
720
+ DENSITY_LOW,
721
+ DENSITY_MEDIUM,
722
+ DENSITY_SETTINGS,
723
+ ERA_MARKER,
724
+ MAJOR_MARKER,
725
+ MINOR_MARKER,
726
+ PRECISION_BILLION_YEARS,
727
+ PRECISION_CENTURY,
728
+ PRECISION_DAY,
729
+ PRECISION_DECADE,
730
+ PRECISION_HOUR,
731
+ PRECISION_MILLENNIUM,
732
+ PRECISION_MILLION_YEARS,
733
+ PRECISION_MILLISECOND,
734
+ PRECISION_MINUTE,
735
+ PRECISION_MONTH,
736
+ PRECISION_SECOND,
737
+ PRECISION_YEAR,
738
+ RANGE_ALL,
739
+ RANGE_SCREEN,
740
+ YEAR_PREFIXES,
741
+ ZOOM_100_MILLION_YEARS,
742
+ ZOOM_100_THOUSAND_YEARS,
743
+ ZOOM_10_MILLION_YEARS,
744
+ ZOOM_10_THOUSAND_YEARS,
745
+ ZOOM_BILLION_YEARS,
746
+ ZOOM_CENTURY,
747
+ ZOOM_DAY,
748
+ ZOOM_DECADE,
749
+ ZOOM_HOUR,
750
+ ZOOM_MILLENNIUM,
751
+ ZOOM_MILLION_YEARS,
752
+ ZOOM_MILLISECOND,
753
+ ZOOM_MINUTE,
754
+ ZOOM_MONTH,
755
+ ZOOM_SECOND,
756
+ ZOOM_YEAR
757
+ }, Symbol.toStringTag, { value: "Module" }));
758
+ const _LoggerImpl = class _LoggerImpl {
759
+ constructor() {
760
+ this._enabled = false;
761
+ this._prefix = "[Histropedia]";
762
+ const c = typeof console !== "undefined" ? console : null;
763
+ this._console = c;
764
+ this._fns = {
765
+ log: c && c.log ? c.log.bind(c) : () => {
766
+ },
767
+ warn: c && c.warn ? c.warn.bind(c) : () => {
768
+ },
769
+ error: c && c.error ? c.error.bind(c) : () => {
770
+ },
771
+ info: c && c.info ? c.info.bind(c) : () => {
772
+ },
773
+ debug: c && c.debug ? c.debug.bind(c) : c && c.log ? c.log.bind(c) : () => {
774
+ },
775
+ group: c && c.group ? c.group.bind(c) : c && c.log ? c.log.bind(c) : () => {
776
+ },
777
+ groupCollapsed: c && c.groupCollapsed ? c.groupCollapsed.bind(c) : c && c.group ? c.group.bind(c) : c && c.log ? c.log.bind(c) : () => {
778
+ },
779
+ groupEnd: c && c.groupEnd ? c.groupEnd.bind(c) : () => {
780
+ }
781
+ };
782
+ }
783
+ setEnabled(enabled) {
784
+ this._enabled = !!enabled;
785
+ }
786
+ isEnabled() {
787
+ return !!this._enabled;
788
+ }
789
+ setPrefix(prefix) {
790
+ this._prefix = String(prefix || "");
791
+ }
792
+ getPrefix() {
793
+ return this._prefix;
794
+ }
795
+ _withPrefixedArgs(argsArray) {
796
+ if (!this._prefix) {
797
+ return argsArray;
798
+ }
799
+ if (argsArray && argsArray.length > 0 && typeof argsArray[0] === "string") {
800
+ const cloned = argsArray.slice();
801
+ cloned[0] = `${this._prefix} ${cloned[0]}`;
802
+ return cloned;
803
+ }
804
+ return [this._prefix, ...argsArray];
805
+ }
806
+ _log(method, args) {
807
+ if (!this._enabled) {
808
+ return;
809
+ }
810
+ const fn = this._fns[method] || this._fns.log;
811
+ fn(...this._withPrefixedArgs(args));
812
+ }
813
+ log(...args) {
814
+ this._log("log", args);
815
+ }
816
+ warn(...args) {
817
+ this._log("warn", args);
818
+ }
819
+ error(...args) {
820
+ this._log("error", args);
821
+ }
822
+ info(...args) {
823
+ this._log("info", args);
824
+ }
825
+ debug(...args) {
826
+ this._log("debug", args);
827
+ }
828
+ group(...args) {
829
+ if (!this._enabled) {
830
+ return;
831
+ }
832
+ this._fns.group(...this._withPrefixedArgs(args));
833
+ }
834
+ groupCollapsed(...args) {
835
+ if (!this._enabled) {
836
+ return;
837
+ }
838
+ this._fns.groupCollapsed(...this._withPrefixedArgs(args));
839
+ }
840
+ groupEnd() {
841
+ if (!this._enabled) {
842
+ return;
843
+ }
844
+ this._fns.groupEnd();
845
+ }
846
+ };
847
+ __name(_LoggerImpl, "LoggerImpl");
848
+ let LoggerImpl = _LoggerImpl;
849
+ const Logger = new LoggerImpl();
850
+ const DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
851
+ const MONTH_NAMES = [
852
+ "Jan",
853
+ "Feb",
854
+ "Mar",
855
+ "Apr",
856
+ "May",
857
+ "Jun",
858
+ "Jul",
859
+ "Aug",
860
+ "Sep",
861
+ "Oct",
862
+ "Nov",
863
+ "Dec"
864
+ ];
865
+ const LEGACY_PRECISIONS = {
866
+ 1: "billion-years",
867
+ 3: "million-years",
868
+ 6: "millennium",
869
+ 7: "century",
870
+ 8: "decade",
871
+ 9: "year",
872
+ 10: "month",
873
+ 11: "day",
874
+ 12: "hour",
875
+ 13: "minute",
876
+ 14: "second",
877
+ 15: "millisecond"
878
+ };
879
+ const DMY_STRING_PATTERN = /^(-?\d+)(?:-(\d{1,2}))?(?:-(\d{1,2}))?(?:[T ](\d{1,2})(?::(\d{1,2}))?(?::(\d{1,2})(?:\.(\d{1,3}))?)?)?$/;
880
+ const MILLISECONDS_PER_SECOND = 1e3;
881
+ const MILLISECONDS_PER_MINUTE = 60 * MILLISECONDS_PER_SECOND;
882
+ const MILLISECONDS_PER_HOUR = 60 * MILLISECONDS_PER_MINUTE;
883
+ const MILLISECONDS_PER_DAY = 24 * MILLISECONDS_PER_HOUR;
884
+ function normalizePrecision(precision) {
885
+ return Object.prototype.hasOwnProperty.call(LEGACY_PRECISIONS, precision) ? LEGACY_PRECISIONS[precision] : precision || "day";
886
+ }
887
+ __name(normalizePrecision, "normalizePrecision");
888
+ function getDatePrecision(parts) {
889
+ if (parts.precision !== void 0) {
890
+ return parts.precision;
891
+ }
892
+ if (!(parts instanceof Dmy)) {
893
+ for (const component of [
894
+ PRECISION_MILLISECOND,
895
+ PRECISION_SECOND,
896
+ PRECISION_MINUTE,
897
+ PRECISION_HOUR
898
+ ]) {
899
+ if (parts[component] !== void 0) {
900
+ return component;
901
+ }
902
+ }
903
+ }
904
+ return PRECISION_DAY;
905
+ }
906
+ __name(getDatePrecision, "getDatePrecision");
907
+ function getHistoricalPeriodBounds(year, size) {
908
+ if (year <= 0) {
909
+ const historicalYear = 1 - year;
910
+ const oldestYear = Math.ceil(historicalYear / size) * size;
911
+ return { startYear: 1 - oldestYear, endYear: size - oldestYear };
912
+ }
913
+ const endYear = Math.ceil(year / size) * size;
914
+ return {
915
+ startYear: endYear - size + 1,
916
+ endYear
917
+ };
918
+ }
919
+ __name(getHistoricalPeriodBounds, "getHistoricalPeriodBounds");
920
+ function getDecadeBounds(year) {
921
+ if (year <= 0) {
922
+ const decade = Math.floor((1 - year) / 10) * 10;
923
+ return { startYear: 1 - (decade + 9), endYear: 1 - Math.max(1, decade) };
924
+ }
925
+ const startYear = Math.floor(year / 10) * 10;
926
+ return { startYear: Math.max(1, startYear), endYear: startYear + 9 };
927
+ }
928
+ __name(getDecadeBounds, "getDecadeBounds");
929
+ function clampInteger(value, fallback, minimum, maximum) {
930
+ const parsed = Number(value);
931
+ if (!Number.isFinite(parsed)) {
932
+ return fallback;
933
+ }
934
+ return Math.min(maximum, Math.max(minimum, Math.trunc(parsed)));
935
+ }
936
+ __name(clampInteger, "clampInteger");
937
+ function setTimeParts(target, hour, minute, second, millisecond) {
938
+ const values = {
939
+ hour: clampInteger(hour, 0, 0, 23),
940
+ minute: clampInteger(minute, 0, 0, 59),
941
+ second: clampInteger(second, 0, 0, 59),
942
+ millisecond: clampInteger(millisecond, 0, 0, 999)
943
+ };
944
+ for (const [key, value] of Object.entries(values)) {
945
+ Object.defineProperty(target, key, {
946
+ value,
947
+ enumerable: value !== 0,
948
+ configurable: true,
949
+ writable: true
950
+ });
951
+ }
952
+ }
953
+ __name(setTimeParts, "setTimeParts");
954
+ function setPrecision(target, precision) {
955
+ if (precision === void 0) {
956
+ return;
957
+ }
958
+ Object.defineProperty(target, "precision", {
959
+ value: precision,
960
+ enumerable: false,
961
+ configurable: true,
962
+ writable: true
963
+ });
964
+ }
965
+ __name(setPrecision, "setPrecision");
966
+ function createAdjustedDmy(source, values) {
967
+ return new Dmy({ ...values, precision: getDatePrecision(source) });
968
+ }
969
+ __name(createAdjustedDmy, "createAdjustedDmy");
970
+ function Dmy(year, month, day, hour, minute, second, millisecond) {
971
+ if (typeof year === "object") {
972
+ const options = year;
973
+ this.year = options.year;
974
+ this.month = options.month;
975
+ this.day = getCorrectDay(options.year, options.month, options.day);
976
+ setTimeParts(this, options.hour, options.minute, options.second, options.millisecond);
977
+ setPrecision(this, getDatePrecision(options));
978
+ } else {
979
+ this.year = year;
980
+ this.month = month;
981
+ this.day = getCorrectDay(year, month, day);
982
+ setTimeParts(this, hour, minute, second, millisecond);
983
+ }
984
+ }
985
+ __name(Dmy, "Dmy");
986
+ function getCorrectDay(year, month, day) {
987
+ return day > 28 ? Math.min(day, daysInMonth(year, month)) : day;
988
+ }
989
+ __name(getCorrectDay, "getCorrectDay");
990
+ function daysInMonth(year, month) {
991
+ if (month === 2) {
992
+ if (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0) {
993
+ return 29;
994
+ }
995
+ }
996
+ return DAYS_IN_MONTH[month - 1];
997
+ }
998
+ __name(daysInMonth, "daysInMonth");
999
+ function digitGroupedNumber(number, separator) {
1000
+ number = number.toString();
1001
+ separator = typeof separator === "string" ? separator : ",";
1002
+ if (number.length <= 4) {
1003
+ return number;
1004
+ }
1005
+ return number.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
1006
+ }
1007
+ __name(digitGroupedNumber, "digitGroupedNumber");
1008
+ Dmy.prototype.getDaysTo = function(other) {
1009
+ const dayDifference = other.getDaysSinceYearZero() - this.getDaysSinceYearZero();
1010
+ const timeDifference = other.getMillisecondsOfDay() - this.getMillisecondsOfDay();
1011
+ return dayDifference + timeDifference / MILLISECONDS_PER_DAY;
1012
+ };
1013
+ Dmy.prototype.getMillisecondsOfDay = function() {
1014
+ return this.hour * MILLISECONDS_PER_HOUR + this.minute * MILLISECONDS_PER_MINUTE + this.second * MILLISECONDS_PER_SECOND + this.millisecond;
1015
+ };
1016
+ Dmy.prototype.getMonthsTo = function(other) {
1017
+ return this.getYearsTo(other) * 12;
1018
+ };
1019
+ Dmy.prototype.getYearsTo = function(other) {
1020
+ let yearDiff = other.year - this.year;
1021
+ yearDiff += (other.month - this.month) / 12 + (other.day - this.day) / 365.2422 + (other.getMillisecondsOfDay() - this.getMillisecondsOfDay()) / (MILLISECONDS_PER_DAY * 365.2422);
1022
+ return yearDiff;
1023
+ };
1024
+ Dmy.prototype.getLeapYearsSinceYearZero = function() {
1025
+ let year = this.year;
1026
+ if (this.month < 3) {
1027
+ year--;
1028
+ }
1029
+ return Math.floor(year / 4) - Math.floor(year / 100) + Math.floor(year / 400);
1030
+ };
1031
+ Dmy.prototype.getDaysSinceYearZero = function() {
1032
+ const year = this.year;
1033
+ let days = year * 365 + this.day;
1034
+ for (let i = 0; i < this.month - 1; i++) {
1035
+ days += DAYS_IN_MONTH[i];
1036
+ }
1037
+ days += this.getLeapYearsSinceYearZero();
1038
+ return days;
1039
+ };
1040
+ Dmy.prototype.getDayOfYear = function() {
1041
+ let dayOfYear = this.day;
1042
+ for (let m = 1; m < this.month; m++) {
1043
+ dayOfYear += daysInMonth(this.year, m);
1044
+ }
1045
+ return dayOfYear;
1046
+ };
1047
+ Dmy.getByDayOfYear = function(year, dayOfYear) {
1048
+ const dmy = new Dmy(year, 1, 1);
1049
+ let dim = DAYS_IN_MONTH[0];
1050
+ for (let i = 0; i < dayOfYear - 1; i++) {
1051
+ dmy.day++;
1052
+ if (dmy.day > dim) {
1053
+ dmy.day = 1;
1054
+ dmy.month++;
1055
+ if (dmy.month > 12) {
1056
+ dmy.month = 1;
1057
+ dmy.year++;
1058
+ }
1059
+ dim = dmy.month === 2 ? daysInMonth(dmy.year, dmy.month) : DAYS_IN_MONTH[dmy.month - 1];
1060
+ }
1061
+ }
1062
+ return dmy;
1063
+ };
1064
+ Dmy.prototype.getNextDay = function() {
1065
+ return this.addDays(1);
1066
+ };
1067
+ Dmy.prototype.addDays = function(amount) {
1068
+ let day = this.day;
1069
+ let month = this.month;
1070
+ let year = this.year;
1071
+ const direction = amount < 0 ? -1 : 1;
1072
+ let remaining = Math.abs(Math.trunc(amount));
1073
+ while (remaining > 0) {
1074
+ if (direction > 0) {
1075
+ day++;
1076
+ if (day > daysInMonth(year, month)) {
1077
+ day = 1;
1078
+ month++;
1079
+ if (month > 12) {
1080
+ month = 1;
1081
+ year++;
1082
+ }
1083
+ }
1084
+ } else {
1085
+ day--;
1086
+ if (day < 1) {
1087
+ month--;
1088
+ if (month < 1) {
1089
+ month = 12;
1090
+ year--;
1091
+ }
1092
+ day = daysInMonth(year, month);
1093
+ }
1094
+ }
1095
+ remaining--;
1096
+ }
1097
+ return createAdjustedDmy(this, {
1098
+ year,
1099
+ month,
1100
+ day,
1101
+ hour: this.hour,
1102
+ minute: this.minute,
1103
+ second: this.second,
1104
+ millisecond: this.millisecond
1105
+ });
1106
+ };
1107
+ Dmy.prototype.addMilliseconds = function(amount) {
1108
+ let date = this;
1109
+ let milliseconds = this.getMillisecondsOfDay() + Math.trunc(amount);
1110
+ while (milliseconds < 0) {
1111
+ date = date.addDays(-1);
1112
+ milliseconds += MILLISECONDS_PER_DAY;
1113
+ }
1114
+ while (milliseconds >= MILLISECONDS_PER_DAY) {
1115
+ date = date.addDays(1);
1116
+ milliseconds -= MILLISECONDS_PER_DAY;
1117
+ }
1118
+ const hour = Math.floor(milliseconds / MILLISECONDS_PER_HOUR);
1119
+ milliseconds -= hour * MILLISECONDS_PER_HOUR;
1120
+ const minute = Math.floor(milliseconds / MILLISECONDS_PER_MINUTE);
1121
+ milliseconds -= minute * MILLISECONDS_PER_MINUTE;
1122
+ const second = Math.floor(milliseconds / MILLISECONDS_PER_SECOND);
1123
+ const millisecond = milliseconds - second * MILLISECONDS_PER_SECOND;
1124
+ return createAdjustedDmy(this, {
1125
+ year: date.year,
1126
+ month: date.month,
1127
+ day: date.day,
1128
+ hour,
1129
+ minute,
1130
+ second,
1131
+ millisecond
1132
+ });
1133
+ };
1134
+ Dmy.prototype.addSeconds = function(amount) {
1135
+ return this.addMilliseconds(amount * MILLISECONDS_PER_SECOND);
1136
+ };
1137
+ Dmy.prototype.addMinutes = function(amount) {
1138
+ return this.addMilliseconds(amount * MILLISECONDS_PER_MINUTE);
1139
+ };
1140
+ Dmy.prototype.addHours = function(amount) {
1141
+ return this.addMilliseconds(amount * MILLISECONDS_PER_HOUR);
1142
+ };
1143
+ Dmy.prototype.addMonths = function(amount) {
1144
+ let month = this.month;
1145
+ let year = this.year;
1146
+ for (let i = 0; i < amount; i++) {
1147
+ month++;
1148
+ if (month > 12) {
1149
+ month = 1;
1150
+ year++;
1151
+ }
1152
+ }
1153
+ return createAdjustedDmy(this, { year, month, day: 1 });
1154
+ };
1155
+ Dmy.prototype.getPreviousDay = function() {
1156
+ return this.addDays(-1);
1157
+ };
1158
+ Dmy.prototype.getNextMonth = function() {
1159
+ let month = this.month;
1160
+ let year = this.year;
1161
+ month++;
1162
+ if (month > 12) {
1163
+ month = 1;
1164
+ year++;
1165
+ }
1166
+ return createAdjustedDmy(this, { year, month, day: 1 });
1167
+ };
1168
+ Dmy.prototype.getPreviousMonth = function() {
1169
+ let month = this.month;
1170
+ let year = this.year;
1171
+ month--;
1172
+ if (month < 1) {
1173
+ month = 12;
1174
+ year--;
1175
+ }
1176
+ return createAdjustedDmy(this, { year, month, day: 1 });
1177
+ };
1178
+ Dmy.prototype.addYears = function(amount) {
1179
+ return createAdjustedDmy(this, { year: this.year + amount, month: 1, day: 1 });
1180
+ };
1181
+ function pad(value, length) {
1182
+ return String(value).padStart(length, "0");
1183
+ }
1184
+ __name(pad, "pad");
1185
+ Dmy.prototype.format = function(format, options) {
1186
+ options = options || {};
1187
+ format = format || "D MMM YYYY";
1188
+ const prefixSettings = options.yearPrefix;
1189
+ const bceText = typeof options.bceText === "string" ? options.bceText : " ʙᴄᴇ";
1190
+ const isBc = this.year <= 0;
1191
+ const is1Bc = this.year === 0;
1192
+ const thousandsSeparator = options.thousandsSeparator;
1193
+ if (prefixSettings && !is1Bc) {
1194
+ const prefixValue = prefixSettings.value || 1;
1195
+ const prefixLabel = prefixSettings.label || "";
1196
+ let formattedYear;
1197
+ if (isBc) {
1198
+ formattedYear = digitGroupedNumber((-this.year + 1) / prefixValue, thousandsSeparator) + prefixLabel + bceText;
1199
+ } else {
1200
+ formattedYear = digitGroupedNumber(this.year / prefixValue, thousandsSeparator) + prefixLabel;
1201
+ }
1202
+ return formattedYear;
1203
+ }
1204
+ return format.replace(
1205
+ "YYYY",
1206
+ isBc ? digitGroupedNumber(-this.year + 1, thousandsSeparator) + bceText : digitGroupedNumber(this.year, thousandsSeparator)
1207
+ ).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));
1208
+ };
1209
+ Dmy.prototype.isSame = function(other) {
1210
+ 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;
1211
+ };
1212
+ Dmy.prototype.toKeyString = function() {
1213
+ const dateKey = `${this.year}|${this.month}|${this.day}`;
1214
+ if (this.getMillisecondsOfDay() === 0) {
1215
+ return dateKey;
1216
+ }
1217
+ return `${dateKey}|${this.hour}|${this.minute}|${this.second}|${this.millisecond}`;
1218
+ };
1219
+ Dmy.prototype.isAfter = function(other) {
1220
+ const fields = ["year", "month", "day", "hour", "minute", "second", "millisecond"];
1221
+ for (let i = 0; i < fields.length; i++) {
1222
+ const field = fields[i];
1223
+ const thisValue = this[field] || 0;
1224
+ const otherValue = other[field] || 0;
1225
+ if (thisValue !== otherValue) {
1226
+ return thisValue > otherValue;
1227
+ }
1228
+ }
1229
+ return false;
1230
+ };
1231
+ Dmy.prototype.isBetween = function(from, to) {
1232
+ return this.isAfter(from) && to.isAfter(this);
1233
+ };
1234
+ Dmy.prototype.compare = function(other) {
1235
+ if (this.isSame(other)) {
1236
+ return 0;
1237
+ }
1238
+ if (this.isAfter(other)) {
1239
+ return 1;
1240
+ }
1241
+ return -1;
1242
+ };
1243
+ Dmy.prototype.asFloat = function() {
1244
+ const m = this.month - 1;
1245
+ const d = this.day - 1;
1246
+ const dayFraction = this.getMillisecondsOfDay() / MILLISECONDS_PER_DAY;
1247
+ if (m === 0 && d === 0 && dayFraction === 0) {
1248
+ return this.year;
1249
+ }
1250
+ return Math.round((this.year + (m * 31 + d + dayFraction) / 371) * 100) / 100;
1251
+ };
1252
+ Dmy.prototype.isInFuture = function() {
1253
+ const date = /* @__PURE__ */ new Date();
1254
+ const now = new Dmy(
1255
+ date.getFullYear(),
1256
+ date.getMonth() + 1,
1257
+ date.getDate(),
1258
+ date.getHours(),
1259
+ date.getMinutes(),
1260
+ date.getSeconds(),
1261
+ date.getMilliseconds()
1262
+ );
1263
+ return this.isAfter(now);
1264
+ };
1265
+ Dmy.prototype.convertToIso = function() {
1266
+ if (this.year < 0) {
1267
+ this.year += 1;
1268
+ }
1269
+ return this;
1270
+ };
1271
+ Dmy.CreateAsStartOfPeriod = function(isoDmy, precision) {
1272
+ const isoYear = isoDmy.year;
1273
+ const month = isoDmy.month || 1;
1274
+ const day = isoDmy.day || 1;
1275
+ precision = normalizePrecision(precision);
1276
+ if (precision === "millisecond") {
1277
+ return new Dmy(isoDmy);
1278
+ }
1279
+ if (precision === "second") {
1280
+ return new Dmy(isoYear, month, day, isoDmy.hour, isoDmy.minute, isoDmy.second, 0);
1281
+ }
1282
+ if (precision === "minute") {
1283
+ return new Dmy(isoYear, month, day, isoDmy.hour, isoDmy.minute, 0, 0);
1284
+ }
1285
+ if (precision === "hour") {
1286
+ return new Dmy(isoYear, month, day, isoDmy.hour, 0, 0, 0);
1287
+ }
1288
+ if (precision === "day") {
1289
+ return new Dmy(isoYear, month, day);
1290
+ }
1291
+ if (precision === "month") {
1292
+ return new Dmy(isoYear, month, 1);
1293
+ }
1294
+ if (precision === "year") {
1295
+ return new Dmy(isoYear, 1, 1);
1296
+ }
1297
+ if (precision === "million-years" || precision === "billion-years") {
1298
+ const size = precision === "million-years" ? 1e6 : 1e9;
1299
+ return new Dmy(
1300
+ isoYear <= 0 ? getHistoricalPeriodBounds(isoYear, size).startYear : isoYear,
1301
+ 1,
1302
+ 1
1303
+ );
1304
+ }
1305
+ if (precision === "decade") {
1306
+ return new Dmy(getDecadeBounds(isoYear).startYear, 1, 1);
1307
+ }
1308
+ if (precision === "century") {
1309
+ return new Dmy(getHistoricalPeriodBounds(isoYear, 100).startYear, 1, 1);
1310
+ }
1311
+ if (precision === "millennium") {
1312
+ return new Dmy(getHistoricalPeriodBounds(isoYear, 1e3).startYear, 1, 1);
1313
+ }
1314
+ return new Dmy(isoYear, month, day);
1315
+ };
1316
+ Dmy.CreateAsEndOfPeriod = function(isoDmy, precision) {
1317
+ const isoYear = isoDmy.year;
1318
+ const month = isoDmy.month || 1;
1319
+ const day = isoDmy.day || 1;
1320
+ precision = normalizePrecision(precision);
1321
+ if (precision === "millisecond") {
1322
+ return new Dmy(isoDmy);
1323
+ }
1324
+ if (precision === "second") {
1325
+ return new Dmy(isoYear, month, day, isoDmy.hour, isoDmy.minute, isoDmy.second, 999);
1326
+ }
1327
+ if (precision === "minute") {
1328
+ return new Dmy(isoYear, month, day, isoDmy.hour, isoDmy.minute, 59, 999);
1329
+ }
1330
+ if (precision === "hour") {
1331
+ return new Dmy(isoYear, month, day, isoDmy.hour, 59, 59, 999);
1332
+ }
1333
+ if (precision === "day") {
1334
+ return new Dmy(isoYear, month, day);
1335
+ }
1336
+ if (precision === "month") {
1337
+ return new Dmy(isoYear, month, daysInMonth(isoYear, month));
1338
+ }
1339
+ if (precision === "year") {
1340
+ return new Dmy(isoYear, 12, 31);
1341
+ }
1342
+ if (precision === "decade") {
1343
+ return new Dmy(getDecadeBounds(isoYear).endYear, 12, 31);
1344
+ }
1345
+ if (precision === "century") {
1346
+ return new Dmy(getHistoricalPeriodBounds(isoYear, 100).endYear, 12, 31);
1347
+ }
1348
+ if (precision === "millennium") {
1349
+ return new Dmy(getHistoricalPeriodBounds(isoYear, 1e3).endYear, 12, 31);
1350
+ }
1351
+ if (precision === "million-years" || precision === "billion-years") {
1352
+ const size = precision === "million-years" ? 1e6 : 1e9;
1353
+ return new Dmy(
1354
+ isoYear <= 0 ? getHistoricalPeriodBounds(isoYear, size).endYear : isoYear + size - 1,
1355
+ 12,
1356
+ 31
1357
+ );
1358
+ }
1359
+ Logger.error("precision is not implemented");
1360
+ return new Dmy(isoYear, month, day);
1361
+ };
1362
+ Dmy.CreateAsExclusiveEndOfPeriod = function(isoDmy, precision) {
1363
+ precision = normalizePrecision(precision);
1364
+ const start = Dmy.CreateAsStartOfPeriod(isoDmy, precision);
1365
+ if (precision === "millisecond") {
1366
+ return start.addMilliseconds(1);
1367
+ }
1368
+ if (precision === "second") {
1369
+ return start.addSeconds(1);
1370
+ }
1371
+ if (precision === "minute") {
1372
+ return start.addMinutes(1);
1373
+ }
1374
+ if (precision === "hour") {
1375
+ return start.addHours(1);
1376
+ }
1377
+ if (precision === "day") {
1378
+ return start.addDays(1);
1379
+ }
1380
+ return Dmy.CreateAsEndOfPeriod(isoDmy, precision).addDays(1);
1381
+ };
1382
+ Dmy.now = function() {
1383
+ const now = /* @__PURE__ */ new Date();
1384
+ return new Dmy({
1385
+ year: now.getYear() + 1900,
1386
+ month: now.getMonth() + 1,
1387
+ day: now.getDate()
1388
+ });
1389
+ };
1390
+ function parseDmyString(dateString) {
1391
+ const match = String(dateString).match(DMY_STRING_PATTERN);
1392
+ if (!match) {
1393
+ return null;
1394
+ }
1395
+ const year = parseInt(match[1], 10);
1396
+ const month = match[2] == null ? 1 : parseInt(match[2], 10);
1397
+ const day = match[3] == null ? 1 : parseInt(match[3], 10);
1398
+ const hour = match[4] == null ? 0 : parseInt(match[4], 10);
1399
+ const minute = match[5] == null ? 0 : parseInt(match[5], 10);
1400
+ const second = match[6] == null ? 0 : parseInt(match[6], 10);
1401
+ const millisecond = match[7] ? parseInt(match[7].padEnd(3, "0"), 10) : 0;
1402
+ return {
1403
+ // These fields are already defaulted; keep string parsing outside object inference.
1404
+ date: new Dmy(year, month, day, hour, minute, second, millisecond),
1405
+ hasMonth: match[2] != null,
1406
+ hasDay: match[3] != null,
1407
+ hasTime: match[4] != null
1408
+ };
1409
+ }
1410
+ __name(parseDmyString, "parseDmyString");
1411
+ Dmy.fromString = function(dateString) {
1412
+ const parsed = parseDmyString(dateString);
1413
+ return parsed ? parsed.date : new Dmy(NaN, 1, 1);
1414
+ };
1415
+ function merge(target, ...sources) {
1416
+ return Object.assign(target, ...sources);
1417
+ }
1418
+ __name(merge, "merge");
1419
+ function deepMerge(target, ...sources) {
1420
+ const ensureSafeProto = /* @__PURE__ */ __name((obj) => {
1421
+ if (obj && typeof obj === "object" && !Object.prototype.hasOwnProperty.call(obj, "__proto__")) {
1422
+ try {
1423
+ Object.defineProperty(obj, "__proto__", {
1424
+ value: void 0,
1425
+ writable: true,
1426
+ enumerable: false,
1427
+ configurable: true
1428
+ });
1429
+ } catch {
1430
+ }
1431
+ }
1432
+ }, "ensureSafeProto");
1433
+ ensureSafeProto(target);
1434
+ const isUnsafeKey = /* @__PURE__ */ __name((key) => key === "__proto__" || key === "constructor" || key === "prototype", "isUnsafeKey");
1435
+ const isPlainObject = /* @__PURE__ */ __name((obj) => {
1436
+ if (obj === null || typeof obj !== "object") {
1437
+ return false;
1438
+ }
1439
+ const proto = Object.getPrototypeOf(obj);
1440
+ return proto === Object.prototype || proto === null;
1441
+ }, "isPlainObject");
1442
+ for (const src of sources) {
1443
+ if (!src || typeof src !== "object") {
1444
+ continue;
1445
+ }
1446
+ for (const k of Object.keys(src)) {
1447
+ if (isUnsafeKey(k)) {
1448
+ continue;
1449
+ }
1450
+ const v = src[k];
1451
+ if (Array.isArray(v)) {
1452
+ target[k] = v.slice();
1453
+ continue;
1454
+ }
1455
+ if (isPlainObject(v)) {
1456
+ const base = isPlainObject(target[k]) ? target[k] : {};
1457
+ ensureSafeProto(base);
1458
+ target[k] = deepMerge(base, v);
1459
+ continue;
1460
+ }
1461
+ target[k] = v;
1462
+ }
1463
+ }
1464
+ ensureSafeProto(target);
1465
+ return target;
1466
+ }
1467
+ __name(deepMerge, "deepMerge");
1468
+ function buildObjectFromPath(path, value) {
1469
+ const pathParts = path.split(".");
1470
+ const pathEnd = pathParts[pathParts.length - 1];
1471
+ let obj = {};
1472
+ obj[pathEnd] = value;
1473
+ for (let i = pathParts.length - 2; i >= 0; i--) {
1474
+ const previousPathPart = pathParts[i];
1475
+ const objClone = deepMerge({}, obj);
1476
+ obj = {};
1477
+ obj[previousPathPart] = objClone;
1478
+ }
1479
+ return obj;
1480
+ }
1481
+ __name(buildObjectFromPath, "buildObjectFromPath");
1482
+ function defineValueOrFunctionProperty(obj, propName) {
1483
+ const privatePropertyName = `_${propName}`;
1484
+ obj[privatePropertyName] = void 0;
1485
+ Object.defineProperty(obj, propName, {
1486
+ get() {
1487
+ const value = this[privatePropertyName];
1488
+ if (typeof value === "function") {
1489
+ return value(this);
1490
+ }
1491
+ return value;
1492
+ },
1493
+ set(value) {
1494
+ this[privatePropertyName] = value;
1495
+ },
1496
+ enumerable: true,
1497
+ configurable: false
1498
+ });
1499
+ }
1500
+ __name(defineValueOrFunctionProperty, "defineValueOrFunctionProperty");
1501
+ function isUndefined(value) {
1502
+ return typeof value === "undefined";
1503
+ }
1504
+ __name(isUndefined, "isUndefined");
1505
+ const propertyAbbreviations = {
1506
+ id: "i",
1507
+ title: "t",
1508
+ rank: "r",
1509
+ subtitle: "s",
1510
+ "from.year": "fy",
1511
+ "from.month": "fm",
1512
+ "from.day": "fd",
1513
+ "from.hour": "fhr",
1514
+ "from.minute": "fmi",
1515
+ "from.second": "fs",
1516
+ "from.millisecond": "fms",
1517
+ "from.precision": "fp",
1518
+ "to.year": "ty",
1519
+ "to.month": "tm",
1520
+ "to.day": "td",
1521
+ "to.hour": "thr",
1522
+ "to.minute": "tmi",
1523
+ "to.second": "ts",
1524
+ "to.millisecond": "tms",
1525
+ "to.precision": "tp",
1526
+ isToPresent: "p",
1527
+ isStarred: "v",
1528
+ "offset.left": "ol",
1529
+ "offset.top": "ot",
1530
+ imageUrl: "m",
1531
+ lane: "ln",
1532
+ style: "st",
1533
+ activeStyle: "ast",
1534
+ hiddenByFilter: "h",
1535
+ hidePeriodLine: "hp"
1536
+ };
1537
+ function extractProperty(data, property) {
1538
+ return Object.prototype.hasOwnProperty.call(data, property) ? data[property] : data[propertyAbbreviations[property]];
1539
+ }
1540
+ __name(extractProperty, "extractProperty");
1541
+ function extractPropertyFromPath(data, path) {
1542
+ const pathParts = path.split(".");
1543
+ const value = pathParts.reduce((curr, next) => curr ? curr[next] : void 0, data);
1544
+ return isUndefined(value) ? data[propertyAbbreviations[path]] : value;
1545
+ }
1546
+ __name(extractPropertyFromPath, "extractPropertyFromPath");
1547
+ function isPath(property) {
1548
+ return property.indexOf(".") > -1;
1549
+ }
1550
+ __name(isPath, "isPath");
1551
+ function getPropertyFromData(data, property) {
1552
+ if (isPath(property)) {
1553
+ return extractPropertyFromPath(data, property);
1554
+ }
1555
+ return extractProperty(data, property);
1556
+ }
1557
+ __name(getPropertyFromData, "getPropertyFromData");
1558
+ function getDmyFromData(data, prefix) {
1559
+ const precision = getDatePrecision(
1560
+ Object.fromEntries(
1561
+ ["precision", "hour", "minute", "second", "millisecond"].map((key) => [
1562
+ key,
1563
+ getPropertyFromData(data, `${prefix}.${key}`)
1564
+ ])
1565
+ )
1566
+ );
1567
+ const parts = Object.fromEntries(
1568
+ ["year", "month", "day", "hour", "minute", "second", "millisecond"].map((key) => [
1569
+ key,
1570
+ parseInt(getPropertyFromData(data, `${prefix}.${key}`))
1571
+ ])
1572
+ );
1573
+ return new Dmy({ ...parts, precision });
1574
+ }
1575
+ __name(getDmyFromData, "getDmyFromData");
1576
+ function existsInData(data, property) {
1577
+ if (isPath(property)) {
1578
+ return !isUndefined(extractPropertyFromPath(data, property));
1579
+ }
1580
+ return !isUndefined(extractProperty(data, property));
1581
+ }
1582
+ __name(existsInData, "existsInData");
1583
+ defineValueOrFunctionProperty(Article.prototype, "hidePeriodLine");
1584
+ defineValueOrFunctionProperty(Article.prototype, "hiddenByFilter");
1585
+ function Article(owner, id) {
1586
+ this.id = id;
1587
+ this.owner = owner;
1588
+ this.isDataLoaded = false;
1589
+ this.imageLoaded = false;
1590
+ this.stacking = 0;
1591
+ this.groupIndex = 0;
1592
+ this.isActive = false;
1593
+ this.isVisible = false;
1594
+ this.isVisibleInLane = true;
1595
+ this.isInRange = false;
1596
+ this.isInView = false;
1597
+ this.isVisibleInGroup = false;
1598
+ this.isVisibleInRows = true;
1599
+ this.isStarred = false;
1600
+ this.isMouseOverStar = false;
1601
+ this.isMouseover = false;
1602
+ this.isDragging = false;
1603
+ this.registeredPosition = { left: 0, top: 0 };
1604
+ this.position = { left: 0, top: 0 };
1605
+ this.dragStartOffset = { left: 0, top: 0 };
1606
+ this.indicator = { fromX: 0, toX: 0 };
1607
+ this.offset = { left: 0, top: 0 };
1608
+ this.finalOffset = { left: 0, top: 0 };
1609
+ this.isVisibleAfterFade = false;
1610
+ this.opacity = 0;
1611
+ this.fadeAnimation = {
1612
+ finalOpacity: 0,
1613
+ dummyElement: null
1614
+ };
1615
+ this.moveAnimation = {
1616
+ finalOffset: { left: 0, top: 0 },
1617
+ dummyElement: void 0
1618
+ };
1619
+ this.row = 0;
1620
+ this.laneId = null;
1621
+ this.laneOrder = 0;
1622
+ this.isFading = false;
1623
+ this.isMoving = false;
1624
+ this._cachedHeight = 0;
1625
+ this._cachedWidth = 0;
1626
+ this._sizeValid = false;
1627
+ this._sizeCacheKey = null;
1628
+ this._layoutCaches = null;
1629
+ this._resolvedDefaultCardLayout = null;
1630
+ this._resolvedCardLayoutName = null;
1631
+ }
1632
+ __name(Article, "Article");
1633
+ Article.prototype.setupByReceivedData = function(receivedData) {
1634
+ this.owner._assignArticleToLane(this, this.owner._resolveLaneIdFromArticleData(receivedData));
1635
+ const articleDefaultData = this.owner._getResolvedArticleOptions(this).defaultData;
1636
+ const data = deepMerge({}, articleDefaultData, receivedData);
1637
+ if (!existsInData(receivedData, "to")) {
1638
+ delete data.to;
1639
+ }
1640
+ this.data = deepMerge({}, receivedData);
1641
+ this.title = getPropertyFromData(data, "title") || "";
1642
+ this.rank = getPropertyFromData(data, "rank") || 0;
1643
+ this.subtitle = getPropertyFromData(data, "subtitle") || "";
1644
+ this._setupArticlePeriod(data);
1645
+ this.offset.left = this.finalOffset.left = this.moveAnimation.finalOffset.left = data.offsetLeft || 0;
1646
+ this.offset.top = this.finalOffset.top = this.moveAnimation.finalOffset.top = data.offsetTop || 0;
1647
+ this.isStarred = !!data.starred;
1648
+ this.cardLayout = getPropertyFromData(data, "cardLayout") || null;
1649
+ this.initialiseStyles(data);
1650
+ this.hiddenByFilter = getPropertyFromData(data, "hiddenByFilter");
1651
+ this.hidePeriodLine = existsInData(data, "hidePeriodLine") ? getPropertyFromData(data, "hidePeriodLine") : this.owner.options.article.periodLine.defaultHide;
1652
+ this.isDataLoaded = true;
1653
+ this.isImageInfoLoaded = false;
1654
+ };
1655
+ Article.prototype._setupArticlePeriod = function(data) {
1656
+ let fromDmy = getDmyFromData(data, "from");
1657
+ fromDmy = this.owner.getDmyFromInput(fromDmy);
1658
+ const fromPrecision = fromDmy.precision;
1659
+ const isToPresentProp = getPropertyFromData(data, "isToPresent");
1660
+ const isToPresent = isToPresentProp === true || isToPresentProp === 1;
1661
+ let toDmy, toPrecision;
1662
+ if (isToPresent) {
1663
+ toDmy = Dmy.now();
1664
+ } else if (existsInData(data, "to")) {
1665
+ toDmy = getDmyFromData(data, "to");
1666
+ toDmy = this.owner.getDmyFromInput(toDmy);
1667
+ toPrecision = toDmy.precision;
1668
+ } else {
1669
+ toDmy = fromDmy;
1670
+ toPrecision = fromPrecision;
1671
+ }
1672
+ const from = Dmy.CreateAsStartOfPeriod(fromDmy, fromPrecision);
1673
+ const to = Dmy.CreateAsExclusiveEndOfPeriod(toDmy, toPrecision);
1674
+ this.period = { from, to, isToPresent };
1675
+ this.period.years = this.period.to.asFloat() - this.period.from.asFloat();
1676
+ };
1677
+ Article.prototype.setImage = function() {
1678
+ this.isImageInfoLoaded = true;
1679
+ if (getPropertyFromData(this.data, "imageUrl")) {
1680
+ this.owner.enqueueImageLoad(this);
1681
+ } else {
1682
+ this._releaseImageResource();
1683
+ this.image = null;
1684
+ this.imageLoaded = false;
1685
+ }
1686
+ };
1687
+ Article.prototype._releaseImageResource = function(options = {}) {
1688
+ const releaser = typeof this._closeImage === "function" ? this._closeImage : null;
1689
+ if (releaser) {
1690
+ this._closeImage = null;
1691
+ try {
1692
+ releaser(options);
1693
+ } catch {
1694
+ }
1695
+ return;
1696
+ }
1697
+ if (!options.keepState) {
1698
+ this.image = null;
1699
+ this.imageLoaded = false;
1700
+ this._loadedImageKey = null;
1701
+ }
1702
+ };
1703
+ Article.prototype.registerPosition = function(pos) {
1704
+ this.registeredPosition = this.position = pos;
1705
+ };
1706
+ Article.prototype.overlaps = function(other) {
1707
+ return other.period.from.isSame(this.period.from) && other.period.to.isSame(this.period.to) || other.period.from.isBetween(this.period.from, this.period.to) || other.period.to.isBetween(this.period.from, this.period.to) || this.period.from.isBetween(other.period.from, other.period.to) || this.period.to.isBetween(other.period.from, other.period.to);
1708
+ };
1709
+ Article.prototype.overlapsInclusiveWithDates = function(from, to) {
1710
+ return !(this.period.from.isAfter(to) || from.isAfter(this.period.to));
1711
+ };
1712
+ Article.prototype.overlapsInclusive = function(other) {
1713
+ return this.overlapsInclusiveWithDates(other.period.from, other.period.to);
1714
+ };
1715
+ Article.prototype.isInside = function(pos) {
1716
+ if (!this.isVisible) {
1717
+ return false;
1718
+ }
1719
+ this._ensureSizeCache();
1720
+ const left = this.position.left;
1721
+ const top = this.position.top;
1722
+ const width = this._cachedWidth;
1723
+ const height = this._cachedHeight;
1724
+ return pos.left >= left && pos.left <= left + width && pos.top >= top && pos.top <= top + height;
1725
+ };
1726
+ Article.prototype.pointerEnter = function(event) {
1727
+ this.isMouseover = true;
1728
+ this.owner.trigger("article-pointerenter", this, event);
1729
+ };
1730
+ Article.prototype.pointerLeave = function(event) {
1731
+ this.isMouseover = false;
1732
+ this.owner.trigger("article-pointerleave", this, event);
1733
+ };
1734
+ Article.prototype.updateIsMouseOverStar = function(pos) {
1735
+ const star = this.getIconBox();
1736
+ if (!star) {
1737
+ return false;
1738
+ }
1739
+ const oldState = this.isMouseOverStar;
1740
+ this.isMouseOverStar = pos.left >= star.left && pos.left <= star.left + star.width && pos.top >= star.top && pos.top <= star.top + star.height;
1741
+ if (this.isMouseOverStar !== oldState && !this.owner.isAnimating) {
1742
+ this.owner.redraw();
1743
+ }
1744
+ return this.isMouseOverStar;
1745
+ };
1746
+ Article.prototype.getCursor = function(pos) {
1747
+ const cursor = this.owner.options.style.cursor;
1748
+ if (this.isDragging) {
1749
+ return cursor.article.dragging;
1750
+ }
1751
+ this.updateIsMouseOverStar(pos);
1752
+ if (!this.owner.options.article.draggable) {
1753
+ return cursor.clickable;
1754
+ }
1755
+ if (this.isActive) {
1756
+ return this.isMouseOverStar ? cursor.clickable : cursor.article.hoverDraggable;
1757
+ }
1758
+ return cursor.clickable;
1759
+ };
1760
+ Article.prototype.clicked = function(pos) {
1761
+ this.updateIsMouseOverStar(pos);
1762
+ if (this.isMouseOverStar) {
1763
+ this.isStarred = !this.isStarred;
1764
+ return true;
1765
+ }
1766
+ return false;
1767
+ };
1768
+ Article.prototype.getStatusForSave = function() {
1769
+ const state = { i: this.id };
1770
+ if (this.offset.left !== 0) {
1771
+ state.l = this.offset.left;
1772
+ }
1773
+ if (this.offset.top !== 0) {
1774
+ state.t = this.offset.top;
1775
+ }
1776
+ if (this.isStarred) {
1777
+ state.v = true;
1778
+ }
1779
+ return state;
1780
+ };
1781
+ Article.prototype.headerOverlapsWith = function(other) {
1782
+ const thisLeft = this.registeredPosition.left;
1783
+ const otherLeft = other.registeredPosition.left;
1784
+ const thisRight = thisLeft + this.getWidth();
1785
+ const otherRight = otherLeft + other.getWidth();
1786
+ return otherRight >= thisLeft && thisRight >= otherLeft;
1787
+ };
1788
+ Article.prototype._getWidth = function() {
1789
+ return this.getCurrentStyle().width;
1790
+ };
1791
+ Article.prototype.getWidth = function() {
1792
+ this._ensureSizeCache();
1793
+ return this._cachedWidth;
1794
+ };
1795
+ Article.prototype.getHeight = function() {
1796
+ this._ensureSizeCache();
1797
+ return this._cachedHeight;
1798
+ };
1799
+ Article.prototype.setOption = function(option, value) {
1800
+ let needsDefaultRedraw = false;
1801
+ if (typeof option === "string") {
1802
+ if (typeof value === "undefined") {
1803
+ const selectedOption = getPropertyFromData(this.data, option);
1804
+ return selectedOption;
1805
+ }
1806
+ option = buildObjectFromPath(option, value);
1807
+ }
1808
+ deepMerge(this.data, option);
1809
+ if (existsInData(option, "id")) {
1810
+ this.id = option.id;
1811
+ }
1812
+ if (existsInData(option, "title")) {
1813
+ this.title = option.title;
1814
+ this.titleLines = void 0;
1815
+ }
1816
+ if (existsInData(option, "subtitle")) {
1817
+ this.subtitle = option.subtitle;
1818
+ this.summarisedSubtitle = void 0;
1819
+ }
1820
+ if (existsInData(option, "from") || existsInData(option, "to") || existsInData(option, "isToPresent")) {
1821
+ this._setupArticlePeriod(this.data);
1822
+ needsDefaultRedraw = true;
1823
+ }
1824
+ if (existsInData(option, "imageUrl")) {
1825
+ this.setImage();
1826
+ }
1827
+ if (existsInData(option, "rank")) {
1828
+ this.rank = option.rank;
1829
+ needsDefaultRedraw = true;
1830
+ }
1831
+ if (existsInData(option, "starred")) {
1832
+ this.isStarred = option.starred;
1833
+ }
1834
+ if (existsInData(option, "hiddenByFilter")) {
1835
+ this.hiddenByFilter = option.hiddenByFilter;
1836
+ }
1837
+ if (existsInData(option, "hidePeriodLine")) {
1838
+ this.hidePeriodLine = option.hidePeriodLine;
1839
+ }
1840
+ const laneChanged = existsInData(option, "lane");
1841
+ if (laneChanged) {
1842
+ this.owner._assignArticleToLane(this, option.lane);
1843
+ this.initialiseStyles(this.data);
1844
+ this.invalidateCaches();
1845
+ needsDefaultRedraw = true;
1846
+ }
1847
+ const styleChanged = existsInData(option, "style");
1848
+ const activeStyleChanged = existsInData(option, "activeStyle");
1849
+ const hoverStyleChanged = existsInData(option, "hoverStyle");
1850
+ if (styleChanged || hoverStyleChanged || activeStyleChanged) {
1851
+ this.initialiseStyles(this.data);
1852
+ }
1853
+ this.invalidateCaches();
1854
+ const cardLayoutChanged = existsInData(option, "cardLayout");
1855
+ if (cardLayoutChanged) {
1856
+ this.setCardLayout(option.cardLayout);
1857
+ }
1858
+ if (laneChanged) {
1859
+ this.owner.updateArticlesGroupIndex();
1860
+ }
1861
+ if (needsDefaultRedraw) {
1862
+ this.owner.requestRedraw();
1863
+ } else {
1864
+ this.owner.requestRedraw(this.redraw);
1865
+ }
1866
+ };
1867
+ Article.prototype.initialiseStyles = function(data = this.data) {
1868
+ const resolvedDefaultCardLayout = this.owner._resolveDefaultCardLayoutName(this);
1869
+ const explicitCardLayout = this.owner._getExplicitArticleCardLayout(this);
1870
+ const cardLayout = explicitCardLayout || resolvedDefaultCardLayout;
1871
+ this._resolvedDefaultCardLayout = resolvedDefaultCardLayout;
1872
+ this._resolvedCardLayoutName = cardLayout;
1873
+ const styleOverrides = this.owner._getResolvedArticleStyleOverrides(this, cardLayout);
1874
+ const style = deepMerge({}, styleOverrides.style, getPropertyFromData(data, "style") || {});
1875
+ const activeStyle = deepMerge(
1876
+ {},
1877
+ styleOverrides.activeStyle,
1878
+ getPropertyFromData(data, "activeStyle") || {}
1879
+ );
1880
+ const hoverStyle = deepMerge(
1881
+ {},
1882
+ styleOverrides.hoverStyle,
1883
+ getPropertyFromData(data, "hoverStyle") || {}
1884
+ );
1885
+ this.style = style;
1886
+ this.activeStyle = deepMerge({}, style, activeStyle);
1887
+ this.hoverStyle = deepMerge({}, style, hoverStyle);
1888
+ this.activeHoverStyle = deepMerge({}, style, hoverStyle, activeStyle);
1889
+ };
1890
+ Article.prototype.setStyle = function(option, value) {
1891
+ if (typeof option === "string") {
1892
+ if (typeof value === "undefined") {
1893
+ return getPropertyFromData(this.style, option);
1894
+ }
1895
+ option = buildObjectFromPath(option, value);
1896
+ }
1897
+ this.data.style = deepMerge(this.data.style || {}, option);
1898
+ this.initialiseStyles(this.data);
1899
+ this.invalidateCaches();
1900
+ this.owner.requestRedraw();
1901
+ };
1902
+ Article.prototype.setHoverStyle = function(option, value) {
1903
+ if (typeof option === "string") {
1904
+ if (typeof value === "undefined") {
1905
+ return getPropertyFromData(this.activeStyle, option);
1906
+ }
1907
+ option = buildObjectFromPath(option, value);
1908
+ }
1909
+ this.data.hoverStyle = deepMerge(this.data.hoverStyle || {}, option);
1910
+ this.initialiseStyles(this.data);
1911
+ this.owner.requestRedraw();
1912
+ };
1913
+ Article.prototype.setActiveStyle = function(option, value) {
1914
+ if (typeof option === "string") {
1915
+ if (typeof value === "undefined") {
1916
+ return getPropertyFromData(this.activeStyle, option);
1917
+ }
1918
+ option = buildObjectFromPath(option, value);
1919
+ }
1920
+ this.data.activeStyle = deepMerge(this.data.activeStyle || {}, option);
1921
+ this.initialiseStyles(this.data);
1922
+ this.owner.requestRedraw();
1923
+ };
1924
+ Article.prototype.activated = function() {
1925
+ Logger.warn(
1926
+ 'DEPRECATION WARNING: article.activated() was deprecated in v1.3.0. Use timeline.select(article.id) and handle selection with options.on["article-select"] instead.'
1927
+ );
1928
+ this.owner.trigger("article-click", this);
1929
+ };
1930
+ Article.prototype.updateVisibility = function() {
1931
+ const oldVisibility = this.isVisibleAfterFade;
1932
+ const newVisibility = this.isInRange && this.isVisibleInLane && this.isVisibleInGroup && this.isVisibleInRows && !this.isHiddenByFilter;
1933
+ if (!this.isVisibleInLane) {
1934
+ this.setVisibility(false);
1935
+ return;
1936
+ }
1937
+ if (oldVisibility === newVisibility) {
1938
+ return;
1939
+ }
1940
+ if (newVisibility && !this.isImageInfoLoaded) {
1941
+ this.setImage();
1942
+ }
1943
+ if (!this.owner.options.article.animation.fade.active) {
1944
+ this.setVisibility(newVisibility);
1945
+ return;
1946
+ }
1947
+ this.setVisibilityWithFade(newVisibility);
1948
+ };
1949
+ Article.prototype.setVisibility = function(visibility) {
1950
+ if (this.isFading && this.fadeAnimation?.dummyElement?.stop) {
1951
+ this.fadeAnimation.dummyElement.stop();
1952
+ this.isFading = false;
1953
+ if (this.owner?.lastAnimatingArticle?.id === this.id && this.owner.lastAnimatingArticle.animationType === "fade") {
1954
+ this.owner.isAnimatingArticles = false;
1955
+ }
1956
+ }
1957
+ this.isVisible = visibility;
1958
+ this.isVisibleAfterFade = visibility;
1959
+ this.opacity = visibility ? 1 : 0;
1960
+ if (!visibility) {
1961
+ this._releaseImageResource({ skipRedraw: true });
1962
+ }
1963
+ };
1964
+ Article.prototype.setVisibilityWithFade = function(visibility) {
1965
+ const me = this;
1966
+ if (visibility === me.isVisibleAfterFade) {
1967
+ return;
1968
+ }
1969
+ if (me.isFading && me.fadeAnimation?.dummyElement?.stop) {
1970
+ me.fadeAnimation.dummyElement.stop();
1971
+ }
1972
+ me.isFading = true;
1973
+ me.isVisibleAfterFade = visibility;
1974
+ me.fadeAnimation = me.fadeAnimation || {};
1975
+ me.fadeAnimation.finalOpacity = visibility;
1976
+ if (visibility) {
1977
+ me.isVisible = true;
1978
+ }
1979
+ me.owner.notifyArticleAnimating("fade", me.id);
1980
+ const settings = me.owner.options.article.animation.fade;
1981
+ const duration = settings.duration ?? 400;
1982
+ const easingName = settings.easing ?? "swing";
1983
+ const easingFn = EASINGS[easingName] || EASINGS.swing;
1984
+ const startOpacity = me.opacity;
1985
+ const endOpacity = visibility ? 1 : 0;
1986
+ const fadeTween = tween({
1987
+ from: startOpacity,
1988
+ to: endOpacity,
1989
+ duration,
1990
+ easing: easingFn,
1991
+ /** Fired every animation frame */
1992
+ onUpdate(value) {
1993
+ me.opacity = value;
1994
+ me.owner.requestRedraw();
1995
+ },
1996
+ /** Finalise */
1997
+ onComplete() {
1998
+ me.isFading = false;
1999
+ if (!visibility) {
2000
+ me.isVisible = false;
2001
+ me._releaseImageResource({ skipRedraw: true });
2002
+ }
2003
+ const last = me.owner.lastAnimatingArticle;
2004
+ if (me.id === last.id && last.animationType === "fade") {
2005
+ me.owner.isAnimatingArticles = false;
2006
+ }
2007
+ if (typeof settings.complete === "function") {
2008
+ settings.complete.call(me);
2009
+ }
2010
+ }
2011
+ });
2012
+ me.fadeAnimation.dummyElement = fadeTween;
2013
+ };
2014
+ Article.prototype.moveToOffset = function(destination) {
2015
+ this.finalOffset.top = this.offset.top = destination.top || this.offset.top;
2016
+ this.finalOffset.left = this.offset.left = destination.left || this.offset.left;
2017
+ this.position.top = this.registeredPosition.top + this.offset.top;
2018
+ this.position.left = this.registeredPosition.left + this.offset.left;
2019
+ };
2020
+ Article.prototype.moveTo = function(destination) {
2021
+ const finalOffset = {
2022
+ left: destination.left - this.registeredPosition.left,
2023
+ top: destination.top - this.registeredPosition.top
2024
+ };
2025
+ this.moveToOffset(finalOffset);
2026
+ };
2027
+ Article.prototype.moveToWithAnim = function(destination) {
2028
+ const finalOffset = {
2029
+ left: destination.left - this.registeredPosition.left,
2030
+ top: destination.top - this.registeredPosition.top
2031
+ };
2032
+ this.moveToOffsetWithAnim(finalOffset);
2033
+ };
2034
+ Article.prototype.moveToOffsetWithAnim = function(destination) {
2035
+ const me = this;
2036
+ const moveAnimation = me.moveAnimation;
2037
+ if (destination.top === moveAnimation.finalOffset.top && destination.left === moveAnimation.finalOffset.left) {
2038
+ return;
2039
+ }
2040
+ if (me.isMoving && moveAnimation?.dummyElement?.stop) {
2041
+ moveAnimation.dummyElement.stop();
2042
+ }
2043
+ moveAnimation.finalOffset = this.finalOffset = {
2044
+ left: destination.left,
2045
+ top: destination.top
2046
+ };
2047
+ me.isMoving = true;
2048
+ me.owner.notifyArticleAnimating("move", me.id);
2049
+ const settings = me.owner.options.article.animation.move;
2050
+ const duration = settings.duration ?? 400;
2051
+ const easingName = settings.easing ?? "swing";
2052
+ const easingFn = EASINGS[easingName] || EASINGS.swing;
2053
+ const startTop = me.offset.top;
2054
+ const startLeft = me.offset.left;
2055
+ const deltaTop = destination.top - startTop;
2056
+ const deltaLeft = destination.left - startLeft;
2057
+ const moveTween = tween({
2058
+ from: 0,
2059
+ to: 1,
2060
+ duration,
2061
+ easing: easingFn,
2062
+ onUpdate(progress) {
2063
+ me.offset.top = startTop + deltaTop * progress;
2064
+ me.offset.left = startLeft + deltaLeft * progress;
2065
+ me.position.top = me.registeredPosition.top + me.offset.top;
2066
+ me.position.left = me.registeredPosition.left + me.offset.left;
2067
+ me.owner.requestRedraw();
2068
+ },
2069
+ onComplete() {
2070
+ me.offset.top = destination.top;
2071
+ me.offset.left = destination.left;
2072
+ me.position.top = me.registeredPosition.top + destination.top;
2073
+ me.position.left = me.registeredPosition.left + destination.left;
2074
+ me.isMoving = false;
2075
+ const last = me.owner.lastAnimatingArticle;
2076
+ if (me.id === last.id && last.animationType === "move") {
2077
+ me.owner.isAnimatingArticles = false;
2078
+ }
2079
+ }
2080
+ });
2081
+ moveAnimation.dummyElement = moveTween;
2082
+ };
2083
+ function roundPixel(value) {
2084
+ return Math.round(value);
2085
+ }
2086
+ __name(roundPixel, "roundPixel");
2087
+ function snapPixel(value, dpr = 1) {
2088
+ const ratio = typeof dpr === "number" && isFinite(dpr) && dpr > 0 ? dpr : 1;
2089
+ return Math.round(value * ratio) / ratio;
2090
+ }
2091
+ __name(snapPixel, "snapPixel");
2092
+ function retainPixel(value) {
2093
+ return value;
2094
+ }
2095
+ __name(retainPixel, "retainPixel");
2096
+ function createPixelSnap(dpr = 1, mode = "device") {
2097
+ if (mode === false || mode === "none") {
2098
+ return retainPixel;
2099
+ }
2100
+ if (mode === "css") {
2101
+ return roundPixel;
2102
+ }
2103
+ return /* @__PURE__ */ __name(function snapToDevicePixel(value) {
2104
+ return snapPixel(value, dpr);
2105
+ }, "snapToDevicePixel");
2106
+ }
2107
+ __name(createPixelSnap, "createPixelSnap");
2108
+ function createStrokePixelSnap(dpr = 1, mode = "device", lineWidth = 1) {
2109
+ if (mode === false || mode === "none") {
2110
+ return retainPixel;
2111
+ }
2112
+ const deviceRatio = typeof dpr === "number" && isFinite(dpr) && dpr > 0 ? dpr : 1;
2113
+ const ratio = mode === "css" ? 1 : deviceRatio;
2114
+ const width = typeof lineWidth === "number" && isFinite(lineWidth) && lineWidth > 0 ? lineWidth : 1;
2115
+ const halfPhysicalWidth = width * ratio / 2;
2116
+ return /* @__PURE__ */ __name(function snapStrokeCentre(value) {
2117
+ return (Math.round(value * ratio - halfPhysicalWidth) + halfPhysicalWidth) / ratio;
2118
+ }, "snapStrokeCentre");
2119
+ }
2120
+ __name(createStrokePixelSnap, "createStrokePixelSnap");
2121
+ function createInnerSpace(outerSpace, borderWidth, snap) {
2122
+ if (!snap) {
2123
+ snap = roundPixel;
2124
+ }
2125
+ const halfBorder = borderWidth / 2;
2126
+ return {
2127
+ left: snap(outerSpace.left + halfBorder),
2128
+ top: snap(outerSpace.top + halfBorder),
2129
+ width: snap(outerSpace.width - borderWidth),
2130
+ height: snap(outerSpace.height - borderWidth)
2131
+ };
2132
+ }
2133
+ __name(createInnerSpace, "createInnerSpace");
2134
+ Article.prototype.draw = function(ctx) {
2135
+ if (!this.isDataLoaded || isNaN(this.position.left)) {
2136
+ return;
2137
+ }
2138
+ this._ensureSizeCache();
2139
+ ctx.globalAlpha = this.opacity;
2140
+ const cardLayout = this._getCurrentCardLayout();
2141
+ cardLayout.draw.call(this, ctx);
2142
+ };
2143
+ Article.prototype.getCurrentStyle = function() {
2144
+ if (this.isActive) {
2145
+ return this.isMouseover ? this.activeHoverStyle : this.activeStyle;
2146
+ }
2147
+ return this.isMouseover ? this.hoverStyle : this.style;
2148
+ };
2149
+ Article.prototype._getCurrentStyle = function() {
2150
+ return this.getCurrentStyle();
2151
+ };
2152
+ Article.prototype._getPeriodLineRenderGeometry = function(axisY) {
2153
+ const resolvedArticleOptions = this.owner._getResolvedArticleOptions(this);
2154
+ const periodLineOptions = resolvedArticleOptions.periodLine || {};
2155
+ const globalPeriodLineOptions = this.owner.options.article.periodLine || {};
2156
+ const position = globalPeriodLineOptions.position || "axis";
2157
+ const baselineGap = Number.isFinite(periodLineOptions.baselineGap) ? periodLineOptions.baselineGap : 0;
2158
+ const spacing = this.hidePeriodLine ? 0 : periodLineOptions.spacing || 0;
2159
+ const thickness = this.hidePeriodLine ? 0 : periodLineOptions.thickness || 0;
2160
+ const offset = (spacing + thickness) * this.stacking;
2161
+ let anchorY = axisY;
2162
+ let anchorOffset = this.owner.options.style.mainLine.size / 2;
2163
+ if (position === "lane" && this.owner._isLaneLayoutActive()) {
2164
+ const lane = this.owner.getLaneById(this.laneId);
2165
+ if (lane && lane.geometry) {
2166
+ anchorY = Math.floor(lane.geometry.bottom);
2167
+ anchorOffset = 0;
2168
+ }
2169
+ }
2170
+ const y = anchorY - baselineGap - offset - anchorOffset - thickness / 2;
2171
+ return {
2172
+ position,
2173
+ baselineGap,
2174
+ spacing,
2175
+ thickness,
2176
+ anchorY,
2177
+ anchorOffset,
2178
+ y
2179
+ };
2180
+ };
2181
+ Article.prototype.drawPeriodLinesAndConnectors = function(ctx, axisY) {
2182
+ ctx.globalAlpha = this.opacity;
2183
+ const style = this.getCurrentStyle();
2184
+ const geometry = this._getPeriodLineRenderGeometry(axisY);
2185
+ const y = geometry.y;
2186
+ if (!this.hidePeriodLine) {
2187
+ const fromX = this.indicator.fromX, toX = this.indicator.toX;
2188
+ ctx.beginPath();
2189
+ ctx.lineWidth = geometry.thickness;
2190
+ ctx.moveTo(fromX, y);
2191
+ ctx.lineTo(toX, y);
2192
+ if (this.period.isToPresent) {
2193
+ const periodLength = toX - fromX, maxFadeLength = 15, fadeStartColorStop = Math.max(1 - maxFadeLength / periodLength, 0.7), grad = ctx.createLinearGradient(fromX, y, toX, y);
2194
+ grad.addColorStop(0, style.color);
2195
+ grad.addColorStop(fadeStartColorStop, style.color);
2196
+ grad.addColorStop(1, "rgba(255,255,255,0)");
2197
+ ctx.strokeStyle = grad;
2198
+ } else {
2199
+ ctx.strokeStyle = style.color;
2200
+ }
2201
+ ctx.stroke();
2202
+ }
2203
+ if (!style.connectorLine.visible) {
2204
+ return;
2205
+ }
2206
+ const cardLayout = this._getCurrentCardLayout();
2207
+ const connectorEnd = typeof cardLayout.getConnectorEnd === "function" ? cardLayout.getConnectorEnd.call(this) : {
2208
+ left: this.position.left + style.connectorLine.offsetX,
2209
+ top: this.position.top + this.getHeight() + style.connectorLine.offsetY
2210
+ };
2211
+ const x1 = Math.max(0, this.indicator.fromX);
2212
+ const y1 = y;
2213
+ const x2 = connectorEnd.left;
2214
+ const y2 = connectorEnd.top;
2215
+ const isVertical = Math.abs(x1 - x2) < Number.EPSILON;
2216
+ const pixelSnapMode = this.owner?.options?.article?.rendering?.pixelSnap;
2217
+ const snapStroke = createStrokePixelSnap(
2218
+ this.owner?.getCanvasDpr?.() || 1,
2219
+ pixelSnapMode,
2220
+ style.connectorLine.thickness
2221
+ );
2222
+ const connectorX = isVertical ? snapStroke(x2) : null;
2223
+ const drawX1 = connectorX ?? x1;
2224
+ const drawX2 = connectorX ?? x2;
2225
+ ctx.strokeStyle = ctx.fillStyle = style.color;
2226
+ ctx.lineWidth = style.connectorLine.thickness;
2227
+ ctx.beginPath();
2228
+ ctx.moveTo(drawX1, y1);
2229
+ ctx.lineTo(drawX2, y2);
2230
+ ctx.stroke();
2231
+ const radians = Math.atan((y2 - y1) / (drawX2 - drawX1)) + (drawX2 >= drawX1 ? -90 : 90) * Math.PI / 180;
2232
+ ctx.save();
2233
+ ctx.beginPath();
2234
+ ctx.translate(drawX2, y2);
2235
+ ctx.rotate(radians);
2236
+ ctx.moveTo(-style.connectorLine.arrow.width, 0);
2237
+ ctx.lineTo(style.connectorLine.arrow.width, 0);
2238
+ ctx.lineTo(0, -style.connectorLine.arrow.height);
2239
+ ctx.closePath();
2240
+ ctx.restore();
2241
+ ctx.fill();
2242
+ };
2243
+ Article.prototype.getIconBox = function() {
2244
+ const cardLayout = this._getCurrentCardLayout();
2245
+ return cardLayout.getIconBox.call(this);
2246
+ };
2247
+ Article.prototype.startDragging = function(pos, evt) {
2248
+ if (this.isMoving) {
2249
+ this.moveAnimation.dummyElement.stop();
2250
+ }
2251
+ this.isDragging = true;
2252
+ this.dragInitialPosition = { left: this.position.left, top: this.position.top };
2253
+ this.lastDragPosition = { left: this.position.left, top: this.position.top };
2254
+ this.dragStartOffset = {
2255
+ left: pos.left - this.position.left,
2256
+ top: pos.top - this.position.top
2257
+ };
2258
+ this.owner.startAnimation();
2259
+ if (this.owner && typeof this.owner.trigger === "function") {
2260
+ this.owner.trigger("article-drag-start", this, evt);
2261
+ }
2262
+ };
2263
+ Article.prototype.stopDragging = function(evt) {
2264
+ this.offset = this.finalOffset = this.moveAnimation.finalOffset = {
2265
+ left: this.position.left - this.registeredPosition.left,
2266
+ top: this.position.top - this.registeredPosition.top
2267
+ };
2268
+ this.isDragging = false;
2269
+ this.owner?._markTimelineStateChanged?.();
2270
+ if (this.owner && typeof this.owner.trigger === "function") {
2271
+ this.owner.trigger("article-drag-end", this, evt);
2272
+ }
2273
+ };
2274
+ Article.prototype.dragging = function(pos, evt) {
2275
+ const newPosition = {
2276
+ left: pos.left - this.dragStartOffset.left,
2277
+ top: pos.top - this.dragStartOffset.top
2278
+ };
2279
+ const previousPosition = this.lastDragPosition || {
2280
+ left: this.position.left,
2281
+ top: this.position.top
2282
+ };
2283
+ const initialPosition = this.dragInitialPosition || previousPosition;
2284
+ const dx = newPosition.left - previousPosition.left;
2285
+ const dy = newPosition.top - previousPosition.top;
2286
+ const totalDx = newPosition.left - initialPosition.left;
2287
+ const totalDy = newPosition.top - initialPosition.top;
2288
+ this.position = newPosition;
2289
+ this.lastDragPosition = newPosition;
2290
+ if (this.owner && typeof this.owner.trigger === "function") {
2291
+ this.owner.trigger("article-drag", this, { dx, dy, totalDx, totalDy }, evt);
2292
+ }
2293
+ };
2294
+ Article.prototype._cacheBucket = function() {
2295
+ const name = this._getCurrentCardLayoutName();
2296
+ if (!this._layoutCaches) {
2297
+ this._layoutCaches = /* @__PURE__ */ Object.create(null);
2298
+ }
2299
+ return this._layoutCaches[name] || (this._layoutCaches[name] = /* @__PURE__ */ Object.create(null));
2300
+ };
2301
+ Article.prototype.memo = function(key, factory) {
2302
+ const bucket = this._cacheBucket();
2303
+ return key in bucket ? bucket[key] : bucket[key] = factory.call(this);
2304
+ };
2305
+ Article.prototype._getSizeCacheKey = function() {
2306
+ const style = typeof this.getCurrentStyle === "function" ? this.getCurrentStyle() : null;
2307
+ const imageStyle = style && style.image || {};
2308
+ const header = style && style.header || {};
2309
+ const subheader = style && style.subheader || {};
2310
+ const border = style && style.border || {};
2311
+ const layout = typeof this._getCurrentCardLayoutName === "function" ? this._getCurrentCardLayoutName() : "";
2312
+ const hasImage = this.imageLoaded && this.image;
2313
+ const keyParts = [
2314
+ layout,
2315
+ style && style.width,
2316
+ style && style.height,
2317
+ header.height,
2318
+ subheader.height,
2319
+ border.width,
2320
+ imageStyle.margin ?? 0,
2321
+ imageStyle.shape || "",
2322
+ imageStyle.maxHeight ?? "",
2323
+ style && style.maxImageHeight !== void 0 ? style.maxImageHeight : "",
2324
+ hasImage ? this.image.width : "noimg",
2325
+ hasImage ? this.image.height : ""
2326
+ ];
2327
+ return keyParts.join("|");
2328
+ };
2329
+ Article.prototype.updateCachedSize = function() {
2330
+ const cardLayout = this._getCurrentCardLayout();
2331
+ this._cachedWidth = cardLayout.getWidth.call(this);
2332
+ this._cachedHeight = cardLayout.getHeight.call(this);
2333
+ this.height = this._cachedHeight;
2334
+ this._sizeValid = true;
2335
+ this._sizeCacheKey = this._getSizeCacheKey();
2336
+ };
2337
+ Article.prototype._ensureSizeCache = function() {
2338
+ const cacheKey = this._getSizeCacheKey();
2339
+ if (!this._sizeValid || cacheKey !== this._sizeCacheKey) {
2340
+ this.updateCachedSize();
2341
+ }
2342
+ };
2343
+ Article.prototype.invalidateCaches = function() {
2344
+ this._sizeValid = false;
2345
+ this._sizeCacheKey = null;
2346
+ if (this._layoutCaches) {
2347
+ const buckets = this._layoutCaches;
2348
+ for (const layoutName in buckets) {
2349
+ const bucket = buckets[layoutName];
2350
+ if (!bucket) {
2351
+ continue;
2352
+ }
2353
+ for (const k in bucket) {
2354
+ const v = bucket[k];
2355
+ if (v && typeof v.close === "function") {
2356
+ try {
2357
+ v.close();
2358
+ } catch {
2359
+ }
2360
+ }
2361
+ }
2362
+ }
2363
+ }
2364
+ this._layoutCaches = null;
2365
+ };
2366
+ Article.prototype._getCurrentCardLayoutName = function() {
2367
+ return this._resolvedCardLayoutName || this.cardLayout || this._resolvedDefaultCardLayout || this.owner._resolveArticleCardLayoutName(this);
2368
+ };
2369
+ Article.prototype._getCurrentCardLayout = function() {
2370
+ return this.owner.getCardLayout(this._getCurrentCardLayoutName());
2371
+ };
2372
+ Article.prototype.setCardLayout = function(cardLayout) {
2373
+ const layout = this.owner.getCardLayout(cardLayout);
2374
+ if (!layout) {
2375
+ throw new Error(`Card layout "${cardLayout}" not found`);
2376
+ }
2377
+ this.cardLayout = cardLayout;
2378
+ this._resolvedCardLayoutName = cardLayout;
2379
+ this.initialiseStyles();
2380
+ this.invalidateCaches();
2381
+ this.owner.requestRedraw(this.redraw);
2382
+ };
2383
+ function compareArticleIds(idA, idB) {
2384
+ const numA = Number(idA);
2385
+ const numB = Number(idB);
2386
+ const idsAreNumeric = Number.isFinite(numA) && Number.isFinite(numB);
2387
+ if (idsAreNumeric) {
2388
+ return numA - numB;
2389
+ }
2390
+ const strA = String(idA);
2391
+ const strB = String(idB);
2392
+ if (strA === strB) {
2393
+ return 0;
2394
+ }
2395
+ return strA < strB ? -1 : 1;
2396
+ }
2397
+ __name(compareArticleIds, "compareArticleIds");
2398
+ function ARTICLE_DURATION_SORTER(articleA, articleB) {
2399
+ const a = articleA.period.from.getDaysTo(articleA.period.to);
2400
+ const b = articleB.period.from.getDaysTo(articleB.period.to);
2401
+ if (a < b) {
2402
+ return 1;
2403
+ }
2404
+ if (a > b) {
2405
+ return -1;
2406
+ }
2407
+ return compareArticleIds(articleA.id, articleB.id);
2408
+ }
2409
+ __name(ARTICLE_DURATION_SORTER, "ARTICLE_DURATION_SORTER");
2410
+ function ARTICLE_DURATION_YEARS_SORTER(articleA, articleB) {
2411
+ const a = articleA.period.years;
2412
+ const b = articleB.period.years;
2413
+ if (a < b) {
2414
+ return 1;
2415
+ }
2416
+ if (a > b) {
2417
+ return -1;
2418
+ }
2419
+ return compareArticleIds(articleA.id, articleB.id);
2420
+ }
2421
+ __name(ARTICLE_DURATION_YEARS_SORTER, "ARTICLE_DURATION_YEARS_SORTER");
2422
+ function ARTICLE_IMAGE_QUEUE_SORTER(articleA, articleB) {
2423
+ const a = articleA.isInView && articleA.isVisible;
2424
+ const b = articleB.isInView && articleB.isVisible;
2425
+ if (!a && b) {
2426
+ return -1;
2427
+ }
2428
+ if (a && !b) {
2429
+ return 1;
2430
+ }
2431
+ return articleA.position.top - articleB.position.top;
2432
+ }
2433
+ __name(ARTICLE_IMAGE_QUEUE_SORTER, "ARTICLE_IMAGE_QUEUE_SORTER");
2434
+ function ARTICLE_FROM_SORTER(articleA, articleB) {
2435
+ const a = articleA.period.from;
2436
+ const b = articleB.period.from;
2437
+ let result = a.compare(b);
2438
+ if (result === 0) {
2439
+ result = compareArticleIds(articleB.id, articleA.id);
2440
+ }
2441
+ return result;
2442
+ }
2443
+ __name(ARTICLE_FROM_SORTER, "ARTICLE_FROM_SORTER");
2444
+ function ARTICLE_TO_SORTER(articleA, articleB) {
2445
+ const a = articleA.period.to;
2446
+ const b = articleB.period.to;
2447
+ let result = b.compare(a);
2448
+ if (result === 0) {
2449
+ result = compareArticleIds(articleB.id, articleA.id);
2450
+ }
2451
+ return result;
2452
+ }
2453
+ __name(ARTICLE_TO_SORTER, "ARTICLE_TO_SORTER");
2454
+ function ARTICLE_TOP_SORTER(articleA, articleB) {
2455
+ const a = articleA.position.top;
2456
+ const b = articleB.position.top;
2457
+ if (a < b) {
2458
+ return -1;
2459
+ }
2460
+ if (a > b) {
2461
+ return 1;
2462
+ }
2463
+ return compareArticleIds(articleB.id, articleA.id);
2464
+ }
2465
+ __name(ARTICLE_TOP_SORTER, "ARTICLE_TOP_SORTER");
2466
+ function ARTICLE_ROW_SORTER(articleA, articleB) {
2467
+ const laneOrderA = articleA.laneOrder || 0;
2468
+ const laneOrderB = articleB.laneOrder || 0;
2469
+ if (laneOrderA > laneOrderB) {
2470
+ return -1;
2471
+ }
2472
+ if (laneOrderA < laneOrderB) {
2473
+ return 1;
2474
+ }
2475
+ const a = articleA.row;
2476
+ const b = articleB.row;
2477
+ if (a < b) {
2478
+ return 1;
2479
+ }
2480
+ if (a > b) {
2481
+ return -1;
2482
+ }
2483
+ return compareArticleIds(articleB.id, articleA.id);
2484
+ }
2485
+ __name(ARTICLE_ROW_SORTER, "ARTICLE_ROW_SORTER");
2486
+ function ARTICLE_RANK_SORTER(articleA, articleB) {
2487
+ const a = articleA.rank;
2488
+ const b = articleB.rank;
2489
+ if (a < b) {
2490
+ return 1;
2491
+ }
2492
+ if (a > b) {
2493
+ return -1;
2494
+ }
2495
+ return compareArticleIds(articleB.id, articleA.id);
2496
+ }
2497
+ __name(ARTICLE_RANK_SORTER, "ARTICLE_RANK_SORTER");
2498
+ function ARTICLE_EFFECTIVE_RANK_SORTER(articleA, articleB) {
2499
+ const a = articleA.effectiveRank;
2500
+ const b = articleB.effectiveRank;
2501
+ if (a < b) {
2502
+ return 1;
2503
+ }
2504
+ if (a > b) {
2505
+ return -1;
2506
+ }
2507
+ return compareArticleIds(articleB.id, articleA.id);
2508
+ }
2509
+ __name(ARTICLE_EFFECTIVE_RANK_SORTER, "ARTICLE_EFFECTIVE_RANK_SORTER");
2510
+ function ARTICLE_POSITION_SORTER(articleA, articleB) {
2511
+ const a = articleA.position.left;
2512
+ const b = articleB.position.left;
2513
+ let result = a < b ? 1 : a > b ? -1 : 0;
2514
+ if (result === 0) {
2515
+ result = articleA.position.top - articleB.position.top;
2516
+ if (result === 0) {
2517
+ result = articleA.period.from.compare(articleB.period.from);
2518
+ if (result === 0) {
2519
+ result = compareArticleIds(articleA.id, articleB.id);
2520
+ }
2521
+ }
2522
+ }
2523
+ return result;
2524
+ }
2525
+ __name(ARTICLE_POSITION_SORTER, "ARTICLE_POSITION_SORTER");
2526
+ const sorters = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2460
2527
  __proto__: null,
2461
- DENSITY_ALL,
2462
- DENSITY_HIGH,
2463
- DENSITY_LOW,
2464
- DENSITY_MEDIUM,
2465
- DENSITY_SETTINGS,
2466
- ERA_MARKER,
2467
- MAJOR_MARKER,
2468
- MINOR_MARKER,
2469
- PRECISION_BILLION_YEARS,
2470
- PRECISION_CENTURY,
2471
- PRECISION_DAY,
2472
- PRECISION_DECADE,
2473
- PRECISION_HOUR,
2474
- PRECISION_MILLENNIUM,
2475
- PRECISION_MILLION_YEARS,
2476
- PRECISION_MILLISECOND,
2477
- PRECISION_MINUTE,
2478
- PRECISION_MONTH,
2479
- PRECISION_SECOND,
2480
- PRECISION_YEAR,
2481
- RANGE_ALL,
2482
- RANGE_SCREEN,
2483
- YEAR_PREFIXES,
2484
- ZOOM_100_MILLION_YEARS,
2485
- ZOOM_100_THOUSAND_YEARS,
2486
- ZOOM_10_MILLION_YEARS,
2487
- ZOOM_10_THOUSAND_YEARS,
2488
- ZOOM_BILLION_YEARS,
2489
- ZOOM_CENTURY,
2490
- ZOOM_DAY,
2491
- ZOOM_DECADE,
2492
- ZOOM_HOUR,
2493
- ZOOM_MILLENNIUM,
2494
- ZOOM_MILLION_YEARS,
2495
- ZOOM_MILLISECOND,
2496
- ZOOM_MINUTE,
2497
- ZOOM_MONTH,
2498
- ZOOM_SECOND,
2499
- ZOOM_YEAR
2528
+ ARTICLE_DURATION_SORTER,
2529
+ ARTICLE_DURATION_YEARS_SORTER,
2530
+ ARTICLE_EFFECTIVE_RANK_SORTER,
2531
+ ARTICLE_FROM_SORTER,
2532
+ ARTICLE_IMAGE_QUEUE_SORTER,
2533
+ ARTICLE_POSITION_SORTER,
2534
+ ARTICLE_RANK_SORTER,
2535
+ ARTICLE_ROW_SORTER,
2536
+ ARTICLE_TOP_SORTER,
2537
+ ARTICLE_TO_SORTER
2500
2538
  }, Symbol.toStringTag, { value: "Module" }));
2501
2539
  const CHART_RENDERERS = /* @__PURE__ */ new Map();
2502
2540
  function registerChartRenderer(type, renderer) {
@@ -3714,16 +3752,17 @@ function normalizeDate(owner, input) {
3714
3752
  }
3715
3753
  const month = parseFiniteInteger(input.month, 1);
3716
3754
  const day = parseFiniteInteger(input.day, 1);
3717
- const precision = input.precision;
3718
- let dmy = new Dmy(
3755
+ const precision = getDatePrecision(input);
3756
+ let dmy = new Dmy({
3719
3757
  year,
3720
3758
  month,
3721
3759
  day,
3722
- parseFiniteInteger(input.hour, 0),
3723
- parseFiniteInteger(input.minute, 0),
3724
- parseFiniteInteger(input.second, 0),
3725
- parseFiniteInteger(input.millisecond, 0)
3726
- );
3760
+ precision,
3761
+ hour: parseFiniteInteger(input.hour, 0),
3762
+ minute: parseFiniteInteger(input.minute, 0),
3763
+ second: parseFiniteInteger(input.second, 0),
3764
+ millisecond: parseFiniteInteger(input.millisecond, 0)
3765
+ });
3727
3766
  dmy = owner.getDmyFromInput(dmy);
3728
3767
  return Dmy.CreateAsStartOfPeriod(dmy, precision);
3729
3768
  }
@@ -4139,12 +4178,8 @@ function resolveDistanceToBaselineValue(distanceToBaseline, availableHeight, lan
4139
4178
  }
4140
4179
  __name(resolveDistanceToBaselineValue, "resolveDistanceToBaselineValue");
4141
4180
  const ARTICLE_DATA_DEFAULTS = {
4142
- from: {
4143
- precision: "day"
4144
- },
4145
- to: {
4146
- precision: "day"
4147
- },
4181
+ from: {},
4182
+ to: {},
4148
4183
  rank: 0,
4149
4184
  starred: false,
4150
4185
  hidePeriodLine: false,
@@ -4942,17 +4977,9 @@ TimeBand.prototype.setupByReceivedData = function(receivedData) {
4942
4977
  this.isDataLoaded = true;
4943
4978
  };
4944
4979
  TimeBand.prototype._setupPeriod = function(data) {
4945
- let fromDmy = new Dmy(
4946
- parseInt(getPropertyFromData(data, "from.year")),
4947
- parseInt(getPropertyFromData(data, "from.month")),
4948
- parseInt(getPropertyFromData(data, "from.day")),
4949
- parseInt(getPropertyFromData(data, "from.hour")),
4950
- parseInt(getPropertyFromData(data, "from.minute")),
4951
- parseInt(getPropertyFromData(data, "from.second")),
4952
- parseInt(getPropertyFromData(data, "from.millisecond"))
4953
- );
4980
+ let fromDmy = getDmyFromData(data, "from");
4954
4981
  fromDmy = this.owner.getDmyFromInput(fromDmy);
4955
- const fromPrecision = getPropertyFromData(data, "from.precision");
4982
+ const fromPrecision = fromDmy.precision;
4956
4983
  const isToPresentProp = getPropertyFromData(data, "isToPresent");
4957
4984
  const isToPresent = isToPresentProp === true || isToPresentProp === 1;
4958
4985
  let toDmy;
@@ -4960,17 +4987,9 @@ TimeBand.prototype._setupPeriod = function(data) {
4960
4987
  if (isToPresent) {
4961
4988
  toDmy = Dmy.now();
4962
4989
  } else if (existsInData(data, "to")) {
4963
- toDmy = new Dmy(
4964
- parseInt(getPropertyFromData(data, "to.year")),
4965
- parseInt(getPropertyFromData(data, "to.month")),
4966
- parseInt(getPropertyFromData(data, "to.day")),
4967
- parseInt(getPropertyFromData(data, "to.hour")),
4968
- parseInt(getPropertyFromData(data, "to.minute")),
4969
- parseInt(getPropertyFromData(data, "to.second")),
4970
- parseInt(getPropertyFromData(data, "to.millisecond"))
4971
- );
4990
+ toDmy = getDmyFromData(data, "to");
4972
4991
  toDmy = this.owner.getDmyFromInput(toDmy);
4973
- toPrecision = getPropertyFromData(data, "to.precision");
4992
+ toPrecision = toDmy.precision;
4974
4993
  } else {
4975
4994
  toDmy = fromDmy;
4976
4995
  toPrecision = fromPrecision;
@@ -5855,14 +5874,8 @@ function getParentIntervalStart(value, unit) {
5855
5874
  return new Dmy(value.year, value.month, 1);
5856
5875
  case ZOOM_YEAR:
5857
5876
  return new Dmy(value.year, 1, 1);
5858
- case ZOOM_DECADE: {
5859
- if (value.year > 0) {
5860
- return new Dmy(Math.floor(value.year / 10) * 10, 1, 1);
5861
- }
5862
- const displayedYear = 1 - value.year;
5863
- const displayedDecade = Math.floor(displayedYear / 10) * 10;
5864
- return new Dmy(1 - (displayedDecade + 9), 1, 1);
5865
- }
5877
+ case ZOOM_DECADE:
5878
+ return Dmy.CreateAsStartOfPeriod(value, "decade");
5866
5879
  case ZOOM_CENTURY:
5867
5880
  return Dmy.CreateAsStartOfPeriod(value, "century");
5868
5881
  case ZOOM_MILLENNIUM:
@@ -5887,7 +5900,7 @@ function getNextParentInterval(start, unit) {
5887
5900
  case ZOOM_YEAR:
5888
5901
  return start.addYears(1);
5889
5902
  case ZOOM_DECADE:
5890
- return start.addYears(10);
5903
+ return Dmy.CreateAsExclusiveEndOfPeriod(start, "decade");
5891
5904
  case ZOOM_CENTURY:
5892
5905
  return Dmy.CreateAsExclusiveEndOfPeriod(start, "century");
5893
5906
  case ZOOM_MILLENNIUM:
@@ -6024,6 +6037,9 @@ TimescaleManager.prototype.formatParentContextLabel = function(value, unit) {
6024
6037
  case ZOOM_DECADE: {
6025
6038
  const displayedYear = value.year <= 0 ? 1 - value.year : value.year;
6026
6039
  const decade = Math.floor(displayedYear / 10) * 10;
6040
+ if (decade === 0) {
6041
+ return value.year <= 0 ? `9–1${options.bceText}` : "1–9";
6042
+ }
6027
6043
  const formattedDecade = new Dmy(decade, 1, 1).format("YYYY", {
6028
6044
  thousandsSeparator: options.thousandsSeparator,
6029
6045
  bceText: ""
@@ -7452,6 +7468,7 @@ Timeline.prototype.setOption = function(option, value) {
7452
7468
  }
7453
7469
  option = buildObjectFromPath(normalizedOptionPath, value);
7454
7470
  }
7471
+ const previousTop = this.top;
7455
7472
  option = handleDeprecatedOptions(option);
7456
7473
  if (existsInData(option, "article")) {
7457
7474
  deepMerge(this._explicitArticleOptions, option.article || {});
@@ -7529,6 +7546,9 @@ Timeline.prototype.setOption = function(option, value) {
7529
7546
  const articleStyleScope = articleImpact.styleChanged ? "all" : laneRefreshState.styleLaneIds.size > 0 ? laneRefreshState.styleLaneIds : null;
7530
7547
  this._refreshResolvedLanesFromOptions({ articleStyleScope });
7531
7548
  }
7549
+ if (this.top !== previousTop && this.options.article.autoStacking.fitToHeight && !this._isLaneLayoutActive()) {
7550
+ this.fitToHeight();
7551
+ }
7532
7552
  this.requestRedraw();
7533
7553
  };
7534
7554
  Timeline.prototype.setSize = function(width, height) {
@@ -7903,6 +7923,7 @@ function normaliseDateInput(date) {
7903
7923
  throw new Error("Date input requires a numeric year or canonical Histropedia date string");
7904
7924
  }
7905
7925
  return new Dmy({
7926
+ precision: getDatePrecision(parsed),
7906
7927
  year: parsed.year,
7907
7928
  month: parsed.month ?? 1,
7908
7929
  day: parsed.day ?? 1,
@@ -8129,15 +8150,6 @@ function getFitZoomForInternalDates(timeline, internalStart, internalEnd, paddin
8129
8150
  return normaliseZoomForManager(manager, targetZoom);
8130
8151
  }
8131
8152
  __name(getFitZoomForInternalDates, "getFitZoomForInternalDates");
8132
- function getFitZoom(timeline, startDate, endDate, padding) {
8133
- return getFitZoomForInternalDates(
8134
- timeline,
8135
- timeline.getDmyFromInput(normaliseDateInput(startDate)),
8136
- timeline.getDmyFromInput(normaliseDateInput(endDate)),
8137
- padding
8138
- );
8139
- }
8140
- __name(getFitZoom, "getFitZoom");
8141
8153
  function normaliseBoundDate(timeline, date) {
8142
8154
  if (date == null) {
8143
8155
  return null;
@@ -8482,10 +8494,8 @@ function animateDateRangeFit(timeline, targetStartDate, targetEndDate, targetZoo
8482
8494
  const fitPixelSpan = getFitPixelSpan(timeline, padding);
8483
8495
  const startPointAtPadding = getDayPointAtPixel(timeline, padding.left);
8484
8496
  const startEndPointAtPadding = getDayPointAtPixel(timeline, padding.left + fitPixelSpan);
8485
- const targetInternalStart = timeline.getDmyFromInput(normaliseDateInput(targetStartDate));
8486
- const targetInternalEnd = timeline.getDmyFromInput(normaliseDateInput(targetEndDate));
8487
- const targetPoint = getDayPoint(targetInternalStart);
8488
- const targetEndPoint = getDayPoint(targetInternalEnd);
8497
+ const targetPoint = getDayPoint(targetStartDate);
8498
+ const targetEndPoint = getDayPoint(targetEndDate);
8489
8499
  const canInterpolateBoundaries = compareDayPoints(startEndPointAtPadding, startPointAtPadding) > 0 && compareDayPoints(targetEndPoint, targetPoint) > 0;
8490
8500
  const rangeTween = tween({
8491
8501
  from: 0,
@@ -8518,7 +8528,7 @@ function animateDateRangeFit(timeline, targetStartDate, targetEndDate, targetZoo
8518
8528
  if (targetZoom !== timeline.timescaleManager.zoom) {
8519
8529
  timeline.timescaleManager.setZoom(targetZoom);
8520
8530
  }
8521
- setInternalStartDate(timeline, targetInternalStart, padding.left, true);
8531
+ setInternalStartDate(timeline, targetStartDate, padding.left, true);
8522
8532
  timeline.isPanning = false;
8523
8533
  }
8524
8534
  });
@@ -9284,13 +9294,14 @@ Timeline.prototype.getDmyFromInput = function(dmy) {
9284
9294
  normalised = new Dmy(dmy);
9285
9295
  } else {
9286
9296
  normalised = new Dmy({
9297
+ precision: dmy.precision,
9287
9298
  year: dmy.year,
9288
9299
  month: dmy.month ?? 1,
9289
9300
  day: dmy.day ?? 1,
9290
- hour: dmy.hour ?? 0,
9291
- minute: dmy.minute ?? 0,
9292
- second: dmy.second ?? 0,
9293
- millisecond: dmy.millisecond ?? 0
9301
+ hour: dmy.hour,
9302
+ minute: dmy.minute,
9303
+ second: dmy.second,
9304
+ millisecond: dmy.millisecond
9294
9305
  });
9295
9306
  }
9296
9307
  if (!this.options?.shiftBceDates) {
@@ -12424,24 +12435,31 @@ Timeline.prototype.getZoom = function() {
12424
12435
  Timeline.prototype.setCentreDate = function(dmy, pixelOffset) {
12425
12436
  this.setStartDate(dmy, { padding: this.getWidth() / 2 + (pixelOffset || 0) });
12426
12437
  };
12427
- Timeline.prototype.fitDateRange = /* @__PURE__ */ __name(function fitDateRange(start, end, options = {}) {
12438
+ function fitInternalDateRange(timeline, startDate, endDate, options = {}) {
12428
12439
  const padding = normalisePadding(options.padding);
12440
+ const targetZoom = getFitZoomForInternalDates(timeline, startDate, endDate, padding);
12441
+ if (options.animation?.active) {
12442
+ animateDateRangeFit(timeline, startDate, endDate, targetZoom, padding, options.animation);
12443
+ return;
12444
+ }
12445
+ if (targetZoom !== timeline.timescaleManager.zoom) {
12446
+ timeline.setZoom(targetZoom);
12447
+ }
12448
+ setInternalStartDate(timeline, startDate, padding.left, true);
12449
+ }
12450
+ __name(fitInternalDateRange, "fitInternalDateRange");
12451
+ Timeline.prototype.fitDateRange = /* @__PURE__ */ __name(function fitDateRange(start, end, options = {}) {
12429
12452
  let startRange = normaliseDateRangeInput(start);
12430
12453
  let endRange = normaliseDateRangeInput(end);
12431
12454
  if (startRange.start.compare(endRange.start) > 0) {
12432
12455
  [startRange, endRange] = [endRange, startRange];
12433
12456
  }
12434
- const startDate = startRange.start;
12435
- const endDate = endRange.end;
12436
- const targetZoom = getFitZoom(this, startDate, endDate, padding);
12437
- if (options.animation?.active) {
12438
- animateDateRangeFit(this, startDate, endDate, targetZoom, padding, options.animation);
12439
- return;
12440
- }
12441
- if (targetZoom !== this.timescaleManager.zoom) {
12442
- this.setZoom(targetZoom);
12443
- }
12444
- this.setStartDate(startDate, { padding: padding.left });
12457
+ fitInternalDateRange(
12458
+ this,
12459
+ this.getDmyFromInput(startRange.start),
12460
+ this.getDmyFromInput(endRange.end),
12461
+ options
12462
+ );
12445
12463
  }, "fitDateRange");
12446
12464
  Timeline.prototype.settleDateBounds = /* @__PURE__ */ __name(function settleDateBounds(options = {}) {
12447
12465
  let correction = getDateBoundCorrection(this);
@@ -12498,7 +12516,7 @@ Timeline.prototype.fitArticleRange = /* @__PURE__ */ __name(function fitArticleR
12498
12516
  if (!article?.period?.from || !article.period.to) {
12499
12517
  return false;
12500
12518
  }
12501
- this.fitDateRange(article.period.from, article.period.to, {
12519
+ fitInternalDateRange(this, article.period.from, article.period.to, {
12502
12520
  padding: options.padding,
12503
12521
  animation: options.animation
12504
12522
  });
@@ -12517,7 +12535,7 @@ Timeline.prototype.fitArticles = /* @__PURE__ */ __name(function fitArticles(opt
12517
12535
  left: requestedPadding.left + articleRange.maxCardLeftOffset,
12518
12536
  right: requestedPadding.right + articleRange.maxCardRightOffset
12519
12537
  };
12520
- this.fitDateRange(articleRange.earliest, articleRange.latest, {
12538
+ fitInternalDateRange(this, articleRange.earliest, articleRange.latest, {
12521
12539
  padding: fitPadding,
12522
12540
  animation: options.animation
12523
12541
  });