@internetarchive/histogram-date-range 0.1.0-beta → 0.1.3-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demo/index.css +23 -0
- package/demo/index.html +51 -42
- package/dist/src/histogram-date-range.d.ts +22 -13
- package/dist/src/histogram-date-range.js +131 -65
- package/dist/src/histogram-date-range.js.map +1 -1
- package/dist/test/histogram-date-range.test.js +76 -17
- package/dist/test/histogram-date-range.test.js.map +1 -1
- package/docs/_snowpack/pkg/@internetarchive/ia-activity-indicator/ia-activity-indicator.js +9 -2534
- package/docs/_snowpack/pkg/common/lit-element-3254fb50.js +22 -0
- package/docs/_snowpack/pkg/common/lit-html-1d707ff6.js +8 -0
- package/docs/_snowpack/pkg/dayjs/esm/index.js +3 -3
- package/docs/_snowpack/pkg/dayjs/esm/plugin/customParseFormat.js +342 -0
- package/docs/_snowpack/pkg/import-map.json +1 -0
- package/docs/_snowpack/pkg/lit/decorators.js +8 -2
- package/docs/_snowpack/pkg/lit/directives/live.js +4 -4
- package/docs/_snowpack/pkg/lit.js +2 -23
- package/docs/demo/index.css +23 -0
- package/docs/demo/index.html +51 -42
- package/docs/dist/src/histogram-date-range.js +94 -47
- package/package.json +20 -19
- package/src/histogram-date-range.ts +164 -72
- package/test/histogram-date-range.test.ts +107 -23
- package/docs/_snowpack/env.js +0 -3
- package/docs/_snowpack/pkg/common/lit-html-e67c9f49.js +0 -8
- package/types/static.d.ts +0 -4
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
css,
|
|
3
3
|
html,
|
|
4
|
+
nothing,
|
|
4
5
|
LitElement,
|
|
5
6
|
PropertyValues,
|
|
6
7
|
svg,
|
|
@@ -10,6 +11,8 @@ import {
|
|
|
10
11
|
import { property, state, customElement } from 'lit/decorators.js';
|
|
11
12
|
import { live } from 'lit/directives/live.js';
|
|
12
13
|
import dayjs from 'dayjs/esm/index.js';
|
|
14
|
+
import customParseFormat from 'dayjs/esm/plugin/customParseFormat';
|
|
15
|
+
dayjs.extend(customParseFormat);
|
|
13
16
|
import '@internetarchive/ia-activity-indicator/ia-activity-indicator';
|
|
14
17
|
|
|
15
18
|
// these values can be overridden via the component's HTML (camelCased) attributes
|
|
@@ -20,23 +23,25 @@ const TOOLTIP_WIDTH = 125;
|
|
|
20
23
|
const TOOLTIP_HEIGHT = 30;
|
|
21
24
|
const DATE_FORMAT = 'YYYY';
|
|
22
25
|
const MISSING_DATA = 'no data';
|
|
23
|
-
const UPDATE_DEBOUNCE_DELAY_MS =
|
|
26
|
+
const UPDATE_DEBOUNCE_DELAY_MS = 0;
|
|
24
27
|
|
|
25
28
|
// this constant is not set up to be overridden
|
|
26
29
|
const SLIDER_CORNER_SIZE = 4;
|
|
27
30
|
|
|
28
31
|
// these CSS custom props can be overridden from the HTML that is invoking this component
|
|
29
|
-
const
|
|
30
|
-
const
|
|
32
|
+
const sliderColor = css`var(--histogramDateRangeSliderColor, #4B65FE)`;
|
|
33
|
+
const selectedRangeColor = css`var(--histogramDateRangeSelectedRangeColor, #DBE0FF)`;
|
|
31
34
|
const barIncludedFill = css`var(--histogramDateRangeBarIncludedFill, #2C2C2C)`;
|
|
32
35
|
const activityIndicatorColor = css`var(--histogramDateRangeActivityIndicator, #2C2C2C)`;
|
|
33
36
|
const barExcludedFill = css`var(--histogramDateRangeBarExcludedFill, #CCCCCC)`;
|
|
34
37
|
const inputBorder = css`var(--histogramDateRangeInputBorder, 0.5px solid #2C2C2C)`;
|
|
35
38
|
const inputWidth = css`var(--histogramDateRangeInputWidth, 35px)`;
|
|
36
39
|
const inputFontSize = css`var(--histogramDateRangeInputFontSize, 1.2rem)`;
|
|
40
|
+
const inputFontFamily = css`var(--histogramDateRangeInputFontFamily, sans-serif)`;
|
|
37
41
|
const tooltipBackgroundColor = css`var(--histogramDateRangeTooltipBackgroundColor, #2C2C2C)`;
|
|
38
42
|
const tooltipTextColor = css`var(--histogramDateRangeTooltipTextColor, #FFFFFF)`;
|
|
39
43
|
const tooltipFontSize = css`var(--histogramDateRangeTooltipFontSize, 1.1rem)`;
|
|
44
|
+
const tooltipFontFamily = css`var(--histogramDateRangeTooltipFontFamily, sans-serif)`;
|
|
40
45
|
|
|
41
46
|
type SliderId = 'slider-min' | 'slider-max';
|
|
42
47
|
|
|
@@ -123,8 +128,8 @@ export class HistogramDateRange extends LitElement {
|
|
|
123
128
|
return;
|
|
124
129
|
}
|
|
125
130
|
this._histWidth = this.width - this.sliderWidth * 2;
|
|
126
|
-
this._minDateMS =
|
|
127
|
-
this._maxDateMS =
|
|
131
|
+
this._minDateMS = this.getMSFromString(this.minDate);
|
|
132
|
+
this._maxDateMS = this.getMSFromString(this.maxDate);
|
|
128
133
|
this._binWidth = this._histWidth / this._numBins;
|
|
129
134
|
this._previousDateRange = this.currentDateRangeString;
|
|
130
135
|
this._histData = this.calculateHistData();
|
|
@@ -140,11 +145,17 @@ export class HistogramDateRange extends LitElement {
|
|
|
140
145
|
private calculateHistData(): HistogramItem[] {
|
|
141
146
|
const minValue = Math.min(...this.bins);
|
|
142
147
|
const maxValue = Math.max(...this.bins);
|
|
143
|
-
|
|
148
|
+
// if there is no difference between the min and max values, use a range of
|
|
149
|
+
// 1 because log scaling will fail if the range is 0
|
|
150
|
+
const valueRange =
|
|
151
|
+
minValue === maxValue ? 1 : Math.log1p(maxValue - minValue);
|
|
152
|
+
const valueScale = this.height / valueRange;
|
|
144
153
|
const dateScale = this.dateRangeMS / this._numBins;
|
|
145
154
|
return this.bins.map((v: number, i: number) => {
|
|
146
155
|
return {
|
|
147
156
|
value: v,
|
|
157
|
+
// use log scaling for the height of the bar to prevent tall bars from
|
|
158
|
+
// making the smaller ones too small to see
|
|
148
159
|
height: Math.floor(Math.log1p(v) * valueScale),
|
|
149
160
|
binStart: `${this.formatDate(i * dateScale + this._minDateMS)}`,
|
|
150
161
|
binEnd: `${this.formatDate((i + 1) * dateScale + this._minDateMS)}`,
|
|
@@ -163,6 +174,14 @@ export class HistogramDateRange extends LitElement {
|
|
|
163
174
|
return this.bins.length;
|
|
164
175
|
}
|
|
165
176
|
|
|
177
|
+
private get histogramLeftEdgeX(): number {
|
|
178
|
+
return this.sliderWidth;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private get histogramRightEdgeX(): number {
|
|
182
|
+
return this.width - this.sliderWidth;
|
|
183
|
+
}
|
|
184
|
+
|
|
166
185
|
/** component's loading (and disabled) state */
|
|
167
186
|
@property({ type: Boolean }) get loading(): boolean {
|
|
168
187
|
return this._isLoading;
|
|
@@ -175,56 +194,62 @@ export class HistogramDateRange extends LitElement {
|
|
|
175
194
|
|
|
176
195
|
/** formatted minimum date of selected date range */
|
|
177
196
|
@property() get minSelectedDate(): string {
|
|
178
|
-
return this.formatDate(this._minSelectedDate);
|
|
197
|
+
return this.formatDate(this.getMSFromString(this._minSelectedDate));
|
|
179
198
|
}
|
|
180
199
|
|
|
200
|
+
/** updates minSelectedDate if new date is valid */
|
|
181
201
|
set minSelectedDate(rawDate: string) {
|
|
182
202
|
if (!this._minSelectedDate) {
|
|
183
203
|
// because the values needed to calculate valid max/min values are not
|
|
184
204
|
// available during the lit init when it's populating properties from
|
|
185
205
|
// attributes, fall back to just the raw date if nothing is already set
|
|
186
206
|
this._minSelectedDate = rawDate;
|
|
207
|
+
return;
|
|
187
208
|
}
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
209
|
+
const proposedDateMS = this.getMSFromString(rawDate);
|
|
210
|
+
const isValidDate = !Number.isNaN(proposedDateMS);
|
|
211
|
+
const isNotTooRecent =
|
|
212
|
+
proposedDateMS <= this.getMSFromString(this.maxSelectedDate);
|
|
213
|
+
if (isValidDate && isNotTooRecent) {
|
|
214
|
+
this._minSelectedDate = this.formatDate(proposedDateMS);
|
|
192
215
|
}
|
|
193
216
|
this.requestUpdate();
|
|
194
217
|
}
|
|
195
218
|
|
|
196
219
|
/** formatted maximum date of selected date range */
|
|
197
220
|
@property() get maxSelectedDate(): string {
|
|
198
|
-
return this.formatDate(this._maxSelectedDate);
|
|
221
|
+
return this.formatDate(this.getMSFromString(this._maxSelectedDate));
|
|
199
222
|
}
|
|
200
223
|
|
|
224
|
+
/** updates maxSelectedDate if new date is valid */
|
|
201
225
|
set maxSelectedDate(rawDate: string) {
|
|
202
226
|
if (!this._maxSelectedDate) {
|
|
203
|
-
//
|
|
227
|
+
// because the values needed to calculate valid max/min values are not
|
|
228
|
+
// available during the lit init when it's populating properties from
|
|
229
|
+
// attributes, fall back to just the raw date if nothing is already set
|
|
204
230
|
this._maxSelectedDate = rawDate;
|
|
231
|
+
return;
|
|
205
232
|
}
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
233
|
+
const proposedDateMS = this.getMSFromString(rawDate);
|
|
234
|
+
const isValidDate = !Number.isNaN(proposedDateMS);
|
|
235
|
+
const isNotTooOld =
|
|
236
|
+
proposedDateMS >= this.getMSFromString(this.minSelectedDate);
|
|
237
|
+
if (isValidDate && isNotTooOld) {
|
|
238
|
+
this._maxSelectedDate = this.formatDate(proposedDateMS);
|
|
210
239
|
}
|
|
211
240
|
this.requestUpdate();
|
|
212
241
|
}
|
|
242
|
+
|
|
213
243
|
/** horizontal position of min date slider */
|
|
214
244
|
get minSliderX(): number {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
this.translateDateToPosition(this.minSelectedDate) ?? this.sliderWidth
|
|
218
|
-
);
|
|
245
|
+
const x = this.translateDateToPosition(this.minSelectedDate);
|
|
246
|
+
return this.validMinSliderX(x);
|
|
219
247
|
}
|
|
220
248
|
|
|
221
249
|
/** horizontal position of max date slider */
|
|
222
250
|
get maxSliderX(): number {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
this.translateDateToPosition(this.maxSelectedDate) ??
|
|
226
|
-
this.width - this.sliderWidth
|
|
227
|
-
);
|
|
251
|
+
const x = this.translateDateToPosition(this.maxSelectedDate);
|
|
252
|
+
return this.validMaxSliderX(x);
|
|
228
253
|
}
|
|
229
254
|
|
|
230
255
|
private get dateRangeMS(): number {
|
|
@@ -239,12 +264,13 @@ export class HistogramDateRange extends LitElement {
|
|
|
239
264
|
const x = target.x.baseVal.value + this.sliderWidth / 2;
|
|
240
265
|
const dataset = target.dataset as BarDataset;
|
|
241
266
|
const itemsText = `item${dataset.numItems !== '1' ? 's' : ''}`;
|
|
267
|
+
const formattedNumItems = Number(dataset.numItems).toLocaleString();
|
|
242
268
|
|
|
243
269
|
this._tooltipOffset =
|
|
244
270
|
x + (this._binWidth - this.sliderWidth - this.tooltipWidth) / 2;
|
|
245
271
|
|
|
246
272
|
this._tooltipContent = html`
|
|
247
|
-
${
|
|
273
|
+
${formattedNumItems} ${itemsText}<br />
|
|
248
274
|
${dataset.binStart} - ${dataset.binEnd}
|
|
249
275
|
`;
|
|
250
276
|
this._tooltipVisible = true;
|
|
@@ -287,11 +313,14 @@ export class HistogramDateRange extends LitElement {
|
|
|
287
313
|
private move = (e: PointerEvent): void => {
|
|
288
314
|
const newX = e.offsetX - this._dragOffset;
|
|
289
315
|
const slider = this._currentSlider as SVGRectElement;
|
|
290
|
-
const date = this.translatePositionToDate(newX);
|
|
291
316
|
if ((slider.id as SliderId) === 'slider-min') {
|
|
292
|
-
this.minSelectedDate =
|
|
317
|
+
this.minSelectedDate = this.translatePositionToDate(
|
|
318
|
+
this.validMinSliderX(newX)
|
|
319
|
+
);
|
|
293
320
|
} else {
|
|
294
|
-
this.maxSelectedDate =
|
|
321
|
+
this.maxSelectedDate = this.translatePositionToDate(
|
|
322
|
+
this.validMaxSliderX(newX)
|
|
323
|
+
);
|
|
295
324
|
}
|
|
296
325
|
};
|
|
297
326
|
|
|
@@ -299,26 +328,42 @@ export class HistogramDateRange extends LitElement {
|
|
|
299
328
|
* Constrain a proposed value for the minimum (left) slider
|
|
300
329
|
*
|
|
301
330
|
* If the value is less than the leftmost valid position, then set it to the
|
|
302
|
-
* left edge of the
|
|
303
|
-
* the rightmost valid position (the position of the max slider), then
|
|
304
|
-
* to the position of the max slider
|
|
331
|
+
* left edge of the histogram (ie the slider width). If the value is greater
|
|
332
|
+
* than the rightmost valid position (the position of the max slider), then
|
|
333
|
+
* set it to the position of the max slider
|
|
305
334
|
*/
|
|
306
335
|
private validMinSliderX(newX: number): number {
|
|
307
|
-
|
|
308
|
-
|
|
336
|
+
// allow the left slider to go right only to the right slider, even if the
|
|
337
|
+
// max selected date is out of range
|
|
338
|
+
const rightLimit = Math.min(
|
|
339
|
+
this.translateDateToPosition(this.maxSelectedDate),
|
|
340
|
+
this.histogramRightEdgeX
|
|
341
|
+
);
|
|
342
|
+
newX = this.clamp(newX, this.histogramLeftEdgeX, rightLimit);
|
|
343
|
+
const isInvalid =
|
|
344
|
+
Number.isNaN(newX) || rightLimit < this.histogramLeftEdgeX;
|
|
345
|
+
return isInvalid ? this.histogramLeftEdgeX : newX;
|
|
309
346
|
}
|
|
310
347
|
|
|
311
348
|
/**
|
|
312
349
|
* Constrain a proposed value for the maximum (right) slider
|
|
313
350
|
*
|
|
314
351
|
* If the value is greater than the rightmost valid position, then set it to
|
|
315
|
-
* the right edge of the
|
|
316
|
-
* is less than the leftmost valid position (the position of the min
|
|
317
|
-
* then set it to the position of the min slider
|
|
352
|
+
* the right edge of the histogram (ie histogram width - slider width). If the
|
|
353
|
+
* value is less than the leftmost valid position (the position of the min
|
|
354
|
+
* slider), then set it to the position of the min slider
|
|
318
355
|
*/
|
|
319
356
|
private validMaxSliderX(newX: number): number {
|
|
320
|
-
|
|
321
|
-
|
|
357
|
+
// allow the right slider to go left only to the left slider, even if the
|
|
358
|
+
// min selected date is out of range
|
|
359
|
+
const leftLimit = Math.max(
|
|
360
|
+
this.histogramLeftEdgeX,
|
|
361
|
+
this.translateDateToPosition(this.minSelectedDate)
|
|
362
|
+
);
|
|
363
|
+
newX = this.clamp(newX, leftLimit, this.histogramRightEdgeX);
|
|
364
|
+
const isInvalid =
|
|
365
|
+
Number.isNaN(newX) || leftLimit > this.histogramRightEdgeX;
|
|
366
|
+
return isInvalid ? this.histogramRightEdgeX : newX;
|
|
322
367
|
}
|
|
323
368
|
|
|
324
369
|
private addListeners(): void {
|
|
@@ -400,54 +445,87 @@ export class HistogramDateRange extends LitElement {
|
|
|
400
445
|
}
|
|
401
446
|
|
|
402
447
|
/**
|
|
403
|
-
* Returns slider x-position corresponding to given date
|
|
404
|
-
* date)
|
|
448
|
+
* Returns slider x-position corresponding to given date
|
|
405
449
|
*
|
|
406
450
|
* @param date
|
|
407
451
|
* @returns x-position of slider
|
|
408
452
|
*/
|
|
409
|
-
private translateDateToPosition(date: string): number
|
|
410
|
-
const milliseconds =
|
|
411
|
-
|
|
453
|
+
private translateDateToPosition(date: string): number {
|
|
454
|
+
const milliseconds = this.getMSFromString(date);
|
|
455
|
+
return (
|
|
412
456
|
this.sliderWidth +
|
|
413
|
-
((milliseconds - this._minDateMS) * this._histWidth) / this.dateRangeMS
|
|
414
|
-
|
|
457
|
+
((milliseconds - this._minDateMS) * this._histWidth) / this.dateRangeMS
|
|
458
|
+
);
|
|
415
459
|
}
|
|
416
460
|
|
|
417
|
-
|
|
461
|
+
/** ensure that the returned value is between minValue and maxValue */
|
|
462
|
+
private clamp(x: number, minValue: number, maxValue: number): number {
|
|
463
|
+
return Math.min(Math.max(x, minValue), maxValue);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
private handleMinDateInput(e: Event): void {
|
|
418
467
|
const target = e.currentTarget as HTMLInputElement;
|
|
419
468
|
this.minSelectedDate = target.value;
|
|
420
469
|
this.beginEmitUpdateProcess();
|
|
421
470
|
}
|
|
422
471
|
|
|
423
|
-
private handleMaxDateInput(e:
|
|
472
|
+
private handleMaxDateInput(e: Event): void {
|
|
424
473
|
const target = e.currentTarget as HTMLInputElement;
|
|
425
474
|
this.maxSelectedDate = target.value;
|
|
426
475
|
this.beginEmitUpdateProcess();
|
|
427
476
|
}
|
|
428
477
|
|
|
429
|
-
private
|
|
430
|
-
|
|
478
|
+
private handleKeyUp(e: KeyboardEvent): void {
|
|
479
|
+
if (e.key === 'Enter') {
|
|
480
|
+
const target = e.currentTarget as HTMLInputElement;
|
|
481
|
+
target.blur();
|
|
482
|
+
if (target.id === 'date-min') {
|
|
483
|
+
this.handleMinDateInput(e);
|
|
484
|
+
} else if (target.id === 'date-max') {
|
|
485
|
+
this.handleMaxDateInput(e);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
431
488
|
}
|
|
432
489
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
return dayjs(this.minSelectedDate).valueOf();
|
|
490
|
+
private get currentDateRangeString(): string {
|
|
491
|
+
return `${this.minSelectedDate}:${this.maxSelectedDate}`;
|
|
436
492
|
}
|
|
437
493
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
494
|
+
private getMSFromString(date: string): number {
|
|
495
|
+
const digitGroupCount = (date.split(/(\d+)/).length - 1) / 2;
|
|
496
|
+
if (digitGroupCount === 1) {
|
|
497
|
+
// if there's just a single set of digits, assume it's a year
|
|
498
|
+
const dateObj = new Date(0, 0); // start at January 1, 1900
|
|
499
|
+
dateObj.setFullYear(Number(date)); // override year
|
|
500
|
+
return dateObj.getTime(); // get time in milliseconds
|
|
501
|
+
}
|
|
502
|
+
return dayjs(date, [this.dateFormat, DATE_FORMAT]).valueOf();
|
|
441
503
|
}
|
|
442
504
|
|
|
443
|
-
|
|
505
|
+
/**
|
|
506
|
+
* expand or narrow the selected range by moving the slider nearest the
|
|
507
|
+
* clicked bar to the outer edge of the clicked bar
|
|
508
|
+
*
|
|
509
|
+
* @param e Event click event from a histogram bar
|
|
510
|
+
*/
|
|
511
|
+
private handleBarClick(e: Event): void {
|
|
444
512
|
const dataset = (e.currentTarget as SVGRectElement).dataset as BarDataset;
|
|
445
|
-
|
|
446
|
-
|
|
513
|
+
// use the midpoint of the width of the clicked bar to determine which is
|
|
514
|
+
// the nearest slider
|
|
515
|
+
const clickPosition =
|
|
516
|
+
(this.getMSFromString(dataset.binStart) +
|
|
517
|
+
this.getMSFromString(dataset.binEnd)) /
|
|
518
|
+
2;
|
|
519
|
+
const distanceFromMinSlider = Math.abs(
|
|
520
|
+
clickPosition - this.getMSFromString(this.minSelectedDate)
|
|
521
|
+
);
|
|
522
|
+
const distanceFromMaxSlider = Math.abs(
|
|
523
|
+
clickPosition - this.getMSFromString(this.maxSelectedDate)
|
|
524
|
+
);
|
|
525
|
+
// update the selected range by moving the nearer slider
|
|
526
|
+
if (distanceFromMinSlider < distanceFromMaxSlider) {
|
|
447
527
|
this.minSelectedDate = dataset.binStart;
|
|
448
|
-
}
|
|
449
|
-
const binEndDateMS = dayjs(dataset.binEnd).valueOf();
|
|
450
|
-
if (binEndDateMS > this.maxSelectedDateMS) {
|
|
528
|
+
} else {
|
|
451
529
|
this.maxSelectedDate = dataset.binEnd;
|
|
452
530
|
}
|
|
453
531
|
this.beginEmitUpdateProcess();
|
|
@@ -500,7 +578,7 @@ export class HistogramDateRange extends LitElement {
|
|
|
500
578
|
${this._isDragging ? 'dragging' : ''}"
|
|
501
579
|
@pointerdown="${this.drag}"
|
|
502
580
|
>
|
|
503
|
-
<path d="${sliderShape} z" fill="${
|
|
581
|
+
<path d="${sliderShape} z" fill="${sliderColor}" />
|
|
504
582
|
<rect
|
|
505
583
|
x="${
|
|
506
584
|
sliderPositionX - this.sliderWidth * k + this.sliderWidth * 0.4 * k
|
|
@@ -530,7 +608,7 @@ export class HistogramDateRange extends LitElement {
|
|
|
530
608
|
y="0"
|
|
531
609
|
width="${this.maxSliderX - this.minSliderX}"
|
|
532
610
|
height="${this.height}"
|
|
533
|
-
fill="${
|
|
611
|
+
fill="${selectedRangeColor}"
|
|
534
612
|
/>`;
|
|
535
613
|
}
|
|
536
614
|
|
|
@@ -558,7 +636,7 @@ export class HistogramDateRange extends LitElement {
|
|
|
558
636
|
@pointerleave="${this.hideTooltip}"
|
|
559
637
|
@click="${this.handleBarClick}"
|
|
560
638
|
fill="${
|
|
561
|
-
x >= this.minSliderX && x <= this.maxSliderX
|
|
639
|
+
x + barWidth >= this.minSliderX && x <= this.maxSliderX
|
|
562
640
|
? barIncludedFill
|
|
563
641
|
: barExcludedFill
|
|
564
642
|
}"
|
|
@@ -571,9 +649,17 @@ export class HistogramDateRange extends LitElement {
|
|
|
571
649
|
});
|
|
572
650
|
}
|
|
573
651
|
|
|
574
|
-
private formatDate(
|
|
575
|
-
|
|
576
|
-
|
|
652
|
+
private formatDate(dateMS: number): string {
|
|
653
|
+
if (Number.isNaN(dateMS)) {
|
|
654
|
+
return '';
|
|
655
|
+
}
|
|
656
|
+
const date = dayjs(dateMS);
|
|
657
|
+
if (date.year() < 1000) {
|
|
658
|
+
// years before 1000 don't play well with dayjs custom formatting, so fall
|
|
659
|
+
// back to displaying only the year
|
|
660
|
+
return String(date.year());
|
|
661
|
+
}
|
|
662
|
+
return date.format(this.dateFormat);
|
|
577
663
|
}
|
|
578
664
|
|
|
579
665
|
/**
|
|
@@ -590,6 +676,7 @@ export class HistogramDateRange extends LitElement {
|
|
|
590
676
|
type="text"
|
|
591
677
|
@focus="${this.cancelPendingUpdateEvent}"
|
|
592
678
|
@blur="${this.handleMinDateInput}"
|
|
679
|
+
@keyup="${this.handleKeyUp}"
|
|
593
680
|
.value="${live(this.minSelectedDate)}"
|
|
594
681
|
?disabled="${this.disabled}"
|
|
595
682
|
/>
|
|
@@ -604,6 +691,7 @@ export class HistogramDateRange extends LitElement {
|
|
|
604
691
|
type="text"
|
|
605
692
|
@focus="${this.cancelPendingUpdateEvent}"
|
|
606
693
|
@blur="${this.handleMaxDateInput}"
|
|
694
|
+
@keyup="${this.handleKeyUp}"
|
|
607
695
|
.value="${live(this.maxSelectedDate)}"
|
|
608
696
|
?disabled="${this.disabled}"
|
|
609
697
|
/>
|
|
@@ -634,9 +722,9 @@ export class HistogramDateRange extends LitElement {
|
|
|
634
722
|
`;
|
|
635
723
|
}
|
|
636
724
|
|
|
637
|
-
private get activityIndicatorTemplate(): TemplateResult {
|
|
725
|
+
private get activityIndicatorTemplate(): TemplateResult | typeof nothing {
|
|
638
726
|
if (!this.loading) {
|
|
639
|
-
return
|
|
727
|
+
return nothing;
|
|
640
728
|
}
|
|
641
729
|
return html`
|
|
642
730
|
<ia-activity-indicator mode="processing"> </ia-activity-indicator>
|
|
@@ -700,7 +788,7 @@ export class HistogramDateRange extends LitElement {
|
|
|
700
788
|
border-radius: 3px;
|
|
701
789
|
padding: 2px;
|
|
702
790
|
font-size: ${tooltipFontSize};
|
|
703
|
-
font-family:
|
|
791
|
+
font-family: ${tooltipFontFamily};
|
|
704
792
|
touch-action: none;
|
|
705
793
|
pointer-events: none;
|
|
706
794
|
}
|
|
@@ -737,6 +825,7 @@ export class HistogramDateRange extends LitElement {
|
|
|
737
825
|
border-radius: 2px !important;
|
|
738
826
|
text-align: center;
|
|
739
827
|
font-size: ${inputFontSize};
|
|
828
|
+
font-family: ${inputFontFamily};
|
|
740
829
|
}
|
|
741
830
|
`;
|
|
742
831
|
|
|
@@ -777,6 +866,9 @@ export class HistogramDateRange extends LitElement {
|
|
|
777
866
|
`;
|
|
778
867
|
}
|
|
779
868
|
}
|
|
869
|
+
|
|
870
|
+
// help TypeScript provide strong typing when interacting with DOM APIs
|
|
871
|
+
// https://stackoverflow.com/questions/65148695/lit-element-typescript-project-global-interface-declaration-necessary
|
|
780
872
|
declare global {
|
|
781
873
|
interface HTMLElementTagNameMap {
|
|
782
874
|
'histogram-date-range': HistogramDateRange;
|