cx 24.10.4 → 24.10.6

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.
@@ -33,9 +33,14 @@ export class TimeAxis extends Axis {
33
33
 
34
34
  if (this.deadZone) {
35
35
  this.lowerDeadZone = this.deadZone;
36
- this.upperDeadZone = this.deadZone;
36
+ pperDeadZone = this.deadZone;
37
37
  }
38
38
 
39
+ this.minLabelDistanceFormatOverride = {
40
+ ...this.minLabelDistanceFormatOverrideDefaults,
41
+ ...this.minLabelDistanceFormatOverride,
42
+ };
43
+
39
44
  super.init();
40
45
  }
41
46
 
@@ -62,14 +67,16 @@ export class TimeAxis extends Axis {
62
67
  max,
63
68
  this.snapToTicks,
64
69
  this.tickDivisions,
65
- this.minTickDistance,
66
- this.minLabelDistance,
70
+ Math.max(1, this.minTickDistance),
71
+ Math.max(1, this.minLabelDistance),
67
72
  normalized,
68
73
  inverted,
69
74
  this.minTickUnit,
70
75
  lowerDeadZone,
71
76
  upperDeadZone,
72
- this.decode
77
+ this.decode,
78
+ this.useLabelDistanceFormatOverrides ? this.minLabelDistanceFormatOverride : {},
79
+ this.format,
73
80
  );
74
81
  }
75
82
 
@@ -80,12 +87,13 @@ export class TimeAxis extends Axis {
80
87
 
81
88
  if (!data.bounds.valid()) return null;
82
89
 
83
- let format = this.format || calculator.getFormat();
90
+ let format = calculator.resolvedFormat;
91
+ let minLabelDistance = calculator.resolvedMinLabelDistance;
84
92
  let formatter = Format.parse(format);
85
93
 
86
94
  return (
87
95
  <g key={key} className={data.classNames} style={data.style}>
88
- {this.renderTicksAndLabels(context, instance, formatter)}
96
+ {this.renderTicksAndLabels(context, instance, formatter, minLabelDistance)}
89
97
  </g>
90
98
  );
91
99
  }
@@ -112,11 +120,21 @@ TimeAxis.prototype.tickDivisions = {
112
120
  ],
113
121
  };
114
122
 
123
+ const TimeFormats = {
124
+ fullDateAndTime: "datetime;yyyy MMM dd HH mm ss n",
125
+ shortMonthDate: "datetime;yyyy MMM dd",
126
+ };
127
+
115
128
  TimeAxis.prototype.snapToTicks = 0;
116
129
  TimeAxis.prototype.tickSize = 15;
117
130
  TimeAxis.prototype.minLabelDistance = 60;
118
131
  TimeAxis.prototype.minTickDistance = 60;
119
132
  TimeAxis.prototype.minTickUnit = "second";
133
+ TimeAxis.prototype.useLabelDistanceFormatOverrides = false;
134
+ TimeAxis.prototype.minLabelDistanceFormatOverrideDefaults = {
135
+ [TimeFormats.fullDateAndTime]: 150,
136
+ [TimeFormats.shortMonthDate]: 90,
137
+ };
120
138
 
121
139
  function monthNumber(date) {
122
140
  return date.getFullYear() * 12 + date.getMonth() + (date.getDate() - 1) / 31;
@@ -149,7 +167,9 @@ class TimeScale {
149
167
  minTickUnit,
150
168
  lowerDeadZone,
151
169
  upperDeadZone,
152
- decode
170
+ decode,
171
+ minLabelDistanceFormatOverride,
172
+ format,
153
173
  ) {
154
174
  this.dateCache = {};
155
175
  this.min = min != null ? this.decodeValue(min) : null;
@@ -170,6 +190,8 @@ class TimeScale {
170
190
  delete this.maxValuePadded;
171
191
  this.stacks = {};
172
192
  this.decode = decode;
193
+ this.minLabelDistanceFormatOverride = minLabelDistanceFormatOverride;
194
+ this.format = format;
173
195
  }
174
196
 
175
197
  decodeValue(date) {
@@ -193,13 +215,13 @@ class TimeScale {
193
215
  return new Date(v).toISOString();
194
216
  }
195
217
 
196
- getFormat() {
197
- switch (this.tickMeasure) {
218
+ getFormat(unit, scale) {
219
+ switch (unit) {
198
220
  case "year":
199
221
  return "datetime;yyyy";
200
222
 
201
223
  case "month":
202
- if (new Date(this.scale.min).getFullYear() != new Date(this.scale.max).getFullYear()) return "yearOrMonth";
224
+ if (new Date(scale.min).getFullYear() != new Date(scale.max).getFullYear()) return "yearOrMonth";
203
225
  return "datetime;yyyy MMM";
204
226
 
205
227
  case "week":
@@ -207,12 +229,12 @@ class TimeScale {
207
229
 
208
230
  case "day":
209
231
  if (
210
- new Date(this.scale.min).getFullYear() != new Date(this.scale.max).getFullYear() ||
211
- new Date(this.scale.min).getMonth() != new Date(this.scale.max).getMonth()
232
+ new Date(scale.min).getFullYear() != new Date(scale.max).getFullYear() ||
233
+ new Date(scale.min).getMonth() != new Date(scale.max).getMonth()
212
234
  )
213
235
  return "monthOrDay";
214
236
 
215
- return "datetime;yyyy MMM dd";
237
+ return TimeFormats.shortMonthDate;
216
238
 
217
239
  case "hour":
218
240
  return "datetime;HH mm n";
@@ -224,7 +246,7 @@ class TimeScale {
224
246
  return "datetime;mm ss";
225
247
 
226
248
  default:
227
- return "datetime;yyyy MMM dd HH mm ss n";
249
+ return TimeFormats.fullDateAndTime;
228
250
  }
229
251
  }
230
252
 
@@ -288,31 +310,30 @@ class TimeScale {
288
310
 
289
311
  this.origin = this.inverted ? this.b : this.a;
290
312
 
291
- this.scale = this.getScale();
292
-
293
313
  this.calculateTicks();
314
+ if (this.scale == null) {
315
+ this.scale = this.getScale();
316
+ }
294
317
  }
295
318
 
296
319
  getTimezoneOffset(date) {
297
320
  return date.getTimezoneOffset() * 60 * 1000;
298
321
  }
299
322
 
300
- getScale(tickSizes, measure) {
323
+ getScale(tickSize, measure) {
301
324
  let { min, max, upperDeadZone, lowerDeadZone } = this;
302
325
 
303
326
  let smin = min;
304
327
  let smax = max;
305
328
 
306
- if (isNumber(this.snapToTicks) && measure && tickSizes && 0 <= this.snapToTicks && tickSizes.length > 0) {
307
- let tickSize = tickSizes[Math.min(tickSizes.length - 1, this.snapToTicks)];
308
-
329
+ if (tickSize) {
309
330
  let minDate = new Date(min);
310
331
  let maxDate = new Date(max);
311
332
 
312
333
  switch (measure) {
313
334
  case "second":
314
335
  case "minute":
315
- case "hours":
336
+ case "hour":
316
337
  case "day":
317
338
  default:
318
339
  let minOffset = this.getTimezoneOffset(minDate);
@@ -399,7 +420,7 @@ class TimeScale {
399
420
  }
400
421
 
401
422
  findTickSize(minPxDist) {
402
- return this.tickSizes.find((a) => a * Math.abs(this.scale.factor) >= minPxDist);
423
+ return this.tickSizes.find(({ size }) => size * Math.abs(this.scale.factor) >= minPxDist);
403
424
  }
404
425
 
405
426
  getTickSizes() {
@@ -420,62 +441,124 @@ class TimeScale {
420
441
 
421
442
  if (this.tickSizes.length > 0) {
422
443
  //add ticks from higher levels
423
- this.tickSizes.push(...divisions[0].map((s) => s * unitSize));
424
- continue;
444
+ this.tickSizes.push(...divisions[0].map((s) => ({ size: s * unitSize, measure: unit })));
445
+ break;
425
446
  }
426
447
 
427
448
  let bestLabelDistance = Infinity;
449
+ let bestMinLabelDistance = this.minLabelDistance;
428
450
  let bestTicks = [];
429
- let bestScale = this.scale;
451
+ let bestScale = null;
452
+ let bestFormat = null;
430
453
 
431
454
  this.tickMeasure = unit;
432
455
 
433
456
  for (let i = 0; i < divisions.length; i++) {
434
457
  let divs = divisions[i];
435
- let tickSizes = divs.map((s) => s * unitSize);
436
- let scale = this.getScale(tickSizes, unit);
437
- tickSizes.forEach((size, level) => {
438
- let tickDistance = size * Math.abs(scale.factor);
439
- if (tickDistance >= this.minTickDistance && tickDistance < bestLabelDistance) {
458
+ for (let d = 0; d < divs.length; d++) {
459
+ //if (useSnapToTicks && d < Math.min(divs.length - 1, this.snapToTicks)) continue;
460
+ let tickSize = divs[d] * unitSize;
461
+ let scale = this.getScale(null, unit);
462
+ let format = this.format ?? this.getFormat(unit, scale);
463
+ let minLabelDistance = this.minLabelDistanceFormatOverride[format] ?? this.minLabelDistance;
464
+ let labelDistance = tickSize * Math.abs(scale.factor);
465
+ if (labelDistance >= minLabelDistance && labelDistance < bestLabelDistance) {
440
466
  bestScale = scale;
441
- bestTicks = tickSizes;
442
- bestLabelDistance = tickDistance;
467
+ bestTicks = divs.map((s) => s * unitSize);
468
+ bestLabelDistance = labelDistance;
469
+ bestFormat = format;
470
+ bestMinLabelDistance = minLabelDistance;
443
471
  }
444
- });
472
+ }
445
473
  }
474
+
446
475
  this.scale = bestScale;
447
- this.tickSizes = bestTicks.filter((ts) => ts * Math.abs(bestScale.factor) >= this.minTickDistance);
476
+ this.tickSizes = bestTicks
477
+ .filter((ts) => ts * Math.abs(bestScale.factor) >= this.minTickDistance)
478
+ .map((size) => ({ size, measure: this.tickMeasure }));
479
+ this.resolvedFormat = bestFormat;
480
+ this.resolvedMinLabelDistance = bestMinLabelDistance;
481
+ }
482
+
483
+ let lowerTickUnit = null;
484
+ switch (this.tickMeasure) {
485
+ case "year":
486
+ lowerTickUnit = "month";
487
+ break;
488
+ case "month":
489
+ lowerTickUnit = "day";
490
+ break;
491
+ case "week":
492
+ lowerTickUnit = "day";
493
+ break;
494
+ case "day":
495
+ lowerTickUnit = "hour";
496
+ break;
497
+ case "hour":
498
+ lowerTickUnit = "minute";
499
+ break;
500
+ case "minute":
501
+ lowerTickUnit = "second";
502
+ break;
503
+ }
504
+
505
+ if (lowerTickUnit != null && this.scale) {
506
+ let bestMinorTickSize = Infinity;
507
+ let divisions = this.tickDivisions[lowerTickUnit];
508
+ let unitSize = miliSeconds[lowerTickUnit];
509
+ for (let i = 0; i < divisions.length; i++) {
510
+ let divs = divisions[i];
511
+ for (let d = 0; d < divs.length; d++) {
512
+ let tickSize = divs[d] * unitSize;
513
+ if (tickSize * Math.abs(this.scale.factor) >= this.minTickDistance && tickSize < bestMinorTickSize) {
514
+ bestMinorTickSize = tickSize;
515
+ }
516
+ }
517
+ }
518
+ if (bestMinorTickSize != Infinity) {
519
+ this.tickSizes.unshift({ size: bestMinorTickSize, measure: lowerTickUnit });
520
+ if (this.tickSizes.length > 1) {
521
+ let labelStep = this.tickSizes[1].size;
522
+ let lowerScale = this.getScale(null, lowerTickUnit);
523
+ if (lowerScale.max - lowerScale.min >= labelStep) this.scale = lowerScale;
524
+ }
525
+ }
526
+ }
527
+
528
+ if (isNumber(this.snapToTicks) && this.snapToTicks >= 0) {
529
+ let tickSize = this.tickSizes[Math.min(this.tickSizes.length - 1, this.snapToTicks)];
530
+ this.scale = this.getScale(tickSize.size, tickSize.measure);
448
531
  }
449
532
  }
450
533
 
451
534
  getTicks(tickSizes) {
452
- return tickSizes.map((size) => {
535
+ return tickSizes.map(({ size, measure }) => {
453
536
  let result = [],
454
537
  start,
455
538
  end,
456
539
  minDate,
457
540
  maxDate;
458
- if (this.tickMeasure == "year") {
541
+ if (measure == "year") {
459
542
  size /= miliSeconds.year;
460
543
  minDate = new Date(this.scale.min - this.scale.minPadding);
461
544
  maxDate = new Date(this.scale.max + this.scale.maxPadding);
462
545
  start = Math.ceil(yearNumber(minDate) / size) * size;
463
546
  end = Math.floor(yearNumber(maxDate) / size) * size;
464
547
  for (let i = start; i <= end; i += size) result.push(new Date(i, 0, 1).getTime());
465
- } else if (this.tickMeasure == "month") {
548
+ } else if (measure == "month") {
466
549
  size /= miliSeconds.month;
467
550
  minDate = new Date(this.scale.min - this.scale.minPadding);
468
551
  maxDate = new Date(this.scale.max + this.scale.maxPadding);
469
552
  start = Math.ceil(monthNumber(minDate) / size) * size;
470
553
  end = Math.floor(monthNumber(maxDate) / size) * size;
471
554
  for (let i = start; i <= end; i += size) result.push(new Date(Math.floor(i / 12), i % 12, 1).getTime());
472
- } else if (this.tickMeasure == "day" || this.tickMeasure == "week") {
473
- let multiplier = this.tickMeasure == "week" ? 7 : 1;
555
+ } else if (measure == "day" || measure == "week") {
556
+ let multiplier = measure == "week" ? 7 : 1;
474
557
  size /= miliSeconds.day;
475
558
  minDate = new Date(this.scale.min - this.scale.minPadding);
476
559
  maxDate = new Date(this.scale.max + this.scale.maxPadding);
477
560
  let date = zeroTime(minDate);
478
- if (this.tickMeasure == "week") {
561
+ if (measure == "week") {
479
562
  //start on monday
480
563
  while (date.getDay() != 1) {
481
564
  date.setDate(date.getDate() + 1);
@@ -504,7 +587,6 @@ class TimeScale {
504
587
 
505
588
  mapGridlines() {
506
589
  if (this.tickSizes.length == 0) return [];
507
-
508
590
  return this.getTicks([this.tickSizes[0]])[0].map((x) => this.map(x));
509
591
  }
510
592
  }